Commit 6c7b0df8 by Richard Biener Committed by Richard Biener

re PR tree-optimization/92173 (ICE in optab_for_tree_code, at optabs-tree.c:81)

2019-10-22  Richard Biener  <rguenther@suse.de>

	PR tree-optimization/92173
	* tree-vect-loop.c (vectorizable_reduction): If
	vect_transform_reduction cannot handle code-generation try without
	the single-def-use-cycle optimization.  Pass optab_vector to
	optab_for_tree_code to get vector shifts as that's what we'd
	generate.

	* gcc.dg/torture/pr92173.c: New testcase.

From-SVN: r277288
parent 92781ff1
2019-10-22 Richard Biener <rguenther@suse.de>
PR tree-optimization/92173
* tree-vect-loop.c (vectorizable_reduction): If
vect_transform_reduction cannot handle code-generation try without
the single-def-use-cycle optimization. Pass optab_vector to
optab_for_tree_code to get vector shifts as that's what we'd
generate.
2019-10-22 Michael Matz <matz@suse.de> 2019-10-22 Michael Matz <matz@suse.de>
PR middle-end/90796 PR middle-end/90796
2019-10-22 Richard Biener <rguenther@suse.de>
PR tree-optimization/92173
* gcc.dg/torture/pr92173.c: New testcase.
2019-10-22 Michael Matz <matz@suse.de> 2019-10-22 Michael Matz <matz@suse.de>
PR middle-end/90796 PR middle-end/90796
......
...@@ -41,6 +41,42 @@ f2 (void) ...@@ -41,6 +41,42 @@ f2 (void)
} }
__attribute__((noinline, noclone)) void __attribute__((noinline, noclone)) void
f2a (int x)
{
long long a0, a1, a2, a3;
a0 = a[0];
a1 = a[1];
a2 = a[2];
a3 = a[3];
a0 = a0 << x;
a1 = a1 << 2;
a2 = a2 << 2;
a3 = a3 << 2;
a[0] = a0;
a[1] = a1;
a[2] = a2;
a[3] = a3;
}
__attribute__((noinline, noclone)) void
f2b (int x)
{
long long a0, a1, a2, a3;
a0 = a[0];
a1 = a[1];
a2 = a[2];
a3 = a[3];
a0 = a0 << 2;
a1 = a1 << 2;
a2 = a2 << x;
a3 = a3 << 2;
a[0] = a0;
a[1] = a1;
a[2] = a2;
a[3] = a3;
}
__attribute__((noinline, noclone)) void
f3 (int x) f3 (int x)
{ {
long long a0, a1, a2, a3; long long a0, a1, a2, a3;
...@@ -77,5 +113,13 @@ main () ...@@ -77,5 +113,13 @@ main ()
if (a[0] != (4LL << 7) || a[1] != (3LL << 8) if (a[0] != (4LL << 7) || a[1] != (3LL << 8)
|| a[2] != (2LL << 9) || a[3] != (1LL << 10)) || a[2] != (2LL << 9) || a[3] != (1LL << 10))
abort (); abort ();
f2a (3);
if (a[0] != (4LL << 10) || a[1] != (3LL << 10)
|| a[2] != (2LL << 11) || a[3] != (1LL << 12))
abort ();
f2b (3);
if (a[0] != (4LL << 12) || a[1] != (3LL << 12)
|| a[2] != (2LL << 14) || a[3] != (1LL << 14))
abort ();
return 0; return 0;
} }
...@@ -475,8 +475,11 @@ again: ...@@ -475,8 +475,11 @@ again:
/* Check the types of the definitions. */ /* Check the types of the definitions. */
switch (dt) switch (dt)
{ {
case vect_constant_def:
case vect_external_def: case vect_external_def:
/* Make sure to demote the overall operand to external. */
oprnd_info->first_dt = vect_external_def;
/* Fallthru. */
case vect_constant_def:
oprnd_info->def_stmts.quick_push (NULL); oprnd_info->def_stmts.quick_push (NULL);
oprnd_info->ops.quick_push (oprnd); oprnd_info->ops.quick_push (oprnd);
break; break;
...@@ -1504,9 +1507,10 @@ static void ...@@ -1504,9 +1507,10 @@ static void
vect_print_slp_tree (dump_flags_t dump_kind, dump_location_t loc, vect_print_slp_tree (dump_flags_t dump_kind, dump_location_t loc,
slp_tree node, hash_set<slp_tree> &visited) slp_tree node, hash_set<slp_tree> &visited)
{ {
int i; unsigned i;
stmt_vec_info stmt_info; stmt_vec_info stmt_info;
slp_tree child; slp_tree child;
tree op;
if (visited.add (node)) if (visited.add (node))
return; return;
...@@ -1514,11 +1518,23 @@ vect_print_slp_tree (dump_flags_t dump_kind, dump_location_t loc, ...@@ -1514,11 +1518,23 @@ vect_print_slp_tree (dump_flags_t dump_kind, dump_location_t loc,
dump_metadata_t metadata (dump_kind, loc.get_impl_location ()); dump_metadata_t metadata (dump_kind, loc.get_impl_location ());
dump_user_location_t user_loc = loc.get_user_location (); dump_user_location_t user_loc = loc.get_user_location ();
dump_printf_loc (metadata, user_loc, "node%s %p (max_nunits=%u)\n", dump_printf_loc (metadata, user_loc, "node%s %p (max_nunits=%u)\n",
SLP_TREE_DEF_TYPE (node) != vect_internal_def SLP_TREE_DEF_TYPE (node) == vect_external_def
? " (external)" : "", node, ? " (external)"
: (SLP_TREE_DEF_TYPE (node) == vect_constant_def
? " (constant)"
: ""), node,
estimated_poly_value (node->max_nunits)); estimated_poly_value (node->max_nunits));
FOR_EACH_VEC_ELT (SLP_TREE_SCALAR_STMTS (node), i, stmt_info) if (SLP_TREE_SCALAR_STMTS (node).exists ())
dump_printf_loc (metadata, user_loc, "\tstmt %d %G", i, stmt_info->stmt); FOR_EACH_VEC_ELT (SLP_TREE_SCALAR_STMTS (node), i, stmt_info)
dump_printf_loc (metadata, user_loc, "\tstmt %u %G", i, stmt_info->stmt);
else
{
dump_printf_loc (metadata, user_loc, "\t{ ");
FOR_EACH_VEC_ELT (SLP_TREE_SCALAR_OPS (node), i, op)
dump_printf (metadata, "%T%s ", op,
i < SLP_TREE_SCALAR_OPS (node).length () - 1 ? "," : "");
dump_printf (metadata, "}\n");
}
if (SLP_TREE_CHILDREN (node).is_empty ()) if (SLP_TREE_CHILDREN (node).is_empty ())
return; return;
dump_printf_loc (metadata, user_loc, "\tchildren"); dump_printf_loc (metadata, user_loc, "\tchildren");
......
...@@ -5670,8 +5670,11 @@ vectorizable_shift (stmt_vec_info stmt_info, gimple_stmt_iterator *gsi, ...@@ -5670,8 +5670,11 @@ vectorizable_shift (stmt_vec_info stmt_info, gimple_stmt_iterator *gsi,
if (!op1_vectype) if (!op1_vectype)
op1_vectype = get_same_sized_vectype (TREE_TYPE (op1), vectype_out); op1_vectype = get_same_sized_vectype (TREE_TYPE (op1), vectype_out);
if (op1_vectype == NULL_TREE if ((op1_vectype == NULL_TREE
|| TYPE_MODE (op1_vectype) != TYPE_MODE (vectype)) || TYPE_MODE (op1_vectype) != TYPE_MODE (vectype))
&& (!slp_node
|| SLP_TREE_DEF_TYPE
(SLP_TREE_CHILDREN (slp_node)[1]) != vect_constant_def))
{ {
if (dump_enabled_p ()) if (dump_enabled_p ())
dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location, dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
...@@ -5710,7 +5713,10 @@ vectorizable_shift (stmt_vec_info stmt_info, gimple_stmt_iterator *gsi, ...@@ -5710,7 +5713,10 @@ vectorizable_shift (stmt_vec_info stmt_info, gimple_stmt_iterator *gsi,
so make sure the scalar is the right type if we are so make sure the scalar is the right type if we are
dealing with vectors of long long/long/short/char. */ dealing with vectors of long long/long/short/char. */
if (dt[1] == vect_constant_def) if (dt[1] == vect_constant_def)
op1 = fold_convert (TREE_TYPE (vectype), op1); {
if (!slp_node)
op1 = fold_convert (TREE_TYPE (vectype), op1);
}
else if (!useless_type_conversion_p (TREE_TYPE (vectype), else if (!useless_type_conversion_p (TREE_TYPE (vectype),
TREE_TYPE (op1))) TREE_TYPE (op1)))
{ {
...@@ -5821,6 +5827,23 @@ vectorizable_shift (stmt_vec_info stmt_info, gimple_stmt_iterator *gsi, ...@@ -5821,6 +5827,23 @@ vectorizable_shift (stmt_vec_info stmt_info, gimple_stmt_iterator *gsi,
} }
} }
} }
else if (slp_node
&& !useless_type_conversion_p (TREE_TYPE (vectype),
TREE_TYPE (op1)))
{
/* Convert the scalar constant shift amounts in-place. */
slp_tree shift = SLP_TREE_CHILDREN (slp_node)[1];
gcc_assert (SLP_TREE_DEF_TYPE (shift) == vect_constant_def);
for (unsigned i = 0;
i < SLP_TREE_SCALAR_OPS (shift).length (); ++i)
{
SLP_TREE_SCALAR_OPS (shift)[i]
= fold_convert (TREE_TYPE (vectype),
SLP_TREE_SCALAR_OPS (shift)[i]);
gcc_assert ((TREE_CODE (SLP_TREE_SCALAR_OPS (shift)[i])
== INTEGER_CST));
}
}
/* vec_oprnd1 is available if operand 1 should be of a scalar-type /* vec_oprnd1 is available if operand 1 should be of a scalar-type
(a special case for certain kind of vector shifts); otherwise, (a special case for certain kind of vector shifts); otherwise,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment