On Mon, 28 Feb 2022, Tamar Christina wrote:

> Hi All,
> 
> GCC 11 handled negations rather differently than GCC 12.  This difference
> caused the previous backport to regress some of the conjugate cases that it
> used to handle before.  The testsuite in GCC 11 wasn't as robust as that in
> master so it didn't catch it.
> 
> The second patch in this series backports the testcases from master to GCC-11
> to prevent this in the future.
> 
> This patch deals with the conjugate cases correctly by updating the detection
> code to deal with the different order of operands.
> 
> For MUL the problem is that the presence of an ADD can cause the order of the
> operands to flip, unlike in GCC 12.  So to handle this if we detect the shape
> of a MUL but the data-flow check fails, we swap both operands and try again.
> 
> Since a * b == b * a this is fine and allows us to keep the df-check simple.
> This doesn't cause a compile time issue either as most of the data will be in
> the caches from the previous call.
> 
> Bootstrapped Regtested on aarch64-none-linux-gnu,
> x86_64-pc-linux-gnu and no regressions on updated testsuite.
> 
> Ok for GCC 11?

OK.

> Thanks,
> Tamar
> 
> gcc/ChangeLog:
> 
>       * tree-vect-slp-patterns.c (vect_validate_multiplication): Correctly
>       detect conjugate cases.
>       (complex_mul_pattern::matches): Likewise.
>       (complex_fma_pattern::matches): Move accumulator last as expected.
>       (complex_fma_pattern::build): Likewise.
>       (complex_fms_pattern::matches): Handle different conjugate form.
> 
> --- inline copy of patch -- 
> diff --git a/gcc/tree-vect-slp-patterns.c b/gcc/tree-vect-slp-patterns.c
> index 
> a3bd90ff85b4ca5423a94388d480b66051a83e08..8b08a0f33dd1cd23ad9577243524c1feaa5e8ed9
>  100644
> --- a/gcc/tree-vect-slp-patterns.c
> +++ b/gcc/tree-vect-slp-patterns.c
> @@ -873,10 +873,8 @@ compatible_complex_nodes_p (slp_compat_nodes_map_t 
> *compat_cache,
>  static inline bool
>  vect_validate_multiplication (slp_tree_to_load_perm_map_t *perm_cache,
>                             slp_compat_nodes_map_t *compat_cache,
> -                           vec<slp_tree> &left_op,
> -                           vec<slp_tree> &right_op,
> -                           bool subtract,
> -                           enum _conj_status *_status)
> +                           vec<slp_tree> &left_op, vec<slp_tree> &right_op,
> +                           bool subtract, enum _conj_status *_status)
>  {
>    auto_vec<slp_tree> ops;
>    enum _conj_status stats = CONJ_NONE;
> @@ -902,29 +900,31 @@ vect_validate_multiplication 
> (slp_tree_to_load_perm_map_t *perm_cache,
>  
>    /* Default to style and perm 0, most operations use this one.  */
>    int style = 0;
> -  int perm = subtract ? 1 : 0;
> +  int perm = 0;
>  
> -  /* Check if we have a negate operation, if so absorb the node and continue
> -     looking.  */
> +  /* Determine which style we're looking at.  We only have different ones
> +     whenever a conjugate is involved.  If so absorb the node and continue.  
> */
>    bool neg0 = vect_match_expression_p (right_op[0], NEGATE_EXPR);
>    bool neg1 = vect_match_expression_p (right_op[1], NEGATE_EXPR);
>  
> -  /* Determine which style we're looking at.  We only have different ones
> -     whenever a conjugate is involved.  */
> -  if (neg0 && neg1)
> -    ;
> -  else if (neg0)
> -    {
> -      right_op[0] = SLP_TREE_CHILDREN (right_op[0])[0];
> -      stats = CONJ_FST;
> -      if (subtract)
> -     perm = 0;
> -    }
> -  else if (neg1)
> +   /* Determine which style we're looking at.  We only have different ones
> +      whenever a conjugate is involved.  */
> +  if (neg0 != neg1 && (neg0 || neg1))
>      {
> -      right_op[1] = SLP_TREE_CHILDREN (right_op[1])[0];
> -      stats = CONJ_SND;
> -      perm = 1;
> +      unsigned idx = !!neg1;
> +      right_op[idx] = SLP_TREE_CHILDREN (right_op[idx])[0];
> +      if (linear_loads_p (perm_cache, left_op[!!!neg1]) == PERM_EVENEVEN)
> +     {
> +       stats = CONJ_FST;
> +       style = 1;
> +       if (subtract && neg0)
> +         perm = 1;
> +     }
> +      else
> +     {
> +       stats = CONJ_SND;
> +       perm = 1;
> +     }
>      }
>  
>    *_status = stats;
> @@ -1069,7 +1069,16 @@ complex_mul_pattern::matches (complex_operation_t op,
>    enum _conj_status status;
>    if (!vect_validate_multiplication (perm_cache, compat_cache, left_op,
>                                    right_op, false, &status))
> -    return IFN_LAST;
> +    {
> +     /* Try swapping the operands and trying again.  */
> +     std::swap (left_op[0], left_op[1]);
> +     right_op.truncate (0);
> +     right_op.safe_splice (SLP_TREE_CHILDREN (muls[1]));
> +     std::swap (right_op[0], right_op[1]);
> +     if (!vect_validate_multiplication (perm_cache, compat_cache, left_op,
> +                                        right_op, false, &status))
> +       return IFN_LAST;
> +    }
>  
>    if (status == CONJ_NONE)
>      ifn = IFN_COMPLEX_MUL;
> @@ -1089,7 +1098,7 @@ complex_mul_pattern::matches (complex_operation_t op,
>        ops->quick_push (right_op[1]);
>        ops->quick_push (left_op[0]);
>      }
> -  else if (kind == PERM_EVENEVEN && status != CONJ_SND)
> +  else if (kind == PERM_EVENEVEN && status == CONJ_NONE)
>      {
>        ops->quick_push (left_op[0]);
>        ops->quick_push (right_op[0]);
> @@ -1246,15 +1255,15 @@ complex_fma_pattern::matches (complex_operation_t op,
>  
>    if (ifn == IFN_COMPLEX_FMA)
>      {
> -      ops->quick_push (SLP_TREE_CHILDREN (vnode)[0]);
>        ops->quick_push (SLP_TREE_CHILDREN (node)[1]);
>        ops->quick_push (SLP_TREE_CHILDREN (node)[0]);
> +      ops->quick_push (SLP_TREE_CHILDREN (vnode)[0]);
>      }
>    else
>      {
> -      ops->quick_push (SLP_TREE_CHILDREN (vnode)[0]);
>        ops->quick_push (SLP_TREE_CHILDREN (node)[0]);
>        ops->quick_push (SLP_TREE_CHILDREN (node)[1]);
> +      ops->quick_push (SLP_TREE_CHILDREN (vnode)[0]);
>      }
>  
>    return ifn;
> @@ -1290,8 +1299,8 @@ complex_fma_pattern::build (vec_info *vinfo)
>    SLP_TREE_CHILDREN (*this->m_node).create (3);
>    SLP_TREE_CHILDREN (*this->m_node).safe_splice (this->m_ops);
>  
> +  SLP_TREE_REF_COUNT (this->m_ops[0])++;
>    SLP_TREE_REF_COUNT (this->m_ops[1])++;
> -  SLP_TREE_REF_COUNT (this->m_ops[2])++;
>  
>    vect_free_slp_tree (node);
>  
> @@ -1397,24 +1406,32 @@ complex_fms_pattern::matches (complex_operation_t op,
>    if (!vect_pattern_validate_optab (ifn, *ref_node))
>      return IFN_LAST;
>  
> +  child = SLP_TREE_CHILDREN ((*ops)[1])[0];
>    ops->truncate (0);
>    ops->create (4);
>  
>    complex_perm_kinds_t kind = linear_loads_p (perm_cache, right_op[0]);
> -  if (kind == PERM_EVENODD)
> +  if (kind == PERM_EVENODD || kind == PERM_TOP)
>      {
>        ops->quick_push (child);
>        ops->quick_push (right_op[0]);
>        ops->quick_push (right_op[1]);
> -      ops->quick_push (left_op[1]);
> +      ops->quick_push (left_op[0]);
>      }
> -  else
> +  else if (status == CONJ_NONE)
>      {
>        ops->quick_push (child);
>        ops->quick_push (right_op[1]);
>        ops->quick_push (right_op[0]);
>        ops->quick_push (left_op[0]);
>      }
> +  else
> +    {
> +      ops->quick_push (child);
> +      ops->quick_push (right_op[1]);
> +      ops->quick_push (right_op[0]);
> +      ops->quick_push (left_op[1]);
> +    }
>  
>    return ifn;
>  }
> 
> 
> 

-- 
Richard Biener <rguent...@suse.de>
SUSE Software Solutions Germany GmbH, Maxfeldstrasse 5, 90409 Nuernberg,
Germany; GF: Ivo Totev; HRB 36809 (AG Nuernberg)

Reply via email to