summary refs log tree commit diff
path: root/copy.c
diff options
context:
space:
mode:
authorQuentin Carbonneaux <quentin@c9x.me>2019-05-02 20:57:26 +0200
committerQuentin Carbonneaux <quentin@c9x.me>2019-05-02 20:57:26 +0200
commit34fee80e690986175ba9417802fad69fb5b821db (patch)
tree6b5a8676b7bef7c080588fadff1c282ed969d14a /copy.c
parent2e7d6b24eaa1314eb4fe663ef5dc529e461fb8ce (diff)
downloadroux-34fee80e690986175ba9417802fad69fb5b821db.tar.gz
detect ubiquitous simple copies
When lowering pointer arithmetic, it is
natural for a C frontend to generate
those instructions.
Diffstat (limited to 'copy.c')
-rw-r--r--copy.c36
1 files changed, 27 insertions, 9 deletions
diff --git a/copy.c b/copy.c
index b92c5f4..8354929 100644
--- a/copy.c
+++ b/copy.c
@@ -1,7 +1,15 @@
 #include "all.h"
 
 static int
-iscopy(Ins *i, Ref r, Tmp *tmp)
+iscon(Ref r, int64_t bits, Fn *fn)
+{
+	return rtype(r) == RCon
+		&& fn->con[r.val].type == CBits
+		&& fn->con[r.val].bits.i == bits;
+}
+
+static int
+iscopy(Ins *i, Ref r, Fn *fn)
 {
 	static bits extcpy[] = {
 		[WFull] = 0,
@@ -15,15 +23,25 @@ iscopy(Ins *i, Ref r, Tmp *tmp)
 	bits b;
 	Tmp *t;
 
-	if (i->op == Ocopy)
+	switch (i->op) {
+	case Ocopy:
 		return 1;
+	case Omul:
+		return iscon(i->arg[0], 1, fn) || iscon(i->arg[1], 1, fn);
+	case Odiv:
+		return iscon(i->arg[1], 1, fn);
+	case Oadd:
+		return iscon(i->arg[0], 0, fn) || iscon(i->arg[1], 0, fn);
+	default:
+		break;
+	}
 	if (!isext(i->op) || rtype(r) != RTmp)
 		return 0;
 	if (i->op == Oextsw || i->op == Oextuw)
 	if (i->cls == Kw)
 		return 1;
 
-	t = &tmp[r.val];
+	t = &fn->tmp[r.val];
 	assert(KBASE(t->cls) == 0);
 	if (i->cls == Kl && t->cls == Kw)
 		return 0;
@@ -44,7 +62,7 @@ copyof(Ref r, Ref *cpy)
  * and Efficient SSA Construction" by Braun M. et al.
  */
 static void
-phisimpl(Phi *p, Ref r, Ref *cpy, Use ***pstk, BSet *ts, BSet *as, Tmp *tmp)
+phisimpl(Phi *p, Ref r, Ref *cpy, Use ***pstk, BSet *ts, BSet *as, Fn *fn)
 {
 	Use **stk, *u, *u1;
 	uint nstk, a;
@@ -58,7 +76,7 @@ phisimpl(Phi *p, Ref r, Ref *cpy, Use ***pstk, BSet *ts, BSet *as, Tmp *tmp)
 	stk[0] = &(Use){.type = UPhi, .u.phi = p};
 	while (nstk) {
 		u = stk[--nstk];
-		if (u->type == UIns && iscopy(u->u.ins, r, tmp)) {
+		if (u->type == UIns && iscopy(u->u.ins, r, fn)) {
 			p = &(Phi){.narg = 0};
 			t = u->u.ins->to.val;
 		}
@@ -79,8 +97,8 @@ phisimpl(Phi *p, Ref r, Ref *cpy, Use ***pstk, BSet *ts, BSet *as, Tmp *tmp)
 				return;
 			bsset(as, r1.val);
 		}
-		u = tmp[t].use;
-		u1 = &u[tmp[t].nuse];
+		u = fn->tmp[t].use;
+		u1 = &u[fn->tmp[t].nuse];
 		vgrow(pstk, nstk+(u1-u));
 		stk = *pstk;
 		for (; u<u1; u++)
@@ -130,14 +148,14 @@ copy(Fn *fn)
 					r = copyof(p->arg[a], cpy);
 			assert(!req(r, R));
 			cpy[p->to.val] = p->to;
-			phisimpl(p, r, cpy, &stk, ts, as, fn->tmp);
+			phisimpl(p, r, cpy, &stk, ts, as, fn);
 		}
 		for (i=b->ins; i<&b->ins[b->nins]; i++) {
 			assert(rtype(i->to) <= RTmp);
 			if (!req(cpy[i->to.val], R))
 				continue;
 			r = copyof(i->arg[0], cpy);
-			if (iscopy(i, r, fn->tmp))
+			if (iscopy(i, r, fn))
 				cpy[i->to.val] = r;
 			else
 				cpy[i->to.val] = i->to;