aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorguojiufu <guojiufu@linux.ibm.com>2020-10-19 13:48:19 +0800
committerguojiufu <guojiufu@linux.ibm.com>2020-10-19 17:26:41 +0800
commit222f312a773157f53396ba4cb287deb07f84cc34 (patch)
treed865a929bc4d8d6f467ce98e33831931f4a50451 /gcc
parentdccb0f8801363462a11fd13a33ff3f4092ff82bd (diff)
downloadgcc-222f312a773157f53396ba4cb287deb07f84cc34.zip
gcc-222f312a773157f53396ba4cb287deb07f84cc34.tar.gz
gcc-222f312a773157f53396ba4cb287deb07f84cc34.tar.bz2
[PATCH] fold x << (n % C) to x << (n & C-1) if C meets power2
This patch fixes PR66552 which is also as: https://gcc.gnu.org/pipermail/gcc-patches/2020-February/540930.html which requests to optimizes (x shift (n mod C)) to (x shift (n bit_and (C - 1))) when C is a constant and power of two. gcc/ChangeLog 2020-10-19 Li Jia He <helijia@gcc.gnu.org> PR tree-optimization/66552 * match.pd (x << (n % C) -> x << (n & C-1)): New simplification. gcc/testsuite/ChangeLog 2020-10-19 Li Jia He <helijia@gcc.gnu.org> PR tree-optimization/66552 * gcc.dg/pr66552.c: New testcase.
Diffstat (limited to 'gcc')
-rw-r--r--gcc/match.pd12
-rw-r--r--gcc/testsuite/gcc.dg/pr66552.c14
2 files changed, 25 insertions, 1 deletions
diff --git a/gcc/match.pd b/gcc/match.pd
index a7032dc..17ba041 100644
--- a/gcc/match.pd
+++ b/gcc/match.pd
@@ -607,12 +607,22 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
/* Optimize TRUNC_MOD_EXPR by a power of two into a BIT_AND_EXPR,
i.e. "X % C" into "X & (C - 1)", if X and C are positive.
Also optimize A % (C << N) where C is a power of 2,
- to A & ((C << N) - 1). */
+ to A & ((C << N) - 1).
+ Also optimize "A shift (B % C)", if C is a power of 2, to
+ "A shift (B & (C - 1))". SHIFT operation include "<<" and ">>"
+ and assume (B % C) is nonnegative as shifts negative values would
+ be UB. */
(match (power_of_two_cand @1)
INTEGER_CST@1)
(match (power_of_two_cand @1)
(lshift INTEGER_CST@1 @2))
(for mod (trunc_mod floor_mod)
+ (for shift (lshift rshift)
+ (simplify
+ (shift @0 (mod @1 (power_of_two_cand@2 @3)))
+ (if (integer_pow2p (@3) && tree_int_cst_sgn (@3) > 0)
+ (shift @0 (bit_and @1 (minus @2 { build_int_cst (TREE_TYPE (@2),
+ 1); }))))))
(simplify
(mod @0 (convert?@3 (power_of_two_cand@1 @2)))
(if ((TYPE_UNSIGNED (type)
diff --git a/gcc/testsuite/gcc.dg/pr66552.c b/gcc/testsuite/gcc.dg/pr66552.c
new file mode 100644
index 0000000..7583c9a
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr66552.c
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-lower" } */
+
+unsigned a(unsigned x, int n)
+{
+ return x >> (n % 32);
+}
+
+unsigned b(unsigned x, int n)
+{
+ return x << (n % 32);
+}
+
+/* { dg-final { scan-tree-dump-not " % " "lower" } } */