This patch fixes PR tree-optimization/127544 by tightening the conditions
under which gimple_expand_builtin_pow is allowed to convert pow(x,0.5)
into sqrt(x). Specifically, pow(-Inf,0.5) should return +Inf (by POSIX)
but sqrt(-Inf) returns NaN, so this transformation is (also) unsafe in
the presence of -Inf. The patch also fixes an instance of using
REAL_VALUE_ISSIGNALING_NAN when the intended behavior is to check
tree_expr_maybe_signaling_nan_p.
I'm also working on two follow-up patches... Obviously it should be
possible to evaluate pow(-Inf,0.5) at compile-time (with -fno-math-errno)
and in theory the new logic in this patch should enable us to optimize:
double foo(int x) { return __builtin_pow((double)x,0.5); }
into sqrt, as conversion of an integer to double can't produce either
an infinity or a negative zero, but unfortunately the tree_expr_maybe_*
predicates aren't quite clever enough yet.
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-10-05 Roger Sayle <[email protected]>
gcc/ChangeLog
PR tree-optimization/127544
PR tree-optimization/126562
* tree-ssa-math-opts.cc (gimple_expand_builtin_pow): Use
tree_expr_maybe_signaling_nan_p insted of REAL_VALUE_ISSIGNALING_NAN
to check whether an operand may be a signaling NaN. pow(x,0.5)
also can't be transformed to sqrt(x) if x may be -Inf.
gcc/testsuite/ChangeLog
PR tree-optimization/127544
PR tree-optimization/126562
* gcc.dg/pr127544-1.c: New test case.
Thanks in advance,
Roger
--
diff --git a/gcc/tree-ssa-math-opts.cc b/gcc/tree-ssa-math-opts.cc
index 70ac17c9e2f..aa6820cf0af 100644
--- a/gcc/tree-ssa-math-opts.cc
+++ b/gcc/tree-ssa-math-opts.cc
@@ -2020,15 +2020,13 @@ gimple_expand_builtin_pow (gimple_stmt_iterator *gsi,
location_t loc,
if (TREE_CODE (arg1) != REAL_CST)
return NULL_TREE;
- /* Don't perform the operation if flag_signaling_nans is on
- and the operand is a signaling NaN. */
- if (HONOR_SNANS (TYPE_MODE (TREE_TYPE (arg1)))
- && ((TREE_CODE (arg0) == REAL_CST
- && REAL_VALUE_ISSIGNALING_NAN (TREE_REAL_CST (arg0)))
- || REAL_VALUE_ISSIGNALING_NAN (TREE_REAL_CST (arg1))))
+ if (flag_errno_math)
return NULL_TREE;
- if (flag_errno_math)
+ /* Don't perform the operation if flag_signaling_nans is on
+ and either operand is a signaling NaN. */
+ if (tree_expr_maybe_signaling_nan_p (arg0)
+ || tree_expr_maybe_signaling_nan_p (arg1))
return NULL_TREE;
/* If the exponent is equivalent to an integer, expand to an optimal
@@ -2050,12 +2048,15 @@ gimple_expand_builtin_pow (gimple_stmt_iterator *gsi,
location_t loc,
mode = TYPE_MODE (type);
sqrtfn = mathfn_built_in (type, BUILT_IN_SQRT);
- /* Optimize pow(x,0.5) = sqrt(x). This replacement is always safe
- unless signed zeros must be maintained. pow(-0,0.5) = +0, while
- sqrt(-0) = -0. */
+ /* Optimize pow(x,0.5) = sqrt(x). This replacement is safe
+ except for signed zeros and negative infinity.
+ pow(-0,0.5) = +0, while sqrt(-0) = -0.
+ pow(-Inf,0.5) = +Inf, while sqrt(-Inf) is NaN. */
if (sqrtfn
&& real_equal (&c, &dconsthalf)
- && !HONOR_SIGNED_ZEROS (mode))
+ && !tree_expr_maybe_real_minus_zero_p (arg0)
+ && (!tree_expr_maybe_infinite_p (arg0)
+ || tree_expr_nonnegative_p (arg0)))
return build_and_insert_call (gsi, loc, sqrtfn, arg0);
hw_sqrt_exists = optab_handler (sqrt_optab, mode) != CODE_FOR_nothing;
diff --git a/gcc/testsuite/gcc.dg/pr127544-1.c
b/gcc/testsuite/gcc.dg/pr127544-1.c
new file mode 100644
index 00000000000..1493574007e
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr127544-1.c
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fno-math-errno -fno-signed-zeros -fdump-tree-optimized"
} */
+
+double foo()
+{
+ return __builtin_pow(-__builtin_inf(),0.5);
+}
+
+double bar(double x)
+{
+ return __builtin_pow(x,0.5);
+}
+
+/* { dg-final { scan-tree-dump-not "sqrt" "optimized" } } */