]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
remove patterns for (y << x) {<,<=,>,>=} x [PR122733]
authorDhruv Chawla <dhruvc@nvidia.com>
Thu, 27 Nov 2025 11:12:33 +0000 (12:12 +0100)
committerJakub Jelinek <jakub@gcc.gnu.org>
Thu, 27 Nov 2025 11:12:33 +0000 (12:12 +0100)
These patterns should not be in match.pd as they require range
information checks that ideally belong in VRP. They were also causing
breakages as the checks weren't tight enough.

PR tree-optimization/122733
* match.pd ((y << x) {<,<=,>,>=} x): Remove.
((y << x) {==,!=} x): Call constant_boolean_node instead of
build_one_cst/build_zero_cst and combine into one pattern.

* gcc.dg/match-shift-cmp-1.c: Update test to only check
equality.
* gcc.dg/match-shift-cmp-2.c: Likewise.
* gcc.dg/match-shift-cmp-3.c: Likewise.
* gcc.dg/match-shift-cmp-4.c: Removed.

Signed-off-by: Dhruv Chawla <dhruvc@nvidia.com>
gcc/match.pd
gcc/testsuite/gcc.dg/match-shift-cmp-1.c
gcc/testsuite/gcc.dg/match-shift-cmp-2.c
gcc/testsuite/gcc.dg/match-shift-cmp-3.c
gcc/testsuite/gcc.dg/match-shift-cmp-4.c [deleted file]

index fec546a29ed1d10ce46b78d3b00d38501e271ea7..4ebf394d4a4abc977cc20907ab1e8c6854028f74 100644 (file)
@@ -1340,37 +1340,13 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
     (if (INTEGRAL_TYPE_P (type))
       (rshift (op @0 @2) @1))))
 
-/* (y << x) == x -> 0 when y != 0.  */
-(simplify
-  (eq:c (nop_convert1? (lshift @0 @1)) (nop_convert2? @1))
-  (if (INTEGRAL_TYPE_P (TREE_TYPE (@1))
-       && tree_expr_nonzero_p (@0))
-   { build_zero_cst (type); }))
-
-/* (y << x) {<,<=} x -> 0 when y > 0.  */
-(for cmp (lt le)
-  (simplify
-    (cmp:c (nop_convert1? (lshift @0 @1)) (nop_convert2? @1))
-    (if (INTEGRAL_TYPE_P (TREE_TYPE (@1))
-        && tree_expr_nonzero_p (@0)
-        && tree_expr_nonnegative_p (@0))
-     { build_zero_cst (type); })))
-
-/* (y << x) != x -> 1 when y != 0.  */
-(simplify
-  (ne:c (nop_convert1? (lshift @0 @1)) (nop_convert2? @1))
+/* (y << x) == x -> false and (y << x) != x -> true when y != 0.  */
+(for cmp (eq ne)
+ (simplify
+  (cmp:c (nop_convert1? (lshift @0 @1)) (nop_convert2? @1))
   (if (INTEGRAL_TYPE_P (TREE_TYPE (@1))
        && tree_expr_nonzero_p (@0))
-   { build_one_cst (type); }))
-
-/* (y << x) {>,>=} x -> 1 when y > 0.  */
-(for cmp (gt ge)
-  (simplify
-    (cmp:c (nop_convert1? (lshift @0 @1)) (nop_convert2? @1))
-    (if (INTEGRAL_TYPE_P (TREE_TYPE (@1))
-        && tree_expr_nonzero_p (@0)
-        && tree_expr_nonnegative_p (@0))
-     { build_one_cst (type); })))
+      { constant_boolean_node (cmp != EQ_EXPR, type); })))
 
 /* Fold (1 << (C - x)) where C = precision(type) - 1
    into ((1 << C) >> x). */
index b22d57d370f1c114cb1f9f0810a9289318f0517a..7a69cd194376319e37ca62233726e699640ba058 100644 (file)
@@ -34,17 +34,8 @@ typedef enum
 
 TEST_OP_CST (eq, ==, 1)
 TEST_OP_CST (ne, !=, 2)
-TEST_OP_CST (lt, <, 3)
-TEST_OP_CST (gt, >, 4)
-TEST_OP_CST (le, <=, 5)
-TEST_OP_CST (ge, >=, 6)
 
 TEST_OP (eq, ==)
 TEST_OP (ne, !=)
-TEST_OP (lt, <)
-TEST_OP (gt, >)
-TEST_OP (le, <=)
-TEST_OP (ge, >=)
 
-/* FIXME: The lt, le, gt and ge cases for int and enum don't get optimized.  */
-/* { dg-final { scan-tree-dump-times "<<" 8 optimized } } */
+/* { dg-final { scan-tree-dump-not "<<" optimized } } */
index 96a2fd954f639f3fdfb591bccff37fcf0640e74c..3d514ba1ee1b86b16a2c4c806a9c7b2116a412ac 100644 (file)
@@ -36,27 +36,12 @@ typedef enum
 
 TEST_OP_CST (eq, ==, 0)
 TEST_OP_CST (ne, !=, 0)
-TEST_OP_CST (lt, <, 0)
-TEST_OP_CST (gt, >, 0)
-TEST_OP_CST (le, <=, 0)
-TEST_OP_CST (ge, >=, 0)
 
 TEST_OP (eq, ==)
 TEST_OP (ne, !=)
-TEST_OP (lt, <)
-TEST_OP (gt, >)
-TEST_OP (le, <=)
-TEST_OP (ge, >=)
 
 /* These end up getting folded by other patterns.  */
-/* { dg-final { scan-tree-dump-times "x_\\d\\(D\\) == 0" 8 optimized } } */
-/* { dg-final { scan-tree-dump-times "x_\\d\\(D\\) != 0" 8 optimized } } */
-/* { dg-final { scan-tree-dump-times "x_\\d\\(D\\) > 0" 4 optimized } } */
-/* { dg-final { scan-tree-dump-times "x_\\d\\(D\\) < 0" 4 optimized } } */
-/* { dg-final { scan-tree-dump-times "x_\\d\\(D\\) >= 0" 4 optimized } } */
-/* { dg-final { scan-tree-dump-times "x_\\d\\(D\\) <= 0" 4 optimized } } */
-/* { dg-final { scan-tree-dump-times "~x_\\d\\(D\\)" 4 optimized } } */
-/* { dg-final { scan-tree-dump-times "return x_\\d\\(D\\);" 4 optimized } } */
-/* { dg-final { scan-tree-dump-times "return 0;" 4 optimized } } */
-/* { dg-final { scan-tree-dump-times "return 1;" 4 optimized } } */
-/* Total: 48.  */
+/* { dg-final { scan-tree-dump-times "x_\\d\\(D\\) == 0" 6 optimized } } */
+/* { dg-final { scan-tree-dump-times "x_\\d\\(D\\) != 0" 6 optimized } } */
+/* { dg-final { scan-tree-dump-times "~x_\\d\\(D\\)" 2 optimized } } */
+/* { dg-final { scan-tree-dump-times "return x_\\d\\(D\\);" 2 optimized } } */
index 34380cfeb9692b26b8b10491b28ad42420bf9964..e46ac30b905fbb795e5cb22cce23d4e8732f749f 100644 (file)
@@ -1,25 +1,27 @@
 /* { dg-do compile } */
 /* { dg-options "-O2 -fdump-tree-optimized" } */
 
-/* The fold (y << x) <op> x -> 0|1 shouldn't trigger when y is negative or
-   zero unsigned (except for == and !=).  */
+/* The fold (y << x) <op> x -> 0|1 should trigger when y is negative
+   unsigned.  */
 
 #define TEST_ONE_CST(n, op, type, cst)                                         \
-  bool lshift_cst_##type##_##n (type x) { return ((cst << x) op x); }
+  bool lshift_cst_##type##_##n (type x) { return ((unsigned) (cst) << x) op x; }
 
 #define TEST_OP_CST(n, op, cst)                                                \
+  TEST_ONE_CST (n, op, unsigned, cst)                                          \
   TEST_ONE_CST (n, op, int, cst)                                               \
   TEST_ONE_CST (n, op, test_enum, cst)
 
 #define TEST_ONE(n, op, type)                                                  \
   bool lshift_##type##_##n (type x, type y)                                    \
   {                                                                            \
-    if (y > 0)                                                                 \
+    if ((int) y <= 0)                                                          \
       __builtin_unreachable ();                                                \
-    return ((y << x) op x);                                                    \
+    return ((unsigned) (y) << x) op x;                                         \
   }
 
 #define TEST_OP(n, op)                                                         \
+  TEST_ONE (n, op, unsigned)                                                   \
   TEST_ONE (n, op, int)                                                        \
   TEST_ONE (n, op, test_enum)
 
@@ -31,14 +33,11 @@ typedef enum
   TWO = 2
 } test_enum;
 
-TEST_OP_CST (lt, <, -1)
-TEST_OP_CST (gt, >, -2)
-TEST_OP_CST (le, <=, -3)
-TEST_OP_CST (ge, >=, -4)
+TEST_OP_CST (eq, ==, -1)
+TEST_OP_CST (ne, !=, -2)
 
-TEST_OP (lt, <)
-TEST_OP (gt, >)
-TEST_OP (le, <=)
-TEST_OP (ge, >=)
+TEST_OP (eq, ==)
+TEST_OP (ne, !=)
 
-/* { dg-final { scan-tree-dump-times "<<" 16 optimized } } */
+/* { dg-final { scan-tree-dump-times "return 0;" 6 optimized } } */
+/* { dg-final { scan-tree-dump-times "return 1;" 6 optimized } } */
diff --git a/gcc/testsuite/gcc.dg/match-shift-cmp-4.c b/gcc/testsuite/gcc.dg/match-shift-cmp-4.c
deleted file mode 100644 (file)
index 629e2a3..0000000
+++ /dev/null
@@ -1,51 +0,0 @@
-/* { dg-do compile } */
-/* { dg-options "-O2 -fdump-tree-optimized" } */
-
-/* The fold (y << x) <op> x -> 0|1 should trigger when y is negative
-   unsigned.  */
-
-#define TEST_ONE_CST(n, op, type, cst)                                         \
-  bool lshift_cst_##type##_##n (type x) { return ((unsigned) (cst) << x) op x; }
-
-#define TEST_OP_CST(n, op, cst)                                                \
-  TEST_ONE_CST (n, op, unsigned, cst)                                          \
-  TEST_ONE_CST (n, op, int, cst)                                               \
-  TEST_ONE_CST (n, op, test_enum, cst)
-
-#define TEST_ONE(n, op, type)                                                  \
-  bool lshift_##type##_##n (type x, type y)                                    \
-  {                                                                            \
-    if ((int) y <= 0)                                                          \
-      __builtin_unreachable ();                                                \
-    return ((unsigned) (y) << x) op x;                                         \
-  }
-
-#define TEST_OP(n, op)                                                         \
-  TEST_ONE (n, op, unsigned)                                                   \
-  TEST_ONE (n, op, int)                                                        \
-  TEST_ONE (n, op, test_enum)
-
-typedef enum
-{
-  MONE = -1,
-  ZERO = 0,
-  ONE = 1,
-  TWO = 2
-} test_enum;
-
-TEST_OP_CST (eq, ==, -1)
-TEST_OP_CST (ne, !=, -2)
-TEST_OP_CST (lt, <, -3)
-TEST_OP_CST (gt, >, -4)
-TEST_OP_CST (le, <=, -5)
-TEST_OP_CST (ge, >=, -6)
-
-TEST_OP (eq, ==)
-TEST_OP (ne, !=)
-TEST_OP (lt, <)
-TEST_OP (gt, >)
-TEST_OP (le, <=)
-TEST_OP (ge, >=)
-
-/* { dg-final { scan-tree-dump-times "return 0;" 18 optimized } } */
-/* { dg-final { scan-tree-dump-times "return 1;" 18 optimized } } */