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

Reply via email to