[PATCH] PR middle-end/126775: ICE optimizing (T)0.0 - x with -ffinite-math-only
"Roger Sayle" <[email protected]>
| Newsgroups | gmane.comp.gcc.patches |
|---|---|
| Message-ID | <[email protected]> |
This patch fixes PR middle-end/126775, an ICE caused by my recent change
to match.pd around tweaking the conditions under which 0.0 - x can
safely be transformed into -x. Unfortunately, that change assumed
that real_zerop@0 implies that TREE_CODE(@0) == REAL_CST. Alas things
aren't that simple, so this fix introduces a new real_negzerop predicate
that in addition to REAL_CST also handles VECTOR_CST and COMPLEX_CST,
and most importantly fails gracefully on TREE_CODEs that it isn't
expecting.
This patch has been tested on x86_64-pc-linux-gnu with make bootstrap
and make -k check, both with and without --target_board=unix{-m32}
with no new failures. Ok for mainline?
2026-08-19 Roger Sayle <[email protected]>
gcc/ChangeLog
PR middle-end/126775
* match.pd (0.0 - x -> -x): Use new real_negzerop function.
* tree.cc (real_negzerop): New predicate function to test if
a tree expression is -0.0 or equivalent (like real_zerop).
* tree.h (real_negzerop): Prototype here.
gcc/testsuite/ChangeLog
PR middle-end/126775
* gcc.dg/pr126775.c: New test case.
Thanks again, and apologies for any inconvenice.
Roger
--
patchrn4.txt
(text/plain, 2.1 KB)
diff --git a/gcc/match.pd b/gcc/match.pd
index 1ea46fd1726..5888a2f167f 100644
--- a/gcc/match.pd
+++ b/gcc/match.pd
@@ -6014,7 +6014,7 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
&& (!HONOR_SIGNED_ZEROS (type)
|| tree_expr_nonzero_p (@1)
|| (!flag_rounding_math
- && REAL_VALUE_MINUS_ZERO (TREE_REAL_CST (@0)))))
+ && real_negzerop (@0))))
(negate @1)))
/* Transform x * -1 into -x. */
diff --git a/gcc/testsuite/gcc.dg/pr126775.c b/gcc/testsuite/gcc.dg/pr126775.c
new file mode 100644
index 00000000000..12eb8078b15
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr126775.c
@@ -0,0 +1,8 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -ffinite-math-only" } */
+
+_Complex float foo(_Complex float x)
+{
+ _Complex float negzero = -0.0f + -0.0fi;
+ return negzero - x;
+}
diff --git a/gcc/tree.cc b/gcc/tree.cc
index c8aa42b3e10..8bc5fb52a27 100644
--- a/gcc/tree.cc
+++ b/gcc/tree.cc
@@ -3326,6 +3326,29 @@ real_zerop (const_tree expr)
}
}
+/* Return true if EXPR is the real constant negative zero. */
+
+bool
+real_negzerop (const_tree expr)
+{
+ STRIP_ANY_LOCATION_WRAPPER (expr);
+
+ if (TREE_CODE (expr) == VECTOR_CST)
+ {
+ expr = uniform_vector_p (expr);
+ if (!expr)
+ return false;
+ }
+
+ if (TREE_CODE (expr) == COMPLEX_CST)
+ return real_negzerop (TREE_REALPART (expr))
+ && real_negzerop (TREE_IMAGPART (expr));
+
+ return TREE_CODE (expr) == REAL_CST
+ && REAL_VALUE_MINUS_ZERO (TREE_REAL_CST (expr))
+ && !(DECIMAL_FLOAT_MODE_P (TYPE_MODE (TREE_TYPE (expr))));
+}
+
/* Return true if EXPR is the real constant one in real or complex form.
Trailing zeroes matter for decimal float constants, so don't return
true for them.
diff --git a/gcc/tree.h b/gcc/tree.h
index 1ccbf848d9b..c7f394644dd 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -5688,6 +5688,9 @@ extern tree decl_type_context (const_tree);
/* Return true if EXPR is the real constant zero. */
extern bool real_zerop (const_tree);
+/* Return true if EXPR is the real constant negative zero. */
+extern bool real_negzerop (const_tree);
+
/* Initialize the iterator I with arguments from function FNDECL */
inline void