(edge, struct loop *, bool, basic_block *);
static edge slpeel_add_loop_guard (basic_block, tree, basic_block, basic_block);
-static void allocate_new_names (bitmap);
static void rename_use_op (use_operand_p);
-static void rename_def_op (def_operand_p, tree);
static void rename_variables_in_bb (basic_block);
-static void free_new_names (bitmap);
static void rename_variables_in_loop (struct loop *);
/*************************************************************************
General Vectorization Utilities
*************************************************************************/
static void vect_set_dump_settings (void);
-static bool need_imm_uses_for (tree);
/* vect_dump will be set to stderr or dump_file if exist. */
FILE *vect_dump;
to mark that it's uninitialized. */
enum verbosity_levels vect_verbosity_level = MAX_VERBOSITY_LEVEL;
-
+/* Number of loops, at the beginning of vectorization. */
+unsigned int vect_loops_num;
\f
/*************************************************************************
Simple Loop Peeling Utilities
*************************************************************************/
-/* For each definition in DEFINITIONS this function allocates
- new ssa name. */
-
-static void
-allocate_new_names (bitmap definitions)
-{
- unsigned ver;
- bitmap_iterator bi;
-
- EXECUTE_IF_SET_IN_BITMAP (definitions, 0, ver, bi)
- {
- tree def = ssa_name (ver);
- tree *new_name_ptr = xmalloc (sizeof (tree));
-
- bool abnormal = SSA_NAME_OCCURS_IN_ABNORMAL_PHI (def);
-
- *new_name_ptr = duplicate_ssa_name (def, SSA_NAME_DEF_STMT (def));
- SSA_NAME_OCCURS_IN_ABNORMAL_PHI (*new_name_ptr) = abnormal;
-
- SSA_NAME_AUX (def) = new_name_ptr;
- }
-}
-
-
/* Renames the use *OP_P. */
static void
rename_use_op (use_operand_p op_p)
{
- tree *new_name_ptr;
+ tree new_name;
if (TREE_CODE (USE_FROM_PTR (op_p)) != SSA_NAME)
return;
- new_name_ptr = SSA_NAME_AUX (USE_FROM_PTR (op_p));
-
- /* Something defined outside of the loop. */
- if (!new_name_ptr)
- return;
-
- /* An ordinary ssa name defined in the loop. */
-
- SET_USE (op_p, *new_name_ptr);
-}
-
-
-/* Renames the def *OP_P in statement STMT. */
-
-static void
-rename_def_op (def_operand_p op_p, tree stmt)
-{
- tree *new_name_ptr;
-
- if (TREE_CODE (DEF_FROM_PTR (op_p)) != SSA_NAME)
- return;
-
- new_name_ptr = SSA_NAME_AUX (DEF_FROM_PTR (op_p));
+ new_name = get_current_def (USE_FROM_PTR (op_p));
/* Something defined outside of the loop. */
- if (!new_name_ptr)
+ if (!new_name)
return;
/* An ordinary ssa name defined in the loop. */
- SET_DEF (op_p, *new_name_ptr);
- SSA_NAME_DEF_STMT (DEF_FROM_PTR (op_p)) = stmt;
+ SET_USE (op_p, new_name);
}
tree phi;
block_stmt_iterator bsi;
tree stmt;
- stmt_ann_t ann;
- use_optype uses;
- vuse_optype vuses;
- def_optype defs;
- v_may_def_optype v_may_defs;
- v_must_def_optype v_must_defs;
- unsigned i;
+ use_operand_p use_p;
+ ssa_op_iter iter;
edge e;
edge_iterator ei;
struct loop *loop = bb->loop_father;
- for (phi = phi_nodes (bb); phi; phi = PHI_CHAIN (phi))
- rename_def_op (PHI_RESULT_PTR (phi), phi);
-
for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi))
{
stmt = bsi_stmt (bsi);
- get_stmt_operands (stmt);
- ann = stmt_ann (stmt);
-
- uses = USE_OPS (ann);
- for (i = 0; i < NUM_USES (uses); i++)
- rename_use_op (USE_OP_PTR (uses, i));
-
- defs = DEF_OPS (ann);
- for (i = 0; i < NUM_DEFS (defs); i++)
- rename_def_op (DEF_OP_PTR (defs, i), stmt);
-
- vuses = VUSE_OPS (ann);
- for (i = 0; i < NUM_VUSES (vuses); i++)
- rename_use_op (VUSE_OP_PTR (vuses, i));
-
- v_may_defs = V_MAY_DEF_OPS (ann);
- for (i = 0; i < NUM_V_MAY_DEFS (v_may_defs); i++)
- {
- rename_use_op (V_MAY_DEF_OP_PTR (v_may_defs, i));
- rename_def_op (V_MAY_DEF_RESULT_PTR (v_may_defs, i), stmt);
- }
-
- v_must_defs = V_MUST_DEF_OPS (ann);
- for (i = 0; i < NUM_V_MUST_DEFS (v_must_defs); i++)
- {
- rename_use_op (V_MUST_DEF_KILL_PTR (v_must_defs, i));
- rename_def_op (V_MUST_DEF_RESULT_PTR (v_must_defs, i), stmt);
- }
+ FOR_EACH_SSA_USE_OPERAND (use_p, stmt, iter,
+ (SSA_OP_ALL_USES | SSA_OP_ALL_KILLS))
+ rename_use_op (use_p);
}
FOR_EACH_EDGE (e, ei, bb->succs)
}
-/* Releases the structures holding the new ssa names. */
-
-static void
-free_new_names (bitmap definitions)
-{
- unsigned ver;
- bitmap_iterator bi;
-
- EXECUTE_IF_SET_IN_BITMAP (definitions, 0, ver, bi)
- {
- tree def = ssa_name (ver);
-
- if (SSA_NAME_AUX (def))
- {
- free (SSA_NAME_AUX (def));
- SSA_NAME_AUX (def) = NULL;
- }
- }
-}
-
-
/* Renames variables in new generated LOOP. */
static void
slpeel_update_phis_for_duplicate_loop (struct loop *orig_loop,
struct loop *new_loop, bool after)
{
- tree *new_name_ptr, new_ssa_name;
+ tree new_ssa_name;
tree phi_new, phi_orig;
tree def;
edge orig_loop_latch = loop_latch_edge (orig_loop);
if (TREE_CODE (def) != SSA_NAME)
continue;
- new_name_ptr = SSA_NAME_AUX (def);
- if (!new_name_ptr)
+ new_ssa_name = get_current_def (def);
+ if (!new_ssa_name)
/* Something defined outside of the loop. */
continue;
/* An ordinary ssa name defined in the loop. */
- new_ssa_name = *new_name_ptr;
add_phi_arg (phi_new, new_ssa_name, loop_latch_edge (new_loop));
/* step 3 (case 1). */
new_merge
next_bb
- The ssa-names defined in the original loop have an SSA_NAME_AUX pointer
- that records the corresponding new ssa-name used in the new duplicated
- loop copy.
+ The SSA names defined in the original loop have a current
+ reaching definition that that records the corresponding new
+ ssa-name used in the new duplicated loop copy.
*/
/* Function slpeel_update_phi_nodes_for_guard1
{
tree orig_phi, new_phi;
tree update_phi, update_phi2;
- tree *new_name_ptr, *new_name_ptr2;
tree guard_arg, loop_arg;
basic_block new_merge_bb = guard_edge->dest;
edge e = EDGE_SUCC (new_merge_bb, 0);
gcc_assert (PHI_ARG_DEF_FROM_EDGE (update_phi2, new_exit_e) == loop_arg);
SET_PHI_ARG_DEF (update_phi2, new_exit_e->dest_idx, PHI_RESULT (new_phi));
- /* 2.4. Record the newly created name in SSA_NAME_AUX.
+ /* 2.4. Record the newly created name with set_current_def.
We want to find a name such that
- name = *(SSA_NAME_AUX (orig_loop_name))
- and to set its SSA_NAME_AUX as follows:
- *(SSA_NAME_AUX (name)) = new_phi_name
+ name = get_current_def (orig_loop_name)
+ and to set its current definition as follows:
+ set_current_def (name, new_phi_name)
If LOOP is a new loop then loop_arg is already the name we're
looking for. If LOOP is the original loop, then loop_arg is
the orig_loop_name and the relevant name is recorded in its
- SSA_NAME_AUX */
+ current reaching definition. */
if (is_new_loop)
current_new_name = loop_arg;
else
{
- new_name_ptr = SSA_NAME_AUX (loop_arg);
- gcc_assert (new_name_ptr);
- current_new_name = *new_name_ptr;
+ current_new_name = get_current_def (loop_arg);
+ gcc_assert (current_new_name);
}
#ifdef ENABLE_CHECKING
- gcc_assert (! SSA_NAME_AUX (current_new_name));
+ gcc_assert (get_current_def (current_new_name) == NULL_TREE);
#endif
- new_name_ptr2 = xmalloc (sizeof (tree));
- *new_name_ptr2 = PHI_RESULT (new_phi);
- SSA_NAME_AUX (current_new_name) = new_name_ptr2;
+ set_current_def (current_new_name, PHI_RESULT (new_phi));
bitmap_set_bit (*defs, SSA_NAME_VERSION (current_new_name));
}
{
tree orig_phi, new_phi;
tree update_phi, update_phi2;
- tree *new_name_ptr, *new_name_ptr2;
tree guard_arg, loop_arg;
basic_block new_merge_bb = guard_edge->dest;
edge e = EDGE_SUCC (new_merge_bb, 0);
basic_block update_bb = e->dest;
edge new_exit_e;
- tree orig_def;
+ tree orig_def, orig_def_new_name;
tree new_name, new_name2;
tree arg;
{
orig_phi = update_phi;
orig_def = PHI_ARG_DEF_FROM_EDGE (orig_phi, e);
- new_name_ptr = SSA_NAME_AUX (orig_def);
+ orig_def_new_name = get_current_def (orig_def);
arg = NULL_TREE;
/** 1. Handle new-merge-point phis **/
new_merge_bb);
/* 1.2. NEW_MERGE_BB has two incoming edges: GUARD_EDGE and the exit-edge
- of LOOP. Set the two phi args in NEW_PHI for these edges: */
+ of LOOP. Set the two PHI args in NEW_PHI for these edges: */
new_name = orig_def;
new_name2 = NULL_TREE;
- if (new_name_ptr)
+ if (orig_def_new_name)
{
- new_name = *new_name_ptr;
- new_name_ptr2 = SSA_NAME_AUX (new_name);
- if (new_name_ptr2)
- /* Some variables have both loop-entry-phis and loop-exit-phis.
- Such variables were given yet newer names by phis placed in
- guard_bb by slpeel_update_phi_nodes_for_guard1. I.e:
- new_name2 = SSA_NAME_AUX (SSA_NAME_AUX (orig_name)). */
- new_name2 = *new_name_ptr2;
+ new_name = orig_def_new_name;
+ /* Some variables have both loop-entry-phis and loop-exit-phis.
+ Such variables were given yet newer names by phis placed in
+ guard_bb by slpeel_update_phi_nodes_for_guard1. I.e:
+ new_name2 = get_current_def (get_current_def (orig_name)). */
+ new_name2 = get_current_def (new_name);
}
if (is_new_loop)
/** 3. Handle loop-closed-ssa-form phis for first loop **/
- /* 3.1. Find the relevant names that need an exit-phi in GUARD_BB, i.e.
- names for which slpeel_update_phi_nodes_for_guard1 had not already
- created a phi node. This is the case for names that are used outside
+ /* 3.1. Find the relevant names that need an exit-phi in
+ GUARD_BB, i.e. names for which
+ slpeel_update_phi_nodes_for_guard1 had not already created a
+ phi node. This is the case for names that are used outside
the loop (and therefore need an exit phi) but are not updated
- across loop iterations (and therefore don't have a loop-header-phi).
-
- slpeel_update_phi_nodes_for_guard1 is responsible for creating
- loop-exit phis in GUARD_BB for names that have a loop-header-phi. When
- such a phi is created we also record the new name in SSA_NAME_AUX. If
- this new name exists, then guard_arg was set to this new name
- (see 1.2 above). Therefore, if guard_arg is not this new name, this is
- an indication that an exit-phi in GUARD_BB was not yet created, so we
- take care of it here.
- */
+ across loop iterations (and therefore don't have a
+ loop-header-phi).
+
+ slpeel_update_phi_nodes_for_guard1 is responsible for
+ creating loop-exit phis in GUARD_BB for names that have a
+ loop-header-phi. When such a phi is created we also record
+ the new name in its current definition. If this new name
+ exists, then guard_arg was set to this new name (see 1.2
+ above). Therefore, if guard_arg is not this new name, this
+ is an indication that an exit-phi in GUARD_BB was not yet
+ created, so we take care of it here. */
if (guard_arg == new_name2)
continue;
arg = guard_arg;
tree orig_cond = get_loop_exit_condition (loop);
block_stmt_iterator loop_exit_bsi = bsi_last (exit_e->src);
- if (any_marked_for_rewrite_p ())
+ if (need_ssa_update_p ())
return false;
if (loop->inner
second_loop = loop;
}
- definitions = marked_ssa_names ();
- allocate_new_names (definitions);
+ definitions = ssa_names_to_replace ();
slpeel_update_phis_for_duplicate_loop (loop, new_loop, e == exit_e);
rename_variables_in_loop (new_loop);
if (update_first_loop_count)
slpeel_make_loop_iterate_ntimes (first_loop, first_niters);
- free_new_names (definitions);
BITMAP_FREE (definitions);
- unmark_all_for_rewrite ();
+ delete_update_ssa ();
return new_loop;
}
tree stmt = bsi_stmt (si);
stmt_ann_t ann;
- get_stmt_operands (stmt);
ann = stmt_ann (stmt);
set_stmt_info (ann, new_stmt_vec_info (stmt, res));
}
int nunits;
tree vectype;
- if (nbytes == 0)
+ if (nbytes == 0 || nbytes >= UNITS_PER_SIMD_WORD)
return NULL_TREE;
/* FORNOW: Only a single vector size per target (UNITS_PER_SIMD_WORD)
print_generic_expr (vect_dump, vectype, TDF_SLIM);
}
- if (!VECTOR_MODE_P (TYPE_MODE (vectype)))
+ if (!VECTOR_MODE_P (TYPE_MODE (vectype))
+ && !INTEGRAL_MODE_P (TYPE_MODE (vectype)))
{
- /* TODO: tree-complex.c sometimes can parallelize operations
- on generic vectors. We can vectorize the loop in that case,
- but then we should re-run the lowering pass. */
if (vect_print_dump_info (REPORT_DETAILS, UNKNOWN_LOC))
fprintf (vect_dump, "mode not supported by target.");
return NULL_TREE;
}
-/* Function need_imm_uses_for.
-
- Return whether we ought to include information for 'var'
- when calculating immediate uses. For this pass we only want use
- information for non-virtual variables. */
-
-static bool
-need_imm_uses_for (tree var)
-{
- return is_gimple_reg (var);
-}
-
-
/* Function vectorize_loops.
Entry Point to loop vectorization phase. */
void
vectorize_loops (struct loops *loops)
{
- unsigned int i, loops_num;
+ unsigned int i;
unsigned int num_vectorized_loops = 0;
/* Fix the verbosity level if not defined explicitly by the user. */
vect_set_dump_settings ();
- /* Does the target support SIMD? */
- /* FORNOW: until more sophisticated machine modelling is in place. */
- if (!UNITS_PER_SIMD_WORD)
- {
- if (vect_print_dump_info (REPORT_DETAILS, UNKNOWN_LOC))
- fprintf (vect_dump, "vectorizer: target vector size is not defined.");
- return;
- }
-
-#ifdef ENABLE_CHECKING
- verify_loop_closed_ssa ();
-#endif
-
- compute_immediate_uses (TDFA_USE_OPS, need_imm_uses_for);
-
/* ----------- Analyze loops. ----------- */
/* If some loop was duplicated, it gets bigger number
than all previously defined loops. This fact allows us to run
only over initial loops skipping newly generated ones. */
- loops_num = loops->num;
- for (i = 1; i < loops_num; i++)
+ vect_loops_num = loops->num;
+ for (i = 1; i < vect_loops_num; i++)
{
loop_vec_info loop_vinfo;
struct loop *loop = loops->parray[i];
/* ----------- Finalize. ----------- */
- free_df ();
- for (i = 1; i < loops_num; i++)
+ for (i = 1; i < vect_loops_num; i++)
{
struct loop *loop = loops->parray[i];
loop_vec_info loop_vinfo;