Преглед изворни кода

fold scaled offsets in addresses

Quentin Carbonneaux пре 1 година
родитељ
комит
4a809d69b5
5 измењених фајлова са 79 додато и 11 уклоњено
  1. 1 1
      all.h
  2. 1 1
      amd64/emit.c
  3. 6 5
      amd64/isel.c
  4. 64 0
      test/isel4.ssa
  5. 7 4
      util.c

+ 1 - 1
all.h

@@ -484,7 +484,7 @@ void chuse(Ref, int, Fn *);
 int symeq(Sym, Sym);
 Ref newcon(Con *, Fn *);
 Ref getcon(int64_t, Fn *);
-int addcon(Con *, Con *);
+int addcon(Con *, Con *, int);
 void salloc(Ref, Ref, Fn *);
 void dumpts(BSet *, Tmp *, FILE *);
 void runmatch(uchar *, Num *, Ref, Ref *);

+ 1 - 1
amd64/emit.c

@@ -293,7 +293,7 @@ Next:
 			if (rtype(m->base) == RSlot) {
 				off.type = CBits;
 				off.bits.i = slot(m->base, fn);
-				addcon(&m->offset, &off);
+				addcon(&m->offset, &off, 1);
 				m->base = TMP(RBP);
 			}
 			if (m->offset.type != CUndef)

+ 6 - 5
amd64/isel.c

@@ -692,7 +692,7 @@ anumber(Num *tn, Blk *b, Con *con)
 }
 
 static Ref
-adisp(Con *c, Num *tn, Ref r, Fn *fn)
+adisp(Con *c, Num *tn, Ref r, Fn *fn, int s)
 {
 	Ref v[2];
 	int n;
@@ -704,7 +704,7 @@ adisp(Con *c, Num *tn, Ref r, Fn *fn)
 			break;
 		runmatch(matcher[Pob], tn, r, v);
 		assert(rtype(v[0]) == RCon);
-		addcon(c, &fn->con[v[0].val]);
+		addcon(c, &fn->con[v[0].val], s);
 		r = v[1];
 	}
 	return r;
@@ -733,18 +733,18 @@ amatch(Addr *a, Num *tn, Ref r, Fn *fn)
 
 	memset(&co, 0, sizeof co);
 	ro = v[0];
-	rb = adisp(&co, tn, v[1], fn);
+	rb = adisp(&co, tn, v[1], fn, 1);
 	ri = v[2];
 	rs = v[3];
 	s = 1;
 
 	if (*p < 0 && co.type != CUndef)
 	if (amatch(a, tn, rb, fn))
-		return addcon(&a->offset, &co);
+		return addcon(&a->offset, &co, 1);
 	if (!req(ro, R)) {
 		assert(rtype(ro) == RCon);
 		c = &fn->con[ro.val];
-		if (!addcon(&co, c))
+		if (!addcon(&co, c, 1))
 			return 0;
 	}
 	if (!req(rs, R)) {
@@ -753,6 +753,7 @@ amatch(Addr *a, Num *tn, Ref r, Fn *fn)
 		assert(c->type = CBits);
 		s = c->bits.i;
 	}
+	ri = adisp(&co, tn, ri, fn, s);
 	*a = (Addr){co, rb, ri, s};
 
 	if (rtype(ri) == RTmp)

+ 64 - 0
test/isel4.ssa

@@ -0,0 +1,64 @@
+# amd64 address-folding stress
+
+export function w $f0(l %a, l %b) {
+@start
+	%c =l add %b, 2
+	%d =l mul %c, 4
+	%e =l add %a, %d
+	%q =l loadw %e
+	ret %q
+}
+
+export function w $f1(l %a, l %b) {
+@start
+	%c =l add 1, %b
+	%f =l add %c, 1
+	%d =l mul %f, 4
+	%e =l add %d, %a
+	%q =l loadw %e
+	ret %q
+}
+
+export function w $f2(l %a, l %b) {
+@start
+	%l =l mul %b, 4
+	%d =l add 8, %l
+	%e =l add %a, %d
+	%q =l loadw %e
+	ret %q
+}
+
+# fixme: folding is not good here
+export function w $f3(l %a, l %b) {
+@start
+	%l =l mul %b, 4
+	%d =l add 4, %l
+	%f =l add 4, %d
+	%e =l add %a, %f
+	%q =l loadw %e
+	ret %q
+}
+
+export function w $f4(l %a, l %b) {
+@start
+	%c =l add 1, %b
+	%d =l mul %c, 4
+	%e =l add 4, %d
+	%f =l add %e, %a
+	%q =l loadw %f
+	ret %q
+}
+
+# >>> driver
+# int a[] = {1, 2, 3, 4};
+# typedef int loadf(int *, long long);
+# extern loadf f0, f1, f2, f3, f4;
+# loadf *fns[] = {&f0, &f1, &f2, &f3, &f4, 0};
+# int main() {
+# 	loadf **f;
+# 	int n;
+# 	for (n=1,f=fns; *f; f++,n++)
+# 		if ((*f)(a, 1) != 4) return n;
+# 	return 0;
+# }
+# <<<

+ 7 - 4
util.c

@@ -398,18 +398,21 @@ getcon(int64_t val, Fn *fn)
 }
 
 int
-addcon(Con *c0, Con *c1)
+addcon(Con *c0, Con *c1, int m)
 {
-	if (c0->type == CUndef)
+	if (m != 1 && c1->type == CAddr)
+		return 0;
+	if (c0->type == CUndef) {
 		*c0 = *c1;
-	else {
+		c0->bits.i *= m;
+	} else {
 		if (c1->type == CAddr) {
 			if (c0->type == CAddr)
 				return 0;
 			c0->type = CAddr;
 			c0->sym = c1->sym;
 		}
-		c0->bits.i += c1->bits.i;
+		c0->bits.i += c1->bits.i * m;
 	}
 	return 1;
 }