summary refs log tree commit diff
path: root/rega.c
diff options
context:
space:
mode:
authorQuentin Carbonneaux <quentin@c9x.me>2019-02-06 08:34:51 +0100
committerQuentin Carbonneaux <quentin@c9x.me>2019-02-06 09:02:25 +0100
commitce0ab53ed73fb24f9537cab762467efad56f2664 (patch)
treef8fb8d9da412938e1d66d7fc2b7a7f98f7a64f19 /rega.c
parent834b5cb08bbf0f4fbc1992a72327dfc2c0a31796 (diff)
downloadroux-ce0ab53ed73fb24f9537cab762467efad56f2664.tar.gz
2 bug fixes in rega
The worst one was that "part 3" of rega()
could break the critical invariant that
two interferring temporaries get assigned
different registers.  This is fixed by
being careful when changing the register
of a temporary based on predecessor
blocks.

Thanks to Michael Forney for reporting
these bugs and helping with the analysis.
Diffstat (limited to 'rega.c')
-rw-r--r--rega.c8
1 files changed, 5 insertions, 3 deletions
diff --git a/rega.c b/rega.c
index f087f3c..9ceba70 100644
--- a/rega.c
+++ b/rega.c
@@ -571,7 +571,8 @@ rega(Fn *fn)
 				if (rtype(src) != RTmp)
 					continue;
 				x = rfind(&end[b->id], src.val);
-				assert(x != -1);
+				if (x == -1) /* spilled */
+					continue;
 				rl[r] = (!rl[r] || rl[r] == x) ? x : -1;
 			}
 			if (rl[r] == 0)
@@ -586,7 +587,8 @@ rega(Fn *fn)
 				continue;
 			for (bp=s->pred; bp<&s->pred[s->npred]; bp++) {
 				x = rfind(&end[(*bp)->id], t);
-				assert(x != -1);
+				if (x == -1) /* spilled */
+					continue;
 				rl[r] = (!rl[r] || rl[r] == x) ? x : -1;
 			}
 		}
@@ -597,7 +599,7 @@ rega(Fn *fn)
 			r = m->r[j];
 			x = rl[r];
 			assert(x != 0 || t < Tmp0 /* todo, ditto */);
-			if (x > 0) {
+			if (x > 0 && !bshas(m->b, x)) {
 				pmadd(TMP(x), TMP(r), tmp[t].cls);
 				m->r[j] = x;
 			}