diff options
Diffstat (limited to 'src/cmd/6c/cgen.c')
-rw-r--r-- | src/cmd/6c/cgen.c | 48 |
1 files changed, 45 insertions, 3 deletions
diff --git a/src/cmd/6c/cgen.c b/src/cmd/6c/cgen.c index 7f717dcbb..71822586c 100644 --- a/src/cmd/6c/cgen.c +++ b/src/cmd/6c/cgen.c @@ -1237,11 +1237,12 @@ void boolgen(Node *n, int true, Node *nn) { int o; - Prog *p1, *p2; + Prog *p1, *p2, *p3; Node *l, *r, nod, nod1; int32 curs; if(debug['g']) { + print("boolgen %d\n", true); prtree(nn, "boolgen lhs"); prtree(n, "boolgen"); } @@ -1353,6 +1354,15 @@ boolgen(Node *n, int true, Node *nn) case OLO: case OLS: o = n->op; + if(true && typefd[l->type->etype] && (o == OEQ || o == ONE)) { + // Cannot rewrite !(l == r) into l != r with float64; it breaks NaNs. + // Jump around instead. + boolgen(n, 0, Z); + p1 = p; + gbranch(OGOTO); + patch(p1, pc); + goto com; + } if(true) o = comrel[relindex(o)]; if(l->complex >= FNX && r->complex >= FNX) { @@ -1367,6 +1377,10 @@ boolgen(Node *n, int true, Node *nn) break; } if(immconst(l)) { + // NOTE: Reversing the comparison here is wrong + // for floating point ordering comparisons involving NaN, + // but we don't have any of those yet so we don't + // bother worrying about it. o = invrel[relindex(o)]; /* bad, 13 is address of external that becomes constant */ if(r->addable < INDEXED || r->addable == 13) { @@ -1388,10 +1402,11 @@ boolgen(Node *n, int true, Node *nn) cgen(r, &nod1); gopcode(o, l->type, &nod, &nod1); regfree(&nod1); - } else + } else { gopcode(o, l->type, &nod, r); + } regfree(&nod); - goto com; + goto fixfloat; } regalloc(&nod, r, nn); cgen(r, &nod); @@ -1406,6 +1421,33 @@ boolgen(Node *n, int true, Node *nn) } else gopcode(o, l->type, l, &nod); regfree(&nod); + fixfloat: + if(typefd[l->type->etype]) { + switch(o) { + case OEQ: + // Already emitted AJEQ; want AJEQ and AJPC. + p1 = p; + gbranch(OGOTO); + p2 = p; + patch(p1, pc); + gins(AJPC, Z, Z); + patch(p2, pc); + break; + + case ONE: + // Already emitted AJNE; want AJNE or AJPS. + p1 = p; + gins(AJPS, Z, Z); + p2 = p; + gbranch(OGOTO); + p3 = p; + patch(p1, pc); + patch(p2, pc); + gbranch(OGOTO); + patch(p3, pc); + break; + } + } com: if(nn != Z) { |