fold_using_range is provided a range_query object to work on. when all
other options fails when trying to calculate a range, the gimple fold
machinery can be invoked to see if a statement might fold to a constant.
If this object is not the current_range_query (cfun) object, it can
trigger an unexpected call into a different range query.
This is causing problems in ranger_cache which is implemented as a
range_query and expects to complete its query before another one is
invoked. If the query's escape the cache, and go back to the current
range query, this can cause a re-entrance to the cache we don't expect.
This patch simply checks that the current query is th provided query
before invoking gimple fold. This ensures we only get the expected
behaviour.
Bootstrapped on x86_64-pc-linux-gnu with no regressions. pushed.
Andrew
From 6df88a49e162a971f324247b184ddeb76b115ecc Mon Sep 17 00:00:00 2001
From: Andrew MacLeod <[email protected]>
Date: Wed, 17 Jun 2026 16:51:15 -0400
Subject: [PATCH 1/2] Do not invoke a different range query from within
fold_stmt.
fold_using_range works on a specified range_query object. IF this
object is not the current_range_query (cfun) object, do not invoke
the general gimple fold routines as they may call into the current
query.
PR tree-optimization/125854
gcc/
* gimple-range-fold.cc (fold_using_range::fold_stmt): Check if the
range_query matches the current one before invoking fold.
gcc/testsuite/
* g++.dg/pr125854.C: New.
---
gcc/gimple-range-fold.cc | 4 +++-
gcc/testsuite/g++.dg/pr125854.C | 30 ++++++++++++++++++++++++++++++
2 files changed, 33 insertions(+), 1 deletion(-)
create mode 100644 gcc/testsuite/g++.dg/pr125854.C
diff --git a/gcc/gimple-range-fold.cc b/gcc/gimple-range-fold.cc
index bae94dfa44b..50cee517120 100644
--- a/gcc/gimple-range-fold.cc
+++ b/gcc/gimple-range-fold.cc
@@ -757,7 +757,9 @@ fold_using_range::fold_stmt (vrange &r, gimple *s, fur_source &src, tree name)
{
p.set_pt (rhs, true);
}
- else
+ // PR 125854 - Do not attempt to invoke the fold machinery unless this
+ // query is the same as the current query (which fold may invoke).
+ else if (src.query () == get_range_query (cfun))
{
// If we couldn't find anything, try fold.
x_fold_context = { s, src.query () };
diff --git a/gcc/testsuite/g++.dg/pr125854.C b/gcc/testsuite/g++.dg/pr125854.C
new file mode 100644
index 00000000000..d8c38087ac3
--- /dev/null
+++ b/gcc/testsuite/g++.dg/pr125854.C
@@ -0,0 +1,30 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -Wno-stringop-overread -std=c++11" } */
+
+int *__distance___last;
+long move___trans_tmp_9;
+void move(int *__first, int *__result) {
+ move___trans_tmp_9 = __distance___last - __first;
+ if (__builtin_expect(move___trans_tmp_9, true))
+ __builtin_memmove(__result, __first, move___trans_tmp_9);
+}
+struct SmallVectorTemplateCommon {
+ void operator[](long);
+};
+struct SmallVectorTemplateBase : SmallVectorTemplateCommon {};
+void erase(int *CI) { move(CI + 1, CI); }
+struct : SmallVectorTemplateBase {
+} FindInOperandList_Ops;
+int Op, ReassociatePassOptimizeAdd___trans_tmp_1;
+unsigned FindInOperandList(unsigned i) {
+ for (unsigned j = i + 1;;)
+ if (FindInOperandList_Ops[j], Op)
+ return j;
+}
+void ReassociatePassOptimizeAdd() {
+ for (unsigned i;; ++i) {
+ FindInOperandList(i);
+ erase(&ReassociatePassOptimizeAdd___trans_tmp_1 + i);
+ }
+}
+
--
2.45.0