summary refs log tree commit diff
diff options
context:
space:
mode:
authorMichael Forney <mforney@mforney.org>2021-11-18 01:45:27 -0800
committerQuentin Carbonneaux <quentin@c9x.me>2021-11-22 18:07:50 +0100
commitbf153b359e9ce3ebef9bca899eb7ed5bd9045c11 (patch)
tree20857b60dfd9a0f5bb98dee40a1f4b140ba76447
parentb0f16dad64d14f36ffe235b2e9cca96aa3ce35ba (diff)
downloadroux-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.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;