From 6c7b0df8029d01e05577668333660d0bc58a3023 Mon Sep 17 00:00:00 2001 From: Richard Biener Date: Tue, 22 Oct 2019 13:08:53 +0000 Subject: [PATCH] re PR tree-optimization/92173 (ICE in optab_for_tree_code, at optabs-tree.c:81) 2019-10-22 Richard Biener 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 --- gcc/ChangeLog | 9 +++++++ gcc/testsuite/ChangeLog | 5 ++++ gcc/testsuite/gcc.dg/vshift-5.c | 44 +++++++++++++++++++++++++++++++++ gcc/tree-vect-slp.c | 28 ++++++++++++++++----- gcc/tree-vect-stmts.c | 29 +++++++++++++++++++--- 5 files changed, 106 insertions(+), 9 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 34ce686e1a0..f8cfef70508 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,12 @@ +2019-10-22 Richard Biener + + 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 PR middle-end/90796 diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 9caf60787d4..0581b5f50c9 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2019-10-22 Richard Biener + + PR tree-optimization/92173 + * gcc.dg/torture/pr92173.c: New testcase. + 2019-10-22 Michael Matz PR middle-end/90796 diff --git a/gcc/testsuite/gcc.dg/vshift-5.c b/gcc/testsuite/gcc.dg/vshift-5.c index daa5f1c5cd8..62e6328cb28 100644 --- a/gcc/testsuite/gcc.dg/vshift-5.c +++ b/gcc/testsuite/gcc.dg/vshift-5.c @@ -40,6 +40,42 @@ f2 (void) a[3] = a3; } +__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) { @@ -77,5 +113,13 @@ main () if (a[0] != (4LL << 7) || a[1] != (3LL << 8) || a[2] != (2LL << 9) || a[3] != (1LL << 10)) 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; } diff --git a/gcc/tree-vect-slp.c b/gcc/tree-vect-slp.c index 20ea1059a2d..864db64d200 100644 --- a/gcc/tree-vect-slp.c +++ b/gcc/tree-vect-slp.c @@ -475,8 +475,11 @@ again: /* Check the types of the definitions. */ switch (dt) { - case vect_constant_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->ops.quick_push (oprnd); break; @@ -1504,9 +1507,10 @@ static void vect_print_slp_tree (dump_flags_t dump_kind, dump_location_t loc, slp_tree node, hash_set &visited) { - int i; + unsigned i; stmt_vec_info stmt_info; slp_tree child; + tree op; if (visited.add (node)) return; @@ -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_user_location_t user_loc = loc.get_user_location (); dump_printf_loc (metadata, user_loc, "node%s %p (max_nunits=%u)\n", - SLP_TREE_DEF_TYPE (node) != vect_internal_def - ? " (external)" : "", node, + SLP_TREE_DEF_TYPE (node) == vect_external_def + ? " (external)" + : (SLP_TREE_DEF_TYPE (node) == vect_constant_def + ? " (constant)" + : ""), node, estimated_poly_value (node->max_nunits)); - FOR_EACH_VEC_ELT (SLP_TREE_SCALAR_STMTS (node), i, stmt_info) - dump_printf_loc (metadata, user_loc, "\tstmt %d %G", i, stmt_info->stmt); + if (SLP_TREE_SCALAR_STMTS (node).exists ()) + 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 ()) return; dump_printf_loc (metadata, user_loc, "\tchildren"); diff --git a/gcc/tree-vect-stmts.c b/gcc/tree-vect-stmts.c index 7f6100e0ec6..a44c3deb082 100644 --- a/gcc/tree-vect-stmts.c +++ b/gcc/tree-vect-stmts.c @@ -5670,8 +5670,11 @@ vectorizable_shift (stmt_vec_info stmt_info, gimple_stmt_iterator *gsi, if (!op1_vectype) op1_vectype = get_same_sized_vectype (TREE_TYPE (op1), vectype_out); - if (op1_vectype == NULL_TREE - || TYPE_MODE (op1_vectype) != TYPE_MODE (vectype)) + if ((op1_vectype == NULL_TREE + || 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 ()) dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location, @@ -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 dealing with vectors of long long/long/short/char. */ 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), TREE_TYPE (op1))) { @@ -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 (a special case for certain kind of vector shifts); otherwise, -- 2.30.2