aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRuss Cox <rsc@golang.org>2012-01-26 16:23:29 -0500
committerRuss Cox <rsc@golang.org>2012-01-26 16:23:29 -0500
commit109a9763550aac3071e30f6e13cb5ec1172aa017 (patch)
tree160a41b2932fe754262f6de80f2f3212a104d229
parent29dbd988b83e3cb43ca034916e52d030f150c7e1 (diff)
downloadgo-109a9763550aac3071e30f6e13cb5ec1172aa017.tar.gz
go-109a9763550aac3071e30f6e13cb5ec1172aa017.zip
6c, 8c: make floating point code NaN-safe
R=ken2 CC=golang-dev https://golang.org/cl/5569071
-rw-r--r--src/cmd/6c/cgen.c48
-rw-r--r--src/cmd/8c/cgen.c35
2 files changed, 79 insertions, 4 deletions
diff --git a/src/cmd/6c/cgen.c b/src/cmd/6c/cgen.c
index 7f717dcbb4..71822586c4 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 7f02bd96ef..869d31ace4 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) {