aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Biener <rguenther@suse.de>2024-07-21 11:56:07 +0200
committerRichard Biener <rguenth@gcc.gnu.org>2024-08-01 12:27:53 +0200
commited03af4ef3b9ad0bd3b7c5c678c02253e5cb9e0f (patch)
tree7007ccdff6659e84a47c466050a39515caa8b4d9
parentc71646436a55afdd36948d7e7292b3bd5de04e1a (diff)
downloadgcc-ed03af4ef3b9ad0bd3b7c5c678c02253e5cb9e0f.zip
gcc-ed03af4ef3b9ad0bd3b7c5c678c02253e5cb9e0f.tar.gz
gcc-ed03af4ef3b9ad0bd3b7c5c678c02253e5cb9e0f.tar.bz2
tree-optimization/114659 - VN and FP to int punning
The following addresses another case where x87 FP loads mangle the bit representation and thus are not suitable for a representative in other types. VN was value-numbering a later integer load of 'x' as the same as a former float load of 'x'. We can use the new TARGET_MODE_CAN_TRANSFER_BITS hook to identify problematic modes and enforce strict compatibility for those in the reference comparison, improving the handling of modes with padding in visit_reference_op_load. PR tree-optimization/114659 * tree-ssa-sccvn.cc (visit_reference_op_load): Do not prevent punning from modes with padding here, but ... (vn_reference_eq): ... ensure this here, also honoring types with modes that cannot act as bit container. * gcc.target/i386/pr114659.c: New testcase.
-rw-r--r--gcc/testsuite/gcc.target/i386/pr114659.c62
-rw-r--r--gcc/tree-ssa-sccvn.cc11
2 files changed, 66 insertions, 7 deletions
diff --git a/gcc/testsuite/gcc.target/i386/pr114659.c b/gcc/testsuite/gcc.target/i386/pr114659.c
new file mode 100644
index 0000000..e1e24d5
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr114659.c
@@ -0,0 +1,62 @@
+/* { dg-do run } */
+/* { dg-options "-O2" } */
+
+int
+my_totalorderf (float const *x, float const *y)
+{
+ int xs = __builtin_signbit (*x);
+ int ys = __builtin_signbit (*y);
+ if (!xs != !ys)
+ return xs;
+
+ int xn = __builtin_isnan (*x);
+ int yn = __builtin_isnan (*y);
+ if (!xn != !yn)
+ return !xn == !xs;
+ if (!xn)
+ return *x <= *y;
+
+ unsigned int extended_sign = -!!xs;
+ union { unsigned int i; float f; } xu = {0}, yu = {0};
+ __builtin_memcpy (&xu.f, x, sizeof (float));
+ __builtin_memcpy (&yu.f, y, sizeof (float));
+ return (xu.i ^ extended_sign) <= (yu.i ^ extended_sign);
+}
+
+static float
+positive_NaNf ()
+{
+ float volatile nan = 0.0f / 0.0f;
+ return (__builtin_signbit (nan) ? - nan : nan);
+}
+
+typedef union { float value; unsigned int word[1]; } memory_float;
+
+static memory_float
+construct_memory_SNaNf (float quiet_value)
+{
+ memory_float m;
+ m.value = quiet_value;
+ m.word[0] ^= (unsigned int) 1 << 22;
+ m.word[0] |= (unsigned int) 1;
+ return m;
+}
+
+memory_float x[7] =
+ {
+ { 0 },
+ { 1e-5 },
+ { 1 },
+ { 1e37 },
+ { 1.0f / 0.0f },
+ };
+
+int
+main ()
+{
+ x[5] = construct_memory_SNaNf (positive_NaNf ());
+ x[6] = (memory_float) { positive_NaNf () };
+ if (! my_totalorderf (&x[5].value, &x[6].value))
+ __builtin_abort ();
+ return 0;
+}
diff --git a/gcc/tree-ssa-sccvn.cc b/gcc/tree-ssa-sccvn.cc
index dc377fa..0639ba4 100644
--- a/gcc/tree-ssa-sccvn.cc
+++ b/gcc/tree-ssa-sccvn.cc
@@ -837,6 +837,9 @@ vn_reference_eq (const_vn_reference_t const vr1, const_vn_reference_t const vr2)
TYPE_VECTOR_SUBPARTS (vr2->type)))
return false;
}
+ else if (TYPE_MODE (vr1->type) != TYPE_MODE (vr2->type)
+ && !mode_can_transfer_bits (TYPE_MODE (vr1->type)))
+ return false;
i = 0;
j = 0;
@@ -5814,13 +5817,7 @@ visit_reference_op_load (tree lhs, tree op, gimple *stmt)
if (result
&& !useless_type_conversion_p (TREE_TYPE (result), TREE_TYPE (op)))
{
- /* Avoid the type punning in case the result mode has padding where
- the op we lookup has not. */
- if (TYPE_MODE (TREE_TYPE (result)) != BLKmode
- && maybe_lt (GET_MODE_PRECISION (TYPE_MODE (TREE_TYPE (result))),
- GET_MODE_PRECISION (TYPE_MODE (TREE_TYPE (op)))))
- result = NULL_TREE;
- else if (CONSTANT_CLASS_P (result))
+ if (CONSTANT_CLASS_P (result))
result = const_unop (VIEW_CONVERT_EXPR, TREE_TYPE (op), result);
else
{