[PATCH] fold x << (n % C) to x << (n & C-1) if C meets power2
authorguojiufu <guojiufu@linux.ibm.com>
Mon, 19 Oct 2020 05:48:19 +0000 (13:48 +0800)
committerguojiufu <guojiufu@linux.ibm.com>
Mon, 19 Oct 2020 09:26:41 +0000 (17:26 +0800)
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.

gcc/match.pd
gcc/testsuite/gcc.dg/pr66552.c [new file with mode: 0644]

index a7032dcae29b6f9e604b1e67f30208150b0e347f..17ba04100c784681b475aef620d60e89be2460ae 100644 (file)
@@ -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 (file)
index 0000000..7583c9a
--- /dev/null
@@ -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" } } */