diff options
author | Quentin Carbonneaux <quentin@c9x.me> | 2019-02-06 08:34:51 +0100 |
---|---|---|
committer | Quentin Carbonneaux <quentin@c9x.me> | 2019-02-06 09:02:25 +0100 |
commit | ce0ab53ed73fb24f9537cab762467efad56f2664 (patch) | |
tree | f8fb8d9da412938e1d66d7fc2b7a7f98f7a64f19 /rega.c | |
parent | 834b5cb08bbf0f4fbc1992a72327dfc2c0a31796 (diff) | |
download | roux-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.c | 8 |
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; } |