We make some attempts to improve the ranges we pick up from
cond_exprs. We miss the case where its tied to a single ssa-name. ie
_2 = value_3 < 20
_4 = _2 ? 20 : value_3
This is a common idiom for min or max, but it sometimes eludes us for
no good reason.
fold_using_range::condexpr_adjust () attempts to do this for more
complex situations, but misses this trivial one. This patch causes it
to also recognize this case, and adjust the range for value_3 in the
COND_EXPR to reflect the calculated range from the condition.
ie, in this case, it will use the value solved buy GORI for [0,0] =
value_3 < 20, and substitute [20, +INF] for value_3 in the cond_expr.
Bootstrapped on x86_64-pc-linux-gnu with no regressions. Pushed.
Andrew
From 088e19d0938e6453471abd128927fe3622486222 Mon Sep 17 00:00:00 2001
From: Andrew MacLeod <[email protected]>
Date: Fri, 24 Oct 2025 15:09:51 -0400
Subject: [PATCH 1/2] Refine COND_EXPR ranges better.
Recognize COND_EXPRs where there is only one ssa_name used in the
condition as well as one of the fields in the COND_EXPR. ie:
cond = ssa_name < 20
result = cond ? ssa_name : 20
Adjust the range of ssa_name to reflect the conditional value of ssa_name
relative to whether its in the TRUE or FALSE part of the COND_EXPR.
PR tree-optimization/114025
gcc/
* gimple-range-fold.cc (fold_using_range::condexpr_adjust): Handle
the same ssa_name in the condition and the COND_EXPR better.
gcc/testsuite/
* g++.dg/pr114025.C: New.
---
gcc/gimple-range-fold.cc | 11 ++++++++++
gcc/testsuite/g++.dg/pr114025.C | 39 +++++++++++++++++++++++++++++++++
2 files changed, 50 insertions(+)
create mode 100644 gcc/testsuite/g++.dg/pr114025.C
diff --git a/gcc/gimple-range-fold.cc b/gcc/gimple-range-fold.cc
index d18b37b3380..06c645f3d08 100644
--- a/gcc/gimple-range-fold.cc
+++ b/gcc/gimple-range-fold.cc
@@ -1187,6 +1187,17 @@ fold_using_range::condexpr_adjust (vrange &r1, vrange &r2, gimple *, tree cond,
ssa2, src))
r2.intersect (tmp2);
}
+ // If the same name is specified in the condition and COND_EXPR,
+ // combine the calculated condition range and the other one provided. ie:
+ // c_1 = b_2 < 10
+ // f_3 = c_1 ? 0 : b_2
+ // With b_2 providing the false value, the value of f_3 will be
+ // either 0 UNION (0 = b_2 < 10), which is [-INF, 9].
+ // COND_EXPR is
+ if (ssa1 && cond_name == ssa1)
+ r1 = cond_true;
+ else if (ssa2 && cond_name == ssa2)
+ r2 = cond_false;
return true;
}
diff --git a/gcc/testsuite/g++.dg/pr114025.C b/gcc/testsuite/g++.dg/pr114025.C
new file mode 100644
index 00000000000..61bb8f151fc
--- /dev/null
+++ b/gcc/testsuite/g++.dg/pr114025.C
@@ -0,0 +1,39 @@
+/* { dg-do compile } */
+/* { dg-options " -O3 -std=gnu++17 -ffinite-math-only -fdump-tree-optimized" } */
+
+#include <algorithm>
+#include <stdexcept>
+
+#define AINLINE
+
+class TestClass
+{
+public:
+ AINLINE void SetValue(float value);
+
+private:
+ float m_Value;
+};
+
+AINLINE
+void TestClass::SetValue(float value)
+{
+ if (value >= 0.0f && value <= 100.0f) {
+ m_Value = value;
+ }
+ else {
+ throw std::out_of_range("Value must be [0, 100].");
+ }
+}
+
+void TestFunc(TestClass& t, float value)
+{
+ value = std::clamp(value, 30.0f, 50.0f);
+ // When TestClass::SetValue is inlined, the exception throwing code is not eliminated.
+ // Given that at this point we can prove that 'value' lies in the range [30.0f, 50.0f] well within the range required by the setter function, we can rid the not taken paths of code.
+ t.SetValue(value);
+}
+
+
+/* { dg-final { scan-tree-dump-times "std::out_of_range::out_of_range" 1 "optimized" } } */
+
--
2.45.0