diff options
| author | Quentin Carbonneaux <[email protected]> | 2026-01-13 18:11:07 +0100 |
|---|---|---|
| committer | Quentin Carbonneaux <[email protected]> | 2026-01-13 18:11:37 +0100 |
| commit | c6336557dad1161088c3f60a8045d676fb924ed5 (patch) | |
| tree | d82f530fe255b1ee9219cca79b1cbb4eb311af31 | |
| parent | 5c1eb24e2c312021c7af4316e5adde53e270311a (diff) | |
ifopt simplifications
| -rw-r--r-- | amd64/emit.c | 200 | ||||
| -rw-r--r-- | amd64/isel.c | 81 | ||||
| -rw-r--r-- | ops.h | 2 |
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) @@ -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) |
