return (decided_to_slp > 0);
}
-/* Private data for vect_detect_hybrid_slp. */
-struct vdhs_data
-{
- loop_vec_info loop_vinfo;
- vec<stmt_vec_info> *worklist;
-};
-
-/* Walker for walk_gimple_op. */
-
-static tree
-vect_detect_hybrid_slp (tree *tp, int *, void *data)
-{
- walk_stmt_info *wi = (walk_stmt_info *)data;
- vdhs_data *dat = (vdhs_data *)wi->info;
-
- if (wi->is_lhs)
- return NULL_TREE;
-
- stmt_vec_info def_stmt_info = dat->loop_vinfo->lookup_def (*tp);
- if (!def_stmt_info)
- return NULL_TREE;
- def_stmt_info = vect_stmt_to_vectorize (def_stmt_info);
- if (PURE_SLP_STMT (def_stmt_info))
- {
- if (dump_enabled_p ())
- dump_printf_loc (MSG_NOTE, vect_location, "marking hybrid: %G",
- def_stmt_info->stmt);
- STMT_SLP_TYPE (def_stmt_info) = hybrid;
- dat->worklist->safe_push (def_stmt_info);
- }
-
- return NULL_TREE;
-}
-
-/* Look if STMT_INFO is consumed by SLP indirectly and mark it pure_slp
- if so, otherwise pushing it to WORKLIST. */
-
-static void
-maybe_push_to_hybrid_worklist (vec_info *vinfo,
- vec<stmt_vec_info> &worklist,
- stmt_vec_info stmt_info)
-{
- if (dump_enabled_p ())
- dump_printf_loc (MSG_NOTE, vect_location,
- "Processing hybrid candidate : %G", stmt_info->stmt);
- stmt_vec_info orig_info = vect_orig_stmt (stmt_info);
- imm_use_iterator iter2;
- ssa_op_iter iter1;
- use_operand_p use_p;
- def_operand_p def_p;
- bool any_def = false;
- FOR_EACH_PHI_OR_STMT_DEF (def_p, orig_info->stmt, iter1, SSA_OP_DEF)
- {
- any_def = true;
- FOR_EACH_IMM_USE_FAST (use_p, iter2, DEF_FROM_PTR (def_p))
- {
- if (is_gimple_debug (USE_STMT (use_p)))
- continue;
- stmt_vec_info use_info = vinfo->lookup_stmt (USE_STMT (use_p));
- /* An out-of loop use means this is a loop_vect sink. */
- if (!use_info)
- {
- if (dump_enabled_p ())
- dump_printf_loc (MSG_NOTE, vect_location,
- "Found loop_vect sink: %G", stmt_info->stmt);
- worklist.safe_push (stmt_info);
- return;
- }
- else if (!STMT_SLP_TYPE (vect_stmt_to_vectorize (use_info)))
- {
- if (dump_enabled_p ())
- dump_printf_loc (MSG_NOTE, vect_location,
- "Found loop_vect use: %G", use_info->stmt);
- worklist.safe_push (stmt_info);
- return;
- }
- }
- }
- /* No def means this is a loop_vect sink. Gimple conditionals also don't have a
- def but shouldn't be considered sinks. */
- if (!any_def && STMT_VINFO_DEF_TYPE (stmt_info) != vect_condition_def)
- {
- if (dump_enabled_p ())
- dump_printf_loc (MSG_NOTE, vect_location,
- "Found loop_vect sink: %G", stmt_info->stmt);
- worklist.safe_push (stmt_info);
- return;
- }
- if (dump_enabled_p ())
- dump_printf_loc (MSG_NOTE, vect_location,
- "Marked SLP consumed stmt pure: %G", stmt_info->stmt);
- STMT_SLP_TYPE (stmt_info) = pure_slp;
-}
-
-/* Find stmts that must be both vectorized and SLPed. */
-
-bool
-vect_detect_hybrid_slp (loop_vec_info loop_vinfo)
-{
- DUMP_VECT_SCOPE ("vect_detect_hybrid_slp");
-
- /* All stmts participating in SLP are marked pure_slp, all other
- stmts are loop_vect.
- First collect all loop_vect stmts into a worklist.
- SLP patterns cause not all original scalar stmts to appear in
- SLP_TREE_SCALAR_STMTS and thus not all of them are marked pure_slp.
- Rectify this here and do a backward walk over the IL only considering
- stmts as loop_vect when they are used by a loop_vect stmt and otherwise
- mark them as pure_slp. */
- auto_vec<stmt_vec_info> worklist;
- for (int i = LOOP_VINFO_LOOP (loop_vinfo)->num_nodes - 1; i >= 0; --i)
- {
- basic_block bb = LOOP_VINFO_BBS (loop_vinfo)[i];
- for (gphi_iterator gsi = gsi_start_phis (bb); !gsi_end_p (gsi);
- gsi_next (&gsi))
- {
- gphi *phi = gsi.phi ();
- stmt_vec_info stmt_info = loop_vinfo->lookup_stmt (phi);
- if (!STMT_SLP_TYPE (stmt_info) && STMT_VINFO_RELEVANT (stmt_info))
- maybe_push_to_hybrid_worklist (loop_vinfo,
- worklist, stmt_info);
- }
- for (gimple_stmt_iterator gsi = gsi_last_bb (bb); !gsi_end_p (gsi);
- gsi_prev (&gsi))
- {
- gimple *stmt = gsi_stmt (gsi);
- if (is_gimple_debug (stmt))
- continue;
- stmt_vec_info stmt_info = loop_vinfo->lookup_stmt (stmt);
- if (STMT_VINFO_IN_PATTERN_P (stmt_info))
- {
- for (gimple_stmt_iterator gsi2
- = gsi_start (STMT_VINFO_PATTERN_DEF_SEQ (stmt_info));
- !gsi_end_p (gsi2); gsi_next (&gsi2))
- {
- stmt_vec_info patt_info
- = loop_vinfo->lookup_stmt (gsi_stmt (gsi2));
- if (!STMT_SLP_TYPE (patt_info)
- && STMT_VINFO_RELEVANT (patt_info))
- maybe_push_to_hybrid_worklist (loop_vinfo,
- worklist, patt_info);
- }
- stmt_info = STMT_VINFO_RELATED_STMT (stmt_info);
- }
- if (!STMT_SLP_TYPE (stmt_info) && STMT_VINFO_RELEVANT (stmt_info))
- maybe_push_to_hybrid_worklist (loop_vinfo,
- worklist, stmt_info);
- }
- }
-
- /* Now we have a worklist of non-SLP stmts, follow use->def chains and
- mark any SLP vectorized stmt as hybrid.
- ??? We're visiting def stmts N times (once for each non-SLP and
- once for each hybrid-SLP use). */
- walk_stmt_info wi;
- vdhs_data dat;
- dat.worklist = &worklist;
- dat.loop_vinfo = loop_vinfo;
- memset (&wi, 0, sizeof (wi));
- wi.info = (void *)&dat;
- while (!worklist.is_empty ())
- {
- stmt_vec_info stmt_info = worklist.pop ();
- /* Since SSA operands are not set up for pattern stmts we need
- to use walk_gimple_op. */
- wi.is_lhs = 0;
- walk_gimple_op (stmt_info->stmt, vect_detect_hybrid_slp, &wi);
- /* For gather/scatter make sure to walk the offset operand, that
- can be a scaling and conversion away. */
- gather_scatter_info gs_info;
- if (STMT_VINFO_GATHER_SCATTER_P (stmt_info)
- && vect_check_gather_scatter (stmt_info, loop_vinfo, &gs_info))
- {
- int dummy;
- vect_detect_hybrid_slp (&gs_info.offset, &dummy, &wi);
- }
- }
-
- /* Determine if all the stmts in the loop can be SLPed. */
- for (unsigned i = 0; i < LOOP_VINFO_LOOP (loop_vinfo)->num_nodes; i++)
- {
- basic_block bb = LOOP_VINFO_BBS (loop_vinfo)[i];
- for (gphi_iterator si = gsi_start_phis (bb); !gsi_end_p (si);
- gsi_next (&si))
- {
- stmt_vec_info stmt_info = loop_vinfo->lookup_stmt (si.phi ());
- if (!stmt_info)
- continue;
- if ((STMT_VINFO_RELEVANT_P (stmt_info)
- || VECTORIZABLE_CYCLE_DEF (STMT_VINFO_DEF_TYPE (stmt_info)))
- && !PURE_SLP_STMT (stmt_info))
- {
- /* STMT needs both SLP and loop-based vectorization. */
- if (dump_enabled_p ())
- dump_printf_loc (MSG_NOTE, vect_location,
- "Loop contains SLP and non-SLP stmts\n");
- return false;
- }
- }
- for (gimple_stmt_iterator si = gsi_start_bb (bb); !gsi_end_p (si);
- gsi_next (&si))
- {
- if (is_gimple_debug (gsi_stmt (si)))
- continue;
- stmt_vec_info stmt_info = loop_vinfo->lookup_stmt (gsi_stmt (si));
- stmt_info = vect_stmt_to_vectorize (stmt_info);
- if ((STMT_VINFO_RELEVANT_P (stmt_info)
- || VECTORIZABLE_CYCLE_DEF (STMT_VINFO_DEF_TYPE (stmt_info)))
- && !PURE_SLP_STMT (stmt_info))
- {
- /* STMT needs both SLP and loop-based vectorization. */
- if (dump_enabled_p ())
- dump_printf_loc (MSG_NOTE, vect_location,
- "Loop contains SLP and non-SLP stmts\n");
- return false;
- }
- }
- }
-
- if (dump_enabled_p ())
- dump_printf_loc (MSG_NOTE, vect_location,
- "Loop contains only SLP stmts\n");
- return true;
-}
-
-
/* Initialize a bb_vec_info struct for the statements in BBS basic blocks. */
_bb_vec_info::_bb_vec_info (vec<basic_block> _bbs, vec_info_shared *shared)