[Bug libgcc/78759] New: __gcc_qadd could have been "more commutative" when a+c is infinity, but a+c+aa+cc is not
timshen at gcc dot gnu.org
gcc-bugzilla@gcc.gnu.org
Fri Dec 9 22:20:00 GMT 2016
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=78759
Bug ID: 78759
Summary: __gcc_qadd could have been "more commutative" when a+c
is infinity, but a+c+aa+cc is not
Product: gcc
Version: 7.0
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: libgcc
Assignee: unassigned at gcc dot gnu.org
Reporter: timshen at gcc dot gnu.org
Target Milestone: ---
#include <cstdio>
#include <cstdint>
#include <cstring>
#include <cfenv>
int main() {
static_assert(sizeof(long double) == 16, "");
uint64_t raw_input[4] = { 0x7c90000000000000ull, 0, 0x7fefffffffffffffull,
0xf950000000000000ull, };
long double input[2];
memcpy(&input[0], &raw_input[0], sizeof(input));
long double result = input[0] + input[1];
uint64_t output[2];
memcpy(output, &result, sizeof(result));
printf("%lx %lx\n", output[0], output[1]);
return 0;
}
The code above prints:
7ff0000000000000
0
Which stands for inifinity. However, if the addends are exchanged:
- uint64_t raw_input[4] = { 0x7c90000000000000ull, 0, 0x7fefffffffffffffull,
0xf950000000000000ull, };
+ uint64_t raw_input[4] = { 0x7fefffffffffffffull, 0xf950000000000000ull,
0x7c90000000000000ull, 0, };
the result is finite:
7fefffffffffffff
7c8fffffffffffff
Proof of concept fix:
diff --git a/libgcc/config/rs6000/ibm-ldouble.c
b/libgcc/config/rs6000/ibm-ldouble.c
index 3116cf4..d7b5a92 100644
--- a/libgcc/config/rs6000/ibm-ldouble.c
+++ b/libgcc/config/rs6000/ibm-ldouble.c
@@ -118,7 +118,10 @@ __gcc_qadd (double a, double aa, double c, double cc)
{
if (fabs (z) != inf())
return z;
- z = cc + aa + c + a;
+ if (fabs(a) > fabs(c))
+ z = cc + aa + c + a;
+ else
+ z = cc + aa + a + c;
if (nonfinite (z))
return z;
xh = z; /* Will always be DBL_MAX. */
More information about the Gcc-bugs
mailing list