https://gcc.gnu.org/g:48923fca19458948d33351b506319efa3af9e40a
commit r16-4616-g48923fca19458948d33351b506319efa3af9e40a Author: Andrew MacLeod <[email protected]> Date: Fri Oct 24 15:09:51 2025 -0400 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. Diff: --- gcc/gimple-range-fold.cc | 11 +++++++++++ gcc/testsuite/g++.dg/pr114025.C | 39 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 50 insertions(+) diff --git a/gcc/gimple-range-fold.cc b/gcc/gimple-range-fold.cc index d18b37b33800..06c645f3d081 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 000000000000..61bb8f151fc1 --- /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" } } */ +
