diff options
author | Mike Pall <mike> | 2013-04-26 00:26:44 +0200 |
---|---|---|
committer | Mike Pall <mike> | 2013-04-26 00:26:44 +0200 |
commit | eeb204cd87a58f8a6e29022ea30aaba877acb2e0 (patch) | |
tree | 3fd7e85dcd77749ed13b2bdc77aa949b397e937f | |
parent | 7c2844873070f71e2e98765682326e6d98a6b55e (diff) | |
download | luajit-eeb204cd87a58f8a6e29022ea30aaba877acb2e0.tar.gz luajit-eeb204cd87a58f8a6e29022ea30aaba877acb2e0.tar.bz2 luajit-eeb204cd87a58f8a6e29022ea30aaba877acb2e0.zip |
Fix FOLD rules for appending to string buffers.
-rw-r--r-- | src/lj_opt_fold.c | 27 |
1 files changed, 21 insertions, 6 deletions
diff --git a/src/lj_opt_fold.c b/src/lj_opt_fold.c index 75b8e174..2ed0bc93 100644 --- a/src/lj_opt_fold.c +++ b/src/lj_opt_fold.c | |||
@@ -533,6 +533,7 @@ LJFOLDF(bufput_append) | |||
533 | fleft->op1 == IR(fright->op1)->op1) { | 533 | fleft->op1 == IR(fright->op1)->op1) { |
534 | IRRef ref = fins->op1; | 534 | IRRef ref = fins->op1; |
535 | IR(ref)->op2 = (fleft->op2 | IRBUFHDR_APPEND); /* Modify BUFHDR. */ | 535 | IR(ref)->op2 = (fleft->op2 | IRBUFHDR_APPEND); /* Modify BUFHDR. */ |
536 | IR(ref)->op1 = fright->op2; | ||
536 | return ref; | 537 | return ref; |
537 | } | 538 | } |
538 | return EMITFOLD; /* This is a store and always emitted. */ | 539 | return EMITFOLD; /* This is a store and always emitted. */ |
@@ -572,27 +573,41 @@ LJFOLDF(bufstr_kfold_cse) | |||
572 | lua_assert(fright->o == IR_BUFHDR || fright->o == IR_BUFPUT); | 573 | lua_assert(fright->o == IR_BUFHDR || fright->o == IR_BUFPUT); |
573 | if (LJ_LIKELY(J->flags & JIT_F_OPT_FOLD)) { | 574 | if (LJ_LIKELY(J->flags & JIT_F_OPT_FOLD)) { |
574 | if (fright->o == IR_BUFHDR) { /* No put operations? */ | 575 | if (fright->o == IR_BUFHDR) { /* No put operations? */ |
575 | if (!(fright->op2 & IRBUFHDR_APPEND)) /* Empty buffer? */ | 576 | if (!(fright->op2 & IRBUFHDR_APPEND)) { /* Empty buffer? */ |
577 | lj_ir_rollback(J, fins->op1); /* Eliminate the current chain. */ | ||
576 | return lj_ir_kstr(J, &J2G(J)->strempty); | 578 | return lj_ir_kstr(J, &J2G(J)->strempty); |
579 | } | ||
577 | fins->op2 = fright->prev; /* Relies on checks in bufput_append. */ | 580 | fins->op2 = fright->prev; /* Relies on checks in bufput_append. */ |
578 | return CSEFOLD; | 581 | return CSEFOLD; |
579 | } else { | 582 | } else { |
580 | IRIns *irb = IR(fright->op1); | 583 | IRIns *irb = IR(fright->op1); |
581 | if (irb->o == IR_BUFHDR && !(irb->op2 & IRBUFHDR_APPEND)) | 584 | if (irb->o == IR_BUFHDR && !(irb->op2 & IRBUFHDR_APPEND)) { |
585 | lj_ir_rollback(J, fins->op1); /* Eliminate the current chain. */ | ||
582 | return fright->op2; /* Shortcut for a single put operation. */ | 586 | return fright->op2; /* Shortcut for a single put operation. */ |
587 | } | ||
583 | } | 588 | } |
584 | } | 589 | } |
585 | /* Try to CSE the whole chain. */ | 590 | /* Try to CSE the whole chain. */ |
586 | if (LJ_LIKELY(J->flags & JIT_F_OPT_CSE) && !(fleft->op2 & IRBUFHDR_APPEND)) { | 591 | if (LJ_LIKELY(J->flags & JIT_F_OPT_CSE)) { |
587 | IRRef ref = J->chain[IR_BUFSTR]; | 592 | IRRef ref = J->chain[IR_BUFSTR]; |
588 | while (ref) { | 593 | while (ref) { |
594 | IRRef last = fins->op2; | ||
589 | IRIns *irs = IR(ref), *ira = fright, *irb = IR(irs->op2); | 595 | IRIns *irs = IR(ref), *ira = fright, *irb = IR(irs->op2); |
590 | while (ira->o == irb->o && ira->op2 == irb->op2) { | 596 | while (ira->o == irb->o && ira->op2 == irb->op2) { |
591 | if (ira->o == IR_BUFHDR) { | 597 | if (ira->o == IR_BUFHDR && !(ira->op2 & IRBUFHDR_APPEND)) { |
592 | lj_ir_rollback(J, fins->op1); /* Eliminate the current chain. */ | 598 | IRIns *irh; |
599 | for (irh = IR(ira->prev); irh != irb; irh = IR(irh->prev)) | ||
600 | if (irh->op1 == irs->op2) | ||
601 | return ref; /* Do CSE, but avoid rollback if append follows. */ | ||
602 | lj_ir_rollback(J, last); /* Eliminate the current chain. */ | ||
593 | return ref; /* CSE succeeded. */ | 603 | return ref; /* CSE succeeded. */ |
604 | } else if (ira->o == IR_CALLS) { | ||
605 | ira = IR(ira->op1); irb = IR(irb->op1); | ||
606 | lua_assert(ira->o == IR_CARG && irb->o == IR_CARG); | ||
607 | if (ira->op2 != irb->op2) break; | ||
594 | } | 608 | } |
595 | ira = IR(ira->op1); | 609 | last = ira->op1; |
610 | ira = IR(last); | ||
596 | irb = IR(irb->op1); | 611 | irb = IR(irb->op1); |
597 | } | 612 | } |
598 | ref = irs->prev; | 613 | ref = irs->prev; |