Re: [PATCH]middle-end simplify complex if expressions where comparisons are inverse of one another.
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.
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.
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.
> -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.
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.
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.
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.
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.
> -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.
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.
> -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.
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.
> -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.
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.
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 } */ +/* {