https://gcc.gnu.org/g:07800a565abd20814468a4f84a988e0d95bf30b5

commit r16-4534-g07800a565abd20814468a4f84a988e0d95bf30b5
Author: Andrew Pinski <[email protected]>
Date:   Mon Oct 20 15:48:43 2025 -0700

    match: Add support for convert `((signed)x) < 0` to `x >= 
(unsigned)SIGNED_TYPE_MIN` while detecting min/max [PR110068]
    
    This copies the optimization which was done to fix PR 95699 to match 
detection of MIN/MAX
    from minmax_replacement to match.
    This is another step in getting rid of minmax_replacement in phiopt.  There 
are still a few
    more min/max detections that needs to be handled before the removal. 
pr101024-1.c adds one
    example of that but since the testcase currently passes I didn't xfail it.
    
    pr110068-1.c adds a testcase which was not detected beforehand either.
    
    Changes since v1:
    * v2: Fix comment about how it is transformed.
          Use SIGNED_TYPE_MIN everywhere instead of mxing in SIGNED_TYPE_MAX 
too.
    
    Bootstrapped and tested on x86_64-linux-gnu.
    
            PR tree-optimization/95699
            PR tree-optimization/101024
            PR tree-optimization/110068
    
    gcc/ChangeLog:
    
            * match.pd (`(type1)x CMP CST1 ? (type2)x : CST2`): Treat
            `(signed)x </>= 0` as `x >=/< SIGNED_TYPE_MIN`
    
    gcc/testsuite/ChangeLog:
    
            * gcc.dg/tree-ssa/pr101024-1.c: New test.
            * gcc.dg/tree-ssa/pr110068-1.c: New test.
    
    Signed-off-by: Andrew Pinski <[email protected]>

Diff:
---
 gcc/match.pd                               | 21 ++++++++++++++--
 gcc/testsuite/gcc.dg/tree-ssa/pr101024-1.c | 39 ++++++++++++++++++++++++++++++
 gcc/testsuite/gcc.dg/tree-ssa/pr110068-1.c | 22 +++++++++++++++++
 3 files changed, 80 insertions(+), 2 deletions(-)

diff --git a/gcc/match.pd b/gcc/match.pd
index bfc51e6579a9..a4248a521cfd 100644
--- a/gcc/match.pd
+++ b/gcc/match.pd
@@ -6571,6 +6571,23 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
      tree from_type = TREE_TYPE (@1);
      tree c1_type = TREE_TYPE (@3), c2_type = TREE_TYPE (@2);
      enum tree_code code = ERROR_MARK;
+     enum tree_code ncmp = cmp;
+     tree c1 = @3;
+
+     /* `((signed)a) < 0` should be converted back into
+        `a >= (unsigned)SIGNED_TYPE_MIN`.
+       `((signed)a) >= 0` should be converted back into
+       `a < (unsigned)SIGNED_TYPE_MIN`. */
+     if (integer_zerop (c1)
+         && (cmp == GE_EXPR || cmp == LT_EXPR)
+        && TYPE_UNSIGNED (from_type)
+        && !TYPE_UNSIGNED (c1_type)
+        && TYPE_PRECISION (from_type) == TYPE_PRECISION (c1_type))
+       {
+         ncmp = cmp == GE_EXPR ? LT_EXPR : GE_EXPR;
+         c1 = fold_convert (from_type, TYPE_MIN_VALUE (c1_type));
+         c1_type = from_type;
+       }
 
      if (INTEGRAL_TYPE_P (from_type)
         && int_fits_type_p (@2, from_type)
@@ -6583,8 +6600,8 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
                 && (TYPE_UNSIGNED (from_type)
                     || TYPE_SIGN (c2_type) == TYPE_SIGN (from_type)))))
        {
-        if (cmp != EQ_EXPR)
-          code = minmax_from_comparison (cmp, @1, @3, @1, @2);
+        if (ncmp != EQ_EXPR)
+          code = minmax_from_comparison (ncmp, @1, c1, @1, @2);
         /* Can do A == C1 ? A : C2  ->  A == C1 ? C1 : C2?  */
         else if (int_fits_type_p (@3, from_type))
           code = EQ_EXPR;
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr101024-1.c 
b/gcc/testsuite/gcc.dg/tree-ssa/pr101024-1.c
new file mode 100644
index 000000000000..14379bf3b6a2
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr101024-1.c
@@ -0,0 +1,39 @@
+/* PR tree-optimization/95699 */
+/* PR tree-optimization/101024 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized -fdump-tree-phiopt1" } */
+unsigned long long
+f2 (unsigned long long x)
+{
+  if (x < 0x8000000000000000ULL)
+    x = 0x8000000000000000ULL;
+  else
+    {
+        if (x >= 0x8000000000000023ULL)
+          x = 0x8000000000000023ULL;
+    }
+  return x;
+}
+unsigned long long
+f1 (unsigned long long x)
+{
+  if (x >= 100)
+    {
+        if (x >= 0x8000000000000000ULL)
+          x = 0x8000000000000000ULL;
+    }
+  else
+    x = 100;
+  return x;
+}
+/* f2: */
+/* { dg-final { scan-tree-dump "MIN_EXPR <\[^>\n\r]*9223372036854775843>" 
"optimized" } } */
+/* { dg-final { scan-tree-dump "MAX_EXPR <\[^>\n\r]*9223372036854775808>" 
"optimized" } } */
+/* { dg-final { scan-tree-dump "MIN_EXPR <\[^>\n\r]*9223372036854775843>" 
"phiopt1" } } */
+/* { dg-final { scan-tree-dump "MAX_EXPR <\[^>\n\r]*9223372036854775808>" 
"phiopt1" } } */
+
+/* f1: */
+/* { dg-final { scan-tree-dump "MIN_EXPR <\[^>\n\r]*9223372036854775808>" 
"optimized" } } */
+/* { dg-final { scan-tree-dump "MAX_EXPR <\[^>\n\r]*100>" "optimized" } } */
+/* { dg-final { scan-tree-dump "MIN_EXPR <\[^>\n\r]*9223372036854775808>" 
"phiopt1" } } */
+/* { dg-final { scan-tree-dump "MAX_EXPR <\[^>\n\r]*100>" "phiopt1" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr110068-1.c 
b/gcc/testsuite/gcc.dg/tree-ssa/pr110068-1.c
new file mode 100644
index 000000000000..df88553474c3
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr110068-1.c
@@ -0,0 +1,22 @@
+/* PR tree-optimization/95699 */
+/* PR tree-optimization/110068 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized -fdump-tree-phiopt1" } */
+/* { dg-final { scan-tree-dump-times "MIN_EXPR " 2 "phiopt1" } } */
+
+#define min1(x,y) ((x) < (y) ? (x) : (y))
+unsigned 
+f1 (unsigned  x)
+{
+  return min1(x, 1U<<(sizeof(x)*8-1));
+}
+unsigned
+f5 (unsigned  x)
+{
+  bool t = x >= 1U<<(sizeof(x)*8-1);
+  if (!t)
+    ;
+  else
+    x = 1U<<(sizeof(x)*8-1);
+  return x;
+}

Reply via email to