The following adds support for single-lane SLP .GOMP_SIMD_LANE vectorization.
This doesn't handle much, esp. g++.dg/vect/simd-*.cc with their 'inscan' uses are unhandled. * tree-vect-slp.cc (no_arg_map): New. (vect_get_operand_map): Handle IFN_GOMP_SIMD_LANE. (vect_build_slp_tree_1): Likewise. * tree-vect-stmts.cc (vectorizable_call): Handle single-lane SLP for .GOMP_SIMD_LANE calls. --- gcc/tree-vect-slp.cc | 11 +++++++++++ gcc/tree-vect-stmts.cc | 27 +++++++++++++++++++-------- 2 files changed, 30 insertions(+), 8 deletions(-) diff --git a/gcc/tree-vect-slp.cc b/gcc/tree-vect-slp.cc index 3138a815da7..f3743997e9c 100644 --- a/gcc/tree-vect-slp.cc +++ b/gcc/tree-vect-slp.cc @@ -505,6 +505,7 @@ static const int cond_expr_maps[3][5] = { { 4, -2, -1, 1, 2 }, { 4, -1, -2, 2, 1 } }; +static const int no_arg_map[] = { 0 }; static const int arg0_map[] = { 1, 0 }; static const int arg1_map[] = { 1, 1 }; static const int arg2_map[] = { 1, 2 }; @@ -585,6 +586,9 @@ vect_get_operand_map (const gimple *stmt, bool gather_scatter_p = false, case IFN_CTZ: return arg0_map; + case IFN_GOMP_SIMD_LANE: + return no_arg_map; + default: break; } @@ -1168,6 +1172,8 @@ vect_build_slp_tree_1 (vec_info *vinfo, unsigned char *swap, ldst_p = true; rhs_code = CFN_MASK_STORE; } + else if (cfn == CFN_GOMP_SIMD_LANE) + ; else if ((cfn != CFN_LAST && cfn != CFN_MASK_CALL && internal_fn_p (cfn) @@ -1271,6 +1277,11 @@ vect_build_slp_tree_1 (vec_info *vinfo, unsigned char *swap, need_same_oprnds = true; first_op1 = gimple_call_arg (call_stmt, 1); } + else if (rhs_code == CFN_GOMP_SIMD_LANE) + { + need_same_oprnds = true; + first_op1 = gimple_call_arg (call_stmt, 1); + } } else { diff --git a/gcc/tree-vect-stmts.cc b/gcc/tree-vect-stmts.cc index 840ff8a3406..270c5a5dd34 100644 --- a/gcc/tree-vect-stmts.cc +++ b/gcc/tree-vect-stmts.cc @@ -3341,7 +3341,7 @@ vectorizable_call (vec_info *vinfo, if (ifn == IFN_LAST && !fndecl) { if (cfn == CFN_GOMP_SIMD_LANE - && !slp_node + && (!slp_node || SLP_TREE_LANES (slp_node) == 1) && loop_vinfo && LOOP_VINFO_LOOP (loop_vinfo)->simduid && TREE_CODE (gimple_call_arg (stmt, 0)) == SSA_NAME @@ -3487,18 +3487,15 @@ vectorizable_call (vec_info *vinfo, /* Build argument list for the vectorized call. */ if (slp_node) { - vec<tree> vec_oprnds0; - + unsigned int vec_num = SLP_TREE_NUMBER_OF_VEC_STMTS (slp_node); vect_get_slp_defs (vinfo, slp_node, &vec_defs); - vec_oprnds0 = vec_defs[0]; /* Arguments are ready. Create the new vector stmt. */ - FOR_EACH_VEC_ELT (vec_oprnds0, i, vec_oprnd0) + for (i = 0; i < vec_num; ++i) { int varg = 0; if (masked_loop_p && reduc_idx >= 0) { - unsigned int vec_num = vec_oprnds0.length (); /* Always true for SLP. */ gcc_assert (ncopies == 1); vargs[varg++] = vect_get_loop_mask (loop_vinfo, @@ -3539,11 +3536,26 @@ vectorizable_call (vec_info *vinfo, vect_finish_stmt_generation (vinfo, stmt_info, new_stmt, gsi); } + else if (cfn == CFN_GOMP_SIMD_LANE) + { + /* ??? For multi-lane SLP we'd need to build + { 0, 0, .., 1, 1, ... }. */ + tree cst = build_index_vector (vectype_out, + i * nunits_out, 1); + tree new_var + = vect_get_new_ssa_name (vectype_out, vect_simple_var, + "cst_"); + gimple *init_stmt = gimple_build_assign (new_var, cst); + vect_init_vector_1 (vinfo, stmt_info, init_stmt, NULL); + new_temp = make_ssa_name (vec_dest); + new_stmt = gimple_build_assign (new_temp, new_var); + vect_finish_stmt_generation (vinfo, stmt_info, new_stmt, + gsi); + } else { if (len_opno >= 0 && len_loop_p) { - unsigned int vec_num = vec_oprnds0.length (); /* Always true for SLP. */ gcc_assert (ncopies == 1); tree len @@ -3557,7 +3569,6 @@ vectorizable_call (vec_info *vinfo, } else if (mask_opno >= 0 && masked_loop_p) { - unsigned int vec_num = vec_oprnds0.length (); /* Always true for SLP. */ gcc_assert (ncopies == 1); tree mask = vect_get_loop_mask (loop_vinfo, -- 2.43.0