commit bf153b359e9ce3ebef9bca899eb7ed5bd9045c11
parent b0f16dad64d14f36ffe235b2e9cca96aa3ce35ba
Author: Michael Forney <mforney@mforney.org>
Date: Thu, 18 Nov 2021 01:45:27 -0800
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).
Diffstat:
6 files changed, 33 insertions(+), 31 deletions(-)
diff --git 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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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;