diff options
author | Michael Forney <mforney@mforney.org> | 2021-11-18 01:45:27 -0800 |
---|---|---|
committer | Quentin Carbonneaux <quentin@c9x.me> | 2021-11-22 18:07:50 +0100 |
commit | bf153b359e9ce3ebef9bca899eb7ed5bd9045c11 (patch) | |
tree | 20857b60dfd9a0f5bb98dee40a1f4b140ba76447 | |
parent | b0f16dad64d14f36ffe235b2e9cca96aa3ce35ba (diff) | |
download | roux-bf153b359e9ce3ebef9bca899eb7ed5bd9045c11.tar.gz |
reuse previous address constants in fold()
parseref() has code to reuse address constants, but this is not done in other passes such as fold or isel. Introduce a new function newcon() which takes a Con and returns a Ref for that constant, and use this whenever creating address constants. This is necessary to fix folding of address constants when one operand is already folded. For example, in %a =l add $x, 1 %b =l add %a, 2 %c =w loadw %b %a and %b were folded to $x+1 and $x+3 respectively, but then the second add is visited again since it uses %a. This gets folded to $x+3 as well, but as a new distinct constant. This results in %b getting labeled as bottom instead of either constant, disabling the replacement of %b by a constant in subsequent instructions (such as the loadw).
-rw-r--r-- | all.h | 1 | ||||
-rw-r--r-- | amd64/isel.c | 7 | ||||
-rw-r--r-- | fold.c | 12 | ||||
-rw-r--r-- | load.c | 15 | ||||
-rw-r--r-- | parse.c | 10 | ||||
-rw-r--r-- | util.c | 19 |
6 files changed, 33 insertions, 31 deletions
diff --git a/all.h b/all.h index f49b4ef..98b77dd 100644 --- a/all.h +++ b/all.h @@ -431,6 +431,7 @@ int clsmerge(short *, short); int phicls(int, Tmp *); Ref newtmp(char *, int, Fn *); void chuse(Ref, int, Fn *); +Ref newcon(Con *, Fn *); Ref getcon(int64_t, Fn *); int addcon(Con *, Con *); void blit(Ref, uint, Ref, uint, Fn *); diff --git a/amd64/isel.c b/amd64/isel.c index 607c176..0f4c7a5 100644 --- a/amd64/isel.c +++ b/amd64/isel.c @@ -117,12 +117,9 @@ fixarg(Ref *r, int k, Ins *i, Fn *fn) m = &fn->mem[r0.val]; if (req(m->base, R)) if (m->offset.type == CAddr) { - n = fn->ncon; - vgrow(&fn->con, ++fn->ncon); - fn->con[n] = m->offset; - m->offset.type = CUndef; r0 = newtmp("isel", Kl, fn); - emit(Oaddr, Kl, r0, CON(n), R); + emit(Oaddr, Kl, r0, newcon(&m->offset, fn), R); + m->offset.type = CUndef; m->base = r0; } } diff --git a/fold.c b/fold.c index 50a862e..348e532 100644 --- a/fold.c +++ b/fold.c @@ -496,7 +496,7 @@ foldflt(Con *res, int op, int w, Con *cl, Con *cr) static int opfold(int op, int cls, Con *cl, Con *cr, Fn *fn) { - int nc; + Ref r; Con c; if ((op == Odiv || op == Oudiv @@ -507,13 +507,7 @@ opfold(int op, int cls, Con *cl, Con *cr, Fn *fn) return Bot; } else foldflt(&c, op, cls == Kd, cl, cr); - if (c.type == CBits) - nc = getcon(c.bits.i, fn).val; - else { - nc = fn->ncon; - vgrow(&fn->con, ++fn->ncon); - } + r = newcon(&c, fn); assert(!(cls == Ks || cls == Kd) || c.flt); - fn->con[nc] = c; - return nc; + return r.val; } diff --git a/load.c b/load.c index 5d61a6c..2e10a35 100644 --- a/load.c +++ b/load.c @@ -118,7 +118,8 @@ load(Slice sl, bits msk, Loc *l) { Alias *a; Ref r, r1; - int ld, cls, all, c; + int ld, cls, all; + Con c; ld = (int[]){ [1] = Oloadub, @@ -151,13 +152,11 @@ load(Slice sl, bits msk, Loc *l) break; case ACon: case ASym: - c = curf->ncon++; - vgrow(&curf->con, curf->ncon); - curf->con[c].type = CAddr; - curf->con[c].label = a->label; - curf->con[c].bits.i = a->offset; - curf->con[c].local = 0; - r = CON(c); + c.type = CAddr; + c.label = a->label; + c.bits.i = a->offset; + c.local = 0; + r = newcon(&c, curf); break; } } diff --git a/parse.c b/parse.c index 104ca1d..6e22e1f 100644 --- a/parse.c +++ b/parse.c @@ -381,7 +381,6 @@ static Ref parseref() { Con c; - int i; memset(&c, 0, sizeof c); switch (next()) { @@ -405,14 +404,7 @@ parseref() c.type = CAddr; c.label = intern(tokval.str); Look: - for (i=0; i<curf->ncon; i++) - if (curf->con[i].type == c.type - && curf->con[i].bits.i == c.bits.i - && curf->con[i].label == c.label) - return CON(i); - vgrow(&curf->con, ++curf->ncon); - curf->con[i] = c; - return CON(i); + return newcon(&c, curf); default: return R; } diff --git a/util.c b/util.c index 9a3576a..c8b0b9c 100644 --- a/util.c +++ b/util.c @@ -350,6 +350,25 @@ chuse(Ref r, int du, Fn *fn) } Ref +newcon(Con *c0, Fn *fn) +{ + Con *c1; + int i; + + for (i=0; i<fn->ncon; i++) { + c1 = &fn->con[i]; + if (c0->type == c1->type + && c0->bits.i == c1->bits.i + && c0->label == c1->label + && c0->local == c1->local) + return CON(i); + } + vgrow(&fn->con, ++fn->ncon); + fn->con[i] = *c0; + return CON(i); +} + +Ref getcon(int64_t val, Fn *fn) { int c; |