diff options
author | Quentin Carbonneaux <quentin.carbonneaux@yale.edu> | 2017-02-24 10:31:50 -0500 |
---|---|---|
committer | Quentin Carbonneaux <quentin.carbonneaux@yale.edu> | 2017-02-24 10:31:50 -0500 |
commit | 0699cd2e575bcaa951cb7d97bc77ab9acb2c9970 (patch) | |
tree | ca2569cbf21c747e9393d025b2bc5b93973ee7bf /load.c | |
parent | 1bb7652484e1c7ca2cd7fcab858b4bbb18509879 (diff) | |
download | roux-0699cd2e575bcaa951cb7d97bc77ab9acb2c9970.tar.gz |
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.c | 53 |
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; |