aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Pall <mike>2010-12-12 22:28:48 +0100
committerMike Pall <mike>2010-12-12 22:32:52 +0100
commit74317fa0efce58c8cedaae29315113ff609d14fe (patch)
tree9430dc1f8c0a6329839c92e2df6735f4799696e1
parenta22ea8898efa0014bbef8adceb5ed6ee269d4356 (diff)
downloadluajit-74317fa0efce58c8cedaae29315113ff609d14fe.tar.gz
luajit-74317fa0efce58c8cedaae29315113ff609d14fe.tar.bz2
luajit-74317fa0efce58c8cedaae29315113ff609d14fe.zip
Add alias analysis for XLOAD/XSTORE. Add DSE for XSTORE.
-rw-r--r--src/lj_iropt.h1
-rw-r--r--src/lj_opt_fold.c3
-rw-r--r--src/lj_opt_mem.c89
3 files changed, 90 insertions, 3 deletions
diff --git a/src/lj_iropt.h b/src/lj_iropt.h
index 9e7ac9cd..4739f846 100644
--- a/src/lj_iropt.h
+++ b/src/lj_iropt.h
@@ -127,6 +127,7 @@ LJ_FUNC int lj_opt_fwd_wasnonnil(jit_State *J, IROpT loadop, IRRef xref);
127LJ_FUNC TRef LJ_FASTCALL lj_opt_dse_ahstore(jit_State *J); 127LJ_FUNC TRef LJ_FASTCALL lj_opt_dse_ahstore(jit_State *J);
128LJ_FUNC TRef LJ_FASTCALL lj_opt_dse_ustore(jit_State *J); 128LJ_FUNC TRef LJ_FASTCALL lj_opt_dse_ustore(jit_State *J);
129LJ_FUNC TRef LJ_FASTCALL lj_opt_dse_fstore(jit_State *J); 129LJ_FUNC TRef LJ_FASTCALL lj_opt_dse_fstore(jit_State *J);
130LJ_FUNC TRef LJ_FASTCALL lj_opt_dse_xstore(jit_State *J);
130 131
131/* Narrowing. */ 132/* Narrowing. */
132LJ_FUNC TRef LJ_FASTCALL lj_opt_narrow_convert(jit_State *J); 133LJ_FUNC TRef LJ_FASTCALL lj_opt_narrow_convert(jit_State *J);
diff --git a/src/lj_opt_fold.c b/src/lj_opt_fold.c
index 18471abf..cbcbb448 100644
--- a/src/lj_opt_fold.c
+++ b/src/lj_opt_fold.c
@@ -1696,6 +1696,9 @@ LJFOLDX(lj_opt_dse_ustore)
1696LJFOLD(FSTORE any any) 1696LJFOLD(FSTORE any any)
1697LJFOLDX(lj_opt_dse_fstore) 1697LJFOLDX(lj_opt_dse_fstore)
1698 1698
1699LJFOLD(XSTORE any any)
1700LJFOLDX(lj_opt_dse_xstore)
1701
1699LJFOLD(NEWREF any any) /* Treated like a store. */ 1702LJFOLD(NEWREF any any) /* Treated like a store. */
1700LJFOLD(CALLS any any) 1703LJFOLD(CALLS any any)
1701LJFOLD(CALLL any any) /* Safeguard fallback. */ 1704LJFOLD(CALLL any any) /* Safeguard fallback. */
diff --git a/src/lj_opt_mem.c b/src/lj_opt_mem.c
index d47706fb..ec080697 100644
--- a/src/lj_opt_mem.c
+++ b/src/lj_opt_mem.c
@@ -523,12 +523,52 @@ doemit:
523 return EMITFOLD; /* Otherwise we have a conflict or simply no match. */ 523 return EMITFOLD; /* Otherwise we have a conflict or simply no match. */
524} 524}
525 525
526/* -- XLOAD forwarding ---------------------------------------------------- */ 526/* -- XLOAD forwarding and XSTORE elimination ----------------------------- */
527 527
528/* NYI: Alias analysis for XLOAD/XSTORE. */ 528/* Alias analysis for XLOAD/XSTORE. */
529static AliasRet aa_xref(jit_State *J, IRIns *refa, IRIns *refb) 529static AliasRet aa_xref(jit_State *J, IRIns *refa, IRIns *refb)
530{ 530{
531 UNUSED(J); UNUSED(refa); UNUSED(refb); 531 ptrdiff_t ofsa = 0, ofsb = 0;
532 IRIns *basea = refa, *baseb = refb;
533 if (refa == refb)
534 return ALIAS_MUST; /* Shortcut for same refs. */
535 /* This implements (very) strict aliasing rules.
536 ** Different types do NOT alias, except for differences in signedness.
537 ** NYI: this also prevents type punning through unions.
538 */
539 if (!(irt_sametype(refa->t, refb->t) ||
540 (irt_typerange(refa->t, IRT_I8, IRT_INT) &&
541 ((refa->t.irt - IRT_I8) ^ (refb->t.irt - IRT_I8)) == 1)))
542 return ALIAS_NO;
543 /* Offset-based disambiguation. */
544 if (refa->o == IR_ADD && irref_isk(refa->op2)) {
545 IRIns *irk = IR(refa->op2);
546 basea = IR(refa->op1);
547 ofsa = (LJ_64 && irk->o == IR_KINT64) ? (ptrdiff_t)ir_k64(irk)->u64 :
548 (ptrdiff_t)irk->i;
549 if (basea == refb && ofsa != 0)
550 return ALIAS_NO; /* base+-ofs vs. base. */
551 }
552 if (refb->o == IR_ADD && irref_isk(refb->op2)) {
553 IRIns *irk = IR(refb->op2);
554 baseb = IR(refb->op1);
555 ofsb = (LJ_64 && irk->o == IR_KINT64) ? (ptrdiff_t)ir_k64(irk)->u64 :
556 (ptrdiff_t)irk->i;
557 if (refa == baseb && ofsb != 0)
558 return ALIAS_NO; /* base vs. base+-ofs. */
559 }
560 if (basea == baseb) {
561 /* This assumes strictly-typed, non-overlapping accesses. */
562 if (ofsa != ofsb)
563 return ALIAS_NO; /* base+-o1 vs. base+-o2 and o1 != o2. */
564 /* Unsigned vs. signed access to the same address.
565 ** Really ALIAS_MUST, but store forwarding would lose the type.
566 ** This is rare, so return ALIAS_MAY for now.
567 */
568 return ALIAS_MAY;
569 }
570 /* NYI: structural disambiguation. */
571 /* NYI: disambiguate new allocations. */
532 return ALIAS_MAY; 572 return ALIAS_MAY;
533} 573}
534 574
@@ -567,6 +607,49 @@ cselim:
567 return lj_ir_emit(J); 607 return lj_ir_emit(J);
568} 608}
569 609
610/* XSTORE elimination. */
611TRef LJ_FASTCALL lj_opt_dse_xstore(jit_State *J)
612{
613 IRRef xref = fins->op1;
614 IRRef val = fins->op2; /* Stored value reference. */
615 IRIns *xr = IR(xref);
616 IRRef1 *refp = &J->chain[IR_XSTORE];
617 IRRef ref = *refp;
618 while (ref > xref) { /* Search for redundant or conflicting stores. */
619 IRIns *store = IR(ref);
620 switch (aa_xref(J, xr, IR(store->op1))) {
621 case ALIAS_NO:
622 break; /* Continue searching. */
623 case ALIAS_MAY:
624 if (store->op2 != val) /* Conflict if the value is different. */
625 goto doemit;
626 break; /* Otherwise continue searching. */
627 case ALIAS_MUST:
628 if (store->op2 == val) /* Same value: drop the new store. */
629 return DROPFOLD;
630 /* Different value: try to eliminate the redundant store. */
631 if (ref > J->chain[IR_LOOP]) { /* Quick check to avoid crossing LOOP. */
632 IRIns *ir;
633 /* Check for any intervening guards or any XLOADs (no AA performed). */
634 for (ir = IR(J->cur.nins-1); ir > store; ir--)
635 if (irt_isguard(ir->t) || ir->o == IR_XLOAD)
636 goto doemit; /* No elimination possible. */
637 /* Remove redundant store from chain and replace with NOP. */
638 *refp = store->prev;
639 store->o = IR_NOP; /* Unchained NOP -- does anybody care? */
640 store->t.irt = IRT_NIL;
641 store->op1 = store->op2 = 0;
642 store->prev = 0;
643 /* Now emit the new store instead. */
644 }
645 goto doemit;
646 }
647 ref = *(refp = &store->prev);
648 }
649doemit:
650 return EMITFOLD; /* Otherwise we have a conflict or simply no match. */
651}
652
570/* -- Forwarding of lj_tab_len -------------------------------------------- */ 653/* -- Forwarding of lj_tab_len -------------------------------------------- */
571 654
572/* This is rather simplistic right now, but better than nothing. */ 655/* This is rather simplistic right now, but better than nothing. */