diff options
| author | 2025-12-20 17:59:40 +0100 | |
|---|---|---|
| committer | 2025-12-20 19:31:50 +0100 | |
| commit | e6fbab42185f4fb4e3a3b1e3e93eaa5d3d81b7c7 (patch) | |
| tree | dba8dd1a91f532dd104dc1299b32e79babacb499 /ir | |
| parent | a5009ae762541c29e9a123bf70877261db4ff628 (diff) | |
backend: unify pass memory allocation strategies
It was all over the place for temporary data structures used by
individual passes. Now there is an arena specifically for that, which is
nicer.
Diffstat (limited to 'ir')
| -rw-r--r-- | ir/abi0.c | 5 | ||||
| -rw-r--r-- | ir/intrin.c | 2 | ||||
| -rw-r--r-- | ir/ir.c | 9 | ||||
| -rw-r--r-- | ir/ir.h | 2 | ||||
| -rw-r--r-- | ir/mem2reg.c | 29 | ||||
| -rw-r--r-- | ir/regalloc.c | 2 | ||||
| -rw-r--r-- | ir/simpl.c | 3 |
7 files changed, 21 insertions, 31 deletions
@@ -246,13 +246,11 @@ patcharg(struct block *blk, int *icall, struct call *call, return 1; } } - -static struct abiarg abiargsbuf[32]; - void abi0_call(struct function *fn, struct instr *ins, struct block *blk, int *curi) { union ref retmem; + struct abiarg abiargsbuf[32]; struct abiargsvec abiargs = {VINIT(abiargsbuf, countof(abiargsbuf))}; bool sretarghidden = 0; int ni, nf, ns, vararg, nret = 0; @@ -361,6 +359,7 @@ abi0_call(struct function *fn, struct instr *ins, struct block *blk, int *curi) void abi0(struct function *fn) { + struct abiarg abiargsbuf[32]; uint nparam = typedata[fn->fnty.dat].nmemb; const union type *paramty = typedata[fn->fnty.dat].param; struct abiargsvec abiargs = {VINIT(abiargsbuf, countof(abiargsbuf))}; diff --git a/ir/intrin.c b/ir/intrin.c index 53e29fc..d31f9bb 100644 --- a/ir/intrin.c +++ b/ir/intrin.c @@ -49,7 +49,7 @@ void lowerintrin(struct function *fn) { struct block *blk = fn->entry; - static struct arg argsbuf[64]; + struct arg argsbuf[32]; vec_of(struct arg) args = VINIT(argsbuf, countof(argsbuf)); do { @@ -45,6 +45,8 @@ irinit(struct function *fn) static union ref *phisbuf[64]; static struct irdat datsbuf[64]; + assert(fn->arena && !fn->passarena); + ninstr = 0; instrfreelist = -1; vinit(&calltab, callsbuf, countof(callsbuf)); @@ -629,6 +631,9 @@ void irfini(struct function *fn) { extern int nerror; + static union { char m[sizeof(struct arena) + (4<<10)]; struct arena *_align; } amem; + struct arena *passarena = (void *)&amem.m; + fn->passarena = &passarena; if (nerror) { freefn(fn); return; @@ -638,10 +643,12 @@ irfini(struct function *fn) lowerintrin(fn); if (ccopt.o > OPT0) { mem2reg(fn); + freearena(fn->passarena); copyopt(fn); } if (ccopt.o >= OPT1) { simpl(fn); + freearena(fn->passarena); } if (ccopt.dbg.o) { bfmt(ccopt.dbgout, "<< Before isel >>\n"); @@ -649,9 +656,11 @@ irfini(struct function *fn) } mctarg->isel(fn); regalloc(fn); + freearena(fn->passarena); if (!ccopt.dbg.any) mctarg->emit(fn); + freearena(fn->passarena); freefn(fn); } @@ -162,7 +162,7 @@ enum { FNDOM = 1<<3, }; struct function { - struct arena **arena; + struct arena **arena, **passarena; internstr name; struct block *entry, *curblk; struct use *use; diff --git a/ir/mem2reg.c b/ir/mem2reg.c index f9ad245..a1a4132 100644 --- a/ir/mem2reg.c +++ b/ir/mem2reg.c @@ -23,6 +23,7 @@ static const uchar load2ext[] = { /* Implements algorithm in 'Simple and Efficient Construction of Static Single Assignment' (Braun et al) */ struct ssabuilder { + struct arena **arena; imap_of(union ref *) curdefs; /* map of var to (map of block to def of var) */ struct bitset *sealed, /* set of sealed blocks */ *marked; /* blocks marked, for 'Marker Algorithm' in the paper */ @@ -98,7 +99,7 @@ writevar(struct ssabuilder *sb, int var, struct block *blk, union ref val) { union ref **pcurdefs; if (!(pcurdefs = imap_get(&sb->curdefs, var))) { - pcurdefs = imap_set(&sb->curdefs, var, xcalloc(sb->nblk * sizeof(union ref))); + pcurdefs = imap_set(&sb->curdefs, var, allocz(sb->arena, sb->nblk * sizeof(union ref), 0)); } if (val.t == RTMP) assert(instrtab[val.i].op != Onop); (*pcurdefs)[blk->id] = val; @@ -222,25 +223,15 @@ cmpuse(const void *a, const void *b) void mem2reg(struct function *fn) { - static struct bitset bsbuf[2][4]; - struct ssabuilder sb = { .nblk = fn->nblk }; - struct block *blk; + struct ssabuilder sb = { fn->passarena, .nblk = fn->nblk }; FREQUIRE(FNUSE); - if (fn->nblk <= BSNBIT * countof(bsbuf[0])) { - sb.sealed = bsbuf[0]; - sb.marked = bsbuf[1]; - memset(bsbuf[0], 0, BSSIZE(fn->nblk) * sizeof *bsbuf[0]); - memset(bsbuf[1], 0, BSSIZE(fn->nblk) * sizeof *bsbuf[1]); - } else { - sb.sealed = xcalloc(BSSIZE(fn->nblk) * sizeof *sb.sealed); - sb.marked = xcalloc(BSSIZE(fn->nblk) * sizeof *sb.marked); - } - + sb.sealed = allocz(sb.arena, BSSIZE(fn->nblk) * sizeof *sb.sealed, 0); + sb.marked = allocz(sb.arena, BSSIZE(fn->nblk) * sizeof *sb.sealed, 0); sortrpo(fn); - blk = fn->entry; + struct block *blk = fn->entry; do { for (int i = 0; i < blk->ins.n; ++i) { struct use *use, *uend; @@ -326,14 +317,6 @@ mem2reg(struct function *fn) delphi(blk, i--); } while ((blk = blk->lnext) != fn->entry); - if (sb.sealed != bsbuf[0]) { - free(sb.sealed); - free(sb.marked); - } - - for (int i = 0; i < sb.curdefs.mb.N; ++i) - if (bstest(sb.curdefs.mb.bs, i)) - free(sb.curdefs.v[i]); imap_free(&sb.curdefs); if (ccopt.dbg.m) { bfmt(ccopt.dbgout, "<< After mem2reg >>\n"); diff --git a/ir/regalloc.c b/ir/regalloc.c index 9c1f232..e8eccfb 100644 --- a/ir/regalloc.c +++ b/ir/regalloc.c @@ -1274,7 +1274,7 @@ void regalloc(struct function *fn) { static union ref *stkslotrefsbuf[64]; - struct rega ra = {fn, .arena = fn->arena}; + struct rega ra = {fn, .arena = fn->passarena}; struct block *blk, *last; /* setup */ @@ -70,7 +70,7 @@ simpl(struct function *fn) FREQUIRE(FNUSE); int inschange = 0, blkchange = 0; - struct block **jmpfinal = xcalloc(fn->nblk * sizeof *jmpfinal); + struct block **jmpfinal = allocz(fn->passarena, fn->nblk * sizeof *jmpfinal, 0); struct block *blk = fn->entry; do { @@ -140,7 +140,6 @@ simpl(struct function *fn) } while ((blk = blk->lnext) != fn->entry); fillpreds(fn); } - free(jmpfinal); } /* vim:set ts=3 sw=3 expandtab: */ |