mirror of
git://c9x.me/qbe.git
synced 2026-04-05 09:59:47 +00:00
ifopt simplifications
This commit is contained in:
parent
5c1eb24e2c
commit
c6336557da
92
amd64/emit.c
92
amd64/emit.c
@ -12,24 +12,22 @@ struct E {
|
|||||||
};
|
};
|
||||||
|
|
||||||
#define CMP(X) \
|
#define CMP(X) \
|
||||||
X(Ciule, "be") \
|
X(Ciule, "be", "a") \
|
||||||
X(Ciult, "b") \
|
X(Ciult, "b", "ae") \
|
||||||
X(Cisle, "le") \
|
X(Cisle, "le", "g") \
|
||||||
X(Cislt, "l") \
|
X(Cislt, "l", "ge") \
|
||||||
X(Cisgt, "g") \
|
X(Cisgt, "g", "le") \
|
||||||
X(Cisge, "ge") \
|
X(Cisge, "ge", "l") \
|
||||||
X(Ciugt, "a") \
|
X(Ciugt, "a", "be") \
|
||||||
X(Ciuge, "ae") \
|
X(Ciuge, "ae", "b") \
|
||||||
X(Cieq, "z") \
|
X(Cieq, "z", "nz") \
|
||||||
X(Cine, "nz") \
|
X(Cine, "nz", "z") \
|
||||||
X(NCmpI+Cfle, "be") \
|
X(NCmpI+Cfle, "be", "a") \
|
||||||
X(NCmpI+Cflt, "b") \
|
X(NCmpI+Cflt, "b", "ae") \
|
||||||
X(NCmpI+Cfgt, "a") \
|
X(NCmpI+Cfgt, "a", "be") \
|
||||||
X(NCmpI+Cfge, "ae") \
|
X(NCmpI+Cfge, "ae", "b") \
|
||||||
X(NCmpI+Cfeq, "z") \
|
X(NCmpI+Cfo, "np", "p") \
|
||||||
X(NCmpI+Cfne, "nz") \
|
X(NCmpI+Cfuo, "p", "np")
|
||||||
X(NCmpI+Cfo, "np") \
|
|
||||||
X(NCmpI+Cfuo, "p")
|
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
SLong = 0,
|
SLong = 0,
|
||||||
@ -124,13 +122,25 @@ static struct {
|
|||||||
{ Oxcmp, Kd, "ucomisd %D0, %D1" },
|
{ Oxcmp, Kd, "ucomisd %D0, %D1" },
|
||||||
{ Oxcmp, Ki, "cmp%k %0, %1" },
|
{ Oxcmp, Ki, "cmp%k %0, %1" },
|
||||||
{ Oxtest, Ki, "test%k %0, %1" },
|
{ Oxtest, Ki, "test%k %0, %1" },
|
||||||
#define X(c, s) \
|
#define X(c, s, _) \
|
||||||
{ Oflag+c, Ki, "set" s " %B=\n\tmovzb%k %B=, %=" },
|
{ Oflag+c, Ki, "set" s " %B=\n\tmovzb%k %B=, %=" },
|
||||||
CMP(X)
|
CMP(X)
|
||||||
#undef X
|
#undef X
|
||||||
|
{ Oflagfeq, Ki, "setz %B=\n\tmovzb%k %B=, %=" },
|
||||||
|
{ Oflagfne, Ki, "setnz %B=\n\tmovzb%k %B=, %=" },
|
||||||
{ NOp, 0, 0 }
|
{ NOp, 0, 0 }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static char cmov[][2][16] = {
|
||||||
|
#define X(c, s0, s1) \
|
||||||
|
[c] = { \
|
||||||
|
"cmov" s0 " %0, %=", \
|
||||||
|
"cmov" s1 " %1, %=", \
|
||||||
|
},
|
||||||
|
CMP(X)
|
||||||
|
#undef X
|
||||||
|
};
|
||||||
|
|
||||||
static char *rname[][4] = {
|
static char *rname[][4] = {
|
||||||
[RAX] = {"rax", "eax", "ax", "al"},
|
[RAX] = {"rax", "eax", "ax", "al"},
|
||||||
[RBX] = {"rbx", "ebx", "bx", "bl"},
|
[RBX] = {"rbx", "ebx", "bx", "bl"},
|
||||||
@ -401,6 +411,8 @@ emitins(Ins i, E *e)
|
|||||||
|
|
||||||
switch (i.op) {
|
switch (i.op) {
|
||||||
default:
|
default:
|
||||||
|
if (isxsel(i.op))
|
||||||
|
goto case_Oxsel;
|
||||||
Table:
|
Table:
|
||||||
/* most instructions are just pulled out of
|
/* most instructions are just pulled out of
|
||||||
* the table omap[], some special cases are
|
* the table omap[], some special cases are
|
||||||
@ -576,43 +588,15 @@ emitins(Ins i, E *e)
|
|||||||
case Odbgloc:
|
case Odbgloc:
|
||||||
emitdbgloc(i.arg[0].val, i.arg[1].val, e->f);
|
emitdbgloc(i.arg[0].val, i.arg[1].val, e->f);
|
||||||
break;
|
break;
|
||||||
case Oxselieq:
|
case_Oxsel:
|
||||||
case Oxseline:
|
|
||||||
case Oxselisge:
|
|
||||||
case Oxselisgt:
|
|
||||||
case Oxselisle:
|
|
||||||
case Oxselislt:
|
|
||||||
case Oxseliuge:
|
|
||||||
case Oxseliugt:
|
|
||||||
case Oxseliule:
|
|
||||||
case Oxseliult:
|
|
||||||
case Oxselfeq:
|
|
||||||
case Oxselfge:
|
|
||||||
case Oxselfgt:
|
|
||||||
case Oxselfle:
|
|
||||||
case Oxselflt:
|
|
||||||
case Oxselfne:
|
|
||||||
case Oxselfo:
|
|
||||||
case Oxselfuo:
|
|
||||||
{
|
|
||||||
// TODO - how to do this "properly"?
|
|
||||||
static char *F0[] = {
|
|
||||||
"z", "nz", "ge", "g", "le", "l", "ae", "a", "be", "b",
|
|
||||||
"nz", "ae", "a", "be", "b", "nz", "p", "np"
|
|
||||||
};
|
|
||||||
static char *F1[] = {
|
|
||||||
"nz", "z", "l", "le", "g", "ge", "b", "be", "a", "ae",
|
|
||||||
"z", "b", "be", "a", "ae", "z", "p", "np"
|
|
||||||
};
|
|
||||||
char ins[16];
|
|
||||||
sprintf(ins, "cmov%s %%1, %%=", F1[i.op-Oxselieq]);
|
|
||||||
if (req(i.to, i.arg[1]))
|
if (req(i.to, i.arg[1]))
|
||||||
sprintf(ins, "cmov%s %%0, %%=", F0[i.op-Oxselieq]);
|
emitf(cmov[i.op-Oxsel][0], &i, e);
|
||||||
else if (!req(i.to, i.arg[0]))
|
else {
|
||||||
|
if (!req(i.to, i.arg[0]))
|
||||||
emitf("mov %0, %=", &i, e);
|
emitf("mov %0, %=", &i, e);
|
||||||
emitf(ins, &i, e);
|
emitf(cmov[i.op-Oxsel][1], &i, e);
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -641,7 +625,7 @@ void
|
|||||||
amd64_emitfn(Fn *fn, FILE *f)
|
amd64_emitfn(Fn *fn, FILE *f)
|
||||||
{
|
{
|
||||||
static char *ctoa[] = {
|
static char *ctoa[] = {
|
||||||
#define X(c, s) [c] = s,
|
#define X(c, s, _) [c] = s,
|
||||||
CMP(X)
|
CMP(X)
|
||||||
#undef X
|
#undef X
|
||||||
};
|
};
|
||||||
|
|||||||
73
amd64/isel.c
73
amd64/isel.c
@ -429,25 +429,8 @@ sel(Ins i, Num *tn, Fn *fn)
|
|||||||
case Oexts:
|
case Oexts:
|
||||||
case Otruncd:
|
case Otruncd:
|
||||||
case Ocast:
|
case Ocast:
|
||||||
case Oxselieq:
|
case_Oxsel:
|
||||||
case Oxseline:
|
case_Oext:
|
||||||
case Oxselisge:
|
|
||||||
case Oxselisgt:
|
|
||||||
case Oxselisle:
|
|
||||||
case Oxselislt:
|
|
||||||
case Oxseliuge:
|
|
||||||
case Oxseliugt:
|
|
||||||
case Oxseliule:
|
|
||||||
case Oxseliult:
|
|
||||||
case Oxselfeq:
|
|
||||||
case Oxselfge:
|
|
||||||
case Oxselfgt:
|
|
||||||
case Oxselfle:
|
|
||||||
case Oxselflt:
|
|
||||||
case Oxselfne:
|
|
||||||
case Oxselfo:
|
|
||||||
case Oxselfuo:
|
|
||||||
case_OExt:
|
|
||||||
Emit:
|
Emit:
|
||||||
emiti(i);
|
emiti(i);
|
||||||
i1 = curi; /* fixarg() can change curi */
|
i1 = curi; /* fixarg() can change curi */
|
||||||
@ -461,7 +444,9 @@ Emit:
|
|||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
if (isext(i.op))
|
if (isext(i.op))
|
||||||
goto case_OExt;
|
goto case_Oext;
|
||||||
|
if (isxsel(i.op))
|
||||||
|
goto case_Oxsel;
|
||||||
if (isload(i.op))
|
if (isload(i.op))
|
||||||
goto case_Oload;
|
goto case_Oload;
|
||||||
if (iscmp(i.op, &kc, &x)) {
|
if (iscmp(i.op, &kc, &x)) {
|
||||||
@ -518,7 +503,7 @@ flagi(Ins *i0, Ins *i)
|
|||||||
static Ins*
|
static Ins*
|
||||||
selsel(Fn *fn, Blk *b, Ins *i, Num *tn)
|
selsel(Fn *fn, Blk *b, Ins *i, Num *tn)
|
||||||
{
|
{
|
||||||
Ref r, cr0, cr1;
|
Ref r, cr[2];
|
||||||
int c, k, swap, gencmp, gencpy;
|
int c, k, swap, gencmp, gencpy;
|
||||||
Ins *isel0, *isel1, *fi;
|
Ins *isel0, *isel1, *fi;
|
||||||
Tmp *t;
|
Tmp *t;
|
||||||
@ -534,27 +519,36 @@ selsel(Fn *fn, Blk *b, Ins *i, Num *tn)
|
|||||||
assert(rtype(r) == RTmp);
|
assert(rtype(r) == RTmp);
|
||||||
t = &fn->tmp[r.val];
|
t = &fn->tmp[r.val];
|
||||||
fi = flagi(b->ins, isel0);
|
fi = flagi(b->ins, isel0);
|
||||||
cr0 = cr1 = R;
|
cr[0] = cr[1] = R;
|
||||||
gencmp = gencpy = swap = 0;
|
gencmp = gencpy = swap = 0;
|
||||||
k = Kw;
|
k = Kw;
|
||||||
c = Cine;
|
c = Cine;
|
||||||
if (!fi || !req(fi->to, r)) {
|
if (!fi || !req(fi->to, r)) {
|
||||||
gencmp = 1;
|
gencmp = 1;
|
||||||
cr0 = r;
|
cr[0] = r;
|
||||||
cr1 = CON_Z;
|
cr[1] = CON_Z;
|
||||||
} else if (iscmp(fi->op, &k, &c)
|
}
|
||||||
&& c != NCmpI+Cfeq /* see sel() */
|
else if (iscmp(fi->op, &k, &c)) {
|
||||||
&& c != NCmpI+Cfne) {
|
if (c == NCmpI+Cfeq
|
||||||
|
|| c == NCmpI+Cfne) {
|
||||||
|
/* these are selected as 'and'
|
||||||
|
* or 'or', so we check their
|
||||||
|
* result with Cine
|
||||||
|
*/
|
||||||
|
c = Cine;
|
||||||
|
goto Other;
|
||||||
|
}
|
||||||
swap = cmpswap(fi->arg, c);
|
swap = cmpswap(fi->arg, c);
|
||||||
if (swap)
|
if (swap)
|
||||||
c = cmpop(c);
|
c = cmpop(c);
|
||||||
if (t->nuse == 1) {
|
if (t->nuse == 1) {
|
||||||
gencmp = 1;
|
gencmp = 1;
|
||||||
cr0 = fi->arg[0];
|
cr[0] = fi->arg[0];
|
||||||
cr1 = fi->arg[1];
|
cr[1] = fi->arg[1];
|
||||||
*fi = (Ins){.op = Onop};
|
*fi = (Ins){.op = Onop};
|
||||||
}
|
}
|
||||||
} else if (fi->op == Oand && t->nuse == 1
|
}
|
||||||
|
else if (fi->op == Oand && t->nuse == 1
|
||||||
&& (rtype(fi->arg[0]) == RTmp ||
|
&& (rtype(fi->arg[0]) == RTmp ||
|
||||||
rtype(fi->arg[1]) == RTmp)) {
|
rtype(fi->arg[1]) == RTmp)) {
|
||||||
fi->op = Oxtest;
|
fi->op = Oxtest;
|
||||||
@ -564,7 +558,9 @@ selsel(Fn *fn, Blk *b, Ins *i, Num *tn)
|
|||||||
fi->arg[1] = fi->arg[0];
|
fi->arg[1] = fi->arg[0];
|
||||||
fi->arg[0] = r;
|
fi->arg[0] = r;
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
|
Other:
|
||||||
/* since flags are not tracked in liveness,
|
/* since flags are not tracked in liveness,
|
||||||
* the result of the flag-setting instruction
|
* the result of the flag-setting instruction
|
||||||
* has to be marked as live
|
* has to be marked as live
|
||||||
@ -574,17 +570,14 @@ selsel(Fn *fn, Blk *b, Ins *i, Num *tn)
|
|||||||
}
|
}
|
||||||
/* generate conditional moves */
|
/* generate conditional moves */
|
||||||
for (isel1=i; isel0<isel1; --isel1) {
|
for (isel1=i; isel0<isel1; --isel1) {
|
||||||
isel1->op = Oxselieq+c;
|
isel1->op = Oxsel+c;
|
||||||
sel(*isel1, tn, fn);
|
sel(*isel1, tn, fn);
|
||||||
}
|
}
|
||||||
if (gencmp) {
|
assert(!gencmp || !gencpy);
|
||||||
assert(!gencpy);
|
if (gencmp)
|
||||||
selcmp((Ref[2]){cr0, cr1}, k, swap, fn);
|
selcmp(cr, k, swap, fn);
|
||||||
}
|
if (gencpy)
|
||||||
if (gencpy) {
|
|
||||||
assert(!gencmp);
|
|
||||||
emit(Ocopy, Kw, R, r, R);
|
emit(Ocopy, Kw, R, r, R);
|
||||||
}
|
|
||||||
*isel0 = (Ins){.op = Onop};
|
*isel0 = (Ins){.op = Onop};
|
||||||
return isel0;
|
return isel0;
|
||||||
}
|
}
|
||||||
@ -618,7 +611,7 @@ seljmp(Blk *b, Fn *fn)
|
|||||||
b->jmp.type = Jjf + Cine;
|
b->jmp.type = Jjf + Cine;
|
||||||
}
|
}
|
||||||
else if (iscmp(fi->op, &k, &c)
|
else if (iscmp(fi->op, &k, &c)
|
||||||
&& c != NCmpI+Cfeq /* see sel() */
|
&& c != NCmpI+Cfeq /* see sel(), selsel() */
|
||||||
&& c != NCmpI+Cfne) {
|
&& c != NCmpI+Cfne) {
|
||||||
swap = cmpswap(fi->arg, c);
|
swap = cmpswap(fi->arg, c);
|
||||||
if (swap)
|
if (swap)
|
||||||
|
|||||||
2
ops.h
2
ops.h
@ -145,7 +145,7 @@ O(nop, T(x,x,x,x, x,x,x,x), F(0,0,0,0,0,0,0,0,0,0)) X(0,0,1) V(0)
|
|||||||
O(addr, T(m,m,e,e, x,x,e,e), F(0,0,0,0,0,0,0,0,0,0)) X(0,0,1) V(0)
|
O(addr, T(m,m,e,e, x,x,e,e), F(0,0,0,0,0,0,0,0,0,0)) X(0,0,1) V(0)
|
||||||
O(blit0, T(m,e,e,e, m,e,e,e), F(0,0,0,0,0,0,0,0,0,1)) X(0,1,0) V(0)
|
O(blit0, T(m,e,e,e, m,e,e,e), F(0,0,0,0,0,0,0,0,0,1)) X(0,1,0) V(0)
|
||||||
O(blit1, T(w,e,e,e, x,e,e,e), F(0,0,0,0,0,0,0,0,0,1)) X(0,1,0) V(0)
|
O(blit1, T(w,e,e,e, x,e,e,e), F(0,0,0,0,0,0,0,0,0,1)) X(0,1,0) V(0)
|
||||||
O(sel0, T(w,e,e,e, x,x,x,x), F(0,0,0,0,0,0,0,0,0,1)) X(0,0,0) V(0)
|
O(sel0, T(w,e,e,e, x,e,e,e), F(0,0,0,0,0,0,0,0,0,1)) X(0,0,0) V(0)
|
||||||
O(sel1, T(w,l,e,e, w,l,e,e), F(0,0,0,0,0,0,0,0,0,1)) X(0,0,0) V(0)
|
O(sel1, T(w,l,e,e, w,l,e,e), F(0,0,0,0,0,0,0,0,0,1)) X(0,0,0) V(0)
|
||||||
O(swap, T(w,l,s,d, w,l,s,d), F(0,0,0,0,0,0,0,0,0,0)) X(1,0,0) V(0)
|
O(swap, T(w,l,s,d, w,l,s,d), F(0,0,0,0,0,0,0,0,0,0)) X(1,0,0) V(0)
|
||||||
O(sign, T(w,l,e,e, x,x,e,e), F(0,0,0,0,0,0,0,0,0,0)) X(0,0,0) V(0)
|
O(sign, T(w,l,e,e, x,x,e,e), F(0,0,0,0,0,0,0,0,0,0)) X(0,0,0) V(0)
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user