diff options
author | Quentin Carbonneaux <quentin.carbonneaux@yale.edu> | 2015-08-24 12:39:55 -0400 |
---|---|---|
committer | Quentin Carbonneaux <quentin.carbonneaux@yale.edu> | 2015-09-15 23:01:32 -0400 |
commit | 28110b14395e0964d8e70cd2fa57b0d9d8fdaa43 (patch) | |
tree | b2eb86cfb97b7873146096bb35cab3c2cee45893 /lisc | |
parent | 0ad9bf1c602f071a4ae74945d6c751457f9e6f75 (diff) | |
download | roux-28110b14395e0964d8e70cd2fa57b0d9d8fdaa43.tar.gz |
add a size to all operations (wip)
Diffstat (limited to 'lisc')
-rw-r--r-- | lisc/Makefile | 2 | ||||
-rw-r--r-- | lisc/isel.c | 117 | ||||
-rw-r--r-- | lisc/lisc.h | 37 | ||||
-rw-r--r-- | lisc/main.c | 2 | ||||
-rw-r--r-- | lisc/parse.c | 44 | ||||
-rw-r--r-- | lisc/rega.c | 47 | ||||
-rw-r--r-- | lisc/spill.c | 41 | ||||
-rw-r--r-- | lisc/ssa.c | 26 |
8 files changed, 126 insertions, 190 deletions
diff --git a/lisc/Makefile b/lisc/Makefile index 799ec93..8e9d86b 100644 --- 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 index dd70a57..cceb128 100644 --- 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 index 29e0b4c..a5312aa 100644 --- 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 index f4ed6ea..b15332b 100644 --- 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 index 9f8e7a6..94d07ab 100644 --- 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 index 5d2b9f5..6f70851 100644 --- 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 index 30077b9..2625ceb 100644 --- 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 index cd9e1a7..9002443 100644 --- 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]); |