diff mbox series

MATCH: Simplify `min(a, b) op max(a, b)` to `a op b` [PR109401]

Message ID 20240925083028.29652-1-quic_eikagupt@quicinc.com
State New
Headers show
Series MATCH: Simplify `min(a, b) op max(a, b)` to `a op b` [PR109401] | expand

Commit Message

Eikansh Gupta Sept. 25, 2024, 8:30 a.m. UTC
This patch simplify `min(a,b) op max(a,b)` to `a op b`. This optimization
will work for all the binary commutative operations. So, the `op` here can
be one of {plus, mult, bit_and, bit_xor, bit_ior, eq, ne, min, max}.

	PR tree-optimization/109878
	PR 109401

gcc/ChangeLog:

	* match.pd (min(a,b) op max(a,b) -> a op b): New pattern.

gcc/testsuite/ChangeLog:

	* gcc.dg/tree-ssa/pr109401.c: New test.
        * gcc.dg/tree-ssa/pr109401-1.c: New test.
---
 gcc/match.pd                               |  7 +++
 gcc/testsuite/gcc.dg/tree-ssa/pr109401-1.c | 35 +++++++++++++
 gcc/testsuite/gcc.dg/tree-ssa/pr109401.c   | 61 ++++++++++++++++++++++
 3 files changed, 103 insertions(+)
 create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/pr109401-1.c
 create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/pr109401.c

Comments

Jeff Law Sept. 29, 2024, 3:27 p.m. UTC | #1
On 9/25/24 2:30 AM, Eikansh Gupta wrote:
> This patch simplify `min(a,b) op max(a,b)` to `a op b`. This optimization
> will work for all the binary commutative operations. So, the `op` here can
> be one of {plus, mult, bit_and, bit_xor, bit_ior, eq, ne, min, max}.
> 
> 	PR tree-optimization/109878
> 	PR 109401
> 
> gcc/ChangeLog:
> 
> 	* match.pd (min(a,b) op max(a,b) -> a op b): New pattern.
> 
> gcc/testsuite/ChangeLog:
> 
> 	* gcc.dg/tree-ssa/pr109401.c: New test.
>          * gcc.dg/tree-ssa/pr109401-1.c: New test.
> ---
>   gcc/match.pd                               |  7 +++
>   gcc/testsuite/gcc.dg/tree-ssa/pr109401-1.c | 35 +++++++++++++
>   gcc/testsuite/gcc.dg/tree-ssa/pr109401.c   | 61 ++++++++++++++++++++++
>   3 files changed, 103 insertions(+)
>   create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/pr109401-1.c
>   create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/pr109401.c
> 
> diff --git a/gcc/match.pd b/gcc/match.pd
> index 940292d0d49..4f0453344d6 100644
> --- a/gcc/match.pd
> +++ b/gcc/match.pd
> @@ -4463,6 +4463,13 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
>       @0
>       @2)))
>   
> +/* min (a, b) op max (a, b) -> a op b */
> +(for op (plus mult bit_and bit_xor bit_ior eq ne min max)
> + (simplify
> +  (op:c (min:c @0 @1) (max:c @0 @1))
> +   (if (!HONOR_NANS (@0))
> +    (op @0 @1))))
> +
Does it work in the other order  ie max (a, b) op (min (a, b) -> a op b?


What about other OP cases such as subtraction, div/mod?


Jeff
Richard Biener Oct. 1, 2024, 11:53 a.m. UTC | #2
On Sun, Sep 29, 2024 at 5:28 PM Jeff Law <jeffreyalaw@gmail.com> wrote:
>
>
>
> On 9/25/24 2:30 AM, Eikansh Gupta wrote:
> > This patch simplify `min(a,b) op max(a,b)` to `a op b`. This optimization
> > will work for all the binary commutative operations. So, the `op` here can
> > be one of {plus, mult, bit_and, bit_xor, bit_ior, eq, ne, min, max}.
> >
> >       PR tree-optimization/109878
> >       PR 109401
> >
> > gcc/ChangeLog:
> >
> >       * match.pd (min(a,b) op max(a,b) -> a op b): New pattern.
> >
> > gcc/testsuite/ChangeLog:
> >
> >       * gcc.dg/tree-ssa/pr109401.c: New test.
> >          * gcc.dg/tree-ssa/pr109401-1.c: New test.
> > ---
> >   gcc/match.pd                               |  7 +++
> >   gcc/testsuite/gcc.dg/tree-ssa/pr109401-1.c | 35 +++++++++++++
> >   gcc/testsuite/gcc.dg/tree-ssa/pr109401.c   | 61 ++++++++++++++++++++++
> >   3 files changed, 103 insertions(+)
> >   create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/pr109401-1.c
> >   create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/pr109401.c
> >
> > diff --git a/gcc/match.pd b/gcc/match.pd
> > index 940292d0d49..4f0453344d6 100644
> > --- a/gcc/match.pd
> > +++ b/gcc/match.pd
> > @@ -4463,6 +4463,13 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
> >       @0
> >       @2)))
> >
> > +/* min (a, b) op max (a, b) -> a op b */
> > +(for op (plus mult bit_and bit_xor bit_ior eq ne min max)
> > + (simplify
> > +  (op:c (min:c @0 @1) (max:c @0 @1))
> > +   (if (!HONOR_NANS (@0))
> > +    (op @0 @1))))
> > +
> Does it work in the other order  ie max (a, b) op (min (a, b) -> a op b?
>
>
> What about other OP cases such as subtraction, div/mod?

I think it only can work for commutative ops, since there's :c on 'op' both
operand orders are checked.  Do we need !HONOR_SIGNED_ZEROS for
min/max though?  I think that it's enough to have :c on either the min or
the max.

Richard.

>
> Jeff
diff mbox series

Patch

diff --git a/gcc/match.pd b/gcc/match.pd
index 940292d0d49..4f0453344d6 100644
--- a/gcc/match.pd
+++ b/gcc/match.pd
@@ -4463,6 +4463,13 @@  DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
     @0
     @2)))
 
