]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
match: Add support for convert `((signed)x) < 0` to `x >= (unsigned)SIGNED_TYPE_MIN...
authorAndrew Pinski <andrew.pinski@oss.qualcomm.com>
Mon, 20 Oct 2025 22:48:43 +0000 (15:48 -0700)
committerAndrew Pinski <andrew.pinski@oss.qualcomm.com>
Tue, 21 Oct 2025 09:26:09 +0000 (02:26 -0700)
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 <andrew.pinski@oss.qualcomm.com>
gcc/match.pd
gcc/testsuite/gcc.dg/tree-ssa/pr101024-1.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/tree-ssa/pr110068-1.c [new file with mode: 0644]

index bfc51e6579a958e55582178560f99a5d8d2564cd..a4248a521cfdef935b646e80a6079d262b74de7f 100644 (file)
@@ -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 (file)
index 0000000..14379bf
--- /dev/null
@@ -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 (file)
index 0000000..df88553
--- /dev/null
@@ -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;
+}