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