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