summary refs log tree commit diff
diff options
context:
space:
mode:
authorQuentin Carbonneaux <quentin@c9x.me>2022-11-21 11:29:22 +0100
committerQuentin Carbonneaux <quentin@c9x.me>2022-11-21 11:53:00 +0100
commit0db06dad63e02b619671bfb3dd25fc92c0856319 (patch)
tree0a37b3bf581b4918516686a31f0ae2d002d140f2
parent674901b71834739cccf3f8665833dc125d1172b7 (diff)
downloadroux-0db06dad63e02b619671bfb3dd25fc92c0856319.tar.gz
recognize some phis as copies
The copy elimination pass is not
complete. This patch improves
things a bit, but I think we still
have quite a bit of incompleteness.

We now consistently mark phis with
all arguments identical as copies.
Previously, they were inconsistently
eliminated by phisimpl(). An example
where they were not eliminated is
the following:

    @blk2
        %a = phi @blk0 %x, @blk1 %x
	jnz ?, @blk3, @blk4
    @blk3
        %b = copy %x
    @blk4
        %c = phi @blk2 %a, @blk3 %b

In this example, neither %c nor %a
were marked as copies of %x because,
when phisimpl() is called, the copy
information for %b is not available.

The incompleteness is still present
and can be observed by modifying
the example above so that %a takes
a copy of %x through a back-edge.
Then, phisimpl()'s lack of copy
information about %b will prevent
optimization.
-rw-r--r--copy.c21
1 files changed, 15 insertions, 6 deletions
diff --git a/copy.c b/copy.c
index 868d2ba..1f9e1f3 100644
--- a/copy.c
+++ b/copy.c
@@ -134,8 +134,8 @@ copy(Fn *fn)
 	Phi *p, **pp;
 	Ins *i;
 	Blk *b;
-	uint n, a;
-	Ref *cpy, r;
+	uint n, a, eq;
+	Ref *cpy, r, r1;
 	int t;
 
 	bsinit(ts, fn->ntmp);
@@ -150,13 +150,22 @@ copy(Fn *fn)
 			assert(rtype(p->to) == RTmp);
 			if (!req(cpy[p->to.val], R))
 				continue;
+			eq = 0;
 			r = R;
 			for (a=0; a<p->narg; a++)
-				if (p->blk[a]->id < n)
-					r = copyof(p->arg[a], cpy);
+				if (p->blk[a]->id < n) {
+					r1 = copyof(p->arg[a], cpy);
+					if (req(r, R) || req(r1, r))
+						eq++;
+					r = r1;
+				}
 			assert(!req(r, R));
-			cpy[p->to.val] = p->to;
-			phisimpl(p, r, cpy, &stk, ts, as, fn);
+			if (eq == p->narg)
+				cpy[p->to.val] = r;
+			else {
+				cpy[p->to.val] = p->to;
+				phisimpl(p, r, cpy, &stk, ts, as, fn);
+			}
 		}
 		for (i=b->ins; i<&b->ins[b->nins]; i++) {
 			assert(rtype(i->to) <= RTmp);