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

Reply via email to