Open llvmbot opened 4 years ago
At the IR level, I'd be happy to say that arithmetic on unnormal/pseudo-denormal long double produces poison, sure. Which would imply that the arithmetic is UB at the C level. It simplifies our reasoning without affecting any legitimate use cases. Someone would need to write that up in LangRef, though.
For double-double, yes, it's sort of on its way out, but people who are using it care that it doesn't break in weird ways.
2) high and low parts of ppc_fp128 computed at compile-time are interchanged -- I remember seeing a discussion of it somewhere but I cannot find it right now;
I've searched the bugzilla a little bit more and still cannot find it. Filed as bug 45137.
clang doesn't support decimal floating-point formats. For an example of potential future problems please see https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94035#c5 .
x86 extended precision format (x86_fp80): gcc devs seems to consider pseudo-denormals (and other pseudo-*, unnormals etc.) as trap representations -- please see https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94035#c2 .
IBM extended double (double-double) (ppc_fp128): affected but please see what gcc devs say -- https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94035#c4 .
attribute((noipa,optnone)) // imagine it in a separate TU static long double opaque(long double d) { return d; }
int main() { union { long double d; unsigned long l[2]; } x = {opaque(-(long double)-1)};
if (x.d == 1)
printf("%016lx %016lx\n", x.l[0], x.l[1]);
printf("%016lx %016lx\n", x.l[0], x.l[1]);
For comparison:
Here, x has long double value 1. which is represented as the pair (1., -0.) of ordinary doubles, the constant 1 in the if
is converted to the pair (1., 0.). They are the same value (and are necessarily equal) but have different (non-trap) representations.
There are 3 issues here:
1) the sign of the low part of -(long double)-1 differs from gcc -- AIUI both variants are fine so not sure if anybody cares; 2) high and low parts of ppc_fp128 computed at compile-time are interchanged -- I remember seeing a discussion of it somewhere but I cannot find it right now; 3) after we swap high and low parts, the low part computed at compile-time (0000000000000000, i.e. 0.) differs from run-time (8000000000000000, i.e. -0.) -- that's what this PR is about.
This is controlled by impliesEquivalanceIfTrue in llvm/lib/Transforms/Scalar/GVN.cpp .
I'm not exactly sure. I would expect IBM double-double and IEEE 754 decimal floating-point formats to exhibit the same behavior. But I haven't checked this, plus I'm not sure about their support in LLVM.
I guess this is specifically an issue with x87 long double? I'm pretty sure that for all IEEE float formats, given two non-zero, non-NaN values, x==y implies that x and y are bit-wise identical.
Extended Description
The problem happens when:
Example with a pseudo-denormal in long double:
The value 0x1p-16382l admits two representations:
So both
0
and1
forpy[8]
are fine but the testcase should print the same value both times, i.e. the representation of y should be stable.DR 260 Q1 allows for unstable representation but IMO this is wrong.
gcc bug -- https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94035