Richard Biener <[email protected]> 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 <[email protected]>
>
> 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();
> +}