aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorQuentin Carbonneaux <[email protected]>2026-01-13 18:11:07 +0100
committerQuentin Carbonneaux <[email protected]>2026-01-13 18:11:37 +0100
commitc6336557dad1161088c3f60a8045d676fb924ed5 (patch)
treed82f530fe255b1ee9219cca79b1cbb4eb311af31
parent5c1eb24e2c312021c7af4316e5adde53e270311a (diff)
ifopt simplifications
-rw-r--r--amd64/emit.c200
-rw-r--r--amd64/isel.c81
-rw-r--r--ops.h2
3 files changed, 130 insertions, 153 deletions
diff --git a/amd64/emit.c b/amd64/emit.c
index 7290a80..8d715d0 100644
--- a/amd64/emit.c
+++ b/amd64/emit.c
@@ -12,24 +12,22 @@ struct E {
};
#define CMP(X) \
- X(Ciule, "be") \
- X(Ciult, "b") \
- X(Cisle, "le") \
- X(Cislt, "l") \
- X(Cisgt, "g") \
- X(Cisge, "ge") \
- X(Ciugt, "a") \
- X(Ciuge, "ae") \
- X(Cieq, "z") \
- X(Cine, "nz") \
- X(NCmpI+Cfle, "be") \
- X(NCmpI+Cflt, "b") \
- X(NCmpI+Cfgt, "a") \
- X(NCmpI+Cfge, "ae") \
- X(NCmpI+Cfeq, "z") \
- X(NCmpI+Cfne, "nz") \
- X(NCmpI+Cfo, "np") \
- X(NCmpI+Cfuo, "p")
+ X(Ciule, "be", "a") \
+ X(Ciult, "b", "ae") \
+ X(Cisle, "le", "g") \
+ X(Cislt, "l", "ge") \
+ X(Cisgt, "g", "le") \
+ X(Cisge, "ge", "l") \
+ X(Ciugt, "a", "be") \
+ X(Ciuge, "ae", "b") \
+ X(Cieq, "z", "nz") \
+ X(Cine, "nz", "z") \
+ X(NCmpI+Cfle, "be", "a") \
+ X(NCmpI+Cflt, "b", "ae") \
+ X(NCmpI+Cfgt, "a", "be") \
+ X(NCmpI+Cfge, "ae", "b") \
+ X(NCmpI+Cfo, "np", "p") \
+ X(NCmpI+Cfuo, "p", "np")
enum {
SLong = 0,
@@ -72,65 +70,77 @@ static struct {
short cls;
char *fmt;
} omap[] = {
- { Oadd, Ka, "+add%k %1, %=" },
- { Osub, Ka, "-sub%k %1, %=" },
- { Oand, Ki, "+and%k %1, %=" },
- { Oor, Ki, "+or%k %1, %=" },
- { Oxor, Ki, "+xor%k %1, %=" },
- { Osar, Ki, "-sar%k %B1, %=" },
- { Oshr, Ki, "-shr%k %B1, %=" },
- { Oshl, Ki, "-shl%k %B1, %=" },
- { Omul, Ki, "+imul%k %1, %=" },
- { Omul, Ks, "+mulss %1, %=" },
- { Omul, Kd, "+mulsd %1, %=" },
- { Odiv, Ka, "-div%k %1, %=" },
- { Ostorel, Ka, "movq %L0, %M1" },
- { Ostorew, Ka, "movl %W0, %M1" },
- { Ostoreh, Ka, "movw %H0, %M1" },
- { Ostoreb, Ka, "movb %B0, %M1" },
- { Ostores, Ka, "movss %S0, %M1" },
- { Ostored, Ka, "movsd %D0, %M1" },
- { Oload, Ka, "mov%k %M0, %=" },
- { Oloadsw, Kl, "movslq %M0, %L=" },
- { Oloadsw, Kw, "movl %M0, %W=" },
- { Oloaduw, Ki, "movl %M0, %W=" },
- { Oloadsh, Ki, "movsw%k %M0, %=" },
- { Oloaduh, Ki, "movzw%k %M0, %=" },
- { Oloadsb, Ki, "movsb%k %M0, %=" },
- { Oloadub, Ki, "movzb%k %M0, %=" },
- { Oextsw, Kl, "movslq %W0, %L=" },
- { Oextuw, Kl, "movl %W0, %W=" },
- { Oextsh, Ki, "movsw%k %H0, %=" },
- { Oextuh, Ki, "movzw%k %H0, %=" },
- { Oextsb, Ki, "movsb%k %B0, %=" },
- { Oextub, Ki, "movzb%k %B0, %=" },
-
- { Oexts, Kd, "cvtss2sd %0, %=" },
- { Otruncd, Ks, "cvtsd2ss %0, %=" },
- { Ostosi, Ki, "cvttss2si%k %0, %=" },
- { Odtosi, Ki, "cvttsd2si%k %0, %=" },
- { Oswtof, Ka, "cvtsi2%k %W0, %=" },
- { Osltof, Ka, "cvtsi2%k %L0, %=" },
- { Ocast, Ki, "movq %D0, %L=" },
- { Ocast, Ka, "movq %L0, %D=" },
-
- { Oaddr, Ki, "lea%k %M0, %=" },
- { Oswap, Ki, "xchg%k %0, %1" },
- { Osign, Kl, "cqto" },
- { Osign, Kw, "cltd" },
- { Oxdiv, Ki, "div%k %0" },
- { Oxidiv, Ki, "idiv%k %0" },
- { Oxcmp, Ks, "ucomiss %S0, %S1" },
- { Oxcmp, Kd, "ucomisd %D0, %D1" },
- { Oxcmp, Ki, "cmp%k %0, %1" },
- { Oxtest, Ki, "test%k %0, %1" },
-#define X(c, s) \
- { Oflag+c, Ki, "set" s " %B=\n\tmovzb%k %B=, %=" },
+ { Oadd, Ka, "+add%k %1, %=" },
+ { Osub, Ka, "-sub%k %1, %=" },
+ { Oand, Ki, "+and%k %1, %=" },
+ { Oor, Ki, "+or%k %1, %=" },
+ { Oxor, Ki, "+xor%k %1, %=" },
+ { Osar, Ki, "-sar%k %B1, %=" },
+ { Oshr, Ki, "-shr%k %B1, %=" },
+ { Oshl, Ki, "-shl%k %B1, %=" },
+ { Omul, Ki, "+imul%k %1, %=" },
+ { Omul, Ks, "+mulss %1, %=" },
+ { Omul, Kd, "+mulsd %1, %=" },
+ { Odiv, Ka, "-div%k %1, %=" },
+ { Ostorel, Ka, "movq %L0, %M1" },
+ { Ostorew, Ka, "movl %W0, %M1" },
+ { Ostoreh, Ka, "movw %H0, %M1" },
+ { Ostoreb, Ka, "movb %B0, %M1" },
+ { Ostores, Ka, "movss %S0, %M1" },
+ { Ostored, Ka, "movsd %D0, %M1" },
+ { Oload, Ka, "mov%k %M0, %=" },
+ { Oloadsw, Kl, "movslq %M0, %L=" },
+ { Oloadsw, Kw, "movl %M0, %W=" },
+ { Oloaduw, Ki, "movl %M0, %W=" },
+ { Oloadsh, Ki, "movsw%k %M0, %=" },
+ { Oloaduh, Ki, "movzw%k %M0, %=" },
+ { Oloadsb, Ki, "movsb%k %M0, %=" },
+ { Oloadub, Ki, "movzb%k %M0, %=" },
+ { Oextsw, Kl, "movslq %W0, %L=" },
+ { Oextuw, Kl, "movl %W0, %W=" },
+ { Oextsh, Ki, "movsw%k %H0, %=" },
+ { Oextuh, Ki, "movzw%k %H0, %=" },
+ { Oextsb, Ki, "movsb%k %B0, %=" },
+ { Oextub, Ki, "movzb%k %B0, %=" },
+
+ { Oexts, Kd, "cvtss2sd %0, %=" },
+ { Otruncd, Ks, "cvtsd2ss %0, %=" },
+ { Ostosi, Ki, "cvttss2si%k %0, %=" },
+ { Odtosi, Ki, "cvttsd2si%k %0, %=" },
+ { Oswtof, Ka, "cvtsi2%k %W0, %=" },
+ { Osltof, Ka, "cvtsi2%k %L0, %=" },
+ { Ocast, Ki, "movq %D0, %L=" },
+ { Ocast, Ka, "movq %L0, %D=" },
+
+ { Oaddr, Ki, "lea%k %M0, %=" },
+ { Oswap, Ki, "xchg%k %0, %1" },
+ { Osign, Kl, "cqto" },
+ { Osign, Kw, "cltd" },
+ { Oxdiv, Ki, "div%k %0" },
+ { Oxidiv, Ki, "idiv%k %0" },
+ { Oxcmp, Ks, "ucomiss %S0, %S1" },
+ { Oxcmp, Kd, "ucomisd %D0, %D1" },
+ { Oxcmp, Ki, "cmp%k %0, %1" },
+ { Oxtest, Ki, "test%k %0, %1" },
+#define X(c, s, _) \
+ { Oflag+c, Ki, "set" s " %B=\n\tmovzb%k %B=, %=" },
CMP(X)
#undef X
+ { Oflagfeq, Ki, "setz %B=\n\tmovzb%k %B=, %=" },
+ { Oflagfne, Ki, "setnz %B=\n\tmovzb%k %B=, %=" },
{ 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] = {
[RAX] = {"rax", "eax", "ax", "al"},
[RBX] = {"rbx", "ebx", "bx", "bl"},
@@ -401,6 +411,8 @@ emitins(Ins i, E *e)
switch (i.op) {
default:
+ if (isxsel(i.op))
+ goto case_Oxsel;
Table:
/* most instructions are just pulled out of
* the table omap[], some special cases are
@@ -576,44 +588,16 @@ emitins(Ins i, E *e)
case Odbgloc:
emitdbgloc(i.arg[0].val, i.arg[1].val, e->f);
break;
- case Oxselieq:
- 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]);
+ case_Oxsel:
if (req(i.to, i.arg[1]))
- sprintf(ins, "cmov%s %%0, %%=", F0[i.op-Oxselieq]);
- else if (!req(i.to, i.arg[0]))
- emitf("mov %0, %=", &i, e);
- emitf(ins, &i, e);
+ emitf(cmov[i.op-Oxsel][0], &i, e);
+ else {
+ if (!req(i.to, i.arg[0]))
+ emitf("mov %0, %=", &i, e);
+ emitf(cmov[i.op-Oxsel][1], &i, e);
+ }
break;
}
- }
}
static void
@@ -641,7 +625,7 @@ void
amd64_emitfn(Fn *fn, FILE *f)
{
static char *ctoa[] = {
- #define X(c, s) [c] = s,
+ #define X(c, s, _) [c] = s,
CMP(X)
#undef X
};
diff --git a/amd64/isel.c b/amd64/isel.c
index c54b580..73e0860 100644
--- a/amd64/isel.c
+++ b/amd64/isel.c
@@ -429,25 +429,8 @@ sel(Ins i, Num *tn, Fn *fn)
case Oexts:
case Otruncd:
case Ocast:
- case Oxselieq:
- 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:
- case_OExt:
+ case_Oxsel:
+ case_Oext:
Emit:
emiti(i);
i1 = curi; /* fixarg() can change curi */
@@ -461,7 +444,9 @@ Emit:
break;
default:
if (isext(i.op))
- goto case_OExt;
+ goto case_Oext;
+ if (isxsel(i.op))
+ goto case_Oxsel;
if (isload(i.op))
goto case_Oload;
if (iscmp(i.op, &kc, &x)) {
@@ -518,13 +503,13 @@ flagi(Ins *i0, Ins *i)
static Ins*
selsel(Fn *fn, Blk *b, Ins *i, Num *tn)
{
- Ref r, cr0, cr1;
+ Ref r, cr[2];
int c, k, swap, gencmp, gencpy;
Ins *isel0, *isel1, *fi;
Tmp *t;
assert(i->op == Osel1);
- for (isel0 = i; b->ins < isel0; isel0--) {
+ for (isel0=i; b->ins<isel0; isel0--) {
if (isel0->op == Osel0)
break;
assert(isel0->op == Osel1);
@@ -534,29 +519,38 @@ selsel(Fn *fn, Blk *b, Ins *i, Num *tn)
assert(rtype(r) == RTmp);
t = &fn->tmp[r.val];
fi = flagi(b->ins, isel0);
- cr0 = cr1 = R;
+ cr[0] = cr[1] = R;
gencmp = gencpy = swap = 0;
k = Kw;
c = Cine;
if (!fi || !req(fi->to, r)) {
gencmp = 1;
- cr0 = r;
- cr1 = CON_Z;
- } else if (iscmp(fi->op, &k, &c)
- && c != NCmpI+Cfeq /* see sel() */
- && c != NCmpI+Cfne) {
+ cr[0] = r;
+ cr[1] = CON_Z;
+ }
+ else if (iscmp(fi->op, &k, &c)) {
+ 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);
if (swap)
c = cmpop(c);
if (t->nuse == 1) {
gencmp = 1;
- cr0 = fi->arg[0];
- cr1 = fi->arg[1];
+ cr[0] = fi->arg[0];
+ cr[1] = fi->arg[1];
*fi = (Ins){.op = Onop};
}
- } else if (fi->op == Oand && t->nuse == 1
- && (rtype(fi->arg[0]) == RTmp ||
- rtype(fi->arg[1]) == RTmp)) {
+ }
+ else if (fi->op == Oand && t->nuse == 1
+ && (rtype(fi->arg[0]) == RTmp ||
+ rtype(fi->arg[1]) == RTmp)) {
fi->op = Oxtest;
fi->to = R;
if (rtype(fi->arg[1]) == RCon) {
@@ -564,7 +558,9 @@ selsel(Fn *fn, Blk *b, Ins *i, Num *tn)
fi->arg[1] = fi->arg[0];
fi->arg[0] = r;
}
- } else {
+ }
+ else {
+ Other:
/* since flags are not tracked in liveness,
* the result of the flag-setting instruction
* has to be marked as live
@@ -573,18 +569,15 @@ selsel(Fn *fn, Blk *b, Ins *i, Num *tn)
gencpy = 1;
}
/* generate conditional moves */
- for (isel1 = i; isel0 < isel1; --isel1) {
- isel1->op = Oxselieq+c;
+ for (isel1=i; isel0<isel1; --isel1) {
+ isel1->op = Oxsel+c;
sel(*isel1, tn, fn);
}
- if (gencmp) {
- assert(!gencpy);
- selcmp((Ref[2]){cr0, cr1}, k, swap, fn);
- }
- if (gencpy) {
- assert(!gencmp);
+ assert(!gencmp || !gencpy);
+ if (gencmp)
+ selcmp(cr, k, swap, fn);
+ if (gencpy)
emit(Ocopy, Kw, R, r, R);
- }
*isel0 = (Ins){.op = Onop};
return isel0;
}
@@ -618,7 +611,7 @@ seljmp(Blk *b, Fn *fn)
b->jmp.type = Jjf + Cine;
}
else if (iscmp(fi->op, &k, &c)
- && c != NCmpI+Cfeq /* see sel() */
+ && c != NCmpI+Cfeq /* see sel(), selsel() */
&& c != NCmpI+Cfne) {
swap = cmpswap(fi->arg, c);
if (swap)
diff --git a/ops.h b/ops.h
index 2336d5f..f59e757 100644
--- a/ops.h
+++ b/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(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(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(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)