+/* min (a, b) op max (a, b) -> a op b */
+(for op (plus mult bit_and bit_xor bit_ior eq ne min max)
+ (simplify
+  (op:c (min:c @0 @1) (max:c @0 @1))
+   (if (!HONOR_NANS (@0))
+    (op @0 @1))))
+
 /* Simplify min (&var[off0], &var[off1]) etc. depending on whether
    the addresses are known to be less, equal or greater.  */
 (for minmax (min max)
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr109401-1.c b/gcc/testsuite/gcc.dg/tree-ssa/pr109401-1.c
new file mode 100644
index 00000000000..446285e5722
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr109401-1.c
@@ -0,0 +1,35 @@ 
+/* PR tree-optimization/109878 */
+/* { dg-do compile } */
+/* { dg-options "-O1 -fdump-tree-optimized" } */
+
+/* Returns max (a, b) */
+int max(int a, int b) {
+  if (b > a)
+    return b;
+  else
+    return a;
+}
+
+/* Returns min (a, b) */
+int min(int a, int b) {
+  if (b < a)
+    return b;
+  else
+    return a;
+}
+
+/* These functions should return a op b */
+int f8(int a, int b)
+{
+  return min (max (a, b), min (a, b));
+}
+
+int f9(int a, int b)
+{
+  return max (max (a, b), min (a, b));
+}
+
+/* Function min and f8 should have MIN_EXPR */
+/* Function max and f9 should have MAX_EXPR */
+/* { dg-final { scan-tree-dump-times "MIN_EXPR" 2 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "MAX_EXPR" 2 "optimized" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr109401.c b/gcc/testsuite/gcc.dg/tree-ssa/pr109401.c
new file mode 100644
index 00000000000..c1c6aa370c2
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr109401.c
@@ -0,0 +1,61 @@ 
+/* PR tree-optimization/109878 */
+/* { dg-do compile } */
+/* { dg-options "-O1 -fdump-tree-optimized" } */
+
+/* Returns max (a, b) */
+int max(int a, int b) {
+  if (b > a)
+    return b;
+  else
+    return a;
+}
+
+/* Returns min (a, b) */
+int min(int a, int b) {
+  if (b < a)
+    return b;
+  else
+    return a;
+}
+
+/* All the functions here shouldn't evalute min or max of a and b
+ * These functions should return a op b */
+int f(int a, int b)
+{
+  return max (a, b) + min (a, b);
+}
+
+int f1(int a, int b)
+{
+  return max (a, b) * min (a, b);
+}
+
+int f2(int a, int b)
+{
+  return max (a, b) | min (a, b);
+}
+
+int f3(int a, int b)
+{
+  return max (a, b) & min (a, b);
+}
+
+int f5(int a, int b)
+{
+  return max (a, b) ^ min (a, b);
+}
+
+int f6(int a, int b)
+{
+  return max (a, b) == min (a, b);
+}
+
+int f7(int a, int b)
+{
+  return max (a, b) != min (a, b);
+}
+
+/* Function min should have MIN_EXPR */
+/* Function max should have MAX_EXPR */
+/* { dg-final { scan-tree-dump-times "MIN_EXPR" 1 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "MAX_EXPR" 1 "optimized" } } */