On 21/08/25 16:38, Richard Biener wrote:
External email: Use caution opening links or attachments


On Thu, 21 Aug 2025, dhr...@nvidia.com wrote:

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)

The pattern misses the corresponding handling for
(C << x) {!=,<,>,<=,>=} x

You can generalize this to non-constant @0 by checking for
tree_expr_nonzero_p (@0).

Hi,

Sorry for the delay in getting back to this. I got a bit lost
in proving the legality of the transformation. I have sent patch
v2 now.


+  (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 } } */


--
Richard Biener <rguent...@suse.de>
SUSE Software Solutions Germany GmbH,
Frankenstrasse 146, 90461 Nuernberg, Germany;
GF: Ivo Totev, Andrew McDonald, Werner Knoblich; (HRB 36809, AG Nuernberg)


--
Regards,
Dhruv

Reply via email to