ifopt simplifications

This commit is contained in:
Quentin Carbonneaux 2026-01-13 18:11:07 +01:00
parent 5c1eb24e2c
commit c6336557da
3 changed files with 128 additions and 151 deletions

View File

@ -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
}; };

View File

@ -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
View File

@ -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)