This was exposed by the new prange PTA code, but it does show up in trunk, and back as far as GCC 13.

GORI aggressively recomputes values when the inputs have changed on conditi0nal branches.  It avoids PHIS and statements with side effects, but pretty much tries everything else.  THis is too agressive as the following test case shows:

int foo (int x)
{
 int y =  __builtin_constant_p (x);
 if (y)
   isconst (y, x);
  else
   nonconst (y, x);

 if (x == 24)
   {
     /* Y should have the same value as earlier. */
     if (y)
       isconst (y, x);
     else
       nonconst (y, x);
   }
}

y evaluates to [0, 0] as x is not a constant.  However, in the conditional branch x is known to be 24, and GORi recomputes y using this values, and since [24, 24] is a constant, decides y is [1, 1] in this block and promptly folds the condition and leaves a call to isconst (1,24)  instead of the correct nonconst (0, 24)

This hasn't really been much of a problem because for most non range-op statetmets, changing the inputs is not likely to change the resulting range.  Given that, its probably a waste of time to even try.

This patch adds a fields to the gimple_range_op_handler class wihch indicates whether the range_operator is recomputable or not, and defaults them to yes.  GORI then checks this method instead to determine if recomputation should be attempted.

Finally, the flag is set to false for the  __builtin_constant_p handler to avoid recomputing this.  All the rest are OK I think.

Bootstraps on x86_64-pc-linux-gnu with no regressions.  OK for trunk?

Andrew

From 5125458dabfe1309433a191cef797d194227eff3 Mon Sep 17 00:00:00 2001
From: Andrew MacLeod <[email protected]>
Date: Thu, 18 Dec 2025 10:56:44 -0500
Subject: [PATCH] VRP should only recompute known statements.

GORI should only recompute ranges for range-op statements that are known
to be safe.   Disable it for builtin_constant_p.

	PR tree-optimization/123205
	gcc/
	* gimple-range-gori.cc (gori_compute::may_recompute_p): Only
	recompute range-op statements.
	* gimple-range-op.cc (gimple_range_op_handler): Default
	recomputation to true.
	(maybe_builtin_call): CFN_BUILT_IN_CONSTANT_P should not be
	recomputable.
	* gimple-range-op.h (recomputable_p): New.
	(recomputable_p): New.

	gcc/testsuite/
	* gcc.dg/pr123205.c: New.
---
 gcc/gimple-range-gori.cc        |  5 +++--
 gcc/gimple-range-op.cc          |  4 ++++
 gcc/gimple-range-op.h           |  2 ++
 gcc/testsuite/gcc.dg/pr123205.c | 23 +++++++++++++++++++++++
 4 files changed, 32 insertions(+), 2 deletions(-)
 create mode 100644 gcc/testsuite/gcc.dg/pr123205.c

diff --git a/gcc/gimple-range-gori.cc b/gcc/gimple-range-gori.cc
index 9761abffc00..91fd4784ce8 100644
--- a/gcc/gimple-range-gori.cc
+++ b/gcc/gimple-range-gori.cc
@@ -1325,9 +1325,10 @@ gori_compute::may_recompute_p (tree name, basic_block bb, int depth)
   if (!dep1)
     return false;
 
-  // Don't recalculate PHIs or statements with side_effects.
+  // Only recalculate range-op statements that are recomputable.
   gimple *s = SSA_NAME_DEF_STMT (name);
-  if (is_a<gphi *> (s) || gimple_has_side_effects (s))
+  gimple_range_op_handler handler (s);
+  if (!handler || !handler.recomputable_p ())
     return false;
 
   if (!dep2)
diff --git a/gcc/gimple-range-op.cc b/gcc/gimple-range-op.cc
index 3a22606180b..e563d054135 100644
--- a/gcc/gimple-range-op.cc
+++ b/gcc/gimple-range-op.cc
@@ -125,6 +125,8 @@ gimple_range_op_handler::gimple_range_op_handler (gimple *s)
   m_stmt = s;
   m_op1 = NULL_TREE;
   m_op2 = NULL_TREE;
+  // Recomputation defaults to TRUE.
+  m_recomputable = true;
 
   if (oper)
     switch (gimple_code (m_stmt))
@@ -1413,6 +1415,8 @@ gimple_range_op_handler::maybe_builtin_call ()
 	m_operator = &op_cfn_constant_p;
       else if (frange::supports_p (TREE_TYPE (m_op1)))
 	m_operator = &op_cfn_constant_float_p;
+      // builtin_constant_p should not be recomputed.  See PR 123205.
+      m_recomputable = false;
       break;
 
     CASE_FLT_FN (CFN_BUILT_IN_SIGNBIT):
diff --git a/gcc/gimple-range-op.h b/gcc/gimple-range-op.h
index 239740d18e5..2bdacd5a80b 100644
--- a/gcc/gimple-range-op.h
+++ b/gcc/gimple-range-op.h
@@ -39,11 +39,13 @@ public:
 		 relation_trio = TRIO_VARYING);
   bool calc_op2 (vrange &r, const vrange &lhs_range, const vrange &op1_range,
 		 relation_trio = TRIO_VARYING);
+  inline bool recomputable_p () { return m_recomputable; }
 private:
   void maybe_builtin_call ();
   void maybe_non_standard ();
   gimple *m_stmt;
   tree m_op1, m_op2;
+  bool m_recomputable;
 };
 
 // Given stmt S, fill VEC, up to VEC_SIZE elements, with relevant ssa-names
diff --git a/gcc/testsuite/gcc.dg/pr123205.c b/gcc/testsuite/gcc.dg/pr123205.c
new file mode 100644
index 00000000000..80d2ca0fc65
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr123205.c
@@ -0,0 +1,23 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+void isconst (int, int);
+void nonconst (int, int);
+
+int foo (int x)
+{
+ int y =  __builtin_constant_p (x);
+ if (y)
+   isconst (y, x);
+  else
+   nonconst (y, x);
+
+ if (x == 24)
+   {
+     /* Y should have the same value as earlier. */
+     if (y)
+       isconst (y, x);
+     else
+       nonconst (y, x);
+   }
+}
+/* { dg-final { scan-tree-dump-not "isconst"  "optimized" } } */
-- 
2.45.0

Reply via email to