[gcc r17-3466] PR middle-end/126775: ICE optimizing (T)0.0 - x with -ffinite-math-only
Roger Sayle via Gcc-cvs <[email protected]>
| Newsgroups | gmane.comp.gcc.cvs |
|---|---|
| Message-ID | <[email protected]> |
https://gcc.gnu.org/g:579349b0f12681ffcbfd14eafe6efdc8da67a1f2 commit r17-3466-g579349b0f12681ffcbfd14eafe6efdc8da67a1f2 Author: Roger Sayle <[email protected]> Date: Thu Aug 20 09:31:48 2026 +0100 PR middle-end/126775: ICE optimizing (T)0.0 - x with -ffinite-math-only 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. 2026-08-20 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. Diff: --- gcc/match.pd | 2 +- gcc/testsuite/gcc.dg/pr126775.c | 8 ++++++++ gcc/tree.cc | 23 +++++++++++++++++++++++ gcc/tree.h | 3 +++ 4 files changed, 35 insertions(+), 1 deletion(-) diff --git a/gcc/match.pd b/gcc/match.pd index 0d1a61321d49..51f825ec3279 100644 --- a/gcc/match.pd +++ b/gcc/match.pd @@ -6209,7 +6209,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 000000000000..12eb8078b156 --- /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 52313fbd129f..69a7c7e6d34d 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 e079082a81af..bc6a304631dd 100644 --- a/gcc/tree.h +++ b/gcc/tree.h @@ -5693,6 +5693,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