Hi:
  This patch is to simplify A * C + (-D) -> (A - D/C) * C when C is a
power of 2 and D mod C == 0.
  bootstrap and make check is ok.

changelog
gcc/
        * gcc/match.pd (A * C + (-D) = (A - D/C) * C. when C is a
        power of 2 and D mod C == 0): Add new simplification.

gcc/testsuite
        * gcc.dg/pr92980.c: New test.

-- 
BR,
Hongtao
From 41f76f29f0070082e29082460efdb0bb9b9869f7 Mon Sep 17 00:00:00 2001
From: liuhongt <hongtao....@intel.com>
Date: Fri, 13 Dec 2019 15:52:02 +0800
Subject: [PATCH] Simplify A * C + (-D) = (A - D/C) * C. when C is a power of 2
 and D mod C == 0.

gcc/
	* gcc/match.pd (A * C + (-D) = (A - D/C) * C. when C is a
	power of 2 and D mod C == 0): Add new simplification.

gcc/testsuite
	* gcc.dg/pr92980.c: New test.
---
 gcc/match.pd                   | 20 ++++++++++++++++
 gcc/testsuite/gcc.dg/pr92980.c | 43 ++++++++++++++++++++++++++++++++++
 2 files changed, 63 insertions(+)
 create mode 100644 gcc/testsuite/gcc.dg/pr92980.c

diff --git a/gcc/match.pd b/gcc/match.pd
index dda86964b4c..a128733e2c3 100644
--- a/gcc/match.pd
+++ b/gcc/match.pd
@@ -4297,6 +4297,26 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
   (if (tree_single_nonzero_warnv_p (@0, NULL))
    { constant_boolean_node (cmp == NE_EXPR, type); })))
 
+/* Simplify A * C + (-D) = (A - D/C) * C. when C is a power of 2
+   and D mod C == 0.  */
+(simplify
+ (plus (mult @0 integer_pow2p@1) INTEGER_CST@2)
+ (if (TREE_CODE (TREE_TYPE (@0)) == INTEGER_TYPE
+     && TYPE_UNSIGNED (TREE_TYPE (@0))
+     && tree_fits_uhwi_p (@1)
+     && tree_fits_uhwi_p (@2))
+  (with
+   {
+     unsigned HOST_WIDE_INT c = tree_to_uhwi (@1);
+     unsigned HOST_WIDE_INT d = tree_to_uhwi (@2);
+     HOST_WIDE_INT neg_p = wi::sign_mask (d);
+     unsigned HOST_WIDE_INT negd = HOST_WIDE_INT_0U - d;
+     unsigned HOST_WIDE_INT modd = negd % c;
+     unsigned HOST_WIDE_INT divd = negd / c;
+    }
+   (if (neg_p && modd == HOST_WIDE_INT_0U)
+    (mult (minus @0 { build_int_cst (TREE_TYPE (@2), divd);}) @1)))))
+
 /* If we have (A & C) == C where C is a power of 2, convert this into
    (A & C) != 0.  Similarly for NE_EXPR.  */
 (for cmp (eq ne)
diff --git a/gcc/testsuite/gcc.dg/pr92980.c b/gcc/testsuite/gcc.dg/pr92980.c
new file mode 100644
index 00000000000..d7abf20788e
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr92980.c
@@ -0,0 +1,43 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-fre" }  */
+
+int f1(short *src1, int i, int k, int n)
+{
+  int j = k + n;
+  short sum = src1[j];
+  sum += src1[j-1];
+  if (i <= k)
+    {
+      j+=2;
+      sum += src1[j-3];
+    }
+  return sum + j;
+}
+
+int f2(int *src1, int i, int k, int n)
+{
+  int j = k + n;
+  int sum = src1[j];
+  sum += src1[j-1];
+  if (i <= k)
+    {
+      j+=2;
+      sum += src1[j-3];
+    }
+  return sum + j;
+}
+
+int f3(long long *src1, int i, int k, int n)
+{
+  int j = k + n;
+  long long sum = src1[j];
+  sum += src1[j-1];
+  if (i <= k)
+    {
+      j+=2;
+      sum += src1[j-3];
+    }
+  return sum + j;
+}
+
+/* { dg-final { scan-tree-dump-times "= \\*" 6 "fre1" } }  */
-- 
2.18.1

Reply via email to