summary refs log tree commit diff
diff options
context:
space:
mode:
authorQuentin Carbonneaux <quentin@c9x.me>2019-03-12 21:15:21 +0100
committerQuentin Carbonneaux <quentin@c9x.me>2019-03-13 22:02:29 +0100
commitb777cd6c4becf0d834f8fa549315fa11918a53be (patch)
tree10e19572ac0f336c5248565323d6a9c71dceeed1
parentfd65f4275be6dc6603be9610e88c55b8bfc1dc62 (diff)
downloadroux-b777cd6c4becf0d834f8fa549315fa11918a53be.tar.gz
simple heuristic to reuse stack slots
On test/spill1.ssa, the stack frame of
the function f() goes from 56 bytes to
40 bytes.  That's a reduction of close
to 30%.

This patch also opens the door to
folding operations on spill slots.
For example

    movl $15, %r15d
    addl -X(%rbp), %r15d
    movl %r15d, -X(%rbp)

should become

    add $15, -X(%rbp)

when %r15d is not used afterwards.
-rw-r--r--spill.c17
1 files changed, 14 insertions, 3 deletions
diff --git a/spill.c b/spill.c
index 42f0c05..f0b593a 100644
--- a/spill.c
+++ b/spill.c
@@ -309,7 +309,7 @@ void
 spill(Fn *fn)
 {
 	Blk *b, *s1, *s2, *hd, **bp;
-	int j, l, t, k, lvarg[2];
+	int j, l, t, k, s, lvarg[2];
 	uint n;
 	BSet u[1], v[1], w[1];
 	Ins *i;
@@ -407,6 +407,7 @@ spill(Fn *fn)
 			if (!req(i->to, R)) {
 				assert(rtype(i->to) == RTmp);
 				t = i->to.val;
+				s = tmp[t].slot;
 				if (bshas(v, t))
 					bsclr(v, t);
 				else {
@@ -440,6 +441,13 @@ spill(Fn *fn)
 					bsset(v, t);
 					if (j-- <= 0)
 						bsset(w, t);
+					else if (!lvarg[n]) {
+						/* recycle the slot of
+						 * i->to when possible
+						 */
+						if (tmp[t].slot == -1)
+							tmp[t].slot = s;
+					}
 					break;
 				}
 			bscopy(u, v);
@@ -447,9 +455,12 @@ spill(Fn *fn)
 			for (n=0; n<2; n++)
 				if (rtype(i->arg[n]) == RTmp) {
 					t = i->arg[n].val;
-					if (!bshas(v, t)) {
+					if (bshas(v, t)) {
+						if (tmp[t].slot == s)
+							tmp[t].slot = -1;
+					} else {
 						/* do not reload if the
-						 * the temporary was dead
+						 * argument is dead
 						 */
 						if (!lvarg[n])
 							bsclr(u, t);