https://gcc.gnu.org/g:5d00ecd71b59b6c62748c014c6fa54180602192c

commit r17-4194-g5d00ecd71b59b6c62748c014c6fa54180602192c
Author: Andrea Pinski <[email protected]>
Date:   Sat Sep 12 15:33:26 2026 -0700

    match: Fix two_value for boundary conditions [PR127358]
    
    With r14-2299-g71b68cc559b5d3, the removal of prefering
    the unsigned type was removed.  This will cause wrong
    code with the boundary condition of the unsigned values
    of `INT_MAX` and `INT_MAX+1` in some cases.
    
    This adds back the prefering of unsigned types when
    the types precisions are the same.  Fixing the issue as
    we do the subtraction now in unsigned type; avoiding the
    undefined overflow.
    
    Pushed as obvious after a bootstrap/test on x86_64-linux-gnu.
    
            PR tree-optimization/127358
    
    gcc/ChangeLog:
    
            * match.pd (two_value cond): Prefer unsigned types.
    
    gcc/testsuite/ChangeLog:
    
            * gcc.dg/torture/pr127358-1.c: New test.
    
    Signed-off-by: Andrea Pinski <[email protected]>

Diff:
---
 gcc/match.pd                              |  6 +++++-
 gcc/testsuite/gcc.dg/torture/pr127358-1.c | 23 +++++++++++++++++++++++
 2 files changed, 28 insertions(+), 1 deletion(-)

diff --git a/gcc/match.pd b/gcc/match.pd
index 8278cf1fd6db..3d7091e81b79 100644
--- a/gcc/match.pd
+++ b/gcc/match.pd
@@ -6946,12 +6946,16 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
        tree type1;
        if ((eqne == EQ_EXPR) ^ (wi::to_wide (@1) == min))
          std::swap (arg0, arg1);
-       if (TYPE_PRECISION (TREE_TYPE (@0)) > TYPE_PRECISION (type))
+       if (TYPE_PRECISION (TREE_TYPE (@0)) > TYPE_PRECISION (type)
+           // Prefer unsigned type if the two has the same precision.
+           || (TYPE_PRECISION (TREE_TYPE (@0)) == TYPE_PRECISION (type)
+               && !TYPE_UNSIGNED (type)))
         type1 = TREE_TYPE (@0);
        else
         type1 = type;
        auto prec = TYPE_PRECISION (type1);
        auto unsign = TYPE_UNSIGNED (type1);
+       // For boolean types, use an integer type for the plus/minus.
        if (TREE_CODE (type1) == BOOLEAN_TYPE)
        type1 = build_nonstandard_integer_type (prec, unsign);
        min = wide_int::from (min, prec,
diff --git a/gcc/testsuite/gcc.dg/torture/pr127358-1.c 
b/gcc/testsuite/gcc.dg/torture/pr127358-1.c
new file mode 100644
index 000000000000..0e403e3471db
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr127358-1.c
@@ -0,0 +1,23 @@
+/* { dg-do run } */
+/* PR tree-optimization/127358 */
+
+__attribute__((noipa))
+int compute(unsigned x){
+  unsigned max = __INT_MAX__;
+  if (x != __INT_MAX__
+      && x != (((unsigned)__INT_MAX__)+1))
+    __builtin_unreachable();
+  int r = (x == max) ? 5 : 6;
+  return r;
+}
+
+int main(void){
+  volatile unsigned a = __INT_MAX__;
+  volatile unsigned b = a+1;
+  if (compute(a) != 5)
+    __builtin_abort ();
+  if (compute(b) != 6)
+    __builtin_abort ();
+  return 0;
+}
+

Reply via email to