aboutsummaryrefslogtreecommitdiff
path: root/load.c
diff options
context:
space:
mode:
authorQuentin Carbonneaux <[email protected]>2017-02-24 10:31:50 -0500
committerQuentin Carbonneaux <[email protected]>2017-02-24 10:31:50 -0500
commit0699cd2e575bcaa951cb7d97bc77ab9acb2c9970 (patch)
treeca2569cbf21c747e9393d025b2bc5b93973ee7bf /load.c
parent1bb7652484e1c7ca2cd7fcab858b4bbb18509879 (diff)
improve the range of action of load elimination
When eliminating `load %foo`, don't limit the search to the live range of %foo, but to the live range of its aliasing information. For example, if %foo is a constant offset into a stack-allocated slot, %foo =l add %slot, 42 the search will proceed on all the code in which %slot is live, not only below the definition of %foo, like before.
Diffstat (limited to 'load.c')
-rw-r--r--load.c53
1 files changed, 48 insertions, 5 deletions
diff --git a/load.c b/load.c
index 3e22b57..4805720 100644
--- a/load.c
+++ b/load.c
@@ -113,8 +113,9 @@ mask(int cls, Ref *r, bits msk, Loc *l)
static Ref
load(Slice sl, bits msk, Loc *l)
{
- Ref r;
- int ld, cls, all;
+ Alias *a;
+ Ref r, r1;
+ int ld, cls, all, c;
ld = (int[]){
[1] = Oloadub,
@@ -127,12 +128,54 @@ load(Slice sl, bits msk, Loc *l)
cls = sl.cls;
else
cls = sl.sz > 4 ? Kl : Kw;
- r = iins(cls, ld, sl.ref, R, l);
+ r = sl.ref;
+ /* sl.ref might not be live here,
+ * but its alias base ref will be
+ * (see killsl() below) */
+ if (rtype(r) == RTmp) {
+ a = &curf->tmp[r.val].alias;
+ switch (a->type) {
+ default:
+ die("unreachable");
+ case ALoc:
+ case AEsc:
+ case AUnk:
+ r = a->base;
+ if (!a->offset)
+ break;
+ r1 = getcon(a->offset, curf);
+ r = iins(Kl, Oadd, r, r1, l);
+ break;
+ case ACon:
+ case ASym:
+ c = curf->ncon++;
+ vgrow(&curf->con, curf->ncon);
+ curf->con[c].type = CAddr;
+ strcpy(curf->con[c].label, a->label);
+ curf->con[c].bits.i = a->offset;
+ curf->con[c].local = 0;
+ r = CON(c);
+ break;
+ }
+ }
+ r = iins(cls, ld, r, R, l);
if (!all)
mask(cls, &r, msk, l);
return r;
}
+static int
+killsl(Ref r, Slice sl)
+{
+ Alias *a;
+
+ if (rtype(sl.ref) != RTmp)
+ return 0;
+ a = &curf->tmp[sl.ref.val].alias;
+ assert(a->type==ALoc || a->type==AEsc || a->type==AUnk);
+ return req(a->base, r);
+}
+
/* returns a ref containing the contents of the slice
* passed as argument, all the bits set to 0 in the
* mask argument are zeroed in the result;
@@ -181,7 +224,7 @@ def(Slice sl, bits msk, Blk *b, Ins *i, Loc *il)
while (i > b->ins) {
--i;
- if (req(i->to, sl.ref)
+ if (killsl(i->to, sl)
|| (i->op == Ocall && escapes(sl.ref, curf)))
goto Load;
ld = isload(i->op);
@@ -251,7 +294,7 @@ def(Slice sl, bits msk, Blk *b, Ins *i, Loc *il)
}
for (p=b->phi; p; p=p->link)
- if (req(p->to, sl.ref))
+ if (killsl(p->to, sl))
/* scanning predecessors in that
* case would be unsafe */
goto Load;