Richard Biener <rguent...@suse.de> writes:
> We have to check each operand for being in a pattern, not just the
> first when avoiding build from scalars (we could possibly handle
> the special case of some of them being the pattern stmt root, but
> that would be a followup improvement).
>
> Bootstrap & regtest running on x86-64-unknown-linux-gnu.
>
> Richard.
>
> 2019-10-25  Richard Biener  <rguent...@suse.de>
>
>       PR tree-optimization/92222
>       * tree-vect-slp.c (_slp_oprnd_info::first_pattern): Remove.
>       (_slp_oprnd_info::second_pattern): Likewise.
>       (_slp_oprnd_info::any_pattern): New.
>       (vect_create_oprnd_info): Adjust.
>       (vect_get_and_check_slp_defs): Compute whether any stmt is
>       in a pattern.
>       (vect_build_slp_tree_2): Avoid building up a node from scalars
>       if any of the operand defs, not just the first, is in a pattern.

Is recording this in vect_get_and_check_slp_defs enough?  AIUI we don't
get that far if vect_build_slp_tree_1 fails, but that doesn't prevent us
from building the vector from scalars on return from vect_build_slp_tree.

Was wondering whether we should use a helper function that explicitly
checks whether any stmt_info in the vec is a pattern statement, rather
than computing it on the fly.

Thanks,
Richard

>
>       * gcc.dg/torture/pr92222.c: New testcase.
>
> Index: gcc/tree-vect-slp.c
> ===================================================================
> --- gcc/tree-vect-slp.c       (revision 277441)
> +++ gcc/tree-vect-slp.c       (working copy)
> @@ -177,8 +177,7 @@ typedef struct _slp_oprnd_info
>       stmt.  */
>    tree first_op_type;
>    enum vect_def_type first_dt;
> -  bool first_pattern;
> -  bool second_pattern;
> +  bool any_pattern;
>  } *slp_oprnd_info;
>  
>  
> @@ -199,8 +198,7 @@ vect_create_oprnd_info (int nops, int gr
>        oprnd_info->ops.create (group_size);
>        oprnd_info->first_dt = vect_uninitialized_def;
>        oprnd_info->first_op_type = NULL_TREE;
> -      oprnd_info->first_pattern = false;
> -      oprnd_info->second_pattern = false;
> +      oprnd_info->any_pattern = false;
>        oprnds_info.quick_push (oprnd_info);
>      }
>  
> @@ -339,13 +337,11 @@ vect_get_and_check_slp_defs (vec_info *v
>    tree oprnd;
>    unsigned int i, number_of_oprnds;
>    enum vect_def_type dt = vect_uninitialized_def;
> -  bool pattern = false;
>    slp_oprnd_info oprnd_info;
>    int first_op_idx = 1;
>    unsigned int commutative_op = -1U;
>    bool first_op_cond = false;
>    bool first = stmt_num == 0;
> -  bool second = stmt_num == 1;
>  
>    if (gcall *stmt = dyn_cast <gcall *> (stmt_info->stmt))
>      {
> @@ -418,13 +414,12 @@ again:
>         return -1;
>       }
>  
> -      if (second)
> -     oprnd_info->second_pattern = pattern;
> +      if (def_stmt_info && is_pattern_stmt_p (def_stmt_info))
> +     oprnd_info->any_pattern = true;
>  
>        if (first)
>       {
>         oprnd_info->first_dt = dt;
> -       oprnd_info->first_pattern = pattern;
>         oprnd_info->first_op_type = TREE_TYPE (oprnd);
>       }
>        else
> @@ -1311,7 +1306,7 @@ vect_build_slp_tree_2 (vec_info *vinfo,
>             /* ???  Rejecting patterns this way doesn't work.  We'd have to
>                do extra work to cancel the pattern so the uses see the
>                scalar version.  */
> -           && !is_pattern_stmt_p (SLP_TREE_SCALAR_STMTS (child)[0]))
> +           && !oprnd_info->any_pattern)
>           {
>             slp_tree grandchild;
>  
> @@ -1358,18 +1353,16 @@ vect_build_slp_tree_2 (vec_info *vinfo,
>         /* ???  Rejecting patterns this way doesn't work.  We'd have to
>            do extra work to cancel the pattern so the uses see the
>            scalar version.  */
> -       && !is_pattern_stmt_p (stmt_info))
> +       && !is_pattern_stmt_p (stmt_info)
> +       && !oprnd_info->any_pattern)
>       {
>         if (dump_enabled_p ())
>           dump_printf_loc (MSG_NOTE, vect_location,
>                            "Building vector operands from scalars\n");
>         this_tree_size++;
> -       child = vect_create_new_slp_node (oprnd_info->def_stmts);
> -       SLP_TREE_DEF_TYPE (child) = vect_external_def;
> -       SLP_TREE_SCALAR_OPS (child) = oprnd_info->ops;
> +       child = vect_create_new_slp_node (oprnd_info->ops);
>         children.safe_push (child);
>         oprnd_info->ops = vNULL;
> -       oprnd_info->def_stmts = vNULL;
>         continue;
>       }
>  
> @@ -1469,7 +1440,7 @@ vect_build_slp_tree_2 (vec_info *vinfo,
>                 /* ???  Rejecting patterns this way doesn't work.  We'd have
>                    to do extra work to cancel the pattern so the uses see the
>                    scalar version.  */
> -               && !is_pattern_stmt_p (SLP_TREE_SCALAR_STMTS (child)[0]))
> +               && !oprnd_info->any_pattern)
>               {
>                 unsigned int j;
>                 slp_tree grandchild;
> Index: gcc/testsuite/gcc.dg/torture/pr92222.c
> ===================================================================
> --- gcc/testsuite/gcc.dg/torture/pr92222.c    (nonexistent)
> +++ gcc/testsuite/gcc.dg/torture/pr92222.c    (working copy)
> @@ -0,0 +1,17 @@
> +/* { dg-do compile } */
> +/* { dg-additional-options "-ftree-vectorize" } */
> +
> +unsigned char *a;
> +int b;
> +void f();
> +void c()
> +{
> +  char *d;
> +  int e;
> +  for (; b; b++) {
> +      e = 7;
> +      for (; e >= 0; e--)
> +     *d++ = a[b] & 1 << e ? '1' : '0';
> +  }
> +  f();
> +}

Reply via email to