ref: 064b5d2b2f9c54fcbd0e928d75253032e51f7e6f
parent: 1750fba1a4fc55641cfd5a9ced3a33f012ff221f
author: Ori Bernstein <[email protected]>
date: Mon Jan 20 11:47:23 EST 2014
Correctly handle signed/unsigned comparisons.
--- a/6/insns.def
+++ b/6/insns.def
@@ -60,6 +60,10 @@
Insn(Isetle, "\tsetle %v\n", Use(), Def(.l={1}))
Insn(Isetg, "\tsetg %v\n", Use(), Def(.l={1}))
Insn(Isetge, "\tsetge %v\n", Use(), Def(.l={1}))
+Insn(Isetb, "\tsetb %v\n", Use(), Def(.l={1}))
+Insn(Isetbe, "\tsetbe %v\n", Use(), Def(.l={1}))
+Insn(Iseta, "\tseta %v\n", Use(), Def(.l={1}))
+Insn(Isetae, "\tsetae %v\n", Use(), Def(.l={1}))
/* fp specific instructions */
Insn(Imovs, "\tmovs%1t %x,%x\n", Use(.l={1}), Def(.l={2}))
@@ -82,6 +86,10 @@
Insn(Ijle, "\tjle %v\n", Use(.l={1}), Def())
Insn(Ijg, "\tjg %v\n", Use(.l={1}), Def())
Insn(Ijge, "\tjge %v\n", Use(.l={1}), Def())
+Insn(Ijb, "\tjb %v\n", Use(.l={1}), Def())
+Insn(Ijbe, "\tjbe %v\n", Use(.l={1}), Def())
+Insn(Ija, "\tja %v\n", Use(.l={1}), Def())
+Insn(Ijae, "\tjae %v\n", Use(.l={1}), Def())
Insn(Iret, "\tret\n", Use(), Def())
/* not really an insn... */
--- a/6/isel.c
+++ b/6/isel.c
@@ -40,18 +40,32 @@
/* used to decide which operator is appropriate
* for implementing various conditional operators */
struct {
- AsmOp itest;
- AsmOp fptest;
+ AsmOp test;
AsmOp jmp;
AsmOp getflag;
} reloptab[Numops] = {
- [Olnot] = {Itest, 0, Ijz, Isetz}, /* lnot invalid for floats */
- [Oeq] = {Icmp, Icomis, Ijz, Isetz},
- [One] = {Icmp, Icomis, Ijnz, Isetnz},
- [Ogt] = {Icmp, Icomis, Ijg, Isetg},
- [Oge] = {Icmp, Icomis, Ijge, Isetge},
- [Olt] = {Icmp, Icomis, Ijl, Isetl},
- [Ole] = {Icmp, Icomis, Ijle, Isetle}
+ [Olnot] = {Itest, Ijz, Isetz}, /* lnot invalid for floats */
+ /* signed int */
+ [Oeq] = {Icmp, Ijz, Isetz},
+ [One] = {Icmp, Ijnz, Isetnz},
+ [Ogt] = {Icmp, Ijg, Isetg},
+ [Oge] = {Icmp, Ijge, Isetge},
+ [Olt] = {Icmp, Ijl, Isetl},
+ [Ole] = {Icmp, Ijle, Isetle},
+ /* unsigned int */
+ [Oueq] = {Icmp, Ijz, Isetz},
+ [Oune] = {Icmp, Ijnz, Isetnz},
+ [Ougt] = {Icmp, Ija, Iseta},
+ [Ouge] = {Icmp, Ijae, Isetae},
+ [Oult] = {Icmp, Ijb, Isetb},
+ [Oule] = {Icmp, Ijbe, Isetbe},
+ /* float */
+ [Ofeq] = {Icomis, Ijz, Isetz},
+ [Ofne] = {Icomis, Ijnz, Isetnz},
+ [Ofgt] = {Icomis, Ija, Iseta},
+ [Ofge] = {Icomis, Ijae, Isetae},
+ [Oflt] = {Icomis, Ijb, Isetb},
+ [Ofle] = {Icomis, Ijbe, Isetbe},
};
static Mode mode(Node *n)
@@ -235,14 +249,6 @@
return inr(s, a);
}
-static int floatcompare(Node *e)
-{
- if (exprop(e) == Ovar || exprop(e) == Olit)
- return floatnode(e);
- assert(e->expr.nargs > 0);
- return floatnode(e->expr.args[0]);
-}
-
/* If we're testing equality, etc, it's a bit silly
* to generate the test, store it to a bite, expand it
* to the right width, and then test it again. Try to optimize
@@ -258,10 +264,7 @@
Loc *l1, *l2;
AsmOp cond, jmp;
- if (floatcompare(args[0]))
- cond = reloptab[exprop(args[0])].fptest;
- else
- cond = reloptab[exprop(args[0])].itest;
+ cond = reloptab[exprop(args[0])].test;
jmp = reloptab[exprop(args[0])].jmp;
/* if we have a cond, we're knocking off the redundant test,
* and want to eval the children */
@@ -610,21 +613,20 @@
b = locreg(ModeB);
r = locreg(mode(n));
/* lnot only valid for integer-like values */
- g(s, reloptab[exprop(n)].itest, a, a, NULL);
+ g(s, reloptab[exprop(n)].test, a, a, NULL);
g(s, reloptab[exprop(n)].getflag, b, NULL);
movz(s, b, r);
break;
case Oeq: case One: case Ogt: case Oge: case Olt: case Ole:
+ case Ofeq: case Ofne: case Ofgt: case Ofge: case Oflt: case Ofle:
+ case Oueq: case Oune: case Ougt: case Ouge: case Oult: case Oule:
a = selexpr(s, args[0]);
b = selexpr(s, args[1]);
a = inr(s, a);
c = locreg(ModeB);
r = locreg(mode(n));
- if (floatnode(args[0]))
- g(s, reloptab[exprop(n)].fptest, b, a, NULL);
- else
- g(s, reloptab[exprop(n)].itest, b, a, NULL);
+ g(s, reloptab[exprop(n)].test, b, a, NULL);
g(s, reloptab[exprop(n)].getflag, c, NULL);
movz(s, c, r);
return r;
--- a/6/simp.c
+++ b/6/simp.c
@@ -1246,8 +1246,15 @@
[Obsleq] = Obsl,
[Obsreq] = Obsr,
};
+ const Op cmpmap[Numops][3] = {
+ [Oeq] = {Oeq, Ofeq, Oueq},
+ [One] = {One, Ofne, Oune},
+ [Ogt] = {Ogt, Ofgt, Ougt},
+ [Oge] = {Oge, Ofge, Ouge},
+ [Olt] = {Olt, Oflt, Oult},
+ [Ole] = {Ole, Ofle, Oule}
+ };
-
r = NULL;
args = n->expr.args;
switch (exprop(n)) {
@@ -1431,6 +1438,17 @@
if (s->nloopstep == 0)
fatal(n->line, "trying to continue when not in loop");
jmp(s, s->loopstep[s->nloopstep - 1]);
+ break;
+ case Oeq: case One: case Ogt: case Oge: case Olt: case Ole:
+ if (istyfloat(tybase(exprtype(args[0]))))
+ i = 1;
+ else if (istysigned(tybase(exprtype(args[0]))))
+ i = 0;
+ else
+ i = 2;
+ assert(cmpmap[n->expr.op][i] != Obad);
+ n->expr.op = cmpmap[n->expr.op][i];
+ r = visit(s, n);
break;
default:
if (istyfloat(exprtype(n))) {
--- a/parse/infer.c
+++ b/parse/infer.c
@@ -1245,6 +1245,8 @@
case Otrunc: case Oswiden: case Ozwiden:
case Oint2flt: case Oflt2int:
case Ofadd: case Ofsub: case Ofmul: case Ofdiv: case Ofneg:
+ case Ofeq: case Ofne: case Ofgt: case Ofge: case Oflt: case Ofle:
+ case Oueq: case Oune: case Ougt: case Ouge: case Oult: case Oule:
case Ouget:
die("Should not see %s in fe", opstr(exprop(n)));
break;
--- a/parse/ops.def
+++ b/parse/ops.def
@@ -56,7 +56,8 @@
O(Otup, 1)
O(Ostruct, 1)
O(Oarr, 1)
-/* backend-only */
+
+/* all below this point are backend-only */
O(Ocjmp, 1) /* conditional jump */
O(Oset, 1) /* store to var */
O(Osllen, 1) /* size of slice */
@@ -72,3 +73,18 @@
O(Ofmul, 1)
O(Ofdiv, 1)
O(Ofneg, 1)
+
+/* floating point comparisons */
+O(Ofeq, 1)
+O(Ofne, 1)
+O(Ofgt, 1)
+O(Ofge, 1)
+O(Oflt, 1)
+O(Ofle, 1)
+/* unsigned comparisons */
+O(Oueq, 1)
+O(Oune, 1)
+O(Ougt, 1)
+O(Ouge, 1)
+O(Oult, 1)
+O(Oule, 1)