diff mbox series

[v2] match: Change (A * B) + (-C) to (B - C/A) * A, if C multiple of A [PR109393]

Message ID 20240917074215.2978559-1-konstantinos.eleftheriou@vrull.eu
State New
Headers show
Series [v2] match: Change (A * B) + (-C) to (B - C/A) * A, if C multiple of A [PR109393] | expand

Commit Message

Konstantinos Eleftheriou Sept. 17, 2024, 7:42 a.m. UTC
From: kelefth <konstantinos.eleftheriou@vrull.eu>

The following function:

int foo(int *a, int j)
{
  int k = j - 1;
  return a[j - 1] == a[k];
}

does not fold to `return 1;` using -O2 or higher. The cause of this is that
the expression `4 * j + (-4)` for the index computation is not folded to
`4 * (j - 1)`. Existing simplifications that handle similar cases are applied
when A == C, which is not the case in this instance.

A previous attempt to address this issue is
https://gcc.gnu.org/pipermail/gcc-patches/2024-April/649896.html

This patch adds the following simplification in match.pd:
(A * B) + (-C) -> (B - C/A) * A, if C a multiple of A

which also handles cases where the index is j - 2, j - 3, etc.

Bootstrapped for all languages and regression tested on x86-64 and aarch64.

	PR tree-optimization/109393

gcc/ChangeLog:

	* match.pd: (A * B) + (-C) -> (B - C/A) * A, if C a multiple of A.

gcc/testsuite/ChangeLog:

	* gcc.dg/pr109393.c: New test.

Tested-by: Christoph Müllner <christoph.muellner@vrull.eu>
Signed-off-by: Philipp Tomsich <philipp.tomsich@vrull.eu>
Signed-off-by: Konstantinos Eleftheriou <konstantinos.eleftheriou@vrull.eu>
---
 gcc/match.pd                    | 21 ++++++++++++++++++++-
 gcc/testsuite/gcc.dg/pr109393.c | 23 +++++++++++++++++++++++
 2 files changed, 43 insertions(+), 1 deletion(-)
 create mode 100644 gcc/testsuite/gcc.dg/pr109393.c

Comments

Richard Biener Sept. 25, 2024, 12:56 p.m. UTC | #1
On Tue, Sep 17, 2024 at 9:43 AM Konstantinos Eleftheriou
<konstantinos.eleftheriou@vrull.eu> wrote:
>
> From: kelefth <konstantinos.eleftheriou@vrull.eu>
>
> The following function:
>
> int foo(int *a, int j)
> {
>   int k = j - 1;
>   return a[j - 1] == a[k];
> }
>
> does not fold to `return 1;` using -O2 or higher. The cause of this is that
> the expression `4 * j + (-4)` for the index computation is not folded to
> `4 * (j - 1)`. Existing simplifications that handle similar cases are applied
> when A == C, which is not the case in this instance.
>
> A previous attempt to address this issue is
> https://gcc.gnu.org/pipermail/gcc-patches/2024-April/649896.html
>
> This patch adds the following simplification in match.pd:
> (A * B) + (-C) -> (B - C/A) * A, if C a multiple of A
>
> which also handles cases where the index is j - 2, j - 3, etc.
>
> Bootstrapped for all languages and regression tested on x86-64 and aarch64.

OK.

Thanks,
Richard.

