+2015-11-03 Richard Biener <rguenther@suse.de>
+
+ * tree-vect-data-refs.c (vect_analyze_data_refs): Do not collect
+ data references here.
+ * tree-vect-loop.c: Include cgraph.h.
+ (vect_analyze_loop_2): Collect data references here.
+ * tree-vect-slp.c (find_bb_location): Inline ...
+ (vect_slp_bb): ... here. Renamed from vect_slp_analyze_bb.
+ Factor in vect_slp_transform_bb.
+ (vect_slp_transform_bb): Removed.
+ (vect_slp_analyze_bb_1): Collect data references here.
+ * tree-vectorizer.c (pass_slp_vectorize::execute): Call
+ vect_slp_bb.
+ * tree-vectorizer.h (vect_slp_bb): Declare.
+ (vect_slp_analyze_bb): Remove.
+ (vect_slp_transform_bb): Remove.
+ (find_bb_location): Remove.
+ (vect_analyze_data_refs): Remove stmt count reference parameter.
+
2015-11-03 Evgeny Stupachenko <evstupac@gmail.com>
* multiple_target.c (create_dispatcher_calls): Add target check
*/
bool
-vect_analyze_data_refs (vec_info *vinfo, int *min_vf, unsigned *n_stmts)
+vect_analyze_data_refs (vec_info *vinfo, int *min_vf)
{
struct loop *loop = NULL;
- basic_block bb = NULL;
unsigned int i;
- vec<data_reference_p> datarefs;
struct data_reference *dr;
tree scalar_type;
if (dump_enabled_p ())
dump_printf_loc (MSG_NOTE, vect_location,
- "=== vect_analyze_data_refs ===\n");
+ "=== vect_analyze_data_refs ===\n");
if (loop_vec_info loop_vinfo = dyn_cast <loop_vec_info> (vinfo))
- {
- basic_block *bbs = LOOP_VINFO_BBS (loop_vinfo);
-
- loop = LOOP_VINFO_LOOP (loop_vinfo);
- datarefs = LOOP_VINFO_DATAREFS (loop_vinfo);
- if (!find_loop_nest (loop, &LOOP_VINFO_LOOP_NEST (loop_vinfo)))
- {
- if (dump_enabled_p ())
- dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
- "not vectorized: loop contains function calls"
- " or data references that cannot be analyzed\n");
- return false;
- }
-
- for (i = 0; i < loop->num_nodes; i++)
- {
- gimple_stmt_iterator gsi;
-
- for (gsi = gsi_start_bb (bbs[i]); !gsi_end_p (gsi); gsi_next (&gsi))
- {
- gimple *stmt = gsi_stmt (gsi);
- if (is_gimple_debug (stmt))
- continue;
- ++*n_stmts;
- if (!find_data_references_in_stmt (loop, stmt, &datarefs))
- {
- if (is_gimple_call (stmt) && loop->safelen)
- {
- tree fndecl = gimple_call_fndecl (stmt), op;
- if (fndecl != NULL_TREE)
- {
- struct cgraph_node *node = cgraph_node::get (fndecl);
- if (node != NULL && node->simd_clones != NULL)
- {
- unsigned int j, n = gimple_call_num_args (stmt);
- for (j = 0; j < n; j++)
- {
- op = gimple_call_arg (stmt, j);
- if (DECL_P (op)
- || (REFERENCE_CLASS_P (op)
- && get_base_address (op)))
- break;
- }
- op = gimple_call_lhs (stmt);
- /* Ignore #pragma omp declare simd functions
- if they don't have data references in the
- call stmt itself. */
- if (j == n
- && !(op
- && (DECL_P (op)
- || (REFERENCE_CLASS_P (op)
- && get_base_address (op)))))
- continue;
- }
- }
- }
- LOOP_VINFO_DATAREFS (loop_vinfo) = datarefs;
- if (dump_enabled_p ())
- dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
- "not vectorized: loop contains function "
- "calls or data references that cannot "
- "be analyzed\n");
- return false;
- }
- }
- }
-
- LOOP_VINFO_DATAREFS (loop_vinfo) = datarefs;
- }
- else
- {
- bb_vec_info bb_vinfo = as_a <bb_vec_info> (vinfo);
- gimple_stmt_iterator gsi;
-
- bb = BB_VINFO_BB (bb_vinfo);
- for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
- {
- gimple *stmt = gsi_stmt (gsi);
- if (is_gimple_debug (stmt))
- continue;
- ++*n_stmts;
- if (!find_data_references_in_stmt (NULL, stmt,
- &BB_VINFO_DATAREFS (bb_vinfo)))
- {
- /* Mark the rest of the basic-block as unvectorizable. */
- for (; !gsi_end_p (gsi); gsi_next (&gsi))
- {
- stmt = gsi_stmt (gsi);
- STMT_VINFO_VECTORIZABLE (vinfo_for_stmt (stmt)) = false;
- }
- break;
- }
- }
-
- datarefs = BB_VINFO_DATAREFS (bb_vinfo);
- }
+ loop = LOOP_VINFO_LOOP (loop_vinfo);
/* Go through the data-refs, check that the analysis succeeded. Update
pointer from stmt_vec_info struct to DR and vectype. */
+ vec<data_reference_p> datarefs = vinfo->datarefs;
FOR_EACH_VEC_ELT (datarefs, i, dr)
{
gimple *stmt;
#include "tree-scalar-evolution.h"
#include "tree-vectorizer.h"
#include "gimple-fold.h"
+#include "cgraph.h"
/* Loop Vectorization Pass.
unsigned int n_stmts = 0;
/* Find all data references in the loop (which correspond to vdefs/vuses)
- and analyze their evolution in the loop. Also adjust the minimal
- vectorization factor according to the loads and stores.
+ and analyze their evolution in the loop. */
- FORNOW: Handle only simple, array references, which
- alignment can be forced, and aligned pointer-references. */
+ basic_block *bbs = LOOP_VINFO_BBS (loop_vinfo);
+
+ loop_p loop = LOOP_VINFO_LOOP (loop_vinfo);
+ if (!find_loop_nest (loop, &LOOP_VINFO_LOOP_NEST (loop_vinfo)))
+ {
+ if (dump_enabled_p ())
+ dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
+ "not vectorized: loop contains function calls"
+ " or data references that cannot be analyzed\n");
+ return false;
+ }
+
+ for (unsigned i = 0; i < loop->num_nodes; i++)
+ for (gimple_stmt_iterator gsi = gsi_start_bb (bbs[i]);
+ !gsi_end_p (gsi); gsi_next (&gsi))
+ {
+ gimple *stmt = gsi_stmt (gsi);
+ if (is_gimple_debug (stmt))
+ continue;
+ ++n_stmts;
+ if (!find_data_references_in_stmt (loop, stmt,
+ &LOOP_VINFO_DATAREFS (loop_vinfo)))
+ {
+ if (is_gimple_call (stmt) && loop->safelen)
+ {
+ tree fndecl = gimple_call_fndecl (stmt), op;
+ if (fndecl != NULL_TREE)
+ {
+ cgraph_node *node = cgraph_node::get (fndecl);
+ if (node != NULL && node->simd_clones != NULL)
+ {
+ unsigned int j, n = gimple_call_num_args (stmt);
+ for (j = 0; j < n; j++)
+ {
+ op = gimple_call_arg (stmt, j);
+ if (DECL_P (op)
+ || (REFERENCE_CLASS_P (op)
+ && get_base_address (op)))
+ break;
+ }
+ op = gimple_call_lhs (stmt);
+ /* Ignore #pragma omp declare simd functions
+ if they don't have data references in the
+ call stmt itself. */
+ if (j == n
+ && !(op
+ && (DECL_P (op)
+ || (REFERENCE_CLASS_P (op)
+ && get_base_address (op)))))
+ continue;
+ }
+ }
+ }
+ if (dump_enabled_p ())
+ dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
+ "not vectorized: loop contains function "
+ "calls or data references that cannot "
+ "be analyzed\n");
+ return false;
+ }
+ }
+
+ /* Analyze the data references and also adjust the minimal
+ vectorization factor according to the loads and stores. */
- ok = vect_analyze_data_refs (loop_vinfo, &min_vf, &n_stmts);
+ ok = vect_analyze_data_refs (loop_vinfo, &min_vf);
if (!ok)
{
if (dump_enabled_p ())
#include "tree-vectorizer.h"
#include "langhooks.h"
#include "gimple-walk.h"
-
-/* Extract the location of the basic block in the source code.
- Return the basic block location if succeed and NULL if not. */
-
-source_location
-find_bb_location (basic_block bb)
-{
- gimple *stmt = NULL;
- gimple_stmt_iterator si;
-
- if (!bb)
- return UNKNOWN_LOCATION;
-
- for (si = gsi_start_bb (bb); !gsi_end_p (si); gsi_next (&si))
- {
- stmt = gsi_stmt (si);
- if (gimple_location (stmt) != UNKNOWN_LOCATION)
- return gimple_location (stmt);
- }
-
- return UNKNOWN_LOCATION;
-}
+#include "dbgcnt.h"
/* Recursively free the memory allocated for the SLP tree rooted at NODE. */
if (!bb_vinfo)
return NULL;
- if (!vect_analyze_data_refs (bb_vinfo, &min_vf, &n_stmts))
+ /* Gather all data references in the basic-block. */
+
+ for (gimple_stmt_iterator gsi = gsi_start_bb (bb);
+ !gsi_end_p (gsi); gsi_next (&gsi))
+ {
+ gimple *stmt = gsi_stmt (gsi);
+ if (is_gimple_debug (stmt))
+ continue;
+ ++n_stmts;
+ if (!find_data_references_in_stmt (NULL, stmt,
+ &BB_VINFO_DATAREFS (bb_vinfo)))
+ {
+ /* Mark the rest of the basic-block as unvectorizable. */
+ for (; !gsi_end_p (gsi); gsi_next (&gsi))
+ {
+ stmt = gsi_stmt (gsi);
+ STMT_VINFO_VECTORIZABLE (vinfo_for_stmt (stmt)) = false;
+ }
+ break;
+ }
+ }
+
+ /* Analyze the data references. */
+
+ if (!vect_analyze_data_refs (bb_vinfo, &min_vf))
{
if (dump_enabled_p ())
dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
}
-bb_vec_info
-vect_slp_analyze_bb (basic_block bb)
+/* Main entry for the BB vectorizer. Analyze and transform BB, returns
+ true if anything in the basic-block was vectorized. */
+
+bool
+vect_slp_bb (basic_block bb)
{
bb_vec_info bb_vinfo;
int insns = 0;
&& !gimple_nop_p (stmt)
&& gimple_code (stmt) != GIMPLE_LABEL)
insns++;
+ if (gimple_location (stmt) != UNKNOWN_LOCATION)
+ vect_location = gimple_location (stmt);
}
if (insns > PARAM_VALUE (PARAM_SLP_MAX_INSNS_IN_BB))
"not vectorized: too many instructions in "
"basic block.\n");
- return NULL;
+ return false;
}
/* Autodetect first vector size we try. */
{
bb_vinfo = vect_slp_analyze_bb_1 (bb);
if (bb_vinfo)
- return bb_vinfo;
+ {
+ if (!dbg_cnt (vect_slp))
+ {
+ destroy_bb_vec_info (bb_vinfo);
+ return false;
+ }
+
+ if (dump_enabled_p ())
+ dump_printf_loc (MSG_NOTE, vect_location, "SLPing BB\n");
+
+ vect_schedule_slp (bb_vinfo);
+
+ if (dump_enabled_p ())
+ dump_printf_loc (MSG_NOTE, vect_location,
+ "BASIC BLOCK VECTORIZED\n");
+
+ destroy_bb_vec_info (bb_vinfo);
+
+ return true;
+ }
destroy_bb_vec_info (bb_vinfo);
vector_sizes &= ~current_vector_size;
if (vector_sizes == 0
|| current_vector_size == 0)
- return NULL;
+ return false;
/* Try the next biggest vector size. */
current_vector_size = 1 << floor_log2 (vector_sizes);
return is_store;
}
-
-
-/* Vectorize the basic block. */
-
-void
-vect_slp_transform_bb (basic_block bb)
-{
- bb_vec_info bb_vinfo = vec_info_for_bb (bb);
- gimple_stmt_iterator si;
-
- gcc_assert (bb_vinfo);
-
- if (dump_enabled_p ())
- dump_printf_loc (MSG_NOTE, vect_location, "SLPing BB\n");
-
- for (si = gsi_start_bb (bb); !gsi_end_p (si); gsi_next (&si))
- {
- gimple *stmt = gsi_stmt (si);
- stmt_vec_info stmt_info;
-
- if (dump_enabled_p ())
- {
- dump_printf_loc (MSG_NOTE, vect_location,
- "------>SLPing statement: ");
- dump_gimple_stmt (MSG_NOTE, TDF_SLIM, stmt, 0);
- dump_printf (MSG_NOTE, "\n");
- }
-
- stmt_info = vinfo_for_stmt (stmt);
- gcc_assert (stmt_info);
-
- /* Schedule all the SLP instances when the first SLP stmt is reached. */
- if (STMT_SLP_TYPE (stmt_info))
- {
- vect_schedule_slp (bb_vinfo);
- break;
- }
- }
-
- if (dump_enabled_p ())
- dump_printf_loc (MSG_NOTE, vect_location,
- "BASIC BLOCK VECTORIZED\n");
-
- destroy_bb_vec_info (bb_vinfo);
-}
FOR_EACH_BB_FN (bb, fun)
{
- vect_location = find_bb_location (bb);
-
- if (vect_slp_analyze_bb (bb))
- {
- if (!dbg_cnt (vect_slp))
- break;
-
- vect_slp_transform_bb (bb);
- if (dump_enabled_p ())
- dump_printf_loc (MSG_OPTIMIZED_LOCATIONS, vect_location,
- "basic block vectorized\n");
- }
+ if (vect_slp_bb (bb))
+ dump_printf_loc (MSG_OPTIMIZED_LOCATIONS, vect_location,
+ "basic block vectorized\n");
}
free_stmt_vec_info_vec ();
extern bool vect_prune_runtime_alias_test_list (loop_vec_info);
extern tree vect_check_gather_scatter (gimple *, loop_vec_info, tree *, tree *,
int *);
-extern bool vect_analyze_data_refs (vec_info *, int *, unsigned *);
+extern bool vect_analyze_data_refs (vec_info *, int *);
extern tree vect_create_data_ref_ptr (gimple *, tree, struct loop *, tree,
tree *, gimple_stmt_iterator *,
gimple **, bool, bool *,
extern void vect_detect_hybrid_slp (loop_vec_info);
extern void vect_get_slp_defs (vec<tree> , slp_tree,
vec<vec<tree> > *, int);
-
-extern source_location find_bb_location (basic_block);
-extern bb_vec_info vect_slp_analyze_bb (basic_block);
-extern void vect_slp_transform_bb (basic_block);
+extern bool vect_slp_bb (basic_block);
/* In tree-vect-patterns.c. */
/* Pattern recognition functions.