* Makefile.in (tree-ssa-copy.o): Add $(CFGLOOP_H) dependency.
* tree-ssa-copy.c (init_copy_prop): Do not propagate through
single-argument PHIs if we are in loop-closed SSA form.
* tree-vect-loop-manip.c (slpeel_add_loop_guard): Pass extra guards
for the pre-condition.
(slpeel_tree_peel_loop_to_edge): Likewise.
(vect_build_loop_niters): Take an optional sequence to append stmts.
(vect_generate_tmps_on_preheader): Likewise.
(vect_do_peeling_for_loop_bound): Take extra guards for the
pre-condition.
(vect_do_peeling_for_alignment): Adjust. Unconditionally apply
the cost model check.
(vect_loop_versioning): Take stmt and stmt list to put pre-condition
guards if we are going to peel. Do not apply versioning in that
case.
* tree-vectorizer.h (vect_loop_versioning): Adjust declaration.
(vect_do_peeling_for_loop_bound): Likewise.
* tree-vect-loop.c (vect_transform_loop): If we are peeling for
loop bound only record extra pre-conditions, do not apply loop
versioning.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@145551
138bc75d-0d04-0410-961f-
82ee72b054a4
2009-04-04 Richard Guenther <rguenther@suse.de>
2009-04-04 Richard Guenther <rguenther@suse.de>
+ * Makefile.in (tree-ssa-copy.o): Add $(CFGLOOP_H) dependency.
+ * tree-ssa-copy.c (init_copy_prop): Do not propagate through
+ single-argument PHIs if we are in loop-closed SSA form.
+ * tree-vect-loop-manip.c (slpeel_add_loop_guard): Pass extra guards
+ for the pre-condition.
+ (slpeel_tree_peel_loop_to_edge): Likewise.
+ (vect_build_loop_niters): Take an optional sequence to append stmts.
+ (vect_generate_tmps_on_preheader): Likewise.
+ (vect_do_peeling_for_loop_bound): Take extra guards for the
+ pre-condition.
+ (vect_do_peeling_for_alignment): Adjust. Unconditionally apply
+ the cost model check.
+ (vect_loop_versioning): Take stmt and stmt list to put pre-condition
+ guards if we are going to peel. Do not apply versioning in that
+ case.
+ * tree-vectorizer.h (vect_loop_versioning): Adjust declaration.
+ (vect_do_peeling_for_loop_bound): Likewise.
+ * tree-vect-loop.c (vect_transform_loop): If we are peeling for
+ loop bound only record extra pre-conditions, do not apply loop
+ versioning.
+
+2009-04-04 Richard Guenther <rguenther@suse.de>
+
* tree-ssa-operands.c (pop_stmt_changes): Remove automatic
renaming code.
* tree-ssa-operands.c (pop_stmt_changes): Remove automatic
renaming code.
tree-ssa-copy.o : tree-ssa-copy.c $(TREE_FLOW_H) $(CONFIG_H) $(SYSTEM_H) \
$(RTL_H) $(TREE_H) $(TM_P_H) $(EXPR_H) $(GGC_H) output.h $(DIAGNOSTIC_H) \
$(FUNCTION_H) $(TIMEVAR_H) $(TM_H) coretypes.h $(TREE_DUMP_H) \
tree-ssa-copy.o : tree-ssa-copy.c $(TREE_FLOW_H) $(CONFIG_H) $(SYSTEM_H) \
$(RTL_H) $(TREE_H) $(TM_P_H) $(EXPR_H) $(GGC_H) output.h $(DIAGNOSTIC_H) \
$(FUNCTION_H) $(TIMEVAR_H) $(TM_H) coretypes.h $(TREE_DUMP_H) \
- $(BASIC_BLOCK_H) tree-pass.h langhooks.h tree-ssa-propagate.h $(FLAGS_H)
+ $(BASIC_BLOCK_H) tree-pass.h langhooks.h tree-ssa-propagate.h $(FLAGS_H) \
+ $(CFGLOOP_H)
tree-ssa-propagate.o : tree-ssa-propagate.c $(TREE_FLOW_H) $(CONFIG_H) \
$(SYSTEM_H) $(RTL_H) $(TREE_H) $(TM_P_H) $(EXPR_H) $(GGC_H) output.h \
$(DIAGNOSTIC_H) $(FUNCTION_H) $(TIMEVAR_H) $(TM_H) coretypes.h \
tree-ssa-propagate.o : tree-ssa-propagate.c $(TREE_FLOW_H) $(CONFIG_H) \
$(SYSTEM_H) $(RTL_H) $(TREE_H) $(TM_P_H) $(EXPR_H) $(GGC_H) output.h \
$(DIAGNOSTIC_H) $(FUNCTION_H) $(TIMEVAR_H) $(TM_H) coretypes.h \
#include "tree-pass.h"
#include "tree-ssa-propagate.h"
#include "langhooks.h"
#include "tree-pass.h"
#include "tree-ssa-propagate.h"
#include "langhooks.h"
/* This file implements the copy propagation pass and provides a
handful of interfaces for performing const/copy propagation and
/* This file implements the copy propagation pass and provides a
handful of interfaces for performing const/copy propagation and
tree def;
def = gimple_phi_result (phi);
tree def;
def = gimple_phi_result (phi);
- if (!is_gimple_reg (def))
+ if (!is_gimple_reg (def)
+ /* In loop-closed SSA form do not copy-propagate through
+ PHI nodes. Technically this is only needed for loop
+ exit PHIs, but this is difficult to query. */
+ || (current_loops
+ && gimple_phi_num_args (phi) == 1
+ && loops_state_satisfies_p (LOOP_CLOSED_SSA)))
prop_set_simulate_again (phi, false);
else
prop_set_simulate_again (phi, true);
prop_set_simulate_again (phi, false);
else
prop_set_simulate_again (phi, true);
/* Given the condition statement COND, put it as the last statement
of GUARD_BB; EXIT_BB is the basic block to skip the loop;
Assumes that this is the single exit of the guarded loop.
/* Given the condition statement COND, put it as the last statement
of GUARD_BB; EXIT_BB is the basic block to skip the loop;
Assumes that this is the single exit of the guarded loop.
- Returns the skip edge. */
+ Returns the skip edge, inserts new stmts on the COND_EXPR_STMT_LIST. */
-slpeel_add_loop_guard (basic_block guard_bb, tree cond, basic_block exit_bb,
- basic_block dom_bb)
+slpeel_add_loop_guard (basic_block guard_bb, tree cond,
+ gimple_seq cond_expr_stmt_list,
+ basic_block exit_bb, basic_block dom_bb)
{
gimple_stmt_iterator gsi;
edge new_e, enter_e;
{
gimple_stmt_iterator gsi;
edge new_e, enter_e;
gsi = gsi_last_bb (guard_bb);
cond = force_gimple_operand (cond, &gimplify_stmt_list, true, NULL_TREE);
gsi = gsi_last_bb (guard_bb);
cond = force_gimple_operand (cond, &gimplify_stmt_list, true, NULL_TREE);
+ if (gimplify_stmt_list)
+ gimple_seq_add_seq (&cond_expr_stmt_list, gimplify_stmt_list);
cond_stmt = gimple_build_cond (NE_EXPR,
cond, build_int_cst (TREE_TYPE (cond), 0),
NULL_TREE, NULL_TREE);
cond_stmt = gimple_build_cond (NE_EXPR,
cond, build_int_cst (TREE_TYPE (cond), 0),
NULL_TREE, NULL_TREE);
- if (gimplify_stmt_list)
- gsi_insert_seq_after (&gsi, gimplify_stmt_list, GSI_NEW_STMT);
+ if (cond_expr_stmt_list)
+ gsi_insert_seq_after (&gsi, cond_expr_stmt_list, GSI_NEW_STMT);
gsi = gsi_last_bb (guard_bb);
gsi_insert_after (&gsi, cond_stmt, GSI_NEW_STMT);
gsi = gsi_last_bb (guard_bb);
gsi_insert_after (&gsi, cond_stmt, GSI_NEW_STMT);
The second guard is:
if (FIRST_NITERS == NITERS) then skip the second loop.
The second guard is:
if (FIRST_NITERS == NITERS) then skip the second loop.
+ If the optional COND_EXPR and COND_EXPR_STMT_LIST arguments are given
+ then the generated condition is combined with COND_EXPR and the
+ statements in COND_EXPR_STMT_LIST are emitted together with it.
+
FORNOW only simple loops are supported (see slpeel_can_duplicate_loop_p).
FORNOW the resulting code will not be in loop-closed-ssa form.
*/
FORNOW only simple loops are supported (see slpeel_can_duplicate_loop_p).
FORNOW the resulting code will not be in loop-closed-ssa form.
*/
slpeel_tree_peel_loop_to_edge (struct loop *loop,
edge e, tree first_niters,
tree niters, bool update_first_loop_count,
slpeel_tree_peel_loop_to_edge (struct loop *loop,
edge e, tree first_niters,
tree niters, bool update_first_loop_count,
- unsigned int th, bool check_profitability)
+ unsigned int th, bool check_profitability,
+ tree cond_expr, gimple_seq cond_expr_stmt_list)
{
struct loop *new_loop = NULL, *first_loop, *second_loop;
edge skip_e;
{
struct loop *new_loop = NULL, *first_loop, *second_loop;
edge skip_e;
profitable than the vector one. This occurs when
this function is invoked for epilogue generation
and the cost model check needs to be done at run
profitable than the vector one. This occurs when
this function is invoked for epilogue generation
and the cost model check needs to be done at run
+ time. This check is combined with any pre-existing
+ check in COND_EXPR to avoid versioning.
Resulting CFG after prologue peeling would be:
Resulting CFG after prologue peeling would be:
pre_condition = fold_build2 (TRUTH_OR_EXPR, boolean_type_node,
cost_pre_condition, pre_condition);
}
pre_condition = fold_build2 (TRUTH_OR_EXPR, boolean_type_node,
cost_pre_condition, pre_condition);
}
+ if (cond_expr)
+ {
+ pre_condition =
+ fold_build2 (TRUTH_OR_EXPR, boolean_type_node,
+ pre_condition,
+ fold_build1 (TRUTH_NOT_EXPR, boolean_type_node,
+ cond_expr));
+ }
}
/* Prologue peeling. */
}
/* Prologue peeling. */
}
skip_e = slpeel_add_loop_guard (bb_before_first_loop, pre_condition,
}
skip_e = slpeel_add_loop_guard (bb_before_first_loop, pre_condition,
bb_before_second_loop, bb_before_first_loop);
slpeel_update_phi_nodes_for_guard1 (skip_e, first_loop,
first_loop == new_loop,
bb_before_second_loop, bb_before_first_loop);
slpeel_update_phi_nodes_for_guard1 (skip_e, first_loop,
first_loop == new_loop,
pre_condition =
fold_build2 (EQ_EXPR, boolean_type_node, first_niters, niters);
pre_condition =
fold_build2 (EQ_EXPR, boolean_type_node, first_niters, niters);
- skip_e = slpeel_add_loop_guard (bb_between_loops, pre_condition,
+ skip_e = slpeel_add_loop_guard (bb_between_loops, pre_condition, NULL,
bb_after_second_loop, bb_before_first_loop);
slpeel_update_phi_nodes_for_guard2 (skip_e, second_loop,
second_loop == new_loop, &new_exit_bb);
bb_after_second_loop, bb_before_first_loop);
slpeel_update_phi_nodes_for_guard2 (skip_e, second_loop,
second_loop == new_loop, &new_exit_bb);
/* This function builds ni_name = number of iterations loop executes
/* This function builds ni_name = number of iterations loop executes
- on the loop preheader. */
+ on the loop preheader. If SEQ is given the stmt is instead emitted
+ there. */
-vect_build_loop_niters (loop_vec_info loop_vinfo)
+vect_build_loop_niters (loop_vec_info loop_vinfo, gimple_seq seq)
{
tree ni_name, var;
gimple_seq stmts = NULL;
{
tree ni_name, var;
gimple_seq stmts = NULL;
pe = loop_preheader_edge (loop);
if (stmts)
{
pe = loop_preheader_edge (loop);
if (stmts)
{
- basic_block new_bb = gsi_insert_seq_on_edge_immediate (pe, stmts);
- gcc_assert (!new_bb);
+ if (seq)
+ gimple_seq_add_seq (&seq, stmts);
+ else
+ {
+ basic_block new_bb = gsi_insert_seq_on_edge_immediate (pe, stmts);
+ gcc_assert (!new_bb);
+ }
ratio = ni_name / vf
ratio_mult_vf_name = ratio * vf
ratio = ni_name / vf
ratio_mult_vf_name = ratio * vf
- and places them at the loop preheader edge. */
+ and places them at the loop preheader edge or in COND_EXPR_STMT_LIST
+ if that is non-NULL. */
static void
vect_generate_tmps_on_preheader (loop_vec_info loop_vinfo,
tree *ni_name_ptr,
tree *ratio_mult_vf_name_ptr,
static void
vect_generate_tmps_on_preheader (loop_vec_info loop_vinfo,
tree *ni_name_ptr,
tree *ratio_mult_vf_name_ptr,
+ tree *ratio_name_ptr,
+ gimple_seq cond_expr_stmt_list)
/* Generate temporary variable that contains
number of iterations loop executes. */
/* Generate temporary variable that contains
number of iterations loop executes. */
- ni_name = vect_build_loop_niters (loop_vinfo);
+ ni_name = vect_build_loop_niters (loop_vinfo, cond_expr_stmt_list);
log_vf = build_int_cst (TREE_TYPE (ni), exact_log2 (vf));
/* Create: ratio = ni >> log2(vf) */
log_vf = build_int_cst (TREE_TYPE (ni), exact_log2 (vf));
/* Create: ratio = ni >> log2(vf) */
stmts = NULL;
ratio_name = force_gimple_operand (ratio_name, &stmts, true, var);
stmts = NULL;
ratio_name = force_gimple_operand (ratio_name, &stmts, true, var);
- pe = loop_preheader_edge (loop);
- new_bb = gsi_insert_seq_on_edge_immediate (pe, stmts);
- gcc_assert (!new_bb);
+ if (cond_expr_stmt_list)
+ gimple_seq_add_seq (&cond_expr_stmt_list, stmts);
+ else
+ {
+ pe = loop_preheader_edge (loop);
+ new_bb = gsi_insert_seq_on_edge_immediate (pe, stmts);
+ gcc_assert (!new_bb);
+ }
}
/* Create: ratio_mult_vf = ratio << log2 (vf). */
}
/* Create: ratio_mult_vf = ratio << log2 (vf). */
stmts = NULL;
ratio_mult_vf_name = force_gimple_operand (ratio_mult_vf_name, &stmts,
true, var);
stmts = NULL;
ratio_mult_vf_name = force_gimple_operand (ratio_mult_vf_name, &stmts,
true, var);
- pe = loop_preheader_edge (loop);
- new_bb = gsi_insert_seq_on_edge_immediate (pe, stmts);
- gcc_assert (!new_bb);
+ if (cond_expr_stmt_list)
+ gimple_seq_add_seq (&cond_expr_stmt_list, stmts);
+ else
+ {
+ pe = loop_preheader_edge (loop);
+ new_bb = gsi_insert_seq_on_edge_immediate (pe, stmts);
+ gcc_assert (!new_bb);
+ }
}
*ni_name_ptr = ni_name;
}
*ni_name_ptr = ni_name;
NITERS % VECTORIZATION_FACTOR times.
The original loop will later be made to iterate
NITERS % VECTORIZATION_FACTOR times.
The original loop will later be made to iterate
- NITERS / VECTORIZATION_FACTOR times (this value is placed into RATIO). */
+ NITERS / VECTORIZATION_FACTOR times (this value is placed into RATIO).
+
+ COND_EXPR and COND_EXPR_STMT_LIST are combined with a new generated
+ test. */
-vect_do_peeling_for_loop_bound (loop_vec_info loop_vinfo, tree *ratio)
+vect_do_peeling_for_loop_bound (loop_vec_info loop_vinfo, tree *ratio,
+ tree cond_expr, gimple_seq cond_expr_stmt_list)
{
tree ni_name, ratio_mult_vf_name;
struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
{
tree ni_name, ratio_mult_vf_name;
struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
ratio = ni_name / vf
ratio_mult_vf_name = ratio * vf */
vect_generate_tmps_on_preheader (loop_vinfo, &ni_name,
ratio = ni_name / vf
ratio_mult_vf_name = ratio * vf */
vect_generate_tmps_on_preheader (loop_vinfo, &ni_name,
- &ratio_mult_vf_name, ratio);
+ &ratio_mult_vf_name, ratio,
+ cond_expr_stmt_list);
peeling for alignment. */
if (!VEC_length (gimple, LOOP_VINFO_MAY_MISALIGN_STMTS (loop_vinfo))
&& !VEC_length (ddr_p, LOOP_VINFO_MAY_ALIAS_DDRS (loop_vinfo))
peeling for alignment. */
if (!VEC_length (gimple, LOOP_VINFO_MAY_MISALIGN_STMTS (loop_vinfo))
&& !VEC_length (ddr_p, LOOP_VINFO_MAY_ALIAS_DDRS (loop_vinfo))
- && !LOOP_PEELING_FOR_ALIGNMENT (loop_vinfo))
+ && !LOOP_PEELING_FOR_ALIGNMENT (loop_vinfo)
+ && !cond_expr)
{
check_profitability = true;
{
check_profitability = true;
new_loop = slpeel_tree_peel_loop_to_edge (loop, single_exit (loop),
ratio_mult_vf_name, ni_name, false,
new_loop = slpeel_tree_peel_loop_to_edge (loop, single_exit (loop),
ratio_mult_vf_name, ni_name, false,
- th, check_profitability);
+ th, check_profitability,
+ cond_expr, cond_expr_stmt_list);
gcc_assert (new_loop);
gcc_assert (loop_num == loop->num);
#ifdef ENABLE_CHECKING
gcc_assert (new_loop);
gcc_assert (loop_num == loop->num);
#ifdef ENABLE_CHECKING
tree niters_of_prolog_loop, ni_name;
tree n_iters;
struct loop *new_loop;
tree niters_of_prolog_loop, ni_name;
tree n_iters;
struct loop *new_loop;
- bool check_profitability = false;
unsigned int th = 0;
int min_profitable_iters;
unsigned int th = 0;
int min_profitable_iters;
initialize_original_copy_tables ();
initialize_original_copy_tables ();
- ni_name = vect_build_loop_niters (loop_vinfo);
+ ni_name = vect_build_loop_niters (loop_vinfo, NULL);
niters_of_prolog_loop = vect_gen_niters_for_prolog_loop (loop_vinfo, ni_name);
niters_of_prolog_loop = vect_gen_niters_for_prolog_loop (loop_vinfo, ni_name);
- /* If cost model check not done during versioning. */
- if (!VEC_length (gimple, LOOP_VINFO_MAY_MISALIGN_STMTS (loop_vinfo))
- && !VEC_length (ddr_p, LOOP_VINFO_MAY_ALIAS_DDRS (loop_vinfo)))
- {
- check_profitability = true;
-
- /* Get profitability threshold for vectorized loop. */
- min_profitable_iters = LOOP_VINFO_COST_MODEL_MIN_ITERS (loop_vinfo);
-
- th = conservative_cost_threshold (loop_vinfo,
- min_profitable_iters);
- }
+ /* Get profitability threshold for vectorized loop. */
+ min_profitable_iters = LOOP_VINFO_COST_MODEL_MIN_ITERS (loop_vinfo);
+ th = conservative_cost_threshold (loop_vinfo,
+ min_profitable_iters);
/* Peel the prolog loop and iterate it niters_of_prolog_loop. */
new_loop =
slpeel_tree_peel_loop_to_edge (loop, loop_preheader_edge (loop),
niters_of_prolog_loop, ni_name, true,
/* Peel the prolog loop and iterate it niters_of_prolog_loop. */
new_loop =
slpeel_tree_peel_loop_to_edge (loop, loop_preheader_edge (loop),
niters_of_prolog_loop, ni_name, true,
- th, check_profitability);
+ th, true, NULL_TREE, NULL);
gcc_assert (new_loop);
#ifdef ENABLE_CHECKING
gcc_assert (new_loop);
#ifdef ENABLE_CHECKING
The test generated to check which version of loop is executed
is modified to also check for profitability as indicated by the
The test generated to check which version of loop is executed
is modified to also check for profitability as indicated by the
- cost model initially. */
+ cost model initially.
+
+ The versioning precondition(s) are placed in *COND_EXPR and
+ *COND_EXPR_STMT_LIST. If DO_VERSIONING is true versioning is
+ also performed, otherwise only the conditions are generated. */
-vect_loop_versioning (loop_vec_info loop_vinfo)
+vect_loop_versioning (loop_vec_info loop_vinfo, bool do_versioning,
+ tree *cond_expr, gimple_seq *cond_expr_stmt_list)
{
struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
struct loop *nloop;
{
struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
struct loop *nloop;
- tree cond_expr = NULL_TREE;
- gimple_seq cond_expr_stmt_list = NULL;
basic_block condition_bb;
gimple_stmt_iterator gsi, cond_exp_gsi;
basic_block merge_bb;
basic_block condition_bb;
gimple_stmt_iterator gsi, cond_exp_gsi;
basic_block merge_bb;
th = conservative_cost_threshold (loop_vinfo,
min_profitable_iters);
th = conservative_cost_threshold (loop_vinfo,
min_profitable_iters);
fold_build2 (GT_EXPR, boolean_type_node, scalar_loop_iters,
build_int_cst (TREE_TYPE (scalar_loop_iters), th));
fold_build2 (GT_EXPR, boolean_type_node, scalar_loop_iters,
build_int_cst (TREE_TYPE (scalar_loop_iters), th));
- cond_expr = force_gimple_operand (cond_expr, &cond_expr_stmt_list,
- false, NULL_TREE);
+ *cond_expr = force_gimple_operand (*cond_expr, cond_expr_stmt_list,
+ false, NULL_TREE);
if (VEC_length (gimple, LOOP_VINFO_MAY_MISALIGN_STMTS (loop_vinfo)))
if (VEC_length (gimple, LOOP_VINFO_MAY_MISALIGN_STMTS (loop_vinfo)))
- vect_create_cond_for_align_checks (loop_vinfo, &cond_expr,
- &cond_expr_stmt_list);
+ vect_create_cond_for_align_checks (loop_vinfo, cond_expr,
+ cond_expr_stmt_list);
if (VEC_length (ddr_p, LOOP_VINFO_MAY_ALIAS_DDRS (loop_vinfo)))
if (VEC_length (ddr_p, LOOP_VINFO_MAY_ALIAS_DDRS (loop_vinfo)))
- vect_create_cond_for_alias_checks (loop_vinfo, &cond_expr,
- &cond_expr_stmt_list);
-
- cond_expr =
- fold_build2 (NE_EXPR, boolean_type_node, cond_expr, integer_zero_node);
- cond_expr =
- force_gimple_operand (cond_expr, &gimplify_stmt_list, true, NULL_TREE);
- gimple_seq_add_seq (&cond_expr_stmt_list, gimplify_stmt_list);
+ vect_create_cond_for_alias_checks (loop_vinfo, cond_expr,
+ cond_expr_stmt_list);
+
+ *cond_expr =
+ fold_build2 (NE_EXPR, boolean_type_node, *cond_expr, integer_zero_node);
+ *cond_expr =
+ force_gimple_operand (*cond_expr, &gimplify_stmt_list, true, NULL_TREE);
+ gimple_seq_add_seq (cond_expr_stmt_list, gimplify_stmt_list);
+
+ /* If we only needed the extra conditions and a new loop copy
+ bail out here. */
+ if (!do_versioning)
+ return;
initialize_original_copy_tables ();
initialize_original_copy_tables ();
- nloop = loop_version (loop, cond_expr, &condition_bb,
+ nloop = loop_version (loop, *cond_expr, &condition_bb,
prob, prob, REG_BR_PROB_BASE - prob, true);
free_original_copy_tables();
prob, prob, REG_BR_PROB_BASE - prob, true);
free_original_copy_tables();
/* End loop-exit-fixes after versioning. */
update_ssa (TODO_update_ssa);
/* End loop-exit-fixes after versioning. */
update_ssa (TODO_update_ssa);
- if (cond_expr_stmt_list)
+ if (*cond_expr_stmt_list)
{
cond_exp_gsi = gsi_last_bb (condition_bb);
{
cond_exp_gsi = gsi_last_bb (condition_bb);
- gsi_insert_seq_before (&cond_exp_gsi, cond_expr_stmt_list, GSI_SAME_STMT);
+ gsi_insert_seq_before (&cond_exp_gsi, *cond_expr_stmt_list,
+ GSI_SAME_STMT);
+ *cond_expr_stmt_list = NULL;
+ *cond_expr = NULL_TREE;
bool strided_store;
bool slp_scheduled = false;
unsigned int nunits;
bool strided_store;
bool slp_scheduled = false;
unsigned int nunits;
+ tree cond_expr = NULL_TREE;
+ gimple_seq cond_expr_stmt_list = NULL;
+ bool do_peeling_for_loop_bound;
if (vect_print_dump_info (REPORT_DETAILS))
fprintf (vect_dump, "=== vec_transform_loop ===");
if (vect_print_dump_info (REPORT_DETAILS))
fprintf (vect_dump, "=== vec_transform_loop ===");
+ /* Peel the loop if there are data refs with unknown alignment.
+ Only one data ref with unknown store is allowed. */
+
+ if (LOOP_PEELING_FOR_ALIGNMENT (loop_vinfo))
+ vect_do_peeling_for_alignment (loop_vinfo);
+
+ do_peeling_for_loop_bound
+ = (!LOOP_VINFO_NITERS_KNOWN_P (loop_vinfo)
+ || (LOOP_VINFO_NITERS_KNOWN_P (loop_vinfo)
+ && LOOP_VINFO_INT_NITERS (loop_vinfo) % vectorization_factor != 0));
+
if (VEC_length (gimple, LOOP_VINFO_MAY_MISALIGN_STMTS (loop_vinfo))
|| VEC_length (ddr_p, LOOP_VINFO_MAY_ALIAS_DDRS (loop_vinfo)))
if (VEC_length (gimple, LOOP_VINFO_MAY_MISALIGN_STMTS (loop_vinfo))
|| VEC_length (ddr_p, LOOP_VINFO_MAY_ALIAS_DDRS (loop_vinfo)))
- vect_loop_versioning (loop_vinfo);
+ vect_loop_versioning (loop_vinfo,
+ !do_peeling_for_loop_bound,
+ &cond_expr, &cond_expr_stmt_list);
/* CHECKME: we wouldn't need this if we called update_ssa once
for all loops. */
bitmap_zero (vect_memsyms_to_rename);
/* CHECKME: we wouldn't need this if we called update_ssa once
for all loops. */
bitmap_zero (vect_memsyms_to_rename);
-
- /* Peel the loop if there are data refs with unknown alignment.
- Only one data ref with unknown store is allowed. */
-
- if (LOOP_PEELING_FOR_ALIGNMENT (loop_vinfo))
- vect_do_peeling_for_alignment (loop_vinfo);
/* If the loop has a symbolic number of iterations 'n' (i.e. it's not a
compile time constant), or it is a constant that doesn't divide by the
/* If the loop has a symbolic number of iterations 'n' (i.e. it's not a
compile time constant), or it is a constant that doesn't divide by the
will remain scalar and will compute the remaining (n%VF) iterations.
(VF is the vectorization factor). */
will remain scalar and will compute the remaining (n%VF) iterations.
(VF is the vectorization factor). */
- if (!LOOP_VINFO_NITERS_KNOWN_P (loop_vinfo)
- || (LOOP_VINFO_NITERS_KNOWN_P (loop_vinfo)
- && LOOP_VINFO_INT_NITERS (loop_vinfo) % vectorization_factor != 0))
- vect_do_peeling_for_loop_bound (loop_vinfo, &ratio);
+ if (do_peeling_for_loop_bound)
+ vect_do_peeling_for_loop_bound (loop_vinfo, &ratio,
+ cond_expr, cond_expr_stmt_list);
else
ratio = build_int_cst (TREE_TYPE (LOOP_VINFO_NITERS (loop_vinfo)),
LOOP_VINFO_INT_NITERS (loop_vinfo) / vectorization_factor);
else
ratio = build_int_cst (TREE_TYPE (LOOP_VINFO_NITERS (loop_vinfo)),
LOOP_VINFO_INT_NITERS (loop_vinfo) / vectorization_factor);
in tree-vect-loop-manip.c. */
extern void slpeel_make_loop_iterate_ntimes (struct loop *, tree);
extern bool slpeel_can_duplicate_loop_p (const struct loop *, const_edge);
in tree-vect-loop-manip.c. */
extern void slpeel_make_loop_iterate_ntimes (struct loop *, tree);
extern bool slpeel_can_duplicate_loop_p (const struct loop *, const_edge);
-extern void vect_loop_versioning (loop_vec_info);
-extern void vect_do_peeling_for_loop_bound (loop_vec_info, tree *);
+extern void vect_loop_versioning (loop_vec_info, bool, tree *, gimple_seq *);
+extern void vect_do_peeling_for_loop_bound (loop_vec_info, tree *,
+ tree, gimple_seq);
extern void vect_do_peeling_for_alignment (loop_vec_info);
extern LOC find_loop_location (struct loop *);
extern bool vect_can_advance_ivs_p (loop_vec_info);
extern void vect_do_peeling_for_alignment (loop_vec_info);
extern LOC find_loop_location (struct loop *);
extern bool vect_can_advance_ivs_p (loop_vec_info);