Fix FOLD rules for appending to string buffers.

This commit is contained in:
Mike Pall 2013-04-26 00:26:44 +02:00
parent 7c28448730
commit eeb204cd87

View File

@ -533,6 +533,7 @@ LJFOLDF(bufput_append)
fleft->op1 == IR(fright->op1)->op1) { fleft->op1 == IR(fright->op1)->op1) {
IRRef ref = fins->op1; IRRef ref = fins->op1;
IR(ref)->op2 = (fleft->op2 | IRBUFHDR_APPEND); /* Modify BUFHDR. */ IR(ref)->op2 = (fleft->op2 | IRBUFHDR_APPEND); /* Modify BUFHDR. */
IR(ref)->op1 = fright->op2;
return ref; return ref;
} }
return EMITFOLD; /* This is a store and always emitted. */ return EMITFOLD; /* This is a store and always emitted. */
@ -572,27 +573,41 @@ LJFOLDF(bufstr_kfold_cse)
lua_assert(fright->o == IR_BUFHDR || fright->o == IR_BUFPUT); lua_assert(fright->o == IR_BUFHDR || fright->o == IR_BUFPUT);
if (LJ_LIKELY(J->flags & JIT_F_OPT_FOLD)) { if (LJ_LIKELY(J->flags & JIT_F_OPT_FOLD)) {
if (fright->o == IR_BUFHDR) { /* No put operations? */ if (fright->o == IR_BUFHDR) { /* No put operations? */
if (!(fright->op2 & IRBUFHDR_APPEND)) /* Empty buffer? */ if (!(fright->op2 & IRBUFHDR_APPEND)) { /* Empty buffer? */
lj_ir_rollback(J, fins->op1); /* Eliminate the current chain. */
return lj_ir_kstr(J, &J2G(J)->strempty); return lj_ir_kstr(J, &J2G(J)->strempty);
}
fins->op2 = fright->prev; /* Relies on checks in bufput_append. */ fins->op2 = fright->prev; /* Relies on checks in bufput_append. */
return CSEFOLD; return CSEFOLD;
} else { } else {
IRIns *irb = IR(fright->op1); IRIns *irb = IR(fright->op1);
if (irb->o == IR_BUFHDR && !(irb->op2 & IRBUFHDR_APPEND)) if (irb->o == IR_BUFHDR && !(irb->op2 & IRBUFHDR_APPEND)) {
lj_ir_rollback(J, fins->op1); /* Eliminate the current chain. */
return fright->op2; /* Shortcut for a single put operation. */ return fright->op2; /* Shortcut for a single put operation. */
} }
} }
}
/* Try to CSE the whole chain. */ /* Try to CSE the whole chain. */
if (LJ_LIKELY(J->flags & JIT_F_OPT_CSE) && !(fleft->op2 & IRBUFHDR_APPEND)) { if (LJ_LIKELY(J->flags & JIT_F_OPT_CSE)) {
IRRef ref = J->chain[IR_BUFSTR]; IRRef ref = J->chain[IR_BUFSTR];
while (ref) { while (ref) {
IRRef last = fins->op2;
IRIns *irs = IR(ref), *ira = fright, *irb = IR(irs->op2); IRIns *irs = IR(ref), *ira = fright, *irb = IR(irs->op2);
while (ira->o == irb->o && ira->op2 == irb->op2) { while (ira->o == irb->o && ira->op2 == irb->op2) {
if (ira->o == IR_BUFHDR) { if (ira->o == IR_BUFHDR && !(ira->op2 & IRBUFHDR_APPEND)) {
lj_ir_rollback(J, fins->op1); /* Eliminate the current chain. */ IRIns *irh;
for (irh = IR(ira->prev); irh != irb; irh = IR(irh->prev))
if (irh->op1 == irs->op2)
return ref; /* Do CSE, but avoid rollback if append follows. */
lj_ir_rollback(J, last); /* Eliminate the current chain. */
return ref; /* CSE succeeded. */ return ref; /* CSE succeeded. */
} else if (ira->o == IR_CALLS) {
ira = IR(ira->op1); irb = IR(irb->op1);
lua_assert(ira->o == IR_CARG && irb->o == IR_CARG);
if (ira->op2 != irb->op2) break;
} }
ira = IR(ira->op1); last = ira->op1;
ira = IR(last);
irb = IR(irb->op1); irb = IR(irb->op1);
} }
ref = irs->prev; ref = irs->prev;