diff options
author | Quentin Carbonneaux <quentin.carbonneaux@yale.edu> | 2016-04-12 18:29:10 -0400 |
---|---|---|
committer | Quentin Carbonneaux <quentin.carbonneaux@yale.edu> | 2016-04-13 09:53:50 -0400 |
commit | 32d9e33191a08e9162cebfac6e19cbd56eb1b3b6 (patch) | |
tree | a9fa469fdf84f42097c2bbbc07d20862add264a4 /mem.c | |
parent | 02b70c0cb1203a9a3cc9a0bda0f013188a2a4942 (diff) | |
download | roux-32d9e33191a08e9162cebfac6e19cbd56eb1b3b6.tar.gz |
harden memopt()
Diffstat (limited to 'mem.c')
-rw-r--r-- | mem.c | 84 |
1 files changed, 55 insertions, 29 deletions
diff --git a/mem.c b/mem.c index 521fa96..b94f0a7 100644 --- a/mem.c +++ b/mem.c @@ -1,12 +1,29 @@ #include "all.h" -/* Memory optimization: - * - * - replace alloced slots used only in - * load/store operations - * Assumption: all the accesses have the - * same size (this could be wrong...) - */ +static int +loadsz(Ins *l) +{ + switch (l->op) { + case OLoadsb: case OLoadub: return 1; + case OLoadsh: case OLoaduh: return 2; + case OLoadsw: case OLoaduw: return 4; + case OLoad: return KWIDE(l->cls) ? 8 : 4; + } + die("unreachable"); +} + +static int +storesz(Ins *s) +{ + switch (s->op) { + case OStoreb: return 1; + case OStoreh: return 2; + case OStorew: case OStores: return 4; + case OStorel: case OStored: return 8; + } + die("unreachable"); +} + /* require use, maintains use counts */ void @@ -16,8 +33,9 @@ memopt(Fn *fn) Ins *i, *l; Tmp *t; Use *u, *ue; - int a; + int s, k; + /* promote uniform stack slots to temporaries */ b = fn->start; for (i=b->ins; i-b->ins < b->nins; i++) { if (OAlloc > i->op || i->op > OAlloc1) @@ -25,13 +43,26 @@ memopt(Fn *fn) /* specific to NAlign == 3 */ assert(rtype(i->to) == RTmp); t = &fn->tmp[i->to.val]; + k = -1; + s = -1; for (u=t->use; u != &t->use[t->nuse]; u++) { if (u->type != UIns) - goto NextIns; + goto Skip; l = u->u.ins; - if (!isload(l->op) - && (!isstore(l->op) || req(i->to, l->arg[0]))) - goto NextIns; + if (isload(l->op)) + if (s == -1 || s == loadsz(l)) { + s = loadsz(l); + continue; + } + if (isstore(l->op)) + if (req(i->to, l->arg[1]) && !req(i->to, l->arg[0])) + if (s == -1 || s == storesz(l)) + if (k == -1 || k == opdesc[l->op].argcls[0][0]) { + s = storesz(l); + k = opdesc[l->op].argcls[0][0]; + continue; + } + goto Skip; } /* get rid of the alloc and replace uses */ *i = (Ins){.op = ONop}; @@ -40,39 +71,34 @@ memopt(Fn *fn) for (u=t->use; u!=ue; u++) { l = u->u.ins; if (isstore(l->op)) { - if (l->op == OStores) - l->cls = Kd; - else if (l->op == OStored) - l->cls = Kd; - else if (l->op == OStorel) - l->cls = Kl; - else - l->cls = Kw; + l->cls = k; l->op = OCopy; l->to = l->arg[1]; l->arg[1] = R; t->nuse--; t->ndef++; - } else + } else { + if (k == -1) + err("slot %%%s is read but never stored to", + fn->tmp[l->arg[0].val].name); /* try to turn loads into copies so we * can eliminate them later */ switch(l->op) { case OLoad: - l->op = OCopy; - break; case OLoadsw: case OLoaduw: - l->cls = Kw; - l->op = OCopy; + if (KBASE(k) != KBASE(l->cls)) + l->op = OCast; + else + l->op = OCopy; break; default: - /* keep l->cls */ - a = l->op - OLoadsb; - l->op = OExtsb + a; + l->op = OExtsb + (l->op - OLoadsb); break; } + } } - NextIns:; + Skip:; } if (debug['M']) { fprintf(stderr, "\n> After memory optimization:\n"); |