>         PR tree-optimization/109393
>
> gcc/ChangeLog:
>
>         * match.pd: (A * B) + (-C) -> (B - C/A) * A, if C a multiple of A.
>
> gcc/testsuite/ChangeLog:
>
>         * gcc.dg/pr109393.c: New test.
>
> Tested-by: Christoph Müllner <christoph.muellner@vrull.eu>
> Signed-off-by: Philipp Tomsich <philipp.tomsich@vrull.eu>
> Signed-off-by: Konstantinos Eleftheriou <konstantinos.eleftheriou@vrull.eu>
> ---
>  gcc/match.pd                    | 21 ++++++++++++++++++++-
>  gcc/testsuite/gcc.dg/pr109393.c | 23 +++++++++++++++++++++++
>  2 files changed, 43 insertions(+), 1 deletion(-)
>  create mode 100644 gcc/testsuite/gcc.dg/pr109393.c
>
> diff --git a/gcc/match.pd b/gcc/match.pd
> index 5566c0e4c41..6aeb92cdad0 100644
> --- a/gcc/match.pd
> +++ b/gcc/match.pd
> @@ -4245,7 +4245,26 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
>                          ? wi::max_value (TYPE_PRECISION (type), SIGNED)
>                          : wi::min_value (TYPE_PRECISION (type), SIGNED))))))
>          && single_use (@3))
> -     (mult (plusminus @2 { build_one_cst (type); }) @0))))))
> +      (mult (plusminus @2 { build_one_cst (type); }) @0)))))
> + /* (A * B) + (-C) -> (B - C/A) * A, if C is a multiple of A.  */
> + (if (!ALL_FRACT_MODE_P (TYPE_MODE (type)))
> +  (simplify
> +    (plus (mult:cs integer_nonzerop@0 @1) INTEGER_CST@2)
> +    /* Exclude the case that @2 == min to prevent UB when calculating abs
> +       and (B - C/A).  */
> +    (if (TREE_CODE (type) == INTEGER_TYPE
> +       && wi::neg_p (wi::to_wide (@2))
> +       && wi::to_wide (@2) != wi::min_value (TYPE_PRECISION (type), SIGNED))
> +      (with {
> +       wide_int c0 = wi::to_wide (@0);
> +       wide_int c2 = wi::to_wide (@2);
> +       wide_int c2_abs = wi::abs (c2); }
> +      (if (wi::multiple_of_p (c2_abs, c0, TYPE_SIGN (type)))
> +       (with {
> +         /* Calculate @2 / @0 in order to factorize the expression.  */
> +         wide_int div_res = wi::sdiv_trunc (c2, c0);
> +         tree div_cst = wide_int_to_tree (type, div_res); }
> +       (mult (plus @1 { div_cst; }) @0))))))))
>
>  #if GIMPLE
>  /* Canonicalize X + (X << C) into X * (1 + (1 << C)) and
> diff --git a/gcc/testsuite/gcc.dg/pr109393.c b/gcc/testsuite/gcc.dg/pr109393.c
> new file mode 100644
> index 00000000000..17bf9330796
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/pr109393.c
> @@ -0,0 +1,23 @@
> +/* PR tree-optimization/109393 */
> +/* { dg-do compile } */
> +/* { dg-options "-O2 -fdump-tree-optimized" } */
> +
> +int foo(int *a, int j)
> +{
> +  int k = j - 1;
> +  return a[j - 1] == a[k];
> +}
> +
> +int foo2(int *a, int j)
> +{
> +  int k = j - 5;
> +  return a[j - 5] == a[k];
> +}
> +
> +int bar(int *a, int j)
> +{
> +  int k = j - 1;
> +  return (&a[j + 1] - 2) == &a[k];
> +}
> +
> +/* { dg-final { scan-tree-dump-times "return 1;" 3 "optimized" } } */
> \ No newline at end of file
> --
> 2.46.0
>
Philipp Tomsich Sept. 25, 2024, 1:47 p.m. UTC | #2
Applied to master, thanks!
--Philipp.


On Wed, 25 Sept 2024 at 14:56, Richard Biener
<richard.guenther@gmail.com> wrote:
>
> On Tue, Sep 17, 2024 at 9:43 AM Konstantinos Eleftheriou
> <konstantinos.eleftheriou@vrull.eu> wrote:
> >
> > From: kelefth <konstantinos.eleftheriou@vrull.eu>
> >
> > The following function:
> >
> > int foo(int *a, int j)
> > {
> >   int k = j - 1;
> >   return a[j - 1] == a[k];
> > }
> >
> > does not fold to `return 1;` using -O2 or higher. The cause of this is that
> > the expression `4 * j + (-4)` for the index computation is not folded to
> > `4 * (j - 1)`. Existing simplifications that handle similar cases are applied
> > when A == C, which is not the case in this instance.
> >
> > A previous attempt to address this issue is
> > https://gcc.gnu.org/pipermail/gcc-patches/2024-April/649896.html
> >
> > This patch adds the following simplification in match.pd:
> > (A * B) + (-C) -> (B - C/A) * A, if C a multiple of A
> >
> > which also handles cases where the index is j - 2, j - 3, etc.
> >
> > Bootstrapped for all languages and regression tested on x86-64 and aarch64.
>
> OK.
>
> Thanks,
> Richard.
>
> >         PR tree-optimization/109393
> >
> > gcc/ChangeLog:
> >
> >         * match.pd: (A * B) + (-C) -> (B - C/A) * A, if C a multiple of A.
> >
> > gcc/testsuite/ChangeLog:
> >
> >         * gcc.dg/pr109393.c: New test.
> >
> > Tested-by: Christoph Müllner <christoph.muellner@vrull.eu>
> > Signed-off-by: Philipp Tomsich <philipp.tomsich@vrull.eu>
> > Signed-off-by: Konstantinos Eleftheriou <konstantinos.eleftheriou@vrull.eu>
> > ---
> >  gcc/match.pd                    | 21 ++++++++++++++++++++-
> >  gcc/testsuite/gcc.dg/pr109393.c | 23 +++++++++++++++++++++++
> >  2 files changed, 43 insertions(+), 1 deletion(-)
> >  create mode 100644 gcc/testsuite/gcc.dg/pr109393.c
> >
> > diff --git a/gcc/match.pd b/gcc/match.pd
> > index 5566c0e4c41..6aeb92cdad0 100644
> > --- a/gcc/match.pd
> > +++ b/gcc/match.pd
> > @@ -4245,7 +4245,26 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
> >                          ? wi::max_value (TYPE_PRECISION (type), SIGNED)
> >                          : wi::min_value (TYPE_PRECISION (type), SIGNED))))))
> >          && single_use (@3))
> > -     (mult (plusminus @2 { build_one_cst (type); }) @0))))))
> > +      (mult (plusminus @2 { build_one_cst (type); }) @0)))))
> > + /* (A * B) + (-C) -> (B - C/A) * A, if C is a multiple of A.  */
> > + (if (!ALL_FRACT_MODE_P (TYPE_MODE (type)))
> > +  (simplify
> > +    (plus (mult:cs integer_nonzerop@0 @1) INTEGER_CST@2)
> > +    /* Exclude the case that @2 == min to prevent UB when calculating abs
> > +       and (B - C/A).  */
> > +    (if (TREE_CODE (type) == INTEGER_TYPE
> > +       && wi::neg_p (wi::to_wide (@2))
> > +       && wi::to_wide (@2) != wi::min_value (TYPE_PRECISION (type), SIGNED))
> > +      (with {
> > +       wide_int c0 = wi::to_wide (@0);
> > +       wide_int c2 = wi::to_wide (@2);
> > +       wide_int c2_abs = wi::abs (c2); }
> > +      (if (wi::multiple_of_p (c2_abs, c0, TYPE_SIGN (type)))
> > +       (with {
> > +         /* Calculate @2 / @0 in order to factorize the expression.  */
> > +         wide_int div_res = wi::sdiv_trunc (c2, c0);
> > +         tree div_cst = wide_int_to_tree (type, div_res); }
> > +       (mult (plus @1 { div_cst; }) @0))))))))
> >
> >  #if GIMPLE
> >  /* Canonicalize X + (X << C) into X * (1 + (1 << C)) and
> > diff --git a/gcc/testsuite/gcc.dg/pr109393.c b/gcc/testsuite/gcc.dg/pr109393.c
> > new file mode 100644
> > index 00000000000..17bf9330796
> > --- /dev/null
> > +++ b/gcc/testsuite/gcc.dg/pr109393.c
> > @@ -0,0 +1,23 @@
> > +/* PR tree-optimization/109393 */
> > +/* { dg-do compile } */
> > +/* { dg-options "-O2 -fdump-tree-optimized" } */
> > +
> > +int foo(int *a, int j)
> > +{
> > +  int k = j - 1;
> > +  return a[j - 1] == a[k];
> > +}
> > +
> > +int foo2(int *a, int j)
> > +{
> > +  int k = j - 5;
> > +  return a[j - 5] == a[k];
> > +}
> > +
> > +int bar(int *a, int j)
> > +{
> > +  int k = j - 1;
> > +  return (&a[j + 1] - 2) == &a[k];
> > +}
> > +
> > +/* { dg-final { scan-tree-dump-times "return 1;" 3 "optimized" } } */
> > \ No newline at end of file
> > --
> > 2.46.0
> >
diff mbox series

Patch

diff --git a/gcc/match.pd b/gcc/match.pd
index 5566c0e4c41..6aeb92cdad0 100644
--- a/gcc/match.pd
+++ b/gcc/match.pd
@@ -4245,7 +4245,26 @@  DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
 			 ? wi::max_value (TYPE_PRECISION (type), SIGNED)
 			 : wi::min_value (TYPE_PRECISION (type), SIGNED))))))
 	 && single_use (@3))
-     (mult (plusminus @2 { build_one_cst (type); }) @0))))))
+      (mult (plusminus @2 { build_one_cst (type); }) @0)))))
+ /* (A * B) + (-C) -> (B - C/A) * A, if C is a multiple of A.  */
+ (if (!ALL_FRACT_MODE_P (TYPE_MODE (type)))
+  (simplify
+    (plus (mult:cs integer_nonzerop@0 @1) INTEGER_CST@2)
+    /* Exclude the case that @2 == min to prevent UB when calculating abs
+       and (B - C/A).  */
+    (if (TREE_CODE (type) == INTEGER_TYPE
+	&& wi::neg_p (wi::to_wide (@2))
+	&& wi::to_wide (@2) != wi::min_value (TYPE_PRECISION (type), SIGNED))
+      (with {
+	wide_int c0 = wi::to_wide (@0);
+	wide_int c2 = wi::to_wide (@2);
+	wide_int c2_abs = wi::abs (c2); }
+      (if (wi::multiple_of_p (c2_abs, c0, TYPE_SIGN (type)))
+	(with {
+	  /* Calculate @2 / @0 in order to factorize the expression.  */
+	  wide_int div_res = wi::sdiv_trunc (c2, c0);
+	  tree div_cst = wide_int_to_tree (type, div_res); }
+	(mult (plus @1 { div_cst; }) @0))))))))
 
 #if GIMPLE
 /* Canonicalize X + (X << C) into X * (1 + (1 << C)) and
diff --git a/gcc/testsuite/gcc.dg/pr109393.c b/gcc/testsuite/gcc.dg/pr109393.c
new file mode 100644
index 00000000000..17bf9330796
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr109393.c
@@ -0,0 +1,23 @@ 
+/* PR tree-optimization/109393 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+
+int foo(int *a, int j)
+{
+  int k = j - 1;
+  return a[j - 1] == a[k];
+}
+
+int foo2(int *a, int j)
+{
+  int k = j - 5;
+  return a[j - 5] == a[k];
+}
+
+int bar(int *a, int j)
+{
+  int k = j - 1;
+  return (&a[j + 1] - 2) == &a[k];
+}
+
+/* { dg-final { scan-tree-dump-times "return 1;" 3 "optimized" } } */
\ No newline at end of file