]> Cypherpunks repositories - gostls13.git/commitdiff
6c, 8c: make floating point code NaN-safe
authorRuss Cox <rsc@golang.org>
Thu, 26 Jan 2012 21:23:29 +0000 (16:23 -0500)
committerRuss Cox <rsc@golang.org>
Thu, 26 Jan 2012 21:23:29 +0000 (16:23 -0500)
R=ken2
CC=golang-dev
https://golang.org/cl/5569071

src/cmd/6c/cgen.c
src/cmd/8c/cgen.c

index 7f717dcbb4cb10e1c976cdbdd72f933c5c62f3e5..71822586c4c7ba06d3a04567652f2f6336898ea5 100644 (file)
@@ -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) {
index 7f02bd96efd3fd848e1a3c97747bbf8fce602b60..869d31ace49a4a305b29c78a591fa442ee7c06a9 100644 (file)
@@ -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) {