Re: [PATCH]middle-end simplify complex if expressions where comparisons are inverse of one another.

2022-10-31 Thread Jeff Law via Gcc-patches



On 10/31/22 05:42, Tamar Christina via Gcc-patches wrote:

Hi,

This is a cleaned up version addressing all feedback.

Bootstrapped Regtested on aarch64-none-linux-gnu,
x86_64-pc-linux-gnu and no issues.

Ok for master?

Thanks,
Tamar

gcc/ChangeLog:

* match.pd: Add new rule.

gcc/testsuite/ChangeLog:

* gcc.target/aarch64/if-compare_1.c: New test.
* gcc.target/aarch64/if-compare_2.c: New test.


OK

jeff




RE: [PATCH]middle-end simplify complex if expressions where comparisons are inverse of one another.

2022-10-31 Thread Tamar Christina via Gcc-patches
Hi,

This is a cleaned up version addressing all feedback.

Bootstrapped Regtested on aarch64-none-linux-gnu,
x86_64-pc-linux-gnu and no issues.

Ok for master?

Thanks,
Tamar

gcc/ChangeLog:

* match.pd: Add new rule.

gcc/testsuite/ChangeLog:

* gcc.target/aarch64/if-compare_1.c: New test.
* gcc.target/aarch64/if-compare_2.c: New test.

--- inline copy of patch ---

diff --git a/gcc/match.pd b/gcc/match.pd
index 
297c4d7a2355c2faa2afb7cfa0b4e171a161ef39..463132bfd35cf61f50381cedd07d7617c638034b
 100644
--- a/gcc/match.pd
+++ b/gcc/match.pd
@@ -1903,6 +1903,61 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
  (if (INTEGRAL_TYPE_P (type))
   (bit_and @0 @1)))
 
+(for cmp (tcc_comparison)
+ icmp (inverted_tcc_comparison)
+ /* Fold (((a < b) & c) | ((a >= b) & d)) into (a < b ? c : d) & 1.  */
+ (simplify
+  (bit_ior
+   (bit_and:c (convert? (cmp@0  @01 @02)) @3)
+   (bit_and:c (convert? (icmp@4 @01 @02)) @5))
+(if (INTEGRAL_TYPE_P (type)
+/* The scalar version has to be canonicalized after vectorization
+   because it makes unconditional loads conditional ones, which
+   means we lose vectorization because the loads may trap.  */
+&& canonicalize_math_after_vectorization_p ())
+ (bit_and (cond @0 @3 @5) { build_one_cst (type); })))
+
+ /* Fold ((-(a < b) & c) | (-(a >= b) & d)) into a < b ? c : d.  This is
+canonicalized further and we recognize the conditional form:
+(a < b ? c : 0) | (a >= b ? d : 0) into a < b ? c : d.  */
+ (simplify
+  (bit_ior
+   (cond (cmp@0  @01 @02) @3 zerop)
+   (cond (icmp@4 @01 @02) @5 zerop))
+(if (INTEGRAL_TYPE_P (type)
+/* The scalar version has to be canonicalized after vectorization
+   because it makes unconditional loads conditional ones, which
+   means we lose vectorization because the loads may trap.  */
+&& canonicalize_math_after_vectorization_p ())
+(cond @0 @3 @5)))
+
+ /* Vector Fold (((a < b) & c) | ((a >= b) & d)) into a < b ? c : d. 
+and ((~(a < b) & c) | (~(a >= b) & d)) into a < b ? c : d.  */
+ (simplify
+  (bit_ior
+   (bit_and:c (vec_cond:s (cmp@0 @6 @7) @4 @5) @2)
+   (bit_and:c (vec_cond:s (icmp@1 @6 @7) @4 @5) @3))
+(if (integer_zerop (@5))
+ (switch
+  (if (integer_onep (@4))
+   (bit_and (vec_cond @0 @2 @3) @4))
+   (if (integer_minus_onep (@4))
+(vec_cond @0 @2 @3)))
+(if (integer_zerop (@4))
+ (switch
+  (if (integer_onep (@5))
+   (bit_and (vec_cond @0 @3 @2) @5))
+  (if (integer_minus_onep (@5))
+   (vec_cond @0 @3 @2))
+
+ /* Scalar Vectorized Fold ((-(a < b) & c) | (-(a >= b) & d))
+into a < b ? d : c.  */
+ (simplify
+  (bit_ior
+   (vec_cond:s (cmp@0 @4 @5) @2 integer_zerop)
+   (vec_cond:s (icmp@1 @4 @5) @3 integer_zerop))
+(vec_cond @0 @2 @3)))
+
 /* Transform X & -Y into X * Y when Y is { 0 or 1 }.  */
 (simplify
  (bit_and:c (convert? (negate zero_one_valued_p@0)) @1)
diff --git a/gcc/testsuite/gcc.target/aarch64/if-compare_1.c 
b/gcc/testsuite/gcc.target/aarch64/if-compare_1.c
new file mode 100644
index 
..53bbd779a30e1a30e0ce0e4e5eaf589bfaf570fe
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/if-compare_1.c
@@ -0,0 +1,47 @@
+/* { dg-do run } */
+/* { dg-additional-options "-O -save-temps" } */
+/* { dg-final { check-function-bodies "**" "" "" { target { le } } } } */
+
+extern void abort ();
+
+/*
+**zoo1:
+** cmp w0, w1
+** cselw0, w2, w3, lt
+** and w0, w0, 1
+** ret
+*/
+__attribute((noipa, noinline))
+int zoo1 (int a, int b, int c, int d)
+{
+   return ((a < b) & c) | ((a >= b) & d);
+}
+
+/*
+**zoo2:
+** cmp w0, w1
+** cselw0, w2, w3, lt
+** ret
+*/
+__attribute((noipa, noinline))
+int zoo2 (int a, int b, int c, int d)
+{
+   return (-(a < b) & c) | (-(a >= b) & d);
+}
+
+int main ()
+{
+  if (zoo1 (-3, 3, 5, 8) != 1)
+abort ();
+
+  if (zoo1 (3, -3, 5, 8) != 0)
+abort ();
+
+  if (zoo2 (-3, 3, 5, 8) != 5)
+abort ();
+
+  if (zoo2 (3, -3, 5, 8) != 8)
+abort ();
+
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/if-compare_2.c 
b/gcc/testsuite/gcc.target/aarch64/if-compare_2.c
new file mode 100644
index 
..14988abac45989578b198f28c7c0ea203959c08b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/if-compare_2.c
@@ -0,0 +1,96 @@
+/* { dg-do run } */
+/* { dg-additional-options "-O3 -std=c99 -save-temps" } */
+/* { dg-final { check-function-bodies "**" "" "" { target { le } } } } */
+
+#pragma GCC target "+nosve"
+
+#include 
+
+typedef int v4si __attribute__ ((vector_size (16)));
+
+/*
+**foo1:
+** cmgtv0.4s, v1.4s, v0.4s
+** bsl v0.16b, v2.16b, v3.16b
+** ret
+*/
+v4si foo1 (v4si a, v4si b, v4si c, v4si d) {
+return ((a < b) & c) | ((a >= b) & d);
+}
+
+/*
+**foo2:
+** cmgtv0.4s, v1.4s, v0.4s
+** bsl v0.16b, v3.16b, v2.16b
+** ret
+*/
+v4si foo2 (v4si a, 

RE: [PATCH]middle-end simplify complex if expressions where comparisons are inverse of one another.

2022-09-26 Thread Richard Biener via Gcc-patches
On Fri, 23 Sep 2022, Tamar Christina wrote:

> > -Original Message-
> > From: Richard Biener 
> > Sent: Friday, September 23, 2022 9:10 AM
> > To: Tamar Christina 
> > Cc: Andrew Pinski ; nd ; gcc-
> > patc...@gcc.gnu.org
> > Subject: RE: [PATCH]middle-end simplify complex if expressions where
> > comparisons are inverse of one another.
> > 
> > On Fri, 23 Sep 2022, Tamar Christina wrote:
> > 
> > > Hello,
> > >
> > > > where logical_inverted is somewhat contradicting using
> > > > zero_one_valued instead of truth_valued_p (I think the former might
> > > > not work for vector booleans?).
> > > >
> > > > In the end I'd prefer zero_one_valued_p but avoiding
> > > > inverse_conditions_p would be nice.
> > > >
> > > > Richard.
> > >
> > > It's not pretty but I've made it work and added more tests.
> > >
> > > Bootstrapped Regtested on aarch64-none-linux-gnu, x86_64-pc-linux-gnu
> > > and no issues.
> > >
> > > Ok for master?
> > >
> > > Thanks,
> > > Tamar
> > >
> > > gcc/ChangeLog:
> > >
> > >   * match.pd: Add new rule.
> > >
> > > gcc/testsuite/ChangeLog:
> > >
> > >   * gcc.target/aarch64/if-compare_1.c: New test.
> > >   * gcc.target/aarch64/if-compare_2.c: New test.
> > >
> > > --- inline copy of patch ---
> > >
> > > diff --git a/gcc/match.pd b/gcc/match.pd index
> > >
> > b61ed70e69b881a49177f10f20c1f92712bb8665..39da61bf117a6eb2924fc8a647
> > 3f
> > > b37ddadd60e9 100644
> > > --- a/gcc/match.pd
> > > +++ b/gcc/match.pd
> > > @@ -1903,6 +1903,101 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
> > >   (if (INTEGRAL_TYPE_P (type))
> > >(bit_and @0 @1)))
> > >
> > > +(for cmp (tcc_comparison)
> > > + icmp (inverted_tcc_comparison)
> > > + /* Fold (((a < b) & c) | ((a >= b) & d)) into (a < b ? c : d) & 1.
> > > +*/  (simplify
> > > +  (bit_ior
> > > +   (bit_and:c (convert? zero_one_valued_p@0) @2)
> > > +   (bit_and:c (convert? zero_one_valued_p@1) @3))
> > > +(with {
> > > +  enum tree_code c1
> > > + = (TREE_CODE (@0) == SSA_NAME
> > > +? gimple_assign_rhs_code (SSA_NAME_DEF_STMT (@0)) :
> > TREE_CODE
> > > +(@0));
> > > +
> > > +  enum tree_code c2
> > > + = (TREE_CODE (@1) == SSA_NAME
> > > +? gimple_assign_rhs_code (SSA_NAME_DEF_STMT (@1)) :
> > TREE_CODE (@1));
> > > + }
> > > +(if (INTEGRAL_TYPE_P (type)
> > > +  && c1 == cmp
> > > +  && c2 == icmp
> > 
> > So that doesn't have any advantage over doing
> > 
> >  (simplify
> >   (bit_ior
> >(bit_and:c (convert? (cmp@0 @01 @02)) @2)
> >(bit_and:c (convert? (icmp@1 @11 @12)) @3)) ...
> > 
> > I don't remember if that's what we had before.
> 
> No, the specific problem has always been applying zero_one_valued_p to the 
> right type.
> Before it was much shorter because I was using the tree  helper function to 
> get the inverses.
> 
> But with your suggestion I think I can do zero_one_valued_p on @0 and @1 
> instead..

But with comparsions and INTEGRAL_TYPE_P the value is always zero or one
so I'm confused.

> > 
> > > +  /* The scalar version has to be canonicalized after vectorization
> > > + because it makes unconditional loads conditional ones, which
> > > + means we lose vectorization because the loads may trap.  */
> > > +  && canonicalize_math_after_vectorization_p ())
> > > + (bit_and (cond @0 @2 @3) { build_one_cst (type); }
> > > +
> > > + /* Fold ((-(a < b) & c) | (-(a >= b) & d)) into a < b ? c : d.  */
> > 
> > The comment doesn't match the pattern below?
> 
> The pattern in the comment gets rewritten to this form eventually,
> so I match it instead.  I can update the comment but I thought the above
> made it more clear why these belong together ?

Please mention the canonicalized form in the comment as well.

> > 
> > > + (simplify
> > > +  (bit_ior
> > > +   (cond zero_one_valued_p@0 @2 zerop)
> > > +   (cond zero_one_valued_p@1 @3 zerop))
> > > +(with {
> > > +  enum tree_code c1
> > > + = (TREE_CODE (@0) == SSA_NAME
> > > +? gimple_assign_rhs_code (SSA_NAME_DEF_STMT (@0)) :
> > TREE_CODE
> > > +(@0));
> > > +
> > > +  enum tree_code c2
> > > + = (TREE_CODE (@1) == SSA_NAME
> > > +? gimple_assign_rhs_code (SSA_NAME_DEF_STMT (@1)) :
> > TREE_CODE (@1));
> > > + }
> > > +(if (INTEGRAL_TYPE_P (type)
> > > +  && c1 == cmp
> > > +  && c2 == icmp
> > > +  /* The scalar version has to be canonicalized after vectorization
> > > + because it makes unconditional loads conditional ones, which
> > > + means we lose vectorization because the loads may trap.  */
> > > +  && canonicalize_math_after_vectorization_p ())
> > > +(cond @0 @2 @3
> > > +
> > > + /* Vector Fold (((a < b) & c) | ((a >= b) & d)) into a < b ? c : d.
> > > +and ((~(a < b) & c) | (~(a >= b) & d)) into a < b ? c : d.  */
> > > +(simplify
> > > +  (bit_ior
> > > +   (bit_and:c (vec_cond:s @0 @4 @5) @2)
> > > +   (bit_and:c (vec_cond:s @1 @4 @5) @3))
> > > +(with {
> > > +  enum tree_code c1
> > > + = (TREE_CODE (@0) == SSA_NAME
> > > +? gimple_assign_rhs_code 

RE: [PATCH]middle-end simplify complex if expressions where comparisons are inverse of one another.

2022-09-23 Thread Tamar Christina via Gcc-patches
> -Original Message-
> From: Richard Biener 
> Sent: Friday, September 23, 2022 9:10 AM
> To: Tamar Christina 
> Cc: Andrew Pinski ; nd ; gcc-
> patc...@gcc.gnu.org
> Subject: RE: [PATCH]middle-end simplify complex if expressions where
> comparisons are inverse of one another.
> 
> On Fri, 23 Sep 2022, Tamar Christina wrote:
> 
> > Hello,
> >
> > > where logical_inverted is somewhat contradicting using
> > > zero_one_valued instead of truth_valued_p (I think the former might
> > > not work for vector booleans?).
> > >
> > > In the end I'd prefer zero_one_valued_p but avoiding
> > > inverse_conditions_p would be nice.
> > >
> > > Richard.
> >
> > It's not pretty but I've made it work and added more tests.
> >
> > Bootstrapped Regtested on aarch64-none-linux-gnu, x86_64-pc-linux-gnu
> > and no issues.
> >
> > Ok for master?
> >
> > Thanks,
> > Tamar
> >
> > gcc/ChangeLog:
> >
> > * match.pd: Add new rule.
> >
> > gcc/testsuite/ChangeLog:
> >
> > * gcc.target/aarch64/if-compare_1.c: New test.
> > * gcc.target/aarch64/if-compare_2.c: New test.
> >
> > --- inline copy of patch ---
> >
> > diff --git a/gcc/match.pd b/gcc/match.pd index
> >
> b61ed70e69b881a49177f10f20c1f92712bb8665..39da61bf117a6eb2924fc8a647
> 3f
> > b37ddadd60e9 100644
> > --- a/gcc/match.pd
> > +++ b/gcc/match.pd
> > @@ -1903,6 +1903,101 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
> >   (if (INTEGRAL_TYPE_P (type))
> >(bit_and @0 @1)))
> >
> > +(for cmp (tcc_comparison)
> > + icmp (inverted_tcc_comparison)
> > + /* Fold (((a < b) & c) | ((a >= b) & d)) into (a < b ? c : d) & 1.
> > +*/  (simplify
> > +  (bit_ior
> > +   (bit_and:c (convert? zero_one_valued_p@0) @2)
> > +   (bit_and:c (convert? zero_one_valued_p@1) @3))
> > +(with {
> > +  enum tree_code c1
> > +   = (TREE_CODE (@0) == SSA_NAME
> > +  ? gimple_assign_rhs_code (SSA_NAME_DEF_STMT (@0)) :
> TREE_CODE
> > +(@0));
> > +
> > +  enum tree_code c2
> > +   = (TREE_CODE (@1) == SSA_NAME
> > +  ? gimple_assign_rhs_code (SSA_NAME_DEF_STMT (@1)) :
> TREE_CODE (@1));
> > + }
> > +(if (INTEGRAL_TYPE_P (type)
> > +&& c1 == cmp
> > +&& c2 == icmp
> 
> So that doesn't have any advantage over doing
> 
>  (simplify
>   (bit_ior
>(bit_and:c (convert? (cmp@0 @01 @02)) @2)
>(bit_and:c (convert? (icmp@1 @11 @12)) @3)) ...
> 
> I don't remember if that's what we had before.

No, the specific problem has always been applying zero_one_valued_p to the 
right type.
Before it was much shorter because I was using the tree  helper function to get 
the inverses.

But with your suggestion I think I can do zero_one_valued_p on @0 and @1 
instead..

> 
> > +/* The scalar version has to be canonicalized after vectorization
> > +   because it makes unconditional loads conditional ones, which
> > +   means we lose vectorization because the loads may trap.  */
> > +&& canonicalize_math_after_vectorization_p ())
> > + (bit_and (cond @0 @2 @3) { build_one_cst (type); }
> > +
> > + /* Fold ((-(a < b) & c) | (-(a >= b) & d)) into a < b ? c : d.  */
> 
> The comment doesn't match the pattern below?

The pattern in the comment gets rewritten to this form eventually,
so I match it instead.  I can update the comment but I thought the above
made it more clear why these belong together 

> 
> > + (simplify
> > +  (bit_ior
> > +   (cond zero_one_valued_p@0 @2 zerop)
> > +   (cond zero_one_valued_p@1 @3 zerop))
> > +(with {
> > +  enum tree_code c1
> > +   = (TREE_CODE (@0) == SSA_NAME
> > +  ? gimple_assign_rhs_code (SSA_NAME_DEF_STMT (@0)) :
> TREE_CODE
> > +(@0));
> > +
> > +  enum tree_code c2
> > +   = (TREE_CODE (@1) == SSA_NAME
> > +  ? gimple_assign_rhs_code (SSA_NAME_DEF_STMT (@1)) :
> TREE_CODE (@1));
> > + }
> > +(if (INTEGRAL_TYPE_P (type)
> > +&& c1 == cmp
> > +&& c2 == icmp
> > +/* The scalar version has to be canonicalized after vectorization
> > +   because it makes unconditional loads conditional ones, which
> > +   means we lose vectorization because the loads may trap.  */
> > +&& canonicalize_math_after_vectorization_p ())
> > +(cond @0 @2 @3
> > +
> > + /* Vector Fold (((a < b) & c) | ((a >= b) & d)) into a < b ? c : d.
> > +and ((~(a < b) & c) | (~(a >= b) & d)) into a < b ? c : d.  */
> > +(simplify
> > +  (bit_ior
> > +   (bit_and:c (vec_cond:s @0 @4 @5) @2)
> > +   (bit_and:c (vec_cond:s @1 @4 @5) @3))
> > +(with {
> > +  enum tree_code c1
> > +   = (TREE_CODE (@0) == SSA_NAME
> > +  ? gimple_assign_rhs_code (SSA_NAME_DEF_STMT (@0)) :
> TREE_CODE
> > +(@0));
> > +
> > +  enum tree_code c2
> > +   = (TREE_CODE (@1) == SSA_NAME
> > +  ? gimple_assign_rhs_code (SSA_NAME_DEF_STMT (@1)) :
> TREE_CODE (@1));
> > + }
> > + (if (c1 == cmp && c2 == icmp)
> > +  (if (integer_zerop (@5))
> > +   (switch
> > +   (if (integer_onep (@4))
> > +(bit_and (vec_cond @0 @2 @3) @4))
> > +   (if (integer_minus_onep (@4))
> > +

RE: [PATCH]middle-end simplify complex if expressions where comparisons are inverse of one another.

2022-09-23 Thread Richard Biener via Gcc-patches
On Fri, 23 Sep 2022, Tamar Christina wrote:

> Hello,
> 
> > where logical_inverted is somewhat contradicting using zero_one_valued
> > instead of truth_valued_p (I think the former might not work for vector
> > booleans?).
> > 
> > In the end I'd prefer zero_one_valued_p but avoiding inverse_conditions_p
> > would be nice.
> > 
> > Richard.
> 
> It's not pretty but I've made it work and added more tests.
> 
> Bootstrapped Regtested on aarch64-none-linux-gnu,
> x86_64-pc-linux-gnu and no issues.
> 
> Ok for master?
> 
> Thanks,
> Tamar
> 
> gcc/ChangeLog:
> 
>   * match.pd: Add new rule.
> 
> gcc/testsuite/ChangeLog:
> 
>   * gcc.target/aarch64/if-compare_1.c: New test.
>   * gcc.target/aarch64/if-compare_2.c: New test.
> 
> --- inline copy of patch ---
> 
> diff --git a/gcc/match.pd b/gcc/match.pd
> index 
> b61ed70e69b881a49177f10f20c1f92712bb8665..39da61bf117a6eb2924fc8a6473fb37ddadd60e9
>  100644
> --- a/gcc/match.pd
> +++ b/gcc/match.pd
> @@ -1903,6 +1903,101 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
>   (if (INTEGRAL_TYPE_P (type))
>(bit_and @0 @1)))
>  
> +(for cmp (tcc_comparison)
> + icmp (inverted_tcc_comparison)
> + /* Fold (((a < b) & c) | ((a >= b) & d)) into (a < b ? c : d) & 1.  */
> + (simplify
> +  (bit_ior
> +   (bit_and:c (convert? zero_one_valued_p@0) @2)
> +   (bit_and:c (convert? zero_one_valued_p@1) @3))
> +(with {
> +  enum tree_code c1
> + = (TREE_CODE (@0) == SSA_NAME
> +? gimple_assign_rhs_code (SSA_NAME_DEF_STMT (@0)) : TREE_CODE (@0));
> +
> +  enum tree_code c2
> + = (TREE_CODE (@1) == SSA_NAME
> +? gimple_assign_rhs_code (SSA_NAME_DEF_STMT (@1)) : TREE_CODE (@1));
> + }
> +(if (INTEGRAL_TYPE_P (type)
> +  && c1 == cmp
> +  && c2 == icmp

So that doesn't have any advantage over doing

 (simplify
  (bit_ior
   (bit_and:c (convert? (cmp@0 @01 @02)) @2)
   (bit_and:c (convert? (icmp@1 @11 @12)) @3))
...

I don't remember if that's what we had before.

> +  /* The scalar version has to be canonicalized after vectorization
> + because it makes unconditional loads conditional ones, which
> + means we lose vectorization because the loads may trap.  */
> +  && canonicalize_math_after_vectorization_p ())
> + (bit_and (cond @0 @2 @3) { build_one_cst (type); }
> +
> + /* Fold ((-(a < b) & c) | (-(a >= b) & d)) into a < b ? c : d.  */

The comment doesn't match the pattern below?

> + (simplify
> +  (bit_ior
> +   (cond zero_one_valued_p@0 @2 zerop)
> +   (cond zero_one_valued_p@1 @3 zerop))
> +(with {
> +  enum tree_code c1
> + = (TREE_CODE (@0) == SSA_NAME
> +? gimple_assign_rhs_code (SSA_NAME_DEF_STMT (@0)) : TREE_CODE (@0));
> +
> +  enum tree_code c2
> + = (TREE_CODE (@1) == SSA_NAME
> +? gimple_assign_rhs_code (SSA_NAME_DEF_STMT (@1)) : TREE_CODE (@1));
> + }
> +(if (INTEGRAL_TYPE_P (type)
> +  && c1 == cmp
> +  && c2 == icmp
> +  /* The scalar version has to be canonicalized after vectorization
> + because it makes unconditional loads conditional ones, which
> + means we lose vectorization because the loads may trap.  */
> +  && canonicalize_math_after_vectorization_p ())
> +(cond @0 @2 @3
> +
> + /* Vector Fold (((a < b) & c) | ((a >= b) & d)) into a < b ? c : d. 
> +and ((~(a < b) & c) | (~(a >= b) & d)) into a < b ? c : d.  */
> + (simplify
> +  (bit_ior
> +   (bit_and:c (vec_cond:s @0 @4 @5) @2)
> +   (bit_and:c (vec_cond:s @1 @4 @5) @3))
> +(with {
> +  enum tree_code c1
> + = (TREE_CODE (@0) == SSA_NAME
> +? gimple_assign_rhs_code (SSA_NAME_DEF_STMT (@0)) : TREE_CODE (@0));
> +
> +  enum tree_code c2
> + = (TREE_CODE (@1) == SSA_NAME
> +? gimple_assign_rhs_code (SSA_NAME_DEF_STMT (@1)) : TREE_CODE (@1));
> + }
> + (if (c1 == cmp && c2 == icmp)
> +  (if (integer_zerop (@5))
> +   (switch
> + (if (integer_onep (@4))
> +  (bit_and (vec_cond @0 @2 @3) @4))
> + (if (integer_minus_onep (@4))
> +  (vec_cond @0 @2 @3)))
> +  (if (integer_zerop (@4))
> +   (switch
> + (if (integer_onep (@5))
> +  (bit_and (vec_cond @0 @3 @2) @5))
> + (if (integer_minus_onep (@5))
> +  (vec_cond @0 @3 @2
> +
> + /* Scalar Vectorized Fold ((-(a < b) & c) | (-(a >= b) & d))
> +into a < b ? d : c.  */
> + (simplify
> +  (bit_ior
> +   (vec_cond:s @0 @2 integer_zerop)
> +   (vec_cond:s @1 @3 integer_zerop))
> +(with {
> +  enum tree_code c1
> + = (TREE_CODE (@0) == SSA_NAME
> +? gimple_assign_rhs_code (SSA_NAME_DEF_STMT (@0)) : TREE_CODE (@0));
> +
> +  enum tree_code c2
> + = (TREE_CODE (@1) == SSA_NAME
> +? gimple_assign_rhs_code (SSA_NAME_DEF_STMT (@1)) : TREE_CODE (@1));
> + }
> + (if (c1 == cmp && c2 == icmp)
> +  (vec_cond @0 @2 @3)
> +

As you say, it's not pretty.  When looking at

int zoo1 (int a, int b, int c, int d)
{  
   return ((a < b) & c) | ((a >= b) 

RE: [PATCH]middle-end simplify complex if expressions where comparisons are inverse of one another.

2022-09-23 Thread Tamar Christina via Gcc-patches
Hello,

> where logical_inverted is somewhat contradicting using zero_one_valued
> instead of truth_valued_p (I think the former might not work for vector
> booleans?).
> 
> In the end I'd prefer zero_one_valued_p but avoiding inverse_conditions_p
> would be nice.
> 
> Richard.

It's not pretty but I've made it work and added more tests.

Bootstrapped Regtested on aarch64-none-linux-gnu,
x86_64-pc-linux-gnu and no issues.

Ok for master?

Thanks,
Tamar

gcc/ChangeLog:

* match.pd: Add new rule.

gcc/testsuite/ChangeLog:

* gcc.target/aarch64/if-compare_1.c: New test.
* gcc.target/aarch64/if-compare_2.c: New test.

--- inline copy of patch ---

diff --git a/gcc/match.pd b/gcc/match.pd
index 
b61ed70e69b881a49177f10f20c1f92712bb8665..39da61bf117a6eb2924fc8a6473fb37ddadd60e9
 100644
--- a/gcc/match.pd
+++ b/gcc/match.pd
@@ -1903,6 +1903,101 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
  (if (INTEGRAL_TYPE_P (type))
   (bit_and @0 @1)))
 
+(for cmp (tcc_comparison)
+ icmp (inverted_tcc_comparison)
+ /* Fold (((a < b) & c) | ((a >= b) & d)) into (a < b ? c : d) & 1.  */
+ (simplify
+  (bit_ior
+   (bit_and:c (convert? zero_one_valued_p@0) @2)
+   (bit_and:c (convert? zero_one_valued_p@1) @3))
+(with {
+  enum tree_code c1
+   = (TREE_CODE (@0) == SSA_NAME
+  ? gimple_assign_rhs_code (SSA_NAME_DEF_STMT (@0)) : TREE_CODE (@0));
+
+  enum tree_code c2
+   = (TREE_CODE (@1) == SSA_NAME
+  ? gimple_assign_rhs_code (SSA_NAME_DEF_STMT (@1)) : TREE_CODE (@1));
+ }
+(if (INTEGRAL_TYPE_P (type)
+&& c1 == cmp
+&& c2 == icmp
+/* The scalar version has to be canonicalized after vectorization
+   because it makes unconditional loads conditional ones, which
+   means we lose vectorization because the loads may trap.  */
+&& canonicalize_math_after_vectorization_p ())
+ (bit_and (cond @0 @2 @3) { build_one_cst (type); }
+
+ /* Fold ((-(a < b) & c) | (-(a >= b) & d)) into a < b ? c : d.  */
+ (simplify
+  (bit_ior
+   (cond zero_one_valued_p@0 @2 zerop)
+   (cond zero_one_valued_p@1 @3 zerop))
+(with {
+  enum tree_code c1
+   = (TREE_CODE (@0) == SSA_NAME
+  ? gimple_assign_rhs_code (SSA_NAME_DEF_STMT (@0)) : TREE_CODE (@0));
+
+  enum tree_code c2
+   = (TREE_CODE (@1) == SSA_NAME
+  ? gimple_assign_rhs_code (SSA_NAME_DEF_STMT (@1)) : TREE_CODE (@1));
+ }
+(if (INTEGRAL_TYPE_P (type)
+&& c1 == cmp
+&& c2 == icmp
+/* The scalar version has to be canonicalized after vectorization
+   because it makes unconditional loads conditional ones, which
+   means we lose vectorization because the loads may trap.  */
+&& canonicalize_math_after_vectorization_p ())
+(cond @0 @2 @3
+
+ /* Vector Fold (((a < b) & c) | ((a >= b) & d)) into a < b ? c : d. 
+and ((~(a < b) & c) | (~(a >= b) & d)) into a < b ? c : d.  */
+ (simplify
+  (bit_ior
+   (bit_and:c (vec_cond:s @0 @4 @5) @2)
+   (bit_and:c (vec_cond:s @1 @4 @5) @3))
+(with {
+  enum tree_code c1
+   = (TREE_CODE (@0) == SSA_NAME
+  ? gimple_assign_rhs_code (SSA_NAME_DEF_STMT (@0)) : TREE_CODE (@0));
+
+  enum tree_code c2
+   = (TREE_CODE (@1) == SSA_NAME
+  ? gimple_assign_rhs_code (SSA_NAME_DEF_STMT (@1)) : TREE_CODE (@1));
+ }
+ (if (c1 == cmp && c2 == icmp)
+  (if (integer_zerop (@5))
+   (switch
+   (if (integer_onep (@4))
+(bit_and (vec_cond @0 @2 @3) @4))
+   (if (integer_minus_onep (@4))
+(vec_cond @0 @2 @3)))
+  (if (integer_zerop (@4))
+   (switch
+   (if (integer_onep (@5))
+(bit_and (vec_cond @0 @3 @2) @5))
+   (if (integer_minus_onep (@5))
+(vec_cond @0 @3 @2
+
+ /* Scalar Vectorized Fold ((-(a < b) & c) | (-(a >= b) & d))
+into a < b ? d : c.  */
+ (simplify
+  (bit_ior
+   (vec_cond:s @0 @2 integer_zerop)
+   (vec_cond:s @1 @3 integer_zerop))
+(with {
+  enum tree_code c1
+   = (TREE_CODE (@0) == SSA_NAME
+  ? gimple_assign_rhs_code (SSA_NAME_DEF_STMT (@0)) : TREE_CODE (@0));
+
+  enum tree_code c2
+   = (TREE_CODE (@1) == SSA_NAME
+  ? gimple_assign_rhs_code (SSA_NAME_DEF_STMT (@1)) : TREE_CODE (@1));
+ }
+ (if (c1 == cmp && c2 == icmp)
+  (vec_cond @0 @2 @3)
+
 /* Transform X & -Y into X * Y when Y is { 0 or 1 }.  */
 (simplify
  (bit_and:c (convert? (negate zero_one_valued_p@0)) @1)
diff --git a/gcc/testsuite/gcc.target/aarch64/if-compare_1.c 
b/gcc/testsuite/gcc.target/aarch64/if-compare_1.c
new file mode 100644
index 
..53bbd779a30e1a30e0ce0e4e5eaf589bfaf570fe
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/if-compare_1.c
@@ -0,0 +1,47 @@
+/* { dg-do run } */
+/* { dg-additional-options "-O -save-temps" } */
+/* { dg-final { check-function-bodies "**" "" "" { target { le } } } } */
+
+extern void abort ();
+
+/*
+**zoo1:
+** 

RE: [PATCH]middle-end simplify complex if expressions where comparisons are inverse of one another.

2022-07-08 Thread Richard Biener via Gcc-patches
On Thu, 7 Jul 2022, Tamar Christina wrote:

> > -Original Message-
> > From: Andrew Pinski 
> > Sent: Wednesday, July 6, 2022 8:37 PM
> > To: Tamar Christina 
> > Cc: Richard Biener ; nd ; gcc-
> > patc...@gcc.gnu.org
> > Subject: Re: [PATCH]middle-end simplify complex if expressions where
> > comparisons are inverse of one another.
> > 
> > On Wed, Jul 6, 2022 at 9:06 AM Tamar Christina 
> > wrote:
> > >
> > > > -Original Message-
> > > > From: Andrew Pinski 
> > > > Sent: Wednesday, July 6, 2022 3:10 AM
> > > > To: Tamar Christina 
> > > > Cc: Richard Biener ; nd ; gcc-
> > > > patc...@gcc.gnu.org
> > > > Subject: Re: [PATCH]middle-end simplify complex if expressions where
> > > > comparisons are inverse of one another.
> > > >
> > > > On Tue, Jul 5, 2022 at 8:16 AM Tamar Christina via Gcc-patches  > > > patc...@gcc.gnu.org> wrote:
> > > > >
> > > > >
> > > > >
> > > > > > -Original Message-
> > > > > > From: Richard Biener 
> > > > > > Sent: Monday, June 20, 2022 9:57 AM
> > > > > > To: Tamar Christina 
> > > > > > Cc: gcc-patches@gcc.gnu.org; nd 
> > > > > > Subject: Re: [PATCH]middle-end simplify complex if expressions
> > > > > > where comparisons are inverse of one another.
> > > > > >
> > > > > > On Thu, 16 Jun 2022, Tamar Christina wrote:
> > > > > >
> > > > > > > Hi All,
> > > > > > >
> > > > > > > This optimizes the following sequence
> > > > > > >
> > > > > > >   ((a < b) & c) | ((a >= b) & d)
> > > > > > >
> > > > > > > into
> > > > > > >
> > > > > > >   (a < b ? c : d) & 1
> > > > > > >
> > > > > > > for scalar. On vector we can omit the & 1.
> > > > > > >
> > > > > > > This changes the code generation from
> > > > > > >
> > > > > > > zoo2:
> > > > > > > cmp w0, w1
> > > > > > > csetw0, lt
> > > > > > > csetw1, ge
> > > > > > > and w0, w0, w2
> > > > > > > and w1, w1, w3
> > > > > > > orr w0, w0, w1
> > > > > > > ret
> > > > > > >
> > > > > > > into
> > > > > > >
> > > > > > > cmp w0, w1
> > > > > > > cselw0, w2, w3, lt
> > > > > > > and w0, w0, 1
> > > > > > > ret
> > > > > > >
> > > > > > > and significantly reduces the number of selects we have to do
> > > > > > > in the vector code.
> > > > > > >
> > > > > > > Bootstrapped Regtested on aarch64-none-linux-gnu,
> > > > > > > x86_64-pc-linux-gnu and no issues.
> > > > > > >
> > > > > > > Ok for master?
> > > > > > >
> > > > > > > Thanks,
> > > > > > > Tamar
> > > > > > >
> > > > > > > gcc/ChangeLog:
> > > > > > >
> > > > > > > * fold-const.cc (inverse_conditions_p): Traverse if SSA_NAME.
> > > > > > > * match.pd: Add new rule.
> > > > > > >
> > > > > > > gcc/testsuite/ChangeLog:
> > > > > > >
> > > > > > > * gcc.target/aarch64/if-compare_1.c: New test.
> > > > > > > * gcc.target/aarch64/if-compare_2.c: New test.
> > > > > > >
> > > > > > > --- inline copy of patch --
> > > > > > > diff --git a/gcc/fold-const.cc b/gcc/fold-const.cc index
> > > > > > >
> > > > > >
> > > >
> > 39a5a52958d87497f301826e706886b290771a2d..f180599b90150acd3ed895a64
> > > > > > 280
> > > > > > > aa3255061256 100644
> > > > > > > --- a/gcc/fold-const.cc
> > > > > > > +++ b/gcc/fold-const.cc
> > > > > > > @@ -2833,15 +2833,38 @@ compcode_to_comparison (enum
> > > > > > comparison_code
> > > > > > > code)  bool  inverse_conditions_p (const_tree cond1,
> > > > > > > const_tree
> > > > > > > cond2) {
> > > > > > > -  return (COMPARISON_CLASS_P (cond1)
> > > > > > > - && COMPARISON_CLASS_P (cond2)
> > > > > > > - && (invert_tree_comparison
> > > > > > > - (TREE_CODE (cond1),
> > > > > > > -  HONOR_NANS (TREE_OPERAND (cond1, 0))) == TREE_CODE
> > > > > > (cond2))
> > > > > > > - && operand_equal_p (TREE_OPERAND (cond1, 0),
> > > > > > > - TREE_OPERAND (cond2, 0), 0)
> > > > > > > - && operand_equal_p (TREE_OPERAND (cond1, 1),
> > > > > > > - TREE_OPERAND (cond2, 1), 0));
> > > > > > > +  if (COMPARISON_CLASS_P (cond1)
> > > > > > > +  && COMPARISON_CLASS_P (cond2)
> > > > > > > +  && (invert_tree_comparison
> > > > > > > +  (TREE_CODE (cond1),
> > > > > > > +   HONOR_NANS (TREE_OPERAND (cond1, 0))) == TREE_CODE
> > > > > > (cond2))
> > > > > > > +  && operand_equal_p (TREE_OPERAND (cond1, 0),
> > > > > > > + TREE_OPERAND (cond2, 0), 0)
> > > > > > > +  && operand_equal_p (TREE_OPERAND (cond1, 1),
> > > > > > > + TREE_OPERAND (cond2, 1), 0))
> > > > > > > +return true;
> > > > > > > +
> > > > > > > +  if (TREE_CODE (cond1) == SSA_NAME
> > > > > > > +  && TREE_CODE (cond2) == SSA_NAME)
> > > > > > > +{
> > > > > > > +  gimple *gcond1 = SSA_NAME_DEF_STMT (cond1);
> > > > > > > +  gimple *gcond2 = SSA_NAME_DEF_STMT (cond2);
> > > > > > > +  if (!is_gimple_assign (gcond1) || !is_gimple_assign 
> > > > > > > (gcond2))
> > > > > > > +   return false;
> > > > > > > +
> > > > > > > +  tree_code 

Re: [PATCH]middle-end simplify complex if expressions where comparisons are inverse of one another.

2022-07-07 Thread Jeff Law via Gcc-patches




On 7/5/2022 8:09 PM, Andrew Pinski via Gcc-patches wrote:


Not your fault but there are now like two different predicates for a
boolean like operand.
zero_one_valued_p and truth_valued_p and a third way to describe it is
to use SSA_NAME and check ssa_name_has_boolean_range.
The latter is meant to catch cases where analysis indicates that a given 
SSA_NAME only takes on the values 0 or 1, regardless of the actual size 
of the SSA_NAME.


It pre-dates having reasonable range information available in DOM and 
from reviewing the existing uses in DOM, I would expect Ranger to make 
most, if not all, of this code useless.


jeff



RE: [PATCH]middle-end simplify complex if expressions where comparisons are inverse of one another.

2022-07-07 Thread Tamar Christina via Gcc-patches
> -Original Message-
> From: Andrew Pinski 
> Sent: Wednesday, July 6, 2022 8:37 PM
> To: Tamar Christina 
> Cc: Richard Biener ; nd ; gcc-
> patc...@gcc.gnu.org
> Subject: Re: [PATCH]middle-end simplify complex if expressions where
> comparisons are inverse of one another.
> 
> On Wed, Jul 6, 2022 at 9:06 AM Tamar Christina 
> wrote:
> >
> > > -Original Message-
> > > From: Andrew Pinski 
> > > Sent: Wednesday, July 6, 2022 3:10 AM
> > > To: Tamar Christina 
> > > Cc: Richard Biener ; nd ; gcc-
> > > patc...@gcc.gnu.org
> > > Subject: Re: [PATCH]middle-end simplify complex if expressions where
> > > comparisons are inverse of one another.
> > >
> > > On Tue, Jul 5, 2022 at 8:16 AM Tamar Christina via Gcc-patches  > > patc...@gcc.gnu.org> wrote:
> > > >
> > > >
> > > >
> > > > > -Original Message-
> > > > > From: Richard Biener 
> > > > > Sent: Monday, June 20, 2022 9:57 AM
> > > > > To: Tamar Christina 
> > > > > Cc: gcc-patches@gcc.gnu.org; nd 
> > > > > Subject: Re: [PATCH]middle-end simplify complex if expressions
> > > > > where comparisons are inverse of one another.
> > > > >
> > > > > On Thu, 16 Jun 2022, Tamar Christina wrote:
> > > > >
> > > > > > Hi All,
> > > > > >
> > > > > > This optimizes the following sequence
> > > > > >
> > > > > >   ((a < b) & c) | ((a >= b) & d)
> > > > > >
> > > > > > into
> > > > > >
> > > > > >   (a < b ? c : d) & 1
> > > > > >
> > > > > > for scalar. On vector we can omit the & 1.
> > > > > >
> > > > > > This changes the code generation from
> > > > > >
> > > > > > zoo2:
> > > > > > cmp w0, w1
> > > > > > csetw0, lt
> > > > > > csetw1, ge
> > > > > > and w0, w0, w2
> > > > > > and w1, w1, w3
> > > > > > orr w0, w0, w1
> > > > > > ret
> > > > > >
> > > > > > into
> > > > > >
> > > > > > cmp w0, w1
> > > > > > cselw0, w2, w3, lt
> > > > > > and w0, w0, 1
> > > > > > ret
> > > > > >
> > > > > > and significantly reduces the number of selects we have to do
> > > > > > in the vector code.
> > > > > >
> > > > > > Bootstrapped Regtested on aarch64-none-linux-gnu,
> > > > > > x86_64-pc-linux-gnu and no issues.
> > > > > >
> > > > > > Ok for master?
> > > > > >
> > > > > > Thanks,
> > > > > > Tamar
> > > > > >
> > > > > > gcc/ChangeLog:
> > > > > >
> > > > > > * fold-const.cc (inverse_conditions_p): Traverse if SSA_NAME.
> > > > > > * match.pd: Add new rule.
> > > > > >
> > > > > > gcc/testsuite/ChangeLog:
> > > > > >
> > > > > > * gcc.target/aarch64/if-compare_1.c: New test.
> > > > > > * gcc.target/aarch64/if-compare_2.c: New test.
> > > > > >
> > > > > > --- inline copy of patch --
> > > > > > diff --git a/gcc/fold-const.cc b/gcc/fold-const.cc index
> > > > > >
> > > > >
> > >
> 39a5a52958d87497f301826e706886b290771a2d..f180599b90150acd3ed895a64
> > > > > 280
> > > > > > aa3255061256 100644
> > > > > > --- a/gcc/fold-const.cc
> > > > > > +++ b/gcc/fold-const.cc
> > > > > > @@ -2833,15 +2833,38 @@ compcode_to_comparison (enum
> > > > > comparison_code
> > > > > > code)  bool  inverse_conditions_p (const_tree cond1,
> > > > > > const_tree
> > > > > > cond2) {
> > > > > > -  return (COMPARISON_CLASS_P (cond1)
> > > > > > - && COMPARISON_CLASS_P (cond2)
> > > > > > - && (invert_tree_comparison
> > > > > > - (TREE_CODE (cond1),
> > > > > > -  HONOR_NANS (TREE_OPERAND (cond1, 0))) == TREE_CODE
> > > > > (cond2))
> > > > > > - && operand_equal_p (TREE_OPERAND (cond1, 0),
> > > > > > - TREE_OPERAND (cond2, 0), 0)
> > > > > > - && operand_equal_p (TREE_OPERAND (cond1, 1),
> > > > > > - TREE_OPERAND (cond2, 1), 0));
> > > > > > +  if (COMPARISON_CLASS_P (cond1)
> > > > > > +  && COMPARISON_CLASS_P (cond2)
> > > > > > +  && (invert_tree_comparison
> > > > > > +  (TREE_CODE (cond1),
> > > > > > +   HONOR_NANS (TREE_OPERAND (cond1, 0))) == TREE_CODE
> > > > > (cond2))
> > > > > > +  && operand_equal_p (TREE_OPERAND (cond1, 0),
> > > > > > + TREE_OPERAND (cond2, 0), 0)
> > > > > > +  && operand_equal_p (TREE_OPERAND (cond1, 1),
> > > > > > + TREE_OPERAND (cond2, 1), 0))
> > > > > > +return true;
> > > > > > +
> > > > > > +  if (TREE_CODE (cond1) == SSA_NAME
> > > > > > +  && TREE_CODE (cond2) == SSA_NAME)
> > > > > > +{
> > > > > > +  gimple *gcond1 = SSA_NAME_DEF_STMT (cond1);
> > > > > > +  gimple *gcond2 = SSA_NAME_DEF_STMT (cond2);
> > > > > > +  if (!is_gimple_assign (gcond1) || !is_gimple_assign (gcond2))
> > > > > > +   return false;
> > > > > > +
> > > > > > +  tree_code code1 = gimple_assign_rhs_code (gcond1);
> > > > > > +  tree_code code2 = gimple_assign_rhs_code (gcond2);
> > > > > > +  return TREE_CODE_CLASS (code1) == tcc_comparison
> > > > > > +&& TREE_CODE_CLASS (code2) == tcc_comparison
> > > > > > +&& invert_tree_comparison (code1,
> > > > > > + 

Re: [PATCH]middle-end simplify complex if expressions where comparisons are inverse of one another.

2022-07-06 Thread Andrew Pinski via Gcc-patches
On Wed, Jul 6, 2022 at 9:06 AM Tamar Christina  wrote:
>
> > -Original Message-
> > From: Andrew Pinski 
> > Sent: Wednesday, July 6, 2022 3:10 AM
> > To: Tamar Christina 
> > Cc: Richard Biener ; nd ; gcc-
> > patc...@gcc.gnu.org
> > Subject: Re: [PATCH]middle-end simplify complex if expressions where
> > comparisons are inverse of one another.
> >
> > On Tue, Jul 5, 2022 at 8:16 AM Tamar Christina via Gcc-patches  > patc...@gcc.gnu.org> wrote:
> > >
> > >
> > >
> > > > -Original Message-
> > > > From: Richard Biener 
> > > > Sent: Monday, June 20, 2022 9:57 AM
> > > > To: Tamar Christina 
> > > > Cc: gcc-patches@gcc.gnu.org; nd 
> > > > Subject: Re: [PATCH]middle-end simplify complex if expressions where
> > > > comparisons are inverse of one another.
> > > >
> > > > On Thu, 16 Jun 2022, Tamar Christina wrote:
> > > >
> > > > > Hi All,
> > > > >
> > > > > This optimizes the following sequence
> > > > >
> > > > >   ((a < b) & c) | ((a >= b) & d)
> > > > >
> > > > > into
> > > > >
> > > > >   (a < b ? c : d) & 1
> > > > >
> > > > > for scalar. On vector we can omit the & 1.
> > > > >
> > > > > This changes the code generation from
> > > > >
> > > > > zoo2:
> > > > > cmp w0, w1
> > > > > csetw0, lt
> > > > > csetw1, ge
> > > > > and w0, w0, w2
> > > > > and w1, w1, w3
> > > > > orr w0, w0, w1
> > > > > ret
> > > > >
> > > > > into
> > > > >
> > > > > cmp w0, w1
> > > > > cselw0, w2, w3, lt
> > > > > and w0, w0, 1
> > > > > ret
> > > > >
> > > > > and significantly reduces the number of selects we have to do in
> > > > > the vector code.
> > > > >
> > > > > Bootstrapped Regtested on aarch64-none-linux-gnu,
> > > > > x86_64-pc-linux-gnu and no issues.
> > > > >
> > > > > Ok for master?
> > > > >
> > > > > Thanks,
> > > > > Tamar
> > > > >
> > > > > gcc/ChangeLog:
> > > > >
> > > > > * fold-const.cc (inverse_conditions_p): Traverse if SSA_NAME.
> > > > > * match.pd: Add new rule.
> > > > >
> > > > > gcc/testsuite/ChangeLog:
> > > > >
> > > > > * gcc.target/aarch64/if-compare_1.c: New test.
> > > > > * gcc.target/aarch64/if-compare_2.c: New test.
> > > > >
> > > > > --- inline copy of patch --
> > > > > diff --git a/gcc/fold-const.cc b/gcc/fold-const.cc index
> > > > >
> > > >
> > 39a5a52958d87497f301826e706886b290771a2d..f180599b90150acd3ed895a64
> > > > 280
> > > > > aa3255061256 100644
> > > > > --- a/gcc/fold-const.cc
> > > > > +++ b/gcc/fold-const.cc
> > > > > @@ -2833,15 +2833,38 @@ compcode_to_comparison (enum
> > > > comparison_code
> > > > > code)  bool  inverse_conditions_p (const_tree cond1, const_tree
> > > > > cond2) {
> > > > > -  return (COMPARISON_CLASS_P (cond1)
> > > > > - && COMPARISON_CLASS_P (cond2)
> > > > > - && (invert_tree_comparison
> > > > > - (TREE_CODE (cond1),
> > > > > -  HONOR_NANS (TREE_OPERAND (cond1, 0))) == TREE_CODE
> > > > (cond2))
> > > > > - && operand_equal_p (TREE_OPERAND (cond1, 0),
> > > > > - TREE_OPERAND (cond2, 0), 0)
> > > > > - && operand_equal_p (TREE_OPERAND (cond1, 1),
> > > > > - TREE_OPERAND (cond2, 1), 0));
> > > > > +  if (COMPARISON_CLASS_P (cond1)
> > > > > +  && COMPARISON_CLASS_P (cond2)
> > > > > +  && (invert_tree_comparison
> > > > > +  (TREE_CODE (cond1),
> > > > > +   HONOR_NANS (TREE_OPERAND (cond1, 0))) == TREE_CODE
> > > > (cond2))
> > > > > +  && operand_equal_p (TREE_OPERAND (cond1, 0),
> > > > > + TREE_OPERAND (cond2, 0), 0)
> > > > > +  && operand_equal_p (TREE_OPERAND (cond1, 1),
> > > > > + TREE_OPERAND (cond2, 1), 0))
> > > > > +return true;
> > > > > +
> > > > > +  if (TREE_CODE (cond1) == SSA_NAME
> > > > > +  && TREE_CODE (cond2) == SSA_NAME)
> > > > > +{
> > > > > +  gimple *gcond1 = SSA_NAME_DEF_STMT (cond1);
> > > > > +  gimple *gcond2 = SSA_NAME_DEF_STMT (cond2);
> > > > > +  if (!is_gimple_assign (gcond1) || !is_gimple_assign (gcond2))
> > > > > +   return false;
> > > > > +
> > > > > +  tree_code code1 = gimple_assign_rhs_code (gcond1);
> > > > > +  tree_code code2 = gimple_assign_rhs_code (gcond2);
> > > > > +  return TREE_CODE_CLASS (code1) == tcc_comparison
> > > > > +&& TREE_CODE_CLASS (code2) == tcc_comparison
> > > > > +&& invert_tree_comparison (code1,
> > > > > + HONOR_NANS (gimple_arg (gcond1, 0))) == code2
> > > > > +&& operand_equal_p (gimple_arg (gcond1, 0),
> > > > > +gimple_arg (gcond2, 0), 0)
> > > > > +&& operand_equal_p (gimple_arg (gcond1, 1),
> > > > > +gimple_arg (gcond2, 1), 0);
> > > > > +}
> > > > > +
> > > > > +  return false;
> > > >
> > > > if we do extend inverse_condition_p please add an overload like
> > >
> > > Done.
> > >
> > > >
> > > > bool
> > > > inverse_condition_p (enum tree_code, tree op00, tree op01,

RE: [PATCH]middle-end simplify complex if expressions where comparisons are inverse of one another.

2022-07-06 Thread Tamar Christina via Gcc-patches
> -Original Message-
> From: Andrew Pinski 
> Sent: Wednesday, July 6, 2022 3:10 AM
> To: Tamar Christina 
> Cc: Richard Biener ; nd ; gcc-
> patc...@gcc.gnu.org
> Subject: Re: [PATCH]middle-end simplify complex if expressions where
> comparisons are inverse of one another.
> 
> On Tue, Jul 5, 2022 at 8:16 AM Tamar Christina via Gcc-patches  patc...@gcc.gnu.org> wrote:
> >
> >
> >
> > > -Original Message-
> > > From: Richard Biener 
> > > Sent: Monday, June 20, 2022 9:57 AM
> > > To: Tamar Christina 
> > > Cc: gcc-patches@gcc.gnu.org; nd 
> > > Subject: Re: [PATCH]middle-end simplify complex if expressions where
> > > comparisons are inverse of one another.
> > >
> > > On Thu, 16 Jun 2022, Tamar Christina wrote:
> > >
> > > > Hi All,
> > > >
> > > > This optimizes the following sequence
> > > >
> > > >   ((a < b) & c) | ((a >= b) & d)
> > > >
> > > > into
> > > >
> > > >   (a < b ? c : d) & 1
> > > >
> > > > for scalar. On vector we can omit the & 1.
> > > >
> > > > This changes the code generation from
> > > >
> > > > zoo2:
> > > > cmp w0, w1
> > > > csetw0, lt
> > > > csetw1, ge
> > > > and w0, w0, w2
> > > > and w1, w1, w3
> > > > orr w0, w0, w1
> > > > ret
> > > >
> > > > into
> > > >
> > > > cmp w0, w1
> > > > cselw0, w2, w3, lt
> > > > and w0, w0, 1
> > > > ret
> > > >
> > > > and significantly reduces the number of selects we have to do in
> > > > the vector code.
> > > >
> > > > Bootstrapped Regtested on aarch64-none-linux-gnu,
> > > > x86_64-pc-linux-gnu and no issues.
> > > >
> > > > Ok for master?
> > > >
> > > > Thanks,
> > > > Tamar
> > > >
> > > > gcc/ChangeLog:
> > > >
> > > > * fold-const.cc (inverse_conditions_p): Traverse if SSA_NAME.
> > > > * match.pd: Add new rule.
> > > >
> > > > gcc/testsuite/ChangeLog:
> > > >
> > > > * gcc.target/aarch64/if-compare_1.c: New test.
> > > > * gcc.target/aarch64/if-compare_2.c: New test.
> > > >
> > > > --- inline copy of patch --
> > > > diff --git a/gcc/fold-const.cc b/gcc/fold-const.cc index
> > > >
> > >
> 39a5a52958d87497f301826e706886b290771a2d..f180599b90150acd3ed895a64
> > > 280
> > > > aa3255061256 100644
> > > > --- a/gcc/fold-const.cc
> > > > +++ b/gcc/fold-const.cc
> > > > @@ -2833,15 +2833,38 @@ compcode_to_comparison (enum
> > > comparison_code
> > > > code)  bool  inverse_conditions_p (const_tree cond1, const_tree
> > > > cond2) {
> > > > -  return (COMPARISON_CLASS_P (cond1)
> > > > - && COMPARISON_CLASS_P (cond2)
> > > > - && (invert_tree_comparison
> > > > - (TREE_CODE (cond1),
> > > > -  HONOR_NANS (TREE_OPERAND (cond1, 0))) == TREE_CODE
> > > (cond2))
> > > > - && operand_equal_p (TREE_OPERAND (cond1, 0),
> > > > - TREE_OPERAND (cond2, 0), 0)
> > > > - && operand_equal_p (TREE_OPERAND (cond1, 1),
> > > > - TREE_OPERAND (cond2, 1), 0));
> > > > +  if (COMPARISON_CLASS_P (cond1)
> > > > +  && COMPARISON_CLASS_P (cond2)
> > > > +  && (invert_tree_comparison
> > > > +  (TREE_CODE (cond1),
> > > > +   HONOR_NANS (TREE_OPERAND (cond1, 0))) == TREE_CODE
> > > (cond2))
> > > > +  && operand_equal_p (TREE_OPERAND (cond1, 0),
> > > > + TREE_OPERAND (cond2, 0), 0)
> > > > +  && operand_equal_p (TREE_OPERAND (cond1, 1),
> > > > + TREE_OPERAND (cond2, 1), 0))
> > > > +return true;
> > > > +
> > > > +  if (TREE_CODE (cond1) == SSA_NAME
> > > > +  && TREE_CODE (cond2) == SSA_NAME)
> > > > +{
> > > > +  gimple *gcond1 = SSA_NAME_DEF_STMT (cond1);
> > > > +  gimple *gcond2 = SSA_NAME_DEF_STMT (cond2);
> > > > +  if (!is_gimple_assign (gcond1) || !is_gimple_assign (gcond2))
> > > > +   return false;
> > > > +
> > > > +  tree_code code1 = gimple_assign_rhs_code (gcond1);
> > > > +  tree_code code2 = gimple_assign_rhs_code (gcond2);
> > > > +  return TREE_CODE_CLASS (code1) == tcc_comparison
> > > > +&& TREE_CODE_CLASS (code2) == tcc_comparison
> > > > +&& invert_tree_comparison (code1,
> > > > + HONOR_NANS (gimple_arg (gcond1, 0))) == code2
> > > > +&& operand_equal_p (gimple_arg (gcond1, 0),
> > > > +gimple_arg (gcond2, 0), 0)
> > > > +&& operand_equal_p (gimple_arg (gcond1, 1),
> > > > +gimple_arg (gcond2, 1), 0);
> > > > +}
> > > > +
> > > > +  return false;
> > >
> > > if we do extend inverse_condition_p please add an overload like
> >
> > Done.
> >
> > >
> > > bool
> > > inverse_condition_p (enum tree_code, tree op00, tree op01,
> > >  enum tree_code, tree op10, tree op11)
> > >
> > > so you can avoid some code duplication here.
> > >
> > > >  }
> > > >
> > > >  /* Return a tree for the comparison which is the combination of
> > > > diff --git a/gcc/match.pd b/gcc/match.pd index
> > > >
> > >
> 

Re: [PATCH]middle-end simplify complex if expressions where comparisons are inverse of one another.

2022-07-05 Thread Andrew Pinski via Gcc-patches
On Tue, Jul 5, 2022 at 8:16 AM Tamar Christina via Gcc-patches
 wrote:
>
>
>
> > -Original Message-
> > From: Richard Biener 
> > Sent: Monday, June 20, 2022 9:57 AM
> > To: Tamar Christina 
> > Cc: gcc-patches@gcc.gnu.org; nd 
> > Subject: Re: [PATCH]middle-end simplify complex if expressions where
> > comparisons are inverse of one another.
> >
> > On Thu, 16 Jun 2022, Tamar Christina wrote:
> >
> > > Hi All,
> > >
> > > This optimizes the following sequence
> > >
> > >   ((a < b) & c) | ((a >= b) & d)
> > >
> > > into
> > >
> > >   (a < b ? c : d) & 1
> > >
> > > for scalar. On vector we can omit the & 1.
> > >
> > > This changes the code generation from
> > >
> > > zoo2:
> > > cmp w0, w1
> > > csetw0, lt
> > > csetw1, ge
> > > and w0, w0, w2
> > > and w1, w1, w3
> > > orr w0, w0, w1
> > > ret
> > >
> > > into
> > >
> > > cmp w0, w1
> > > cselw0, w2, w3, lt
> > > and w0, w0, 1
> > > ret
> > >
> > > and significantly reduces the number of selects we have to do in the
> > > vector code.
> > >
> > > Bootstrapped Regtested on aarch64-none-linux-gnu, x86_64-pc-linux-gnu
> > > and no issues.
> > >
> > > Ok for master?
> > >
> > > Thanks,
> > > Tamar
> > >
> > > gcc/ChangeLog:
> > >
> > > * fold-const.cc (inverse_conditions_p): Traverse if SSA_NAME.
> > > * match.pd: Add new rule.
> > >
> > > gcc/testsuite/ChangeLog:
> > >
> > > * gcc.target/aarch64/if-compare_1.c: New test.
> > > * gcc.target/aarch64/if-compare_2.c: New test.
> > >
> > > --- inline copy of patch --
> > > diff --git a/gcc/fold-const.cc b/gcc/fold-const.cc index
> > >
> > 39a5a52958d87497f301826e706886b290771a2d..f180599b90150acd3ed895a64
> > 280
> > > aa3255061256 100644
> > > --- a/gcc/fold-const.cc
> > > +++ b/gcc/fold-const.cc
> > > @@ -2833,15 +2833,38 @@ compcode_to_comparison (enum
> > comparison_code
> > > code)  bool  inverse_conditions_p (const_tree cond1, const_tree cond2)
> > > {
> > > -  return (COMPARISON_CLASS_P (cond1)
> > > - && COMPARISON_CLASS_P (cond2)
> > > - && (invert_tree_comparison
> > > - (TREE_CODE (cond1),
> > > -  HONOR_NANS (TREE_OPERAND (cond1, 0))) == TREE_CODE
> > (cond2))
> > > - && operand_equal_p (TREE_OPERAND (cond1, 0),
> > > - TREE_OPERAND (cond2, 0), 0)
> > > - && operand_equal_p (TREE_OPERAND (cond1, 1),
> > > - TREE_OPERAND (cond2, 1), 0));
> > > +  if (COMPARISON_CLASS_P (cond1)
> > > +  && COMPARISON_CLASS_P (cond2)
> > > +  && (invert_tree_comparison
> > > +  (TREE_CODE (cond1),
> > > +   HONOR_NANS (TREE_OPERAND (cond1, 0))) == TREE_CODE
> > (cond2))
> > > +  && operand_equal_p (TREE_OPERAND (cond1, 0),
> > > + TREE_OPERAND (cond2, 0), 0)
> > > +  && operand_equal_p (TREE_OPERAND (cond1, 1),
> > > + TREE_OPERAND (cond2, 1), 0))
> > > +return true;
> > > +
> > > +  if (TREE_CODE (cond1) == SSA_NAME
> > > +  && TREE_CODE (cond2) == SSA_NAME)
> > > +{
> > > +  gimple *gcond1 = SSA_NAME_DEF_STMT (cond1);
> > > +  gimple *gcond2 = SSA_NAME_DEF_STMT (cond2);
> > > +  if (!is_gimple_assign (gcond1) || !is_gimple_assign (gcond2))
> > > +   return false;
> > > +
> > > +  tree_code code1 = gimple_assign_rhs_code (gcond1);
> > > +  tree_code code2 = gimple_assign_rhs_code (gcond2);
> > > +  return TREE_CODE_CLASS (code1) == tcc_comparison
> > > +&& TREE_CODE_CLASS (code2) == tcc_comparison
> > > +&& invert_tree_comparison (code1,
> > > + HONOR_NANS (gimple_arg (gcond1, 0))) == code2
> > > +&& operand_equal_p (gimple_arg (gcond1, 0),
> > > +gimple_arg (gcond2, 0), 0)
> > > +&& operand_equal_p (gimple_arg (gcond1, 1),
> > > +gimple_arg (gcond2, 1), 0);
> > > +}
> > > +
> > > +  return false;
> >
> > if we do extend inverse_condition_p please add an overload like
>
> Done.
>
> >
> > bool
> > inverse_condition_p (enum tree_code, tree op00, tree op01,
> >  enum tree_code, tree op10, tree op11)
> >
> > so you can avoid some code duplication here.
> >
> > >  }
> > >
> > >  /* Return a tree for the comparison which is the combination of diff
> > > --git a/gcc/match.pd b/gcc/match.pd index
> > >
> > 6d691d302b339c0e4556b40af158b5208c12d08f..bad49dd348add751d9ec1e30
> > 23e3
> > > 4d9ac123194f 100644
> > > --- a/gcc/match.pd
> > > +++ b/gcc/match.pd
> > > @@ -1160,6 +1160,32 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
> > >   (convert (bit_and (negate (convert:utype { pmop[0]; }))
> > >(convert:utype @1)))
> > >
> > > +/* Fold (((a < b) & c) | ((a >= b) & d)) into (a < b ? c : d) & 1.
> > > +*/ (simplify  (bit_ior
> > > +  (bit_and:c (convert? @0) @2)
> > > +  (bit_and:c (convert? @1) @3))
> >
> > in case the comparison returns a signed bool this might turn out wrong.
> > Maybe simply use 

RE: [PATCH]middle-end simplify complex if expressions where comparisons are inverse of one another.

2022-07-05 Thread Tamar Christina via Gcc-patches


> -Original Message-
> From: Richard Biener 
> Sent: Monday, June 20, 2022 9:57 AM
> To: Tamar Christina 
> Cc: gcc-patches@gcc.gnu.org; nd 
> Subject: Re: [PATCH]middle-end simplify complex if expressions where
> comparisons are inverse of one another.
> 
> On Thu, 16 Jun 2022, Tamar Christina wrote:
> 
> > Hi All,
> >
> > This optimizes the following sequence
> >
> >   ((a < b) & c) | ((a >= b) & d)
> >
> > into
> >
> >   (a < b ? c : d) & 1
> >
> > for scalar. On vector we can omit the & 1.
> >
> > This changes the code generation from
> >
> > zoo2:
> > cmp w0, w1
> > csetw0, lt
> > csetw1, ge
> > and w0, w0, w2
> > and w1, w1, w3
> > orr w0, w0, w1
> > ret
> >
> > into
> >
> > cmp w0, w1
> > cselw0, w2, w3, lt
> > and w0, w0, 1
> > ret
> >
> > and significantly reduces the number of selects we have to do in the
> > vector code.
> >
> > Bootstrapped Regtested on aarch64-none-linux-gnu, x86_64-pc-linux-gnu
> > and no issues.
> >
> > Ok for master?
> >
> > Thanks,
> > Tamar
> >
> > gcc/ChangeLog:
> >
> > * fold-const.cc (inverse_conditions_p): Traverse if SSA_NAME.
> > * match.pd: Add new rule.
> >
> > gcc/testsuite/ChangeLog:
> >
> > * gcc.target/aarch64/if-compare_1.c: New test.
> > * gcc.target/aarch64/if-compare_2.c: New test.
> >
> > --- inline copy of patch --
> > diff --git a/gcc/fold-const.cc b/gcc/fold-const.cc index
> >
> 39a5a52958d87497f301826e706886b290771a2d..f180599b90150acd3ed895a64
> 280
> > aa3255061256 100644
> > --- a/gcc/fold-const.cc
> > +++ b/gcc/fold-const.cc
> > @@ -2833,15 +2833,38 @@ compcode_to_comparison (enum
> comparison_code
> > code)  bool  inverse_conditions_p (const_tree cond1, const_tree cond2)
> > {
> > -  return (COMPARISON_CLASS_P (cond1)
> > - && COMPARISON_CLASS_P (cond2)
> > - && (invert_tree_comparison
> > - (TREE_CODE (cond1),
> > -  HONOR_NANS (TREE_OPERAND (cond1, 0))) == TREE_CODE
> (cond2))
> > - && operand_equal_p (TREE_OPERAND (cond1, 0),
> > - TREE_OPERAND (cond2, 0), 0)
> > - && operand_equal_p (TREE_OPERAND (cond1, 1),
> > - TREE_OPERAND (cond2, 1), 0));
> > +  if (COMPARISON_CLASS_P (cond1)
> > +  && COMPARISON_CLASS_P (cond2)
> > +  && (invert_tree_comparison
> > +  (TREE_CODE (cond1),
> > +   HONOR_NANS (TREE_OPERAND (cond1, 0))) == TREE_CODE
> (cond2))
> > +  && operand_equal_p (TREE_OPERAND (cond1, 0),
> > + TREE_OPERAND (cond2, 0), 0)
> > +  && operand_equal_p (TREE_OPERAND (cond1, 1),
> > + TREE_OPERAND (cond2, 1), 0))
> > +return true;
> > +
> > +  if (TREE_CODE (cond1) == SSA_NAME
> > +  && TREE_CODE (cond2) == SSA_NAME)
> > +{
> > +  gimple *gcond1 = SSA_NAME_DEF_STMT (cond1);
> > +  gimple *gcond2 = SSA_NAME_DEF_STMT (cond2);
> > +  if (!is_gimple_assign (gcond1) || !is_gimple_assign (gcond2))
> > +   return false;
> > +
> > +  tree_code code1 = gimple_assign_rhs_code (gcond1);
> > +  tree_code code2 = gimple_assign_rhs_code (gcond2);
> > +  return TREE_CODE_CLASS (code1) == tcc_comparison
> > +&& TREE_CODE_CLASS (code2) == tcc_comparison
> > +&& invert_tree_comparison (code1,
> > + HONOR_NANS (gimple_arg (gcond1, 0))) == code2
> > +&& operand_equal_p (gimple_arg (gcond1, 0),
> > +gimple_arg (gcond2, 0), 0)
> > +&& operand_equal_p (gimple_arg (gcond1, 1),
> > +gimple_arg (gcond2, 1), 0);
> > +}
> > +
> > +  return false;
> 
> if we do extend inverse_condition_p please add an overload like

Done. 

> 
> bool
> inverse_condition_p (enum tree_code, tree op00, tree op01,
>  enum tree_code, tree op10, tree op11)
> 
> so you can avoid some code duplication here.
> 
> >  }
> >
> >  /* Return a tree for the comparison which is the combination of diff
> > --git a/gcc/match.pd b/gcc/match.pd index
> >
> 6d691d302b339c0e4556b40af158b5208c12d08f..bad49dd348add751d9ec1e30
> 23e3
> > 4d9ac123194f 100644
> > --- a/gcc/match.pd
> > +++ b/gcc/match.pd
> > @@ -1160,6 +1160,32 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
> >   (convert (bit_and (negate (convert:utype { pmop[0]; }))
> >(convert:utype @1)))
> >
> > +/* Fold (((a < b) & c) | ((a >= b) & d)) into (a < b ? c : d) & 1.
> > +*/ (simplify  (bit_ior
> > +  (bit_and:c (convert? @0) @2)
> > +  (bit_and:c (convert? @1) @3))
> 
> in case the comparison returns a signed bool this might turn out wrong.
> Maybe simply use zero_one_valued_p@0 here instead of (convert? @0)?

I think I still need the convert as the comparison gets promoted to int and
the predicate doesn't handle extensions.

So I left the convert but added the zero_one_valued_p@0 such that it's
checking that the result of the comparison itself is at least 0 or 1.

> 
> > +   (if (inverse_conditions_p (@0, @1)
> > +   /* 

Re: [PATCH]middle-end simplify complex if expressions where comparisons are inverse of one another.

2022-06-20 Thread Richard Biener via Gcc-patches
On Thu, 16 Jun 2022, Tamar Christina wrote:

> Hi All,
> 
> This optimizes the following sequence
> 
>   ((a < b) & c) | ((a >= b) & d)
> 
> into
> 
>   (a < b ? c : d) & 1
> 
> for scalar. On vector we can omit the & 1.
>
> This changes the code generation from
> 
> zoo2:
>   cmp w0, w1
>   csetw0, lt
>   csetw1, ge
>   and w0, w0, w2
>   and w1, w1, w3
>   orr w0, w0, w1
>   ret
> 
> into
> 
>   cmp w0, w1
>   cselw0, w2, w3, lt
>   and w0, w0, 1
>   ret
> 
> and significantly reduces the number of selects we have to do in the vector
> code.
> 
> Bootstrapped Regtested on aarch64-none-linux-gnu,
> x86_64-pc-linux-gnu and no issues.
> 
> Ok for master?
> 
> Thanks,
> Tamar
> 
> gcc/ChangeLog:
> 
>   * fold-const.cc (inverse_conditions_p): Traverse if SSA_NAME.
>   * match.pd: Add new rule.
> 
> gcc/testsuite/ChangeLog:
> 
>   * gcc.target/aarch64/if-compare_1.c: New test.
>   * gcc.target/aarch64/if-compare_2.c: New test.
> 
> --- inline copy of patch -- 
> diff --git a/gcc/fold-const.cc b/gcc/fold-const.cc
> index 
> 39a5a52958d87497f301826e706886b290771a2d..f180599b90150acd3ed895a64280aa3255061256
>  100644
> --- a/gcc/fold-const.cc
> +++ b/gcc/fold-const.cc
> @@ -2833,15 +2833,38 @@ compcode_to_comparison (enum comparison_code code)
>  bool
>  inverse_conditions_p (const_tree cond1, const_tree cond2)
>  {
> -  return (COMPARISON_CLASS_P (cond1)
> -   && COMPARISON_CLASS_P (cond2)
> -   && (invert_tree_comparison
> -   (TREE_CODE (cond1),
> -HONOR_NANS (TREE_OPERAND (cond1, 0))) == TREE_CODE (cond2))
> -   && operand_equal_p (TREE_OPERAND (cond1, 0),
> -   TREE_OPERAND (cond2, 0), 0)
> -   && operand_equal_p (TREE_OPERAND (cond1, 1),
> -   TREE_OPERAND (cond2, 1), 0));
> +  if (COMPARISON_CLASS_P (cond1)
> +  && COMPARISON_CLASS_P (cond2)
> +  && (invert_tree_comparison
> +(TREE_CODE (cond1),
> + HONOR_NANS (TREE_OPERAND (cond1, 0))) == TREE_CODE (cond2))
> +  && operand_equal_p (TREE_OPERAND (cond1, 0),
> +   TREE_OPERAND (cond2, 0), 0)
> +  && operand_equal_p (TREE_OPERAND (cond1, 1),
> +   TREE_OPERAND (cond2, 1), 0))
> +return true;
> +
> +  if (TREE_CODE (cond1) == SSA_NAME
> +  && TREE_CODE (cond2) == SSA_NAME)
> +{
> +  gimple *gcond1 = SSA_NAME_DEF_STMT (cond1);
> +  gimple *gcond2 = SSA_NAME_DEF_STMT (cond2);
> +  if (!is_gimple_assign (gcond1) || !is_gimple_assign (gcond2))
> + return false;
> +
> +  tree_code code1 = gimple_assign_rhs_code (gcond1);
> +  tree_code code2 = gimple_assign_rhs_code (gcond2);
> +  return TREE_CODE_CLASS (code1) == tcc_comparison
> +  && TREE_CODE_CLASS (code2) == tcc_comparison
> +  && invert_tree_comparison (code1,
> +   HONOR_NANS (gimple_arg (gcond1, 0))) == code2
> +  && operand_equal_p (gimple_arg (gcond1, 0),
> +  gimple_arg (gcond2, 0), 0)
> +  && operand_equal_p (gimple_arg (gcond1, 1),
> +  gimple_arg (gcond2, 1), 0);
> +}
> +
> +  return false;

if we do extend inverse_condition_p please add an overload like

bool
inverse_condition_p (enum tree_code, tree op00, tree op01,
 enum tree_code, tree op10, tree op11)

so you can avoid some code duplication here.

>  }
>  
>  /* Return a tree for the comparison which is the combination of
> diff --git a/gcc/match.pd b/gcc/match.pd
> index 
> 6d691d302b339c0e4556b40af158b5208c12d08f..bad49dd348add751d9ec1e3023e34d9ac123194f
>  100644
> --- a/gcc/match.pd
> +++ b/gcc/match.pd
> @@ -1160,6 +1160,32 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
>   (convert (bit_and (negate (convert:utype { pmop[0]; }))
>  (convert:utype @1)))
>  
> +/* Fold (((a < b) & c) | ((a >= b) & d)) into (a < b ? c : d) & 1.  */
> +(simplify
> + (bit_ior
> +  (bit_and:c (convert? @0) @2)
> +  (bit_and:c (convert? @1) @3))

in case the comparison returns a signed bool this might turn out wrong.
Maybe simply use zero_one_valued_p@0 here instead of (convert? @0)?

> +   (if (inverse_conditions_p (@0, @1)
> + /* The scalar version has to be canonicalized after vectorization
> +because it makes unconditional loads conditional ones, which
> +means we lose vectorization because the loads may trap.  */
> + && canonicalize_math_after_vectorization_p ())
> +(bit_and (cond @0 @2 @3) { build_each_one_cst (type); })))

I think you should restrict this to INTEGRAL_TYPE_P and use
build_one_cst (type) (also see below).

you can do inverse_onditions_p with lock-step for over
tcc_comparison and inverted_tcc_comparison{,_with_nans} (see existing 
examples).

> +(simplify
> + (bit_ior
> +  (bit_and:c (convert? (vec_cond:s @0 @4 integer_zerop)) @2)
> +  (bit_and:c (convert? (vec_cond:s @1 @4 

[PATCH]middle-end simplify complex if expressions where comparisons are inverse of one another.

2022-06-16 Thread Tamar Christina via Gcc-patches
Hi All,

This optimizes the following sequence

  ((a < b) & c) | ((a >= b) & d)

into

  (a < b ? c : d) & 1

for scalar. On vector we can omit the & 1.

This changes the code generation from

zoo2:
cmp w0, w1
csetw0, lt
csetw1, ge
and w0, w0, w2
and w1, w1, w3
orr w0, w0, w1
ret

into

cmp w0, w1
cselw0, w2, w3, lt
and w0, w0, 1
ret

and significantly reduces the number of selects we have to do in the vector
code.

Bootstrapped Regtested on aarch64-none-linux-gnu,
x86_64-pc-linux-gnu and no issues.

Ok for master?

Thanks,
Tamar

gcc/ChangeLog:

* fold-const.cc (inverse_conditions_p): Traverse if SSA_NAME.
* match.pd: Add new rule.

gcc/testsuite/ChangeLog:

* gcc.target/aarch64/if-compare_1.c: New test.
* gcc.target/aarch64/if-compare_2.c: New test.

--- inline copy of patch -- 
diff --git a/gcc/fold-const.cc b/gcc/fold-const.cc
index 
39a5a52958d87497f301826e706886b290771a2d..f180599b90150acd3ed895a64280aa3255061256
 100644
--- a/gcc/fold-const.cc
+++ b/gcc/fold-const.cc
@@ -2833,15 +2833,38 @@ compcode_to_comparison (enum comparison_code code)
 bool
 inverse_conditions_p (const_tree cond1, const_tree cond2)
 {
-  return (COMPARISON_CLASS_P (cond1)
- && COMPARISON_CLASS_P (cond2)
- && (invert_tree_comparison
- (TREE_CODE (cond1),
-  HONOR_NANS (TREE_OPERAND (cond1, 0))) == TREE_CODE (cond2))
- && operand_equal_p (TREE_OPERAND (cond1, 0),
- TREE_OPERAND (cond2, 0), 0)
- && operand_equal_p (TREE_OPERAND (cond1, 1),
- TREE_OPERAND (cond2, 1), 0));
+  if (COMPARISON_CLASS_P (cond1)
+  && COMPARISON_CLASS_P (cond2)
+  && (invert_tree_comparison
+  (TREE_CODE (cond1),
+   HONOR_NANS (TREE_OPERAND (cond1, 0))) == TREE_CODE (cond2))
+  && operand_equal_p (TREE_OPERAND (cond1, 0),
+ TREE_OPERAND (cond2, 0), 0)
+  && operand_equal_p (TREE_OPERAND (cond1, 1),
+ TREE_OPERAND (cond2, 1), 0))
+return true;
+
+  if (TREE_CODE (cond1) == SSA_NAME
+  && TREE_CODE (cond2) == SSA_NAME)
+{
+  gimple *gcond1 = SSA_NAME_DEF_STMT (cond1);
+  gimple *gcond2 = SSA_NAME_DEF_STMT (cond2);
+  if (!is_gimple_assign (gcond1) || !is_gimple_assign (gcond2))
+   return false;
+
+  tree_code code1 = gimple_assign_rhs_code (gcond1);
+  tree_code code2 = gimple_assign_rhs_code (gcond2);
+  return TREE_CODE_CLASS (code1) == tcc_comparison
+&& TREE_CODE_CLASS (code2) == tcc_comparison
+&& invert_tree_comparison (code1,
+ HONOR_NANS (gimple_arg (gcond1, 0))) == code2
+&& operand_equal_p (gimple_arg (gcond1, 0),
+gimple_arg (gcond2, 0), 0)
+&& operand_equal_p (gimple_arg (gcond1, 1),
+gimple_arg (gcond2, 1), 0);
+}
+
+  return false;
 }
 
 /* Return a tree for the comparison which is the combination of
diff --git a/gcc/match.pd b/gcc/match.pd
index 
6d691d302b339c0e4556b40af158b5208c12d08f..bad49dd348add751d9ec1e3023e34d9ac123194f
 100644
--- a/gcc/match.pd
+++ b/gcc/match.pd
@@ -1160,6 +1160,32 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
  (convert (bit_and (negate (convert:utype { pmop[0]; }))
   (convert:utype @1)))
 
+/* Fold (((a < b) & c) | ((a >= b) & d)) into (a < b ? c : d) & 1.  */
+(simplify
+ (bit_ior
+  (bit_and:c (convert? @0) @2)
+  (bit_and:c (convert? @1) @3))
+   (if (inverse_conditions_p (@0, @1)
+   /* The scalar version has to be canonicalized after vectorization
+  because it makes unconditional loads conditional ones, which
+  means we lose vectorization because the loads may trap.  */
+   && canonicalize_math_after_vectorization_p ())
+(bit_and (cond @0 @2 @3) { build_each_one_cst (type); })))
+(simplify
+ (bit_ior
+  (bit_and:c (convert? (vec_cond:s @0 @4 integer_zerop)) @2)
+  (bit_and:c (convert? (vec_cond:s @1 @4 integer_zerop)) @3))
+   (if (inverse_conditions_p (@0, @1)
+   && integer_onep (@4))
+(bit_and (vec_cond @0 @2 @3) @4)))
+/* Fold (((a < b) & c) | ((a >= b) & d)) into a < b ? c : d.  */
+(simplify
+ (bit_ior
+  (bit_and:c (convert? (vec_cond:s @0 integer_minus_onep integer_zerop)) @2)
+  (bit_and:c (convert? (vec_cond:s @1 integer_minus_onep integer_zerop)) @3))
+   (if (inverse_conditions_p (@0, @1))
+(vec_cond @0 @2 @3)))
+
 /* X % Y is smaller than Y.  */
 (for cmp (lt ge)
  (simplify
diff --git a/gcc/testsuite/gcc.target/aarch64/if-compare_1.c 
b/gcc/testsuite/gcc.target/aarch64/if-compare_1.c
new file mode 100644
index 
..05a1292fa90c70b14a7985122f43711f55d047ea
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/if-compare_1.c
@@ -0,0 +1,16 @@
+/* { dg-do compile } */
+/* {