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 |
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
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 --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" } } */