diff options
Diffstat (limited to 'lisc/mem.c')
-rw-r--r-- | lisc/mem.c | 71 |
1 files changed, 71 insertions, 0 deletions
diff --git a/lisc/mem.c b/lisc/mem.c new file mode 100644 index 0000000..bfc8218 --- /dev/null +++ b/lisc/mem.c @@ -0,0 +1,71 @@ +#include "lisc.h" + +/* Memory optimization: + * + * - replace alloced slots used only in + * load/store operations + */ + +/* require use, maintains use counts */ +void +memopt(Fn *fn) +{ + Blk *b; + Ins *i, *l; + Tmp *t; + Use *u, *ue; + int a; + + b = fn->start; + for (i=b->ins; i-b->ins < b->nins; i++) { + if (OAlloc > i->op || i->op > OAlloc1) + continue; + assert(NAlign == 3); + assert(rtype(i->to) == RTmp); + t = &fn->tmp[i->to.val]; + for (u=t->use; u != &t->use[t->nuse]; u++) { + if (u->type != UIns) + goto NextIns; + l = u->u.ins; + if (l->op < OStorel || l->op > OStoreb) + if (l->op < OLoad || l->op > OLoad1) + goto NextIns; + } + /* get rid of the alloc and replace uses */ + *i = (Ins){.op = ONop}; + t->ndef--; + ue = &t->use[t->nuse]; + for (u=t->use; u != ue; u++) { + l = u->u.ins; + if (OStorel <= l->op && l->op <= OStoreb) { + l->wide = (l->op == OStorel); + l->op = OCopy; + l->to = l->arg[1]; + l->arg[1] = R; + t->nuse--; + t->ndef++; + } else + switch(l->op) { + case OLoad+Tl: + l->wide = 1; + l->op = OCopy; + break; + case OLoad+Tsw: + case OLoad+Tuw: + l->wide = 0; + l->op = OCopy; + break; + default: + /* keep l->wide */ + a = l->op - OLoad; + l->op = OExt + a; + break; + } + } + NextIns:; + } + if (debug['M']) { + fprintf(stderr, "\n> After memory optimization:\n"); + printfn(fn, stderr); + } +} |