diff options
| author | 2023-07-09 11:02:23 +0200 | |
|---|---|---|
| committer | 2023-07-09 11:02:23 +0200 | |
| commit | cc5bee5519e26b075d0d0dc28527a05fd9b8c987 (patch) | |
| tree | 1e0810265b54b22fd33ce598b1d869f3a394033f /regalloc.c | |
| parent | 5c0732174f4071f1214da6d7eae3df1ca6e34d06 (diff) | |
regalloc fixes and rpo
Diffstat (limited to 'regalloc.c')
| -rw-r--r-- | regalloc.c | 65 |
1 files changed, 55 insertions, 10 deletions
@@ -266,7 +266,7 @@ forcetake(struct rega *ra, int reg, union ref ref, struct block *blk, int curi) static void use(struct rega *ra, struct block *blk, int curi, enum op op, int hint, union ref *ref, union ref other) { - struct instr *ins; + struct instr *iuse, *ins; uvlong excl = other.t == RREG ? 1ull<<other.i : 0; struct alloc *alloc; int reg; @@ -294,6 +294,7 @@ use(struct rega *ra, struct block *blk, int curi, enum op op, int hint, union re } if (ref->t != RTMP) return; + iuse = &instrtab[blk->ins.p[curi]]; ins = &instrtab[ref->i]; if (!ins->cls) return; if (!(alloc = imap_get(&ra->m.allocs, ref->i)) || alloc->t != AREG) { @@ -301,9 +302,14 @@ use(struct rega *ra, struct block *blk, int curi, enum op op, int hint, union re if (alloc && alloc->t == ASTACK) { /* ensure spill isn't overwritten by dest * e.g. in R0 = add %s, 7 => can't spill %s to R0 */ - struct instr *use = &instrtab[blk->ins.p[curi]]; s = alloc->a; - if (use->reg) excl = rsset(excl, use->reg-1); + if (iuse->reg) excl = rsset(excl, iuse->reg-1); + } else if (iuse->inplace && iuse->reg && ref == &iuse->r + && iuse->l.bits != mkref(RREG, iuse->reg-1).bits) { + /* ensure in an inplace operation rhs reg cannot overlap dest reg + * e.g. in R0 = sub R1, %x => cannot allocate %x to R0 + * FIXME in commutative ops this is fine if we swap the operands */ + excl = rsset(excl, iuse->reg-1); } assert(ins->op != Ocall); @@ -401,7 +407,7 @@ pmadd(enum irclass k, struct alloc dst, struct alloc src) static void emitmove(enum irclass k, struct alloc dst, struct alloc src, struct block *blk, int curi) { - struct instr mv; + struct instr mv = {0}; if (dst.t == AREG && src.t == AREG) { insertinstr(blk, curi, mkmove(k, dst.a, src.a)); } else if (dst.t == ASTACK && src.t == AREG) { @@ -573,6 +579,46 @@ resolve(struct function *fn, struct bbrm *bbrm, struct block *blk, struct block dumpallocs("out", out); } +static void +rporec(struct block ***rpo, struct block *b) +{ + if (wasvisited(b)) return; + markvisited(b); + if (b->s2) rporec(rpo, b->s2); + if (b->s1) rporec(rpo, b->s1); + *--*rpo = b; +} + +static 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) rporec(&rpo, fn->entry->s1); + if (fn->entry->s2) rporec(&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); + } +} + static void fixlive(struct function *fn); void @@ -602,6 +648,9 @@ regalloc(struct function *fn) fn->isleaf = 1; vinit(&stkslotrefs, stkslotrefsbuf, arraylength(stkslotrefsbuf)); + /* put into reverse post order */ + sortrpo(fn); + /* fix liveness ranges */ fixlive(fn); @@ -743,10 +792,7 @@ regalloc(struct function *fn) p->jmp.t = Jret; p->s1 = NULL; DelBlk: - vfree(&blk->phi); - vfree(&blk->ins); - blk->lnext->lprev = blk->lprev; - blk->lprev->lnext = blk->lnext; + freeblk(fn, blk); --id; } else if (blk->s1) { /* simplify: @@ -772,7 +818,6 @@ regalloc(struct function *fn) } } } while ((blk = blk->lnext) != fn->entry); - fn->nblk = id; fn->stksiz += ra.maxstk*8; if (fn->stksiz > 1<<24) error(NULL, "'%s' stack frame too big", fn->name); @@ -893,7 +938,7 @@ fixlive(struct function *fn) if (xbcap(pendingphis) <= blk->id) break; pphi = (void *)&pendingphis[blk->id]; - if (pphi->n) --npendingphi; + npendingphi -= pphi->n; for (int i = 0; i < pphi->n; ++i) { fillphi(defined, mkref(RTMP, pphi->p[i].phi), instrtab[pphi->p[i].phi].cls, pphi->p[i].var, blk); } |