commit eebbb69291369c3188064d6c3cb779bc47e09bbe
parent a940cc808e12659ff307294492ec6152c67fb471
Author: Quentin Carbonneaux <quentin.carbonneaux@yale.edu>
Date: Tue, 21 Feb 2017 16:45:20 -0500
do not err on address comparisons
While I was at it I also refreshed some bits
in the instruction selection.
Diffstat:
M | fold.c | | | 15 | ++++++++++----- |
M | isel.c | | | 91 | +++++++++++++++++++++++++++++++++++++++---------------------------------------- |
2 files changed, 55 insertions(+), 51 deletions(-)
diff --git a/fold.c b/fold.c
@@ -323,7 +323,7 @@ fold(Fn *fn)
/* boring folding code */
-static void
+static int
foldint(Con *res, int op, int w, Con *cl, Con *cr)
{
union {
@@ -357,8 +357,11 @@ foldint(Con *res, int op, int w, Con *cl, Con *cr)
else if (cr->type == CAddr)
err("undefined substraction (num - addr)");
}
- else if (cl->type == CAddr || cr->type == CAddr)
+ else if (cl->type == CAddr || cr->type == CAddr) {
+ if (Ocmpl <= op && op <= Ocmpl1)
+ return 1;
err("invalid address operand for '%s'", opdesc[op].name);
+ }
switch (op) {
case Oadd: x = l.u + r.u; break;
case Osub: x = l.u - r.u; break;
@@ -440,6 +443,7 @@ foldint(Con *res, int op, int w, Con *cl, Con *cr)
res->bits.i = x;
if (lab)
strcpy(res->label, lab);
+ return 0;
}
static void
@@ -492,9 +496,10 @@ opfold(int op, int cls, Con *cl, Con *cr, Fn *fn)
if ((op == Odiv || op == Oudiv
|| op == Orem || op == Ourem) && czero(cr, KWIDE(cls)))
err("null divisor in '%s'", opdesc[op].name);
- if (cls == Kw || cls == Kl)
- foldint(&c, op, cls == Kl, cl, cr);
- else
+ if (cls == Kw || cls == Kl) {
+ if (foldint(&c, op, cls == Kl, cl, cr))
+ return Bot;
+ } else
foldflt(&c, op, cls == Kd, cl, cr);
if (c.type == CBits)
nc = getcon(c.bits.i, fn).val;
diff --git a/isel.c b/isel.c
@@ -47,30 +47,24 @@ fcmptoi(int fc)
static int
iscmp(int op, int *pk, int *pc)
{
- int k, c;
-
if (Ocmpw <= op && op <= Ocmpw1) {
- c = op - Ocmpw;
- k = Kw;
+ *pc = op - Ocmpw;
+ *pk = Kw;
}
else if (Ocmpl <= op && op <= Ocmpl1) {
- c = op - Ocmpl;
- k = Kl;
+ *pc = op - Ocmpl;
+ *pk = Kl;
}
else if (Ocmps <= op && op <= Ocmps1) {
- c = fcmptoi(op - Ocmps);
- k = Ks;
+ *pc = fcmptoi(op - Ocmps);
+ *pk = Ks;
}
else if (Ocmpd <= op && op <= Ocmpd1) {
- c = fcmptoi(op - Ocmpd);
- k = Kd;
+ *pc = fcmptoi(op - Ocmpd);
+ *pk = Kd;
}
else
return 0;
- if (pk)
- *pk = k;
- if (pc)
- *pc = c;
return 1;
}
@@ -197,21 +191,28 @@ seladdr(Ref *r, ANum *an, Fn *fn)
}
}
-static void
+static int
selcmp(Ref arg[2], int k, Fn *fn)
{
+ int swap;
Ref r, *iarg;
- if (rtype(arg[0]) == RCon) {
+ swap = rtype(arg[0]) == RCon;
+ if (swap) {
r = arg[1];
arg[1] = arg[0];
arg[0] = r;
}
- assert(rtype(arg[0]) != RCon);
emit(Oxcmp, k, R, arg[1], arg[0]);
- iarg = curi->arg; /* fixarg() can change curi */
+ iarg = curi->arg;
+ if (rtype(arg[0]) == RCon) {
+ assert(k == Kl);
+ iarg[1] = newtmp("isel", k, fn);
+ emit(Ocopy, k, iarg[1], arg[0], R);
+ }
fixarg(&iarg[0], k, 0, fn);
fixarg(&iarg[1], k, 0, fn);
+ return swap;
}
static void
@@ -220,7 +221,7 @@ sel(Ins i, ANum *an, Fn *fn)
Ref r0, r1, *iarg;
int x, k, kc;
int64_t sz;
- Ins *i0;
+ Ins *i0, *i1;
if (rtype(i.to) == RTmp)
if (!isreg(i.to) && !isreg(i.arg[0]) && !isreg(i.arg[1]))
@@ -349,10 +350,10 @@ Emit:
if (isload(i.op))
goto case_Oload;
if (iscmp(i.op, &kc, &x)) {
- if (rtype(i.arg[0]) == RCon)
- x = icmpop(x);
emit(Oxset+x, k, i.to, R, R);
- selcmp(i.arg, kc, fn);
+ i1 = curi;
+ if (selcmp(i.arg, kc, fn))
+ i1->op = Oxset + icmpop(x);
break;
}
die("unknown instruction %s", opdesc[i.op].name);
@@ -400,30 +401,31 @@ seljmp(Blk *b, Fn *fn)
return;
}
fi = flagi(b->ins, &b->ins[b->nins]);
- if (fi && req(fi->to, r)) {
- if (iscmp(fi->op, &k, &c)) {
- if (rtype(fi->arg[0]) == RCon)
+ if (!fi || !req(fi->to, r)) {
+ selcmp((Ref[2]){r, CON_Z}, Kw, fn); /* todo, long jnz */
+ b->jmp.type = Jxjc + ICne;
+ }
+ else if (iscmp(fi->op, &k, &c)) {
+ if (t->nuse == 1) {
+ if (selcmp(fi->arg, k, fn))
c = icmpop(c);
- b->jmp.type = Jxjc + c;
- if (t->nuse == 1) {
- selcmp(fi->arg, k, fn);
- *fi = (Ins){.op = Onop};
- }
- return;
+ *fi = (Ins){.op = Onop};
}
- if (fi->op == Oand && t->nuse == 1
- && (rtype(fi->arg[0]) == RTmp ||
- rtype(fi->arg[1]) == RTmp)) {
- fi->op = Oxtest;
- fi->to = R;
- b->jmp.type = Jxjc + ICne;
- if (rtype(fi->arg[1]) == RCon) {
- r = fi->arg[1];
- fi->arg[1] = fi->arg[0];
- fi->arg[0] = r;
- }
- return;
+ b->jmp.type = Jxjc + c;
+ }
+ else if (fi->op == Oand && t->nuse == 1
+ && (rtype(fi->arg[0]) == RTmp ||
+ rtype(fi->arg[1]) == RTmp)) {
+ fi->op = Oxtest;
+ fi->to = R;
+ b->jmp.type = Jxjc + ICne;
+ if (rtype(fi->arg[1]) == RCon) {
+ r = fi->arg[1];
+ fi->arg[1] = fi->arg[0];
+ fi->arg[0] = r;
}
+ }
+ else {
/* since flags are not tracked in liveness,
* the result of the flag-setting instruction
* has to be marked as live
@@ -431,10 +433,7 @@ seljmp(Blk *b, Fn *fn)
if (t->nuse == 1)
emit(Ocopy, Kw, R, r, R);
b->jmp.type = Jxjc + ICne;
- return;
}
- selcmp((Ref[2]){r, CON_Z}, Kw, fn); /* todo, add long branch if non-zero */
- b->jmp.type = Jxjc + ICne;
}
static int