https://gcc.gnu.org/g:862d4309dcb342adde13bfe3daca54255906fc70
commit r16-5648-g862d4309dcb342adde13bfe3daca54255906fc70 Author: Dhruv Chawla <[email protected]> Date: Thu Nov 27 12:12:33 2025 +0100 remove patterns for (y << x) {<,<=,>,>=} x [PR122733] 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 <[email protected]> Diff: --- gcc/match.pd | 34 ++++----------------- gcc/testsuite/gcc.dg/match-shift-cmp-1.c | 11 +------ gcc/testsuite/gcc.dg/match-shift-cmp-2.c | 23 +++----------- gcc/testsuite/gcc.dg/match-shift-cmp-3.c | 27 ++++++++--------- gcc/testsuite/gcc.dg/match-shift-cmp-4.c | 51 -------------------------------- 5 files changed, 23 insertions(+), 123 deletions(-) diff --git a/gcc/match.pd b/gcc/match.pd index fec546a29ed1..4ebf394d4a4a 100644 --- a/gcc/match.pd +++ b/gcc/match.pd @@ -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). */ diff --git a/gcc/testsuite/gcc.dg/match-shift-cmp-1.c b/gcc/testsuite/gcc.dg/match-shift-cmp-1.c index b22d57d370f1..7a69cd194376 100644 --- a/gcc/testsuite/gcc.dg/match-shift-cmp-1.c +++ b/gcc/testsuite/gcc.dg/match-shift-cmp-1.c @@ -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 } } */ diff --git a/gcc/testsuite/gcc.dg/match-shift-cmp-2.c b/gcc/testsuite/gcc.dg/match-shift-cmp-2.c index 96a2fd954f63..3d514ba1ee1b 100644 --- a/gcc/testsuite/gcc.dg/match-shift-cmp-2.c +++ b/gcc/testsuite/gcc.dg/match-shift-cmp-2.c @@ -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 } } */ diff --git a/gcc/testsuite/gcc.dg/match-shift-cmp-3.c b/gcc/testsuite/gcc.dg/match-shift-cmp-3.c index 34380cfeb969..e46ac30b905f 100644 --- a/gcc/testsuite/gcc.dg/match-shift-cmp-3.c +++ b/gcc/testsuite/gcc.dg/match-shift-cmp-3.c @@ -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 index 629e2a376d11..000000000000 --- a/gcc/testsuite/gcc.dg/match-shift-cmp-4.c +++ /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 } } */
