/* Vectorizer Specific Loop Manipulations
- Copyright (C) 2003-2014 Free Software Foundation, Inc.
+ Copyright (C) 2003-2015 Free Software Foundation, Inc.
Contributed by Dorit Naishlos <dorit@il.ibm.com>
and Ira Rosen <irar@il.ibm.com>
#include "coretypes.h"
#include "dumpfile.h"
#include "tm.h"
+#include "hash-set.h"
+#include "machmode.h"
+#include "vec.h"
+#include "double-int.h"
+#include "input.h"
+#include "alias.h"
+#include "symtab.h"
+#include "wide-int.h"
+#include "inchash.h"
#include "tree.h"
+#include "fold-const.h"
+#include "predict.h"
+#include "hard-reg-set.h"
+#include "input.h"
+#include "function.h"
+#include "dominance.h"
+#include "cfg.h"
+#include "cfganal.h"
#include "basic-block.h"
#include "gimple-pretty-print.h"
#include "tree-ssa-alias.h"
static void
rename_variables_in_bb (basic_block bb)
{
- gimple_stmt_iterator gsi;
gimple stmt;
use_operand_p use_p;
ssa_op_iter iter;
edge_iterator ei;
struct loop *loop = bb->loop_father;
- for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
+ for (gimple_stmt_iterator gsi = gsi_start_bb (bb); !gsi_end_p (gsi);
+ gsi_next (&gsi))
{
stmt = gsi_stmt (gsi);
FOR_EACH_SSA_USE_OPERAND (use_p, stmt, iter, SSA_OP_ALL_USES)
{
if (!flow_bb_inside_loop_p (loop, e->src))
continue;
- for (gsi = gsi_start_phis (bb); !gsi_end_p (gsi); gsi_next (&gsi))
- rename_use_op (PHI_ARG_DEF_PTR_FROM_EDGE (gsi_stmt (gsi), e));
+ for (gphi_iterator gsi = gsi_start_phis (bb); !gsi_end_p (gsi);
+ gsi_next (&gsi))
+ rename_use_op (PHI_ARG_DEF_PTR_FROM_EDGE (gsi.phi (), e));
}
}
slpeel_update_phi_nodes_for_guard1 (edge guard_edge, struct loop *loop,
bool is_new_loop, basic_block *new_exit_bb)
{
- gimple orig_phi, new_phi;
- gimple update_phi, update_phi2;
+ gphi *orig_phi, *new_phi;
+ gphi *update_phi, *update_phi2;
tree guard_arg, loop_arg;
basic_block new_merge_bb = guard_edge->dest;
edge e = EDGE_SUCC (new_merge_bb, 0);
basic_block orig_bb = loop->header;
edge new_exit_e;
tree current_new_name;
- gimple_stmt_iterator gsi_orig, gsi_update;
+ gphi_iterator gsi_orig, gsi_update;
/* Create new bb between loop and new_merge_bb. */
*new_exit_bb = split_edge (single_exit (loop));
{
source_location loop_locus, guard_locus;
tree new_res;
- orig_phi = gsi_stmt (gsi_orig);
- update_phi = gsi_stmt (gsi_update);
+ orig_phi = gsi_orig.phi ();
+ update_phi = gsi_update.phi ();
/** 1. Handle new-merge-point phis **/
/* 1.1. Generate new phi node in NEW_MERGE_BB: */
- new_res = copy_ssa_name (PHI_RESULT (orig_phi), NULL);
+ new_res = copy_ssa_name (PHI_RESULT (orig_phi));
new_phi = create_phi_node (new_res, new_merge_bb);
/* 1.2. NEW_MERGE_BB has two incoming edges: GUARD_EDGE and the exit-edge
continue;
/* 2.1. Generate new phi node in NEW_EXIT_BB: */
- new_res = copy_ssa_name (PHI_RESULT (orig_phi), NULL);
+ new_res = copy_ssa_name (PHI_RESULT (orig_phi));
new_phi = create_phi_node (new_res, *new_exit_bb);
/* 2.2. NEW_EXIT_BB has one incoming edge: the exit-edge of the loop. */
if (!current_new_name)
continue;
}
- gcc_assert (get_current_def (current_new_name) == NULL_TREE);
+ tree new_name = get_current_def (current_new_name);
+ /* Because of peeled_chrec optimization it is possible that we have
+ set this earlier. Verify the PHI has the same value. */
+ if (new_name)
+ {
+ gimple phi = SSA_NAME_DEF_STMT (new_name);
+ gcc_assert (gimple_code (phi) == GIMPLE_PHI
+ && gimple_bb (phi) == *new_exit_bb
+ && (PHI_ARG_DEF_FROM_EDGE (phi, single_exit (loop))
+ == loop_arg));
+ continue;
+ }
set_current_def (current_new_name, PHI_RESULT (new_phi));
}
slpeel_update_phi_nodes_for_guard2 (edge guard_edge, struct loop *loop,
bool is_new_loop, basic_block *new_exit_bb)
{
- gimple orig_phi, new_phi;
- gimple update_phi, update_phi2;
+ gphi *orig_phi, *new_phi;
+ gphi *update_phi, *update_phi2;
tree guard_arg, loop_arg;
basic_block new_merge_bb = guard_edge->dest;
edge e = EDGE_SUCC (new_merge_bb, 0);
tree orig_def, orig_def_new_name;
tree new_name, new_name2;
tree arg;
- gimple_stmt_iterator gsi;
+ gphi_iterator gsi;
/* Create new bb between loop and new_merge_bb. */
*new_exit_bb = split_edge (single_exit (loop));
for (gsi = gsi_start_phis (update_bb); !gsi_end_p (gsi); gsi_next (&gsi))
{
tree new_res;
- update_phi = gsi_stmt (gsi);
+ update_phi = gsi.phi ();
orig_phi = update_phi;
orig_def = PHI_ARG_DEF_FROM_EDGE (orig_phi, e);
/* This loop-closed-phi actually doesn't represent a use
/** 1. Handle new-merge-point phis **/
/* 1.1. Generate new phi node in NEW_MERGE_BB: */
- new_res = copy_ssa_name (PHI_RESULT (orig_phi), NULL);
+ new_res = copy_ssa_name (PHI_RESULT (orig_phi));
new_phi = create_phi_node (new_res, new_merge_bb);
/* 1.2. NEW_MERGE_BB has two incoming edges: GUARD_EDGE and the exit-edge
/** 2. Handle loop-closed-ssa-form phis **/
/* 2.1. Generate new phi node in NEW_EXIT_BB: */
- new_res = copy_ssa_name (PHI_RESULT (orig_phi), NULL);
+ new_res = copy_ssa_name (PHI_RESULT (orig_phi));
new_phi = create_phi_node (new_res, *new_exit_bb);
/* 2.2. NEW_EXIT_BB has one incoming edge: the exit-edge of the loop. */
arg = guard_arg;
/* 3.2. Generate new phi node in GUARD_BB: */
- new_res = copy_ssa_name (PHI_RESULT (orig_phi), NULL);
+ new_res = copy_ssa_name (PHI_RESULT (orig_phi));
new_phi = create_phi_node (new_res, guard_edge->src);
/* 3.3. GUARD_BB has one incoming edge: */
slpeel_make_loop_iterate_ntimes (struct loop *loop, tree niters)
{
tree indx_before_incr, indx_after_incr;
- gimple cond_stmt;
- gimple orig_cond;
+ gcond *cond_stmt;
+ gcond *orig_cond;
edge exit_edge = single_exit (loop);
gimple_stmt_iterator loop_cond_gsi;
gimple_stmt_iterator incr_gsi;
{
if (scalar_loop != loop)
{
- gimple_stmt_iterator gsi;
+ gphi_iterator gsi;
new_exit = redirect_edge_and_branch (new_exit, exit_dest);
for (gsi = gsi_start_phis (exit_dest); !gsi_end_p (gsi);
gsi_next (&gsi))
{
- gimple phi = gsi_stmt (gsi);
+ gphi *phi = gsi.phi ();
tree orig_arg = PHI_ARG_DEF_FROM_EDGE (phi, e);
location_t orig_locus
= gimple_phi_arg_location_from_edge (phi, e);
{
/* Update new_loop->header PHIs, so that on the preheader
edge they are the ones from loop rather than scalar_loop. */
- gimple_stmt_iterator gsi_orig, gsi_new;
+ gphi_iterator gsi_orig, gsi_new;
edge orig_e = loop_preheader_edge (loop);
edge new_e = loop_preheader_edge (new_loop);
!gsi_end_p (gsi_orig) && !gsi_end_p (gsi_new);
gsi_next (&gsi_orig), gsi_next (&gsi_new))
{
- gimple orig_phi = gsi_stmt (gsi_orig);
- gimple new_phi = gsi_stmt (gsi_new);
+ gphi *orig_phi = gsi_orig.phi ();
+ gphi *new_phi = gsi_new.phi ();
tree orig_arg = PHI_ARG_DEF_FROM_EDGE (orig_phi, orig_e);
location_t orig_locus
= gimple_phi_arg_location_from_edge (orig_phi, orig_e);
{
gimple_stmt_iterator gsi;
edge new_e, enter_e;
- gimple cond_stmt;
+ gcond *cond_stmt;
gimple_seq gimplify_stmt_list = NULL;
enter_e = EDGE_SUCC (guard_bb, 0);
{
edge exit_e = single_exit (loop);
edge entry_e = loop_preheader_edge (loop);
- gimple orig_cond = get_loop_exit_condition (loop);
+ gcond *orig_cond = get_loop_exit_condition (loop);
gimple_stmt_iterator loop_exit_gsi = gsi_last_bb (exit_e->src);
if (loop->inner
basic_block cond_bb, then_bb;
tree var, prologue_after_cost_adjust_name;
gimple_stmt_iterator gsi;
- gimple newphi;
+ gphi *newphi;
edge e_true, e_false, e_fallthru;
- gimple cond_stmt;
+ gcond *cond_stmt;
gimple_seq stmts = NULL;
tree cost_pre_condition = NULL_TREE;
tree scalar_loop_iters =
basic_block bb_before_first_loop;
basic_block bb_between_loops;
basic_block new_exit_bb;
- gimple_stmt_iterator gsi;
+ gphi_iterator gsi;
edge exit_e = single_exit (loop);
source_location loop_loc;
/* There are many aspects to how likely the first loop is going to be executed.
for (gsi = gsi_start_phis (loop->header); !gsi_end_p (gsi); gsi_next (&gsi))
if (virtual_operand_p (gimple_phi_result (gsi_stmt (gsi))))
{
- gimple phi = gsi_stmt (gsi);
+ gphi *phi = gsi.phi ();
for (gsi = gsi_start_phis (exit_e->dest);
!gsi_end_p (gsi); gsi_next (&gsi))
if (virtual_operand_p (gimple_phi_result (gsi_stmt (gsi))))
break;
if (gsi_end_p (gsi))
{
- tree new_vop = copy_ssa_name (PHI_RESULT (phi), NULL);
- gimple new_phi = create_phi_node (new_vop, exit_e->dest);
+ tree new_vop = copy_ssa_name (PHI_RESULT (phi));
+ gphi *new_phi = create_phi_node (new_vop, exit_e->dest);
tree vop = PHI_ARG_DEF_FROM_EDGE (phi, EDGE_SUCC (loop->latch, 0));
imm_use_iterator imm_iter;
gimple stmt;
struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
basic_block bb = loop->header;
gimple phi;
- gimple_stmt_iterator gsi;
+ gphi_iterator gsi;
/* Analyze phi functions of the loop header. */
{
tree evolution_part;
- phi = gsi_stmt (gsi);
+ phi = gsi.phi ();
if (dump_enabled_p ())
{
dump_printf_loc (MSG_NOTE, vect_location, "Analyze phi: ");
{
struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
basic_block exit_bb = single_exit (loop)->dest;
- gimple phi, phi1;
- gimple_stmt_iterator gsi, gsi1;
+ gphi *phi, *phi1;
+ gphi_iterator gsi, gsi1;
basic_block update_bb = update_e->dest;
gcc_checking_assert (vect_can_advance_ivs_p (loop_vinfo));
gimple_stmt_iterator last_gsi;
stmt_vec_info stmt_info;
- phi = gsi_stmt (gsi);
- phi1 = gsi_stmt (gsi1);
+ phi = gsi.phi ();
+ phi1 = gsi1.phi ();
if (dump_enabled_p ())
{
dump_printf_loc (MSG_NOTE, vect_location,
: LOOP_VINFO_VECT_FACTOR (loop_vinfo)) - 2;
if (check_profitability)
max_iter = MAX (max_iter, (int) th - 1);
- record_niter_bound (new_loop, double_int::from_shwi (max_iter), false, true);
+ record_niter_bound (new_loop, max_iter, false, true);
dump_printf (MSG_NOTE,
"Setting upper bound of nb iterations for epilogue "
"loop to %d\n", max_iter);
max_iter = LOOP_VINFO_VECT_FACTOR (loop_vinfo) - 2;
if (check_profitability)
max_iter = MAX (max_iter, (int) th - 1);
- record_niter_bound (new_loop, double_int::from_shwi (max_iter), false, true);
+ record_niter_bound (new_loop, max_iter, false, true);
dump_printf (MSG_NOTE,
"Setting upper bound of nb iterations for prologue "
"loop to %d\n", max_iter);
sprintf (tmp_name, "addr2int%d", i);
addr_tmp_name = make_temp_ssa_name (int_ptrsize_type, NULL, tmp_name);
- addr_stmt = gimple_build_assign_with_ops (NOP_EXPR, addr_tmp_name,
- addr_base, NULL_TREE);
+ addr_stmt = gimple_build_assign (addr_tmp_name, NOP_EXPR, addr_base);
gimple_seq_add_stmt (cond_expr_stmt_list, addr_stmt);
/* The addresses are OR together. */
/* create: or_tmp = or_tmp | addr_tmp */
sprintf (tmp_name, "orptrs%d", i);
new_or_tmp_name = make_temp_ssa_name (int_ptrsize_type, NULL, tmp_name);
- or_stmt = gimple_build_assign_with_ops (BIT_IOR_EXPR,
- new_or_tmp_name,
- or_tmp_name, addr_tmp_name);
+ or_stmt = gimple_build_assign (new_or_tmp_name, BIT_IOR_EXPR,
+ or_tmp_name, addr_tmp_name);
gimple_seq_add_stmt (cond_expr_stmt_list, or_stmt);
or_tmp_name = new_or_tmp_name;
}
/* create: and_tmp = or_tmp & mask */
and_tmp_name = make_temp_ssa_name (int_ptrsize_type, NULL, "andmask");
- and_stmt = gimple_build_assign_with_ops (BIT_AND_EXPR, and_tmp_name,
- or_tmp_name, mask_cst);
+ and_stmt = gimple_build_assign (and_tmp_name, BIT_AND_EXPR,
+ or_tmp_name, mask_cst);
gimple_seq_add_stmt (cond_expr_stmt_list, and_stmt);
/* Make and_tmp the left operand of the conditional test against zero.
tree seg_a_min = addr_base_a;
tree seg_a_max = fold_build_pointer_plus (addr_base_a, segment_length_a);
+ /* For negative step, we need to adjust address range by TYPE_SIZE_UNIT
+ bytes, e.g., int a[3] -> a[1] range is [a+4, a+16) instead of
+ [a, a+12) */
if (tree_int_cst_compare (DR_STEP (dr_a.dr), size_zero_node) < 0)
- seg_a_min = seg_a_max, seg_a_max = addr_base_a;
+ {
+ tree unit_size = TYPE_SIZE_UNIT (TREE_TYPE (DR_REF (dr_a.dr)));
+ seg_a_min = fold_build_pointer_plus (seg_a_max, unit_size);
+ seg_a_max = fold_build_pointer_plus (addr_base_a, unit_size);
+ }
tree seg_b_min = addr_base_b;
tree seg_b_max = fold_build_pointer_plus (addr_base_b, segment_length_b);
if (tree_int_cst_compare (DR_STEP (dr_b.dr), size_zero_node) < 0)
- seg_b_min = seg_b_max, seg_b_max = addr_base_b;
+ {
+ tree unit_size = TYPE_SIZE_UNIT (TREE_TYPE (DR_REF (dr_b.dr)));
+ seg_b_min = fold_build_pointer_plus (seg_b_max, unit_size);
+ seg_b_max = fold_build_pointer_plus (addr_base_b, unit_size);
+ }
part_cond_expr =
fold_build2 (TRUTH_OR_EXPR, boolean_type_node,
struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
struct loop *scalar_loop = LOOP_VINFO_SCALAR_LOOP (loop_vinfo);
basic_block condition_bb;
- gimple_stmt_iterator gsi, cond_exp_gsi;
+ gphi_iterator gsi;
+ gimple_stmt_iterator cond_exp_gsi;
basic_block merge_bb;
basic_block new_exit_bb;
edge new_exit_e, e;
- gimple orig_phi, new_phi;
+ gphi *orig_phi, *new_phi;
tree cond_expr = NULL_TREE;
gimple_seq cond_expr_stmt_list = NULL;
tree arg;
for (gsi = gsi_start_phis (merge_bb); !gsi_end_p (gsi); gsi_next (&gsi))
{
tree new_res;
- orig_phi = gsi_stmt (gsi);
- new_res = copy_ssa_name (PHI_RESULT (orig_phi), NULL);
+ orig_phi = gsi.phi ();
+ new_res = copy_ssa_name (PHI_RESULT (orig_phi));
new_phi = create_phi_node (new_res, new_exit_bb);
arg = PHI_ARG_DEF_FROM_EDGE (orig_phi, e);
add_phi_arg (new_phi, arg, new_exit_e,
}
}
-
- /* Extract load statements on memrefs with zero-stride accesses. */
-
- if (LOOP_REQUIRES_VERSIONING_FOR_ALIAS (loop_vinfo))
- {
- /* In the loop body, we iterate each statement to check if it is a load.
- Then we check the DR_STEP of the data reference. If DR_STEP is zero,
- then we will hoist the load statement to the loop preheader. */
-
- basic_block *bbs = LOOP_VINFO_BBS (loop_vinfo);
- int nbbs = loop->num_nodes;
-
- for (int i = 0; i < nbbs; ++i)
- {
- for (gimple_stmt_iterator si = gsi_start_bb (bbs[i]);
- !gsi_end_p (si);)
- {
- gimple stmt = gsi_stmt (si);
- stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
- struct data_reference *dr = STMT_VINFO_DATA_REF (stmt_info);
-
- if (is_gimple_assign (stmt)
- && (!dr
- || (DR_IS_READ (dr) && integer_zerop (DR_STEP (dr)))))
- {
- bool hoist = true;
- ssa_op_iter iter;
- tree var;
-
- /* We hoist a statement if all SSA uses in it are defined
- outside of the loop. */
- FOR_EACH_SSA_TREE_OPERAND (var, stmt, iter, SSA_OP_USE)
- {
- gimple def = SSA_NAME_DEF_STMT (var);
- if (!gimple_nop_p (def)
- && flow_bb_inside_loop_p (loop, gimple_bb (def)))
- {
- hoist = false;
- break;
- }
- }
-
- if (hoist)
- {
- if (dr)
- gimple_set_vuse (stmt, NULL);
-
- gsi_remove (&si, false);
- gsi_insert_on_edge_immediate (loop_preheader_edge (loop),
- stmt);
-
- if (dump_enabled_p ())
- {
- dump_printf_loc
- (MSG_NOTE, vect_location,
- "hoisting out of the vectorized loop: ");
- dump_gimple_stmt (MSG_NOTE, TDF_SLIM, stmt, 0);
- dump_printf (MSG_NOTE, "\n");
- }
- continue;
- }
- }
- gsi_next (&si);
- }
- }
- }
-
/* End loop-exit-fixes after versioning. */
if (cond_expr_stmt_list)