diff options
| author | 2025-09-15 17:11:05 +0200 | |
|---|---|---|
| committer | 2025-09-15 17:11:46 +0200 | |
| commit | b8ae5b14c7bbe28161ea83f4c10045f8af5b766a (patch) | |
| tree | b53e99abf48f82435220aecea86c5569b85a74e6 | |
| parent | bdf9776b0b127b53a34be07f8adc0541df78654e (diff) | |
mem2reg: fix deltrivialphis bug
| -rw-r--r-- | cfg.c | 43 | ||||
| -rw-r--r-- | ir.c | 9 | ||||
| -rw-r--r-- | optmem.c | 21 | ||||
| -rw-r--r-- | regalloc.c | 1 |
4 files changed, 64 insertions, 10 deletions
@@ -0,0 +1,43 @@ +#include "ir.h" + +static void +porec(struct block ***rpo, struct block *b) +{ + if (wasvisited(b)) return; + markvisited(b); + if (b->s2) porec(rpo, b->s2); + if (b->s1) porec(rpo, b->s1); + *--*rpo = b; +} + +void +sortrpo(struct function *fn) +{ + static struct block **rpobuf; + struct block **rpoend, **rpo; + int i, ndead; + + xbgrow(&rpobuf, fn->nblk); + rpo = rpoend = rpobuf + fn->nblk, + + startbbvisit(); + fn->entry->id = 0; + markvisited(fn->entry); + if (fn->entry->s1) porec(&rpo, fn->entry->s1); + if (fn->entry->s2) porec(&rpo, fn->entry->s2); + *--rpo = fn->entry; + ndead = rpo - rpobuf; + for (i = 1, ++rpo; rpo < rpoend; ++rpo, ++i) { + rpo[-1]->lnext = rpo[0]; + rpo[0]->lprev = rpo[-1]; + rpo[0]->id = i; + } + fn->entry->lprev = rpo[-1]; + rpo[-1]->lnext = fn->entry; + for (rpo = rpobuf; ndead > 0; --ndead) { + (*rpo)->lnext = (*rpo)->lprev = NULL; + freeblk(fn, *rpo); + } +} + +/* vim:set ts=3 sw=3 expandtab: */ @@ -288,7 +288,7 @@ newinstr(void) assert(ninstr < arraylength(instrtab)); t = ninstr++; } - if (instrnuse[t] > arraylength(*instrusebuf)) + if (instruse[t] != instrusebuf[t]) xbfree(instruse[t]); instruse[t] = instrusebuf[t]; instrnuse[t] = 0; @@ -298,8 +298,9 @@ newinstr(void) void adduse(struct block *ublk, int ui, union ref r) { struct use user = { ublk, ui }; + if (r.t != RTMP) return; - if (instrnuse[r.i] < arraylength(*instrusebuf)) { + if (instrnuse[r.i] < arraylength(instrusebuf[r.i])) { instruse[r.i][instrnuse[r.i]++] = user; } else if (instrnuse[r.i] == arraylength(*instrusebuf)) { struct use *use = NULL; @@ -416,8 +417,10 @@ replcuses(union ref from, union ref to) void deluses(int ins) { - if (instrnuse[ins] > 2) + if (instruse[ins] != instrusebuf[ins]) { xbfree(instruse[ins]); + instruse[ins] = instrusebuf[ins]; + } instrnuse[ins] = 0; } @@ -43,17 +43,15 @@ deltrivialphis(struct ssabuilder *sb, struct block *blk, union ref phiref) assert(instrtab[phiref.i].op == Ophi); - if (phiref.i == 4) - efmt(""); - for (int i = 0; i < blk->npred; ++i) { - if (args[i].bits == same.bits || args[i].bits == phiref.bits) + if (args[i].bits == same.bits || args[i].bits == phiref.bits) { continue; /* unique value or self-reference */ - if (same.bits != 0) { + } if (same.bits != 0) { return phiref; /* non-trivial */ } same = args[i]; } + if (same.bits == 0) same = UNDREF; /* the phi is unreachable or in the start block */ @@ -78,6 +76,7 @@ Redo: union ref vphi2 = deltrivialphis(sb, use->blk, it); if (vphi2.bits != it.bits) { /* deletion happened so phiref use may have changed */ + if (same.bits == it.bits) same.bits = vphi2.bits; goto Redo; } } @@ -106,6 +105,7 @@ writevar(struct ssabuilder *sb, int var, struct block *blk, union ref val) if (!(pcurdefs = imap_get(&sb->curdefs, var))) { pcurdefs = imap_set(&sb->curdefs, var, xcalloc(sb->nblk * sizeof(union ref))); } + if (val.t == RTMP) assert(instrtab[val.i].op != Onop); (*pcurdefs)[blk->id] = val; } @@ -144,6 +144,7 @@ trysealrec(struct ssabuilder *sb, struct block *blk) { vec_of(struct pendingphi) *pending; +Recur: if (bstest(sb->sealed, blk->id)) return 1; if (blk->id > sb->lastvisit) return 0; markvisited(blk); @@ -160,8 +161,14 @@ trysealrec(struct ssabuilder *sb, struct block *blk) mkref(RTMP, pending->p[i].phi)); } vfree(pending); - if (blk->s1) trysealrec(sb, blk->s1); - if (blk->s2) trysealrec(sb, blk->s2); + if (blk->s1 && !blk->s2) { + blk = blk->s1; + goto Recur; + } else if (blk->s1 && blk->s2) { + trysealrec(sb, blk->s1); + blk = blk->s2; + goto Recur; + } return 1; } @@ -33,6 +33,7 @@ readvar(struct bitset *defined, enum irclass cls, int var, struct block *blk) union ref val; if (bstest(defined, var)) return mkref(RTMP, var); + assert(cls && "?"); /* memoed definition */ if (xbcap(curdefs) > blk->id && xbcap(curdefs[blk->id]) > var && curdefs[blk->id][var]) |