diff --git a/src/cmd/6c/cgen.c b/src/cmd/6c/cgen.c index 7f717dcbb4c..71822586c4c 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) { diff --git a/src/cmd/8c/cgen.c b/src/cmd/8c/cgen.c index 7f02bd96efd..869d31ace49 100644 --- a/src/cmd/8c/cgen.c +++ b/src/cmd/8c/cgen.c @@ -1221,7 +1221,7 @@ void boolgen(Node *n, int true, Node *nn) { int o; - Prog *p1, *p2; + Prog *p1, *p2, *p3; Node *l, *r, nod, nod1; int32 curs; @@ -1346,6 +1346,15 @@ boolgen(Node *n, int true, Node *nn) cgen64(n, Z); goto com; } + 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) { @@ -1378,6 +1387,30 @@ boolgen(Node *n, int true, Node *nn) } else fgopcode(o, l, &fregnode0, 0, 1); } + 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; + } goto com; } if(l->op == OCONST) {