aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Forney <[email protected]>2021-11-18 01:45:27 -0800
committerQuentin Carbonneaux <[email protected]>2021-11-22 18:07:50 +0100
commitbf153b359e9ce3ebef9bca899eb7ed5bd9045c11 (patch)
tree20857b60dfd9a0f5bb98dee40a1f4b140ba76447
parentb0f16dad64d14f36ffe235b2e9cca96aa3ce35ba (diff)
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.h1
-rw-r--r--amd64/isel.c7
-rw-r--r--fold.c12
-rw-r--r--load.c15
-rw-r--r--parse.c10
-rw-r--r--util.c19
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;