1
0
mirror of https://github.com/golang/go synced 2024-11-21 23:04:39 -07:00

6c, 8c: make floating point code NaN-safe

R=ken2
CC=golang-dev
https://golang.org/cl/5569071
This commit is contained in:
Russ Cox 2012-01-26 16:23:29 -05:00
parent 29dbd988b8
commit 109a976355
2 changed files with 79 additions and 4 deletions

View 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) {

View 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) {