commit 28110b14395e0964d8e70cd2fa57b0d9d8fdaa43
parent 0ad9bf1c602f071a4ae74945d6c751457f9e6f75
Author: Quentin Carbonneaux <quentin.carbonneaux@yale.edu>
Date: Mon, 24 Aug 2015 12:39:55 -0400
add a size to all operations (wip)
Diffstat:
8 files changed, 126 insertions(+), 190 deletions(-)
diff --git a/lisc/Makefile b/lisc/Makefile
@@ -1,5 +1,5 @@
BIN = lisc
-OBJ = parse.o ssa.o live.o isel.o spill.o rega.o emit.o main.o
+OBJ = parse.o ssa.o live.o isel.o main.o spill.o # rega.o emit.o main.o
CFLAGS = -Wall -Wextra -std=c99 -g -pedantic
diff --git a/lisc/isel.c b/lisc/isel.c
@@ -20,15 +20,15 @@
extern Ins insb[NIns], *curi; /* shared work buffer */
static void
-emit(short op, Ref to, Ref arg0, Ref arg1)
+emit(int op, int w, Ref to, Ref arg0, Ref arg1)
{
if (curi == insb)
diag("isel: too many instructions");
- *--curi = (Ins){op, to, {arg0, arg1}};
+ *--curi = (Ins){op, w, to, {arg0, arg1}};
}
static Ref
-newtmp(int type, Fn *fn)
+newtmp(Fn *fn)
{
static int n;
int t;
@@ -37,7 +37,7 @@ newtmp(int type, Fn *fn)
fn->tmp = realloc(fn->tmp, fn->ntmp * sizeof fn->tmp[0]);
if (!fn->tmp)
diag("isel: out of memory");
- fn->tmp[t] = (Tmp){.type = type};
+ memset(&fn->tmp[t], 0, sizeof fn->tmp[t]);
sprintf(fn->tmp[t].name, "isel%d", ++n);
return TMP(t);
}
@@ -80,17 +80,10 @@ noimm(Ref r, Fn *fn)
}
}
-static int
-islong(Ref r, Fn *fn)
-{
- return rtype(r) == RTmp && fn->tmp[r.val].type == TLong;
-}
-
static void
-selcmp(Ref arg[2], Fn *fn)
+selcmp(Ref arg[2], int w, Fn *fn)
{
Ref r;
- int lng;
if (rtype(arg[0]) == RCon) {
r = arg[1];
@@ -98,12 +91,11 @@ selcmp(Ref arg[2], Fn *fn)
arg[0] = r;
}
assert(rtype(arg[0]) != RCon);
- lng = islong(arg[0], fn) || islong(arg[1], fn);
- emit(lng ? OXCmpl : OXCmpw, R, arg[1], arg[0]);
+ emit(OXCmp, w, R, arg[1], arg[0]);
r = arg[1];
- if (lng && rtype(r) == RCon && noimm(r, fn)) {
- curi->arg[0] = newtmp(TLong, fn);
- emit(OCopy, curi->arg[0], r, R);
+ if (w && rtype(r) == RCon && noimm(r, fn)) {
+ curi->arg[0] = newtmp(fn);
+ emit(OCopy, w, curi->arg[0], r, R);
}
}
@@ -118,8 +110,8 @@ rslot(Ref r, Fn *fn)
static void
sel(Ins i, Fn *fn)
{
- Ref r0, r1, ra, rd;
- int n, ty, c, s;
+ Ref r0, r1;
+ int n, c, s, w;
int64_t val;
struct {
Ref r;
@@ -131,52 +123,38 @@ sel(Ins i, Fn *fn)
cpy[n].s = 0;
s = rslot(r0, fn);
if (s) {
- r0 = newtmp(TLong, fn);
+ r0 = newtmp(fn);
i.arg[n] = r0;
cpy[n].r = r0;
cpy[n].s = s;
}
}
+ w = i.wide;
switch (i.op) {
case ODiv:
case ORem:
- ty = fn->tmp[i.to.val].type;
- switch (ty) {
- default:
- diag("isel: invalid division");
- case TWord:
- ra = TMP(EAX);
- rd = TMP(EDX);
- break;
- case TLong:
- ra = TMP(RAX);
- rd = TMP(RDX);
- break;
- }
- r0 = i.op == ODiv ? ra : rd;
- r1 = i.op == ODiv ? rd : ra;
- emit(OCopy, i.to, r0, R);
- emit(OCopy, R, r1, R);
+ if (i.op == ODiv)
+ r0 = TMP(RAX), r1 = TMP(RDX);
+ else
+ r0 = TMP(RDX), r1 = TMP(RAX);
+ emit(OCopy, w, i.to, r0, R);
+ emit(OCopy, w, R, r1, R);
if (rtype(i.arg[1]) == RCon) {
/* immediates not allowed for
* divisions in x86
*/
- r0 = newtmp(ty, fn);
+ r0 = newtmp(fn);
} else
r0 = i.arg[1];
- emit(OXDiv, R, r0, R);
- emit(OSign, rd, ra, R);
- emit(OCopy, ra, i.arg[0], R);
+ emit(OXDiv, w, R, r0, R);
+ emit(OSign, w, TMP(RDX), TMP(RAX), R);
+ emit(OCopy, w, TMP(RAX), i.arg[0], R);
if (rtype(i.arg[1]) == RCon)
- emit(OCopy, r0, i.arg[1], R);
+ emit(OCopy, w, r0, i.arg[1], R);
break;
case ONop:
break;
- case OXTestw:
- case OXTestl:
- n = i.op == OXTestl ? 2 : 0;
- goto Emit;
case OSext:
case OZext:
n = 0;
@@ -189,10 +167,8 @@ sel(Ins i, Fn *fn)
case OMul:
case OAnd:
case OCopy:
- if (fn->tmp[i.to.val].type == TLong)
- n = 2;
- else
- n = 0;
+ case OXTest:
+ n = w ? 2 : 0;
goto Emit;
case OStorel:
case OStorew:
@@ -215,7 +191,7 @@ sel(Ins i, Fn *fn)
}
n = 0;
Emit:
- emit(i.op, i.to, i.arg[0], i.arg[1]);
+ emit(i.op, w, i.to, i.arg[0], i.arg[1]);
while (n--) {
/* load constants that do not fit in
* a 32bit signed integer into a
@@ -223,8 +199,8 @@ Emit:
*/
r0 = i.arg[n];
if (rtype(r0) == RCon && noimm(r0, fn)) {
- curi->arg[n] = newtmp(TLong, fn);
- emit(OCopy, curi->arg[n], r0, R);
+ curi->arg[n] = newtmp(fn);
+ emit(OCopy, 1, curi->arg[n], r0, R);
}
}
break;
@@ -243,14 +219,14 @@ Emit:
val = (val + 15) & ~INT64_C(15);
if (val < 0 || val > INT32_MAX)
diag("isel: alloc too large");
- emit(OAlloc, i.to, newcon(val, fn), R);
+ emit(OAlloc, 0, i.to, newcon(val, fn), R);
} else {
/* r0 = (i.arg[0] + 15) & -16 */
- r0 = newtmp(TLong, fn);
- r1 = newtmp(TLong, fn);
- emit(OAlloc, i.to, r0, R);
- emit(OAnd, r0, r1, newcon(-16, fn));
- emit(OAdd, r1, i.arg[0], newcon(15, fn));
+ r0 = newtmp(fn);
+ r1 = newtmp(fn);
+ emit(OAlloc, 0, i.to, r0, R);
+ emit(OAnd, 1, r0, r1, newcon(-16, fn));
+ emit(OAdd, 1, r1, i.arg[0], newcon(15, fn));
}
break;
default:
@@ -258,8 +234,8 @@ Emit:
c = i.op - OCmp;
if (rtype(i.arg[0]) == RCon)
c = COP(c);
- emit(OXSet+c, i.to, R, R);
- selcmp(i.arg, fn);
+ emit(OXSet+c, 0, i.to, R, R);
+ selcmp(i.arg, w, fn);
break;
}
diag("isel: non-exhaustive implementation");
@@ -267,7 +243,7 @@ Emit:
for (n=0; n<2; n++)
if (cpy[n].s)
- emit(OAddr, cpy[n].r, SLOT(cpy[n].s), R);
+ emit(OAddr, 0, cpy[n].r, SLOT(cpy[n].s), R);
}
static Ins *
@@ -327,19 +303,16 @@ seljmp(Blk *b, Fn *fn)
c = COP(c);
b->jmp.type = JXJc + c;
if (fn->tmp[r.val].nuse == 1) {
- assert(fn->tmp[r.val].ndef==1);
- selcmp(fi->arg, fn);
- *fi = (Ins){ONop, R, {R, R}};
+ assert(fn->tmp[r.val].ndef == 1);
+ selcmp(fi->arg, fi->wide, fn);
+ *fi = (Ins){.op = ONop};
}
return;
}
if (fi->op == OAnd && fn->tmp[r.val].nuse == 1
&& (rtype(fi->arg[0]) == RTmp ||
rtype(fi->arg[1]) == RTmp)) {
- if (fn->tmp[r.val].type == TLong)
- fi->op = OXTestl;
- else
- fi->op = OXTestw;
+ fi->op = OXTest;
fi->to = R;
b->jmp.type = JXJc + Cne;
if (rtype(fi->arg[1]) == RCon) {
@@ -354,7 +327,7 @@ seljmp(Blk *b, Fn *fn)
return;
}
}
- selcmp((Ref[2]){r, CON_Z}, fn);
+ selcmp((Ref[2]){r, CON_Z}, 0, fn); /* fixme, add long branch if non-zero */
b->jmp.type = JXJc + Cne;
}
@@ -452,8 +425,8 @@ isel(Fn *fn)
assert(a+1 < p->narg);
s = rslot(p->arg[a], fn);
if (s) {
- p->arg[a] = newtmp(TLong, fn);
- emit(OAddr, p->arg[a], SLOT(s), R);
+ p->arg[a] = newtmp(fn);
+ emit(OAddr, 0, p->arg[a], SLOT(s), R);
}
}
curi = &insb[NIns];
diff --git a/lisc/lisc.h b/lisc/lisc.h
@@ -40,30 +40,11 @@ enum Reg {
RBP, /* reserved */
RSP,
- EAX, /* 32bits */
- ECX,
- EDX,
- ESI,
- EDI,
- R8D,
- R9D,
- R10D,
- R11D,
-
- EBX,
- R12D,
- R13D,
- R14D,
- R15D,
-
Tmp0, /* first non-reg temporary */
NReg = RDX - RAX + 1
};
-#define RWORD(r) (r + (EAX-RAX))
-#define RBASE(r) (r < EAX ? r : r - (EAX-RAX))
-
enum {
NString = 32,
NPred = 15,
@@ -105,6 +86,8 @@ static inline int req(Ref a, Ref b)
{ return a.type == b.type && a.val == b.val; }
static inline int rtype(Ref r)
{ return req(r, R) ? -1 : r.type; }
+static inline int isreg(Ref r)
+{ return rtype(r) == RTmp && r.val < Tmp0; }
enum Cmp {
Ceq,
@@ -153,12 +136,10 @@ enum Op {
OSwap,
OSign,
OXDiv,
- OXCmpw,
- OXCmpl,
+ OXCmp,
OXSet,
OXSet1 = OXSet + NCmp-1,
- OXTestw,
- OXTestl,
+ OXTest,
NOp
};
@@ -179,7 +160,8 @@ struct OpDesc {
};
struct Ins {
- short op;
+ uint16_t op:15;
+ uint16_t wide:1;
Ref to;
Ref arg[2];
};
@@ -189,6 +171,7 @@ struct Phi {
Ref arg[NPred];
Blk *blk[NPred];
uint narg;
+ uint wide;
Phi *link;
};
@@ -215,16 +198,19 @@ struct Blk {
};
struct Tmp {
+#if 0
enum {
TUndef,
TWord,
TLong,
TReg,
} type;
+#endif
char name[NString];
uint ndef, nuse;
uint cost;
- uint spill;
+ short spill;
+ short wide;
int hint;
};
@@ -280,7 +266,6 @@ void fillcost(Fn *);
void spill(Fn *);
/* rega.c */
-int isreg(Ref);
void rega(Fn *);
/* emit.c */
diff --git a/lisc/main.c b/lisc/main.c
@@ -101,6 +101,7 @@ main(int ac, char *av[])
printf("\n");
break;
}
+ #if 0
case 'a': {
fprintf(stderr, "[Testing Register Allocation]\n");
debug['R'] = 1;
@@ -136,6 +137,7 @@ main(int ac, char *av[])
pr = 0;
break;
}
+ #endif
default:
break;
}
diff --git a/lisc/parse.c b/lisc/parse.c
@@ -35,10 +35,8 @@ OpDesc opdesc[NOp] = {
[OSwap] = { "swap", 2, 2 },
[OSign] = { "sign", 1, 0 },
[OXDiv] = { "xdiv", 1, 1 },
- [OXCmpw] = { "xcmpw", 2, 1 },
- [OXCmpl] = { "xcmpl", 2, 1 },
- [OXTestw] = { "xtestw", 2, 1 },
- [OXTestl] = { "xtestl", 2, 1 },
+ [OXCmp] = { "xcmp", 2, 1 },
+ [OXTest] = { "xtest", 2, 1 },
[OAddr] = { "addr", 1, 0 },
[OAlloc] = { "alloc4", 1, 1 },
[OAlloc+1] = { "alloc8", 1, 1 },
@@ -368,7 +366,7 @@ parseline(PState ps)
Phi *phi;
Ref r;
Blk *b;
- int t, op, i;
+ int t, op, i, w;
do
t = next();
@@ -432,10 +430,10 @@ parseline(PState ps)
expect(TEq);
switch (next()) {
case TW:
- tmp[r.val].type = TWord;
+ w = 0;
break;
case TL:
- tmp[r.val].type = TLong;
+ w = 1;
break;
default:
err("class expected after =");
@@ -476,6 +474,7 @@ DoOp:
if (curi - insb >= NIns)
err("too many instructions in block");
curi->op = op;
+ curi->wide = w;
curi->to = r;
curi->arg[0] = arg[0];
curi->arg[1] = arg[1];
@@ -484,6 +483,7 @@ DoOp:
} else {
phi = alloc(sizeof *phi);
phi->to = r;
+ phi->wide = w;
memcpy(phi->arg, arg, i * sizeof arg[0]);
memcpy(phi->blk, blk, i * sizeof blk[0]);
phi->narg = i;
@@ -504,11 +504,8 @@ parsefn(FILE *f)
thead = TXXX;
for (i=0; i<NBlk; i++)
bmap[i] = 0;
- for (i=0; i<NTmp; i++)
- if (i < Tmp0)
- tmp[i] = (Tmp){.type = TReg};
- else
- tmp[i] = (Tmp){.name = ""};
+ for (i=Tmp0; i<NTmp; i++)
+ tmp[i] = (Tmp){.name = ""};
ntmp = Tmp0;
ncon = 1; /* first constant must be 0 */
curi = insb;
@@ -536,23 +533,16 @@ parsefn(FILE *f)
return fn;
}
-static char *
+static void
printref(Ref r, Fn *fn, FILE *f)
{
- static char *ttoa[] = {
- [TUndef] = "?",
- [TWord] = "w",
- [TLong] = "l",
- [TReg] = "",
- };
-
switch (r.type) {
case RTmp:
if (r.val < Tmp0)
fprintf(f, "R%d", r.val);
else
fprintf(f, "%%%s", fn->tmp[r.val].name);
- return ttoa[fn->tmp[r.val].type];
+ break;
case RCon:
switch (fn->con[r.val].type) {
case CAddr:
@@ -571,7 +561,6 @@ printref(Ref r, Fn *fn, FILE *f)
fprintf(f, "S%d", r.val);
break;
}
- return "";
}
void
@@ -590,14 +579,13 @@ printfn(Fn *fn, FILE *f)
Phi *p;
Ins *i;
uint n;
- char *cl;
for (b=fn->start; b; b=b->link) {
fprintf(f, "@%s\n", b->name);
for (p=b->phi; p; p=p->link) {
fprintf(f, "\t");
- cl = printref(p->to, fn, f);
- fprintf(f, " =%s phi ", cl);
+ printref(p->to, fn, f);
+ fprintf(f, " =%s phi ", p->wide ? "l" : "w");
assert(p->narg);
for (n=0;; n++) {
fprintf(f, "@%s ", p->blk[n]->name);
@@ -612,10 +600,12 @@ printfn(Fn *fn, FILE *f)
for (i=b->ins; i-b->ins < b->nins; i++) {
fprintf(f, "\t");
if (!req(i->to, R)) {
- cl = printref(i->to, fn, f);
- fprintf(f, " =%s ", cl);
+ printref(i->to, fn, f);
+ fprintf(f, " =");
}
assert(opdesc[i->op].name);
+ if (OStorel > i->op || i->op > OStoreb)
+ fprintf(f, i->wide ? "l " : "w ");
fprintf(f, "%s", opdesc[i->op].name);
n = opdesc[i->op].arity;
if (n > 0) {
diff --git a/lisc/rega.c b/lisc/rega.c
@@ -4,7 +4,6 @@
#define assert(x) assert_test(#x, x)
#endif
-
typedef struct RMap RMap;
struct RMap {
int t[NReg];
@@ -17,6 +16,7 @@ extern Ins insb[NIns], *curi;
static Tmp *tmp; /* function temporaries */
static struct {
Ref src, dst;
+ int wide;
} *pm; /* parallel move constructed */
static int cpm, npm; /* capacity and size of pm */
@@ -32,20 +32,6 @@ rfind(RMap *m, int t)
}
static Ref
-reg(int r, int t)
-{
- assert(r < Tmp0);
- switch (tmp[t].type) {
- default:
- diag("rega: invalid temporary");
- case TWord:
- return TMP(RWORD(r));
- case TLong:
- return TMP(r);
- }
-}
-
-static Ref
rref(RMap *m, int t)
{
int r, s;
@@ -56,7 +42,7 @@ rref(RMap *m, int t)
assert(s && "should have spilled");
return SLOT(s);
} else
- return reg(r, t);
+ return TMP(r);
}
static void
@@ -80,7 +66,7 @@ ralloc(RMap *m, int t)
int r;
if (t < Tmp0) {
- assert(BGET(m->b, RBASE(t)));
+ assert(BGET(m->b, t));
return TMP(t);
}
if (BGET(m->b, t)) {
@@ -96,7 +82,7 @@ ralloc(RMap *m, int t)
if (tmp[t].hint == -1)
tmp[t].hint = r;
}
- return reg(r, t);
+ return TMP(r);
}
static int
@@ -104,8 +90,6 @@ rfree(RMap *m, int t)
{
int i, r;
- if (t < Tmp0)
- t = RBASE(t);
if (!BGET(m->b, t))
return -1;
for (i=0; m->t[i] != t; i++)
@@ -132,7 +116,7 @@ mdump(RMap *m)
}
static void
-pmadd(Ref src, Ref dst)
+pmadd(Ref src, Ref dst, int w)
{
if (npm == cpm) {
cpm = cpm * 2 + 16;
@@ -142,6 +126,7 @@ pmadd(Ref src, Ref dst)
}
pm[npm].src = src;
pm[npm].dst = dst;
+ pm[npm].wide = w;
npm++;
}
@@ -202,12 +187,6 @@ pmgen()
free(status);
}
-int
-isreg(Ref r)
-{
- return rtype(r) == RTmp && r.val < Tmp0;
-}
-
static Ins *
dopm(Blk *b, Ins *i, RMap *m)
{
@@ -218,7 +197,7 @@ dopm(Blk *b, Ins *i, RMap *m)
m0 = *m;
i1 = i+1;
for (;; i--) {
- r = RBASE(i->arg[0].val);
+ r = i->arg[0].val;
r1 = req(i->to, R) ? -1 : rfree(m, i->to.val);
if (BGET(m->b, r) && r1 != r) {
/* r is used and not by i->to, */
@@ -243,12 +222,12 @@ dopm(Blk *b, Ins *i, RMap *m)
r1 = m->r[n];
r = rfind(&m0, t);
assert(r != -1);
- pmadd(reg(r1, t), reg(r, t));
+ pmadd(TMP(r1), TMP(r));
}
for (ip=i; ip<i1; ip++) {
if (!req(ip->to, R))
rfree(m, ip->to.val);
- r = RBASE(ip->arg[0].val);
+ r = ip->arg[0].val;
if (rfind(m, r) == -1)
radd(m, r, r);
}
@@ -295,9 +274,9 @@ rega(Fn *fn)
if (i->op != OCopy)
continue;
if (rtype(i->arg[0]) == RTmp && isreg(i->to))
- tmp[i->arg[0].val].hint = RBASE(i->to.val);
+ tmp[i->arg[0].val].hint = i->to.val;
if (rtype(i->to) == RTmp && isreg(i->arg[0]))
- tmp[i->to.val].hint = RBASE(i->arg[0].val);
+ tmp[i->to.val].hint = i->arg[0].val;
}
/* 2. assign registers backwards */
@@ -332,7 +311,7 @@ rega(Fn *fn)
continue;
}
if (i->to.val >= Tmp0)
- i->to = reg(r, i->to.val);
+ i->to = TMP(r);
} else
r = 0;
for (x=0; x<2; x++)
@@ -378,7 +357,7 @@ rega(Fn *fn)
r = rfind(&beg[s->id], dst.val);
if (r == -1)
continue;
- dst = reg(r, dst.val);
+ dst = TMP(r);
}
for (a=0; p->blk[a]!=b; a++)
assert(a+1 < p->narg);
diff --git a/lisc/spill.c b/lisc/spill.c
@@ -1,6 +1,5 @@
#include "lisc.h"
-
static void
loopmark(Blk *hd, Blk *b, Phi *p)
{
@@ -170,41 +169,37 @@ slot(int t)
diag("spill: cannot spill register");
s = tmp[t].spill;
if (!s) {
- if (tmp[t].type == TWord)
- s = slota(1, 0, svec);
- else if (tmp[t].type == TLong)
+ if (tmp[t].wide)
s = slota(2, 1, svec);
else
- diag("spill: unknown type (1)");
+ s = slota(1, 0, svec);
tmp[t].spill = s;
}
return SLOT(s);
}
static void
-emit(short op, Ref to, Ref arg0, Ref arg1)
+emit(Ins i)
{
if (curi == insb)
diag("spill: too many instructions");
- *--curi = (Ins){op, to, {arg0, arg1}};
+ *--curi = i;
}
static void
store(Ref r, int s)
{
- if (tmp[r.val].type == TLong)
- emit(OStorel, R, r, SLOT(s));
- else if (tmp[r.val].type == TWord)
- emit(OStorew, R, r, SLOT(s));
+ if (tmp[r.val].wide)
+ emit((Ins){OStorel, 0, R, {r, SLOT(s)}});
else
- diag("spill: unknown type (2)");
+ emit((Ins){OStorew, 0, R, {r, SLOT(s)}});
}
static int
limit(Bits *b, int k, Bits *fst)
{
static int *tarr, maxt;
- int i, t, nt;
+ int i, t, nt, w;
nt = bcnt(b);
if (nt <= k)
@@ -232,8 +227,9 @@ limit(Bits *b, int k, Bits *fst)
for (; i<nt; i++) {
slot(tarr[i]);
if (curi) {
- emit(OLoad, TMP(tarr[i]), slot(tarr[i]), R);
t = tarr[i];
+ w = tmp[t].wide;
+ emit((Ins){OLoad, w, TMP(t), {slot(t)}});
}
}
return t;
@@ -298,10 +294,9 @@ dopm(Blk *b, Ins *i, Bits *v)
break;
}
limit(v, NReg, 0);
- do {
- i1--;
- emit(OCopy, i1->to, i1->arg[0], R);
- } while (i1 != i);
+ do
+ emit(*--i1);
+ while (i1 != i);
return i;
}
@@ -332,6 +327,14 @@ spill(Fn *fn)
ntmp = fn->ntmp;
assert(ntmp < NBit*BITS);
+ for (b=fn->start; b; b=b->link) {
+ for (p=b->phi; p; p=p->link)
+ tmp[p->to.val].wide = p->wide;
+ for (i=b->ins; i-b->ins < b->nins; i++)
+ if (rtype(i->to) == RTmp)
+ tmp[i->to.val].wide = i->wide;
+ }
+
for (n=fn->nblk-1; n>=0; n--) {
/* invariant: m>n => in,out of m updated */
b = fn->rpo[n];
@@ -409,7 +412,7 @@ spill(Fn *fn)
j -= setloc(&i->arg[1], &v, &w);
if (s)
store(i->to, s);
- emit(i->op, i->to, i->arg[0], i->arg[1]);
+ emit(*i);
}
for (p=b->phi; p; p=p->link) {
diff --git a/lisc/ssa.c b/lisc/ssa.c
@@ -90,22 +90,22 @@ fillrpo(Fn *f)
}
static Ref *top, *bot;
-static Ref topdef(Blk *, Fn *);
+static Ref topdef(Blk *, Fn *, int);
static Ref
-botdef(Blk *b, Fn *f)
+botdef(Blk *b, Fn *f, int w)
{
Ref r;
if (!req(bot[b->id], R))
return bot[b->id];
- r = topdef(b, f);
+ r = topdef(b, f, w);
bot[b->id] = r;
return r;
}
static Ref
-topdef(Blk *b, Fn *f)
+topdef(Blk *b, Fn *f, int w)
{
uint i;
int t1;
@@ -116,7 +116,7 @@ topdef(Blk *b, Fn *f)
return top[b->id];
assert(b->npred && "invalid ssa program detected");
if (b->npred == 1) {
- r = botdef(b->pred[0], f);
+ r = botdef(b->pred[0], f, w);
top[b->id] = r;
return r;
}
@@ -128,8 +128,9 @@ topdef(Blk *b, Fn *f)
p->link = b->phi;
b->phi = p;
p->to = r;
+ p->wide = w;
for (i=0; i<b->npred; i++) {
- p->arg[i] = botdef(b->pred[i], f);
+ p->arg[i] = botdef(b->pred[i], f, w);
p->blk[i] = b->pred[i];
}
p->narg = i;
@@ -143,12 +144,13 @@ void
ssafix(Fn *f, int t)
{
uint n;
- int t0, t1;
+ int t0, t1, w;
Ref rt;
Blk *b;
Phi *p;
Ins *i;
+ w = 0;
top = alloc(f->nblk * sizeof top[0]);
bot = alloc(f->nblk * sizeof bot[0]);
rt = TMP(t);
@@ -160,6 +162,7 @@ ssafix(Fn *f, int t)
if (req(p->to, rt)) {
t1 = f->ntmp++;
p->to = TMP(t1);
+ w |= p->wide;
}
for (i=b->ins; i-b->ins < b->nins; i++) {
if (t1) {
@@ -169,6 +172,7 @@ ssafix(Fn *f, int t)
i->arg[1] = TMP(t1);
}
if (req(i->to, rt)) {
+ w |= i->wide;
t1 = f->ntmp++;
i->to = TMP(t1);
}
@@ -182,15 +186,15 @@ ssafix(Fn *f, int t)
for (p=b->phi; p; p=p->link)
for (n=0; n<p->narg; n++)
if (req(p->arg[n], rt))
- p->arg[n] = botdef(p->blk[n], f);
+ p->arg[n] = botdef(p->blk[n], f, w);
for (i=b->ins; i-b->ins < b->nins; i++) {
if (req(i->arg[0], rt))
- i->arg[0] = topdef(b, f);
+ i->arg[0] = topdef(b, f, w);
if (req(i->arg[1], rt))
- i->arg[1] = topdef(b, f);
+ i->arg[1] = topdef(b, f, w);
}
if (req(b->jmp.arg, rt))
- b->jmp.arg = topdef(b, f);
+ b->jmp.arg = topdef(b, f, w);
}
/* add new temporaries */
f->tmp = realloc(f->tmp, f->ntmp * sizeof f->tmp[0]);