aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorlemon <lsof@mailbox.org>2025-12-20 17:59:40 +0100
committerlemon <lsof@mailbox.org>2025-12-20 19:31:50 +0100
commite6fbab42185f4fb4e3a3b1e3e93eaa5d3d81b7c7 (patch)
treedba8dd1a91f532dd104dc1299b32e79babacb499
parenta5009ae762541c29e9a123bf70877261db4ff628 (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.
-rw-r--r--c/c.c2
-rw-r--r--ir/abi0.c5
-rw-r--r--ir/intrin.c2
-rw-r--r--ir/ir.c9
-rw-r--r--ir/ir.h2
-rw-r--r--ir/mem2reg.c29
-rw-r--r--ir/regalloc.c2
-rw-r--r--ir/simpl.c3
-rw-r--r--x86_64/emit.c6
-rw-r--r--x86_64/isel.c3
10 files changed, 24 insertions, 39 deletions
diff --git a/c/c.c b/c/c.c
index 0e3b612..249c009 100644
--- a/c/c.c
+++ b/c/c.c
@@ -4423,7 +4423,7 @@ tldecl(struct comp *cm)
}
decl.isdef = 1;
struct decl *d = putdecl(cm, &decl);
- struct function fn = { &cm->fnarena, decl.name, .globl = d->scls != SCSTATIC, .fnty = decl.ty, .retty = td->ret };
+ struct function fn = { &cm->fnarena, .name = decl.name, .globl = d->scls != SCSTATIC, .fnty = decl.ty, .retty = td->ret };
irinit(&fn);
function(cm, &fn, st.pnames, st.pspans, st.pqual);
if (!nerror && ccopt.dbg.p)
diff --git a/ir/abi0.c b/ir/abi0.c
index 1547722..bd8e297 100644
--- a/ir/abi0.c
+++ b/ir/abi0.c
@@ -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 {
diff --git a/ir/ir.c b/ir/ir.c
index 5f1797c..35a36b4 100644
--- a/ir/ir.c
+++ b/ir/ir.c
@@ -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);
}
diff --git a/ir/ir.h b/ir/ir.h
index ad22eb9..6e8ae88 100644
--- a/ir/ir.h
+++ b/ir/ir.h
@@ -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 */
diff --git a/ir/simpl.c b/ir/simpl.c
index fb89c07..7e6cfd0 100644
--- a/ir/simpl.c
+++ b/ir/simpl.c
@@ -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: */
diff --git a/x86_64/emit.c b/x86_64/emit.c
index 3fc93b0..2786e22 100644
--- a/x86_64/emit.c
+++ b/x86_64/emit.c
@@ -738,7 +738,6 @@ static struct blkaddr {
uint relreloc;
};
} *blkaddr;
-static uint nblkaddr;
static void
Xjcc(uchar **pcode, enum cc cc, struct block *dst)
@@ -1356,10 +1355,7 @@ emitbin(struct function *fn)
} while ((blk = blk->lprev) != fn->entry);
}
- if (nblkaddr < fn->nblk) {
- blkaddr = xrealloc(blkaddr, (nblkaddr = fn->nblk) * sizeof *blkaddr);
- }
- memset(blkaddr, 0, nblkaddr * sizeof *blkaddr);
+ blkaddr = allocz(fn->passarena, fn->nblk * sizeof *blkaddr, 0);
blk = fn->entry;
do {
diff --git a/x86_64/isel.c b/x86_64/isel.c
index 2b087cd..bc49d03 100644
--- a/x86_64/isel.c
+++ b/x86_64/isel.c
@@ -627,7 +627,7 @@ x86_64_isel(struct function *fn)
struct block *blk = fn->entry;
fn->stksiz = 0;
- stkslots = xcalloc((nstkslots = ninstr) * sizeof *stkslots);
+ stkslots = allocz(fn->passarena, (nstkslots = ninstr) * sizeof *stkslots, 0);
do {
int i;
for (i = 0; i < blk->phi.n; ++i) {
@@ -649,7 +649,6 @@ x86_64_isel(struct function *fn)
}
seljmp(fn, blk);
} while ((blk = blk->lnext) != fn->entry);
- free(stkslots);
if (ccopt.dbg.i) {
bfmt(ccopt.dbgout, "<< After isel >>\n");