implement smarter compare+branch
This commit is contained in:
parent
7dc3e5dcf6
commit
ad012e9d55
3 changed files with 132 additions and 30 deletions
129
lisc/isel.c
129
lisc/isel.c
|
@ -39,12 +39,53 @@ newtmp(int type, Fn *fn)
|
|||
return t;
|
||||
}
|
||||
|
||||
static int
|
||||
cneg(int cmp)
|
||||
{
|
||||
switch (cmp) {
|
||||
default: diag("cneg: unhandled comparison");
|
||||
case Ceq: return Cne;
|
||||
case Csle: return Csgt;
|
||||
case Cslt: return Csge;
|
||||
case Csgt: return Csle;
|
||||
case Csge: return Cslt;
|
||||
case Cne: return Ceq;
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
Ref r;
|
||||
int t;
|
||||
|
||||
t = -1;
|
||||
if (rtype(arg[0]) == RCon) {
|
||||
r = arg[1];
|
||||
arg[1] = arg[0];
|
||||
arg[0] = r;
|
||||
if (rtype(r) == RCon) {
|
||||
/* todo, use the constant
|
||||
* size to dimension the
|
||||
* constant */
|
||||
t = newtmp(TWord, fn);
|
||||
arg[0] = TMP(t);
|
||||
}
|
||||
}
|
||||
if (islong(arg[0], fn) || islong(arg[1], fn))
|
||||
emit(OXCmpl, R, arg[1], arg[0]);
|
||||
else
|
||||
emit(OXCmpw, R, arg[1], arg[0]);
|
||||
if (t != -1)
|
||||
emit(OCopy, TMP(t), r, R);
|
||||
}
|
||||
|
||||
static void
|
||||
sel(Ins i, Fn *fn)
|
||||
{
|
||||
|
@ -92,35 +133,78 @@ sel(Ins i, Fn *fn)
|
|||
break;
|
||||
default:
|
||||
if (OCmp <= i.op && i.op <= OCmp1) {
|
||||
t = -1;
|
||||
r0 = i.arg[0];
|
||||
c = i.op - OCmp;
|
||||
if (rtype(i.arg[0]) == RCon) {
|
||||
if (rtype(i.arg[1]) == RCon) {
|
||||
/* todo, use the constant
|
||||
* size to dimension the
|
||||
* constant */
|
||||
t = newtmp(TWord, fn);
|
||||
r0 = TMP(t);
|
||||
} else {
|
||||
r0 = i.arg[1];
|
||||
i.arg[1] = i.arg[0];
|
||||
c = COP(c);
|
||||
}
|
||||
}
|
||||
if (rtype(i.arg[0]) == RCon)
|
||||
c = COP(c);
|
||||
emit(OXSet+c, i.to, R, R);
|
||||
if (islong(r0, fn) || islong(i.arg[1], fn))
|
||||
emit(OXCmpl, R, i.arg[1], r0);
|
||||
else
|
||||
emit(OXCmpw, R, i.arg[1], r0);
|
||||
if (t != -1)
|
||||
emit(OCopy, r0, i.arg[0], R);
|
||||
selcmp(i.arg, fn);
|
||||
break;
|
||||
}
|
||||
diag("isel: non-exhaustive implementation");
|
||||
}
|
||||
}
|
||||
|
||||
static Ins *
|
||||
flagi(Ins *i0, Ins *i)
|
||||
{
|
||||
while (i>i0)
|
||||
switch ((--i)->op) {
|
||||
default:
|
||||
return i;
|
||||
case OCopy:
|
||||
case OStore:
|
||||
case OLoad:;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static Ins *
|
||||
seljmp(Blk *b, Fn *fn)
|
||||
{
|
||||
Ref r;
|
||||
int c;
|
||||
Ins *fi;
|
||||
|
||||
fi = &b->ins[b->nins];
|
||||
if (b->jmp.type != JJez)
|
||||
return fi;
|
||||
r = b->jmp.arg;
|
||||
b->jmp.arg = R;
|
||||
assert(!req(r, R));
|
||||
if (rtype(r) == RCon) {
|
||||
b->jmp.type = JJmp;
|
||||
if (!req(r, CON_Z))
|
||||
b->s1 = b->s2;
|
||||
b->s2 = 0;
|
||||
return fi;
|
||||
}
|
||||
fi = flagi(b->ins, fi);
|
||||
if (fi && req(fi->to, r)) {
|
||||
assert(1 == fn->tmp[r.val].nuse);
|
||||
if (fn->tmp[r.val].nuse == 1
|
||||
&& OCmp <= fi->op && fi->op <= OCmp1) {
|
||||
c = fi->op - OCmp;
|
||||
if (rtype(fi->arg[0]) == RCon)
|
||||
c = COP(c);
|
||||
b->jmp.type = JXJc + cneg(c);
|
||||
selcmp(fi->arg, fn);
|
||||
return fi;
|
||||
}
|
||||
/* what if it is a comparison
|
||||
* that is used more than once?
|
||||
* !!!
|
||||
*/
|
||||
b->jmp.type = JXJc + Ceq;
|
||||
return fi+1;
|
||||
}
|
||||
if (islong(r, fn))
|
||||
emit(OXCmpl, R, CON_Z, r);
|
||||
else
|
||||
emit(OXCmpw, R, CON_Z, r);
|
||||
b->jmp.type = JXJc + Ceq;
|
||||
return &b->ins[b->nins];
|
||||
}
|
||||
|
||||
/* instruction selection
|
||||
* requires use counts (as given by parsing)
|
||||
*/
|
||||
|
@ -133,7 +217,8 @@ isel(Fn *fn)
|
|||
|
||||
for (b=fn->start; b; b=b->link) {
|
||||
curi = &insb[NIns];
|
||||
for (i=&b->ins[b->nins]; i!=b->ins;) {
|
||||
i = seljmp(b, fn);
|
||||
while (i>b->ins) {
|
||||
sel(*--i, fn);
|
||||
}
|
||||
nins = &insb[NIns] - curi;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue