Now that SCEV is calling ranger for values, we need to make sure ranger
doesnt call back into SCEV again or we get infinite loops like this PR.
fold_using_range::range_of_ssa_name_with_loop_info tries to use SCEV
to see if it can refinea PHI result based on loop information. This
patch adds a flag aroudn that call so that if the call into SCEV calls
back into ranger, we won't re-invoke SCEV again.
Bootstraps on x86_64-pc-linux-gnu with npo regressions, and the test now
builds on a riscv64 cross compiler. I think I got the condition on the
testcase right, please fix them if not :-P. Pushed.
Andrew
From 00c16753875ddd9fcc9a6484717a1fc6dc95b691 Mon Sep 17 00:00:00 2001
From: Andrew MacLeod <[email protected]>
Date: Wed, 19 Nov 2025 11:31:16 -0500
Subject: [PATCH] Avoid recursion with SCEV
Ranger should not invoke SCEV if its already in the middle of a SCEV call.
PR tree-optimization/122756
gcc/
* gimple-range-fold.cc (range_of_ssa_name_with_loop_info): Do
not invoke SCEV if already in a SCEV call.
gcc/testsuite/
* gcc.dg/pr122756.c: New.
---
gcc/gimple-range-fold.cc | 15 ++++++++++++---
gcc/testsuite/gcc.dg/pr122756.c | 15 +++++++++++++++
2 files changed, 27 insertions(+), 3 deletions(-)
create mode 100644 gcc/testsuite/gcc.dg/pr122756.c
diff --git a/gcc/gimple-range-fold.cc b/gcc/gimple-range-fold.cc
index 63e114e4d04..bd5e53516b7 100644
--- a/gcc/gimple-range-fold.cc
+++ b/gcc/gimple-range-fold.cc
@@ -1252,11 +1252,15 @@ fold_using_range::range_of_ssa_name_with_loop_info (vrange &r, tree name,
class loop *l, gphi *phi,
fur_source &src)
{
+ static bool in_scev_call = false;
gcc_checking_assert (TREE_CODE (name) == SSA_NAME);
+ // Avoid SCEV callbacks causing infinite recursion.
+ if (in_scev_call)
+ r.set_varying (TREE_TYPE (name));
// SCEV currently invokes get_range_query () for values. If the query
// being passed in is not the same SCEV will use, do not invoke SCEV.
// This can be remove if/when SCEV uses a passed in range-query.
- if (src.query () != get_range_query (cfun))
+ else if (src.query () != get_range_query (cfun))
{
r.set_varying (TREE_TYPE (name));
// Report the msmatch if SRC is not the global query. The cache
@@ -1266,8 +1270,13 @@ fold_using_range::range_of_ssa_name_with_loop_info (vrange &r, tree name,
fprintf (dump_file,
"fold_using-range:: SCEV not invoked due to mismatched queries\n");
}
- else if (!range_of_var_in_loop (r, name, l, phi, src.query ()))
- r.set_varying (TREE_TYPE (name));
+ else
+ {
+ in_scev_call = true;
+ if (!range_of_var_in_loop (r, name, l, phi, src.query ()))
+ r.set_varying (TREE_TYPE (name));
+ in_scev_call = false;
+ }
}
// -----------------------------------------------------------------------
diff --git a/gcc/testsuite/gcc.dg/pr122756.c b/gcc/testsuite/gcc.dg/pr122756.c
new file mode 100644
index 00000000000..62994696ac8
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr122756.c
@@ -0,0 +1,15 @@
+/* { dg-do compile } */
+/* { dg-options "-O3" } */
+/* { dg-additional-options "-march=rv64gcv -mabi=lp64d" { target { rv64 } } } */
+
+long a;
+void b() {
+ unsigned long c, d;
+ for (;; c = d + 2000) {
+ d = c;
+ for (; d < a; d += 2)
+ if (d % 2)
+ for (;;)
+ ;
+ }
+}
--
2.45.0