From: Dhruv Chawla <dhr...@nvidia.com> Bootstrapped and regtested on aarch64-linux-gnu.
Signed-off-by: Dhruv Chawla <dhr...@nvidia.com> gcc/ChangeLog: * match.pd: New pattern. gcc/testsuite/ChangeLog: * gcc.dg/match-constant-shift-1.c: New test. * gcc.dg/match-constant-shift-1.c: Likewise. --- gcc/match.pd | 7 +++++ gcc/testsuite/gcc.dg/match-constant-shift-1.c | 17 ++++++++++++ gcc/testsuite/gcc.dg/match-constant-shift-2.c | 27 +++++++++++++++++++ 3 files changed, 51 insertions(+) create mode 100644 gcc/testsuite/gcc.dg/match-constant-shift-1.c create mode 100644 gcc/testsuite/gcc.dg/match-constant-shift-2.c diff --git a/gcc/match.pd b/gcc/match.pd index 66e8a787449..3d462659d03 100644 --- a/gcc/match.pd +++ b/gcc/match.pd @@ -1316,6 +1316,13 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) (if (INTEGRAL_TYPE_P (type)) (rshift (op @0 @2) @1)))) +/* (C << x) == x -> 0 when C != 0. */ +(simplify + (eq:c (nop_convert? (lshift INTEGER_CST@0 @1)) @1) + (if (INTEGRAL_TYPE_P (TREE_TYPE (@1)) + && !integer_zerop (@0)) + { build_zero_cst (type); })) + /* Fold (1 << (C - x)) where C = precision(type) - 1 into ((1 << C) >> x). */ (simplify diff --git a/gcc/testsuite/gcc.dg/match-constant-shift-1.c b/gcc/testsuite/gcc.dg/match-constant-shift-1.c new file mode 100644 index 00000000000..7d4afad5a49 --- /dev/null +++ b/gcc/testsuite/gcc.dg/match-constant-shift-1.c @@ -0,0 +1,17 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-gimple" } */ + +#define TEST(type, cst) \ + type lshift_##type (type x) { return (type) ((cst << x) == x); } + +typedef enum +{ + ZERO +} test_enum; + +TEST (unsigned, 1) +TEST (int, -1) +TEST (bool, -5) +TEST (test_enum, -6) + +/* { dg-final { scan-tree-dump-not "<<" gimple } } */ diff --git a/gcc/testsuite/gcc.dg/match-constant-shift-2.c b/gcc/testsuite/gcc.dg/match-constant-shift-2.c new file mode 100644 index 00000000000..62b39e3e790 --- /dev/null +++ b/gcc/testsuite/gcc.dg/match-constant-shift-2.c @@ -0,0 +1,27 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-gimple" } */ + +/* The fold (C << x) == x -> 0 shouldn't trigger when C is 0. It ends up + getting folded to x == 0 in that case. */ + +#define TEST(type, cst) \ + type lshift_##type (type x) { return (type) ((cst << x) == x); } + +typedef unsigned _BitInt (6) bit_int; + +typedef enum +{ + ZERO +} test_enum; + +TEST (unsigned, 0) +TEST (int, 0) +TEST (bool, 0) +/* Bitints are not supported by the fold. */ +TEST (bit_int, 0) +TEST (test_enum, 0) + +/* This ends up getting folded by another pattern. */ +/* { dg-final { scan-tree-dump-times "x == 0" 4 gimple } } */ +/* bool gets optimized differently. */ +/* { dg-final { scan-tree-dump-times "~x" 1 gimple } } */ -- 2.44.0