diff options
| -rw-r--r-- | ir.c | 47 | ||||
| -rw-r--r-- | ir.h | 3 | ||||
| -rw-r--r-- | optmem.c | 23 |
3 files changed, 55 insertions, 18 deletions
@@ -250,7 +250,7 @@ newinstr(void) assert(ninstr < arraylength(instrtab)); t = ninstr++; } - if (instrnuse[t] > 2) + if (instrnuse[t] > arraylength(*instrusebuf)) xbfree(instruse[t]); instruse[t] = instrusebuf[t]; instrnuse[t] = 0; @@ -261,12 +261,12 @@ void adduse(struct block *ublk, int ui, union ref r) { struct use user = { ublk, ui }; if (r.t != RTMP) return; - if (instrnuse[r.i] < 2) { + if (instrnuse[r.i] < arraylength(*instrusebuf)) { instruse[r.i][instrnuse[r.i]++] = user; } else if (instrnuse[r.i] == arraylength(*instrusebuf)) { struct use *use = NULL; xbgrow(&use, arraylength(*instrusebuf) + 2); - memcpy(use, instruse[r.i], arraylength(*instrusebuf) * sizeof *use); + memcpy(use, instruse[r.i], sizeof(*instrusebuf)); use[instrnuse[r.i]++] = user; instruse[r.i] = use; } else { @@ -274,6 +274,30 @@ adduse(struct block *ublk, int ui, union ref r) { } } +bool +deluse(struct block *ublk, int ui, union ref r) { + if (r.t != RTMP) return 0; + + for (int i = 0; i < instrnuse[r.i]; ++i) { + if (instruse[r.i][i].blk == ublk && instruse[r.i][i].u == ui) { + for (int k = i; k < instrnuse[r.i] - 1; ++k) { + instruse[r.i][k] = instruse[r.i][k+1]; + } + goto Shrink; + } + } + return 0; + +Shrink: + if (instrnuse[r.i] == arraylength(*instrusebuf) + 1) { + struct use *use = instruse[r.i]; + instruse[r.i] = instrusebuf[r.i]; + memcpy(instruse[r.i], use, sizeof *instrusebuf); + } + --instrnuse[r.i]; + return 1; +} + union ref insertinstr(struct block *blk, int idx, struct instr ins) { @@ -310,7 +334,7 @@ insertphi(struct block *blk, enum irclass cls) /* require use */ void -replcins(union ref from, union ref to) +replcuses(union ref from, union ref to) { struct use *use, *uend; @@ -333,7 +357,9 @@ replcins(union ref from, union ref to) for (i = 0; i < n; ++i) { if (u[i].bits == from.bits) { + deluse(use->blk, use->u, u[i]); u[i].bits = to.bits; + adduse(use->blk, use->u, u[i]); break; } } @@ -361,6 +387,19 @@ delinstr(struct block *blk, int idx) --blk->ins.n; } +void +delphi(struct block *blk, int idx) +{ + int t = blk->phi.p[idx]; + assert(idx >= 0 && idx < blk->phi.n); + memcpy(&instrtab[t], &instrfreelist, sizeof(int)); + instrfreelist = t; + deluses(t); + for (int i = idx; i < blk->phi.n; ++i) + blk->phi.p[i] = blk->phi.p[i + 1]; + --blk->phi.n; +} + /** IR builders **/ struct block * @@ -228,9 +228,10 @@ union ref mkaddr(struct addr); void adduse(struct block *ublk, int ui, union ref r); union ref insertinstr(struct block *, int idx, struct instr); union ref insertphi(struct block *, enum irclass cls); -void replcins(union ref from, union ref to); +void replcuses(union ref from, union ref to); void deluses(int ins); void delinstr(struct block *, int idx); +void delphi(struct block *, int idx); #define blkpred(blk, i) 0[(blk)->npred < 2 ? &(blk)->_pred0 : &(blk)->_pred[i]] /* IR builder functions */ @@ -49,25 +49,22 @@ deltrivialphis(struct block *blk, union ref phiref) same = UNDREF; /* the phi is unreachable or in the start block */ /* replace uses */ - replcins(phiref, same); + replcuses(phiref, same); - /* remove phi */ - for (int i = 0; i < blk->phi.n; ++i) { - if (blk->phi.p[i] == phiref.i) { - for (int k = i; k < blk->phi.n - 1; ++k) - blk->phi.p[k] = blk->phi.p[k + 1]; - --blk->phi.n; - break; - } - } instrtab[phiref.i].op = Onop; /* recursively try to remove all phi users as they might have become trivial */ for (use = instruse[phiref.i], uend = use + instrnuse[phiref.i]; use < uend; ++use) - if (use->u != USERJUMP && instrtab[use->u].op == Ophi && use->u != phiref.i) + if (use->u != USERJUMP && instrtab[use->u].op == Ophi) deltrivialphis(use->blk, mkref(RTMP, use->u)); - deluses(phiref.i); + /* remove phi */ + for (int i = 0; i < blk->phi.n; ++i) { + if (blk->phi.p[i] == phiref.i) { + delphi(blk, i); + break; + } + } return same; } @@ -187,7 +184,7 @@ mem2reg(struct function *fn) } } /* remove alloca */ - delinstr(blk, i); + delinstr(blk, i--); Next:; } |