OSDN Git Service

* collect2.c (add_lto_object): Only define if OBJECT_FORMAT_NONE.
[pf3gnuchains/gcc-fork.git] / gcc / tree-vect-loop-manip.c
index 22d515f..c0b15cd 100644 (file)
@@ -169,15 +169,18 @@ slpeel_update_phis_for_duplicate_loop (struct loop *orig_loop,
        !gsi_end_p (gsi_new) && !gsi_end_p (gsi_orig);
        gsi_next (&gsi_new), gsi_next (&gsi_orig))
     {
+      source_location locus;
       phi_new = gsi_stmt (gsi_new);
       phi_orig = gsi_stmt (gsi_orig);
 
       /* step 1.  */
       def = PHI_ARG_DEF_FROM_EDGE (phi_orig, entry_arg_e);
-      add_phi_arg (phi_new, def, new_loop_entry_e);
+      locus = gimple_phi_arg_location_from_edge (phi_orig, entry_arg_e);
+      add_phi_arg (phi_new, def, new_loop_entry_e, locus);
 
       /* step 2.  */
       def = PHI_ARG_DEF_FROM_EDGE (phi_orig, orig_loop_latch);
+      locus = gimple_phi_arg_location_from_edge (phi_orig, orig_loop_latch);
       if (TREE_CODE (def) != SSA_NAME)
         continue;
 
@@ -190,7 +193,7 @@ slpeel_update_phis_for_duplicate_loop (struct loop *orig_loop,
        }
 
       /* An ordinary ssa name defined in the loop.  */
-      add_phi_arg (phi_new, new_ssa_name, loop_latch_edge (new_loop));
+      add_phi_arg (phi_new, new_ssa_name, loop_latch_edge (new_loop), locus);
 
       /* step 3 (case 1).  */
       if (!after)
@@ -371,7 +374,6 @@ slpeel_update_phi_nodes_for_guard1 (edge guard_edge, struct loop *loop,
   basic_block orig_bb = loop->header;
   edge new_exit_e;
   tree current_new_name;
-  tree name;
   gimple_stmt_iterator gsi_orig, gsi_update;
 
   /* Create new bb between loop and new_merge_bb.  */
@@ -384,18 +386,10 @@ slpeel_update_phi_nodes_for_guard1 (edge guard_edge, struct loop *loop,
        !gsi_end_p (gsi_orig) && !gsi_end_p (gsi_update);
        gsi_next (&gsi_orig), gsi_next (&gsi_update))
     {
+      source_location loop_locus, guard_locus;;
       orig_phi = gsi_stmt (gsi_orig);
       update_phi = gsi_stmt (gsi_update);
 
-      /* Virtual phi; Mark it for renaming. We actually want to call
-        mar_sym_for_renaming, but since all ssa renaming datastructures
-        are going to be freed before we get to call ssa_update, we just
-        record this name for now in a bitmap, and will mark it for
-        renaming later.  */
-      name = PHI_RESULT (orig_phi);
-      if (!is_gimple_reg (SSA_NAME_VAR (name)))
-        bitmap_set_bit (vect_memsyms_to_rename, DECL_UID (SSA_NAME_VAR (name)));
-
       /** 1. Handle new-merge-point phis  **/
 
       /* 1.1. Generate new phi node in NEW_MERGE_BB:  */
@@ -405,10 +399,16 @@ slpeel_update_phi_nodes_for_guard1 (edge guard_edge, struct loop *loop,
       /* 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:  */
       loop_arg = PHI_ARG_DEF_FROM_EDGE (orig_phi, EDGE_SUCC (loop->latch, 0));
+      loop_locus = gimple_phi_arg_location_from_edge (orig_phi, 
+                                                     EDGE_SUCC (loop->latch, 
+                                                                0));
       guard_arg = PHI_ARG_DEF_FROM_EDGE (orig_phi, loop_preheader_edge (loop));
+      guard_locus 
+       = gimple_phi_arg_location_from_edge (orig_phi, 
+                                            loop_preheader_edge (loop));
 
-      add_phi_arg (new_phi, loop_arg, new_exit_e);
-      add_phi_arg (new_phi, guard_arg, guard_edge);
+      add_phi_arg (new_phi, loop_arg, new_exit_e, loop_locus);
+      add_phi_arg (new_phi, guard_arg, guard_edge, guard_locus);
 
       /* 1.3. Update phi in successor block.  */
       gcc_assert (PHI_ARG_DEF_FROM_EDGE (update_phi, e) == loop_arg
@@ -427,7 +427,7 @@ slpeel_update_phi_nodes_for_guard1 (edge guard_edge, struct loop *loop,
                                  *new_exit_bb);
 
       /* 2.2. NEW_EXIT_BB has one incoming edge: the exit-edge of the loop.  */
-      add_phi_arg (new_phi, loop_arg, single_exit (loop));
+      add_phi_arg (new_phi, loop_arg, single_exit (loop), loop_locus);
 
       /* 2.3. Update phi in successor of NEW_EXIT_BB:  */
       gcc_assert (PHI_ARG_DEF_FROM_EDGE (update_phi2, new_exit_e) == loop_arg);
@@ -555,8 +555,8 @@ slpeel_update_phi_nodes_for_guard2 (edge guard_edge, struct loop *loop,
       if (new_name2)
         guard_arg = new_name2;
   
-      add_phi_arg (new_phi, loop_arg, new_exit_e);
-      add_phi_arg (new_phi, guard_arg, guard_edge);
+      add_phi_arg (new_phi, loop_arg, new_exit_e, UNKNOWN_LOCATION);
+      add_phi_arg (new_phi, guard_arg, guard_edge, UNKNOWN_LOCATION);
 
       /* 1.3. Update phi in successor block.  */
       gcc_assert (PHI_ARG_DEF_FROM_EDGE (update_phi, e) == orig_def);
@@ -571,7 +571,7 @@ slpeel_update_phi_nodes_for_guard2 (edge guard_edge, struct loop *loop,
                                  *new_exit_bb);
 
       /* 2.2. NEW_EXIT_BB has one incoming edge: the exit-edge of the loop.  */
-      add_phi_arg (new_phi, loop_arg, single_exit (loop));
+      add_phi_arg (new_phi, loop_arg, single_exit (loop), UNKNOWN_LOCATION);
 
       /* 2.3. Update phi in successor of NEW_EXIT_BB:  */
       gcc_assert (PHI_ARG_DEF_FROM_EDGE (update_phi2, new_exit_e) == loop_arg);
@@ -606,7 +606,8 @@ slpeel_update_phi_nodes_for_guard2 (edge guard_edge, struct loop *loop,
 
       /* 3.3. GUARD_BB has one incoming edge:  */
       gcc_assert (EDGE_COUNT (guard_edge->src->preds) == 1);
-      add_phi_arg (new_phi, arg, EDGE_PRED (guard_edge->src, 0));
+      add_phi_arg (new_phi, arg, EDGE_PRED (guard_edge->src, 0), 
+                  UNKNOWN_LOCATION);
 
       /* 3.4. Update phi in successor of GUARD_BB:  */
       gcc_assert (PHI_ARG_DEF_FROM_EDGE (update_phi2, guard_edge)
@@ -730,13 +731,15 @@ slpeel_tree_duplicate_loop_to_edge_cfg (struct loop *loop, edge e)
       if (phi_arg)
        {
          edge new_loop_exit_edge;
+         source_location locus;
 
+         locus = gimple_phi_arg_location_from_edge (phi, single_exit (loop));
          if (EDGE_SUCC (new_loop->header, 0)->dest == new_loop->latch)
            new_loop_exit_edge = EDGE_SUCC (new_loop->header, 1);
          else
            new_loop_exit_edge = EDGE_SUCC (new_loop->header, 0);
   
-         add_phi_arg (phi, phi_arg, new_loop_exit_edge);       
+         add_phi_arg (phi, phi_arg, new_loop_exit_edge, locus);        
        }
     }    
    
@@ -774,7 +777,8 @@ slpeel_tree_duplicate_loop_to_edge_cfg (struct loop *loop, edge e)
          phi = gsi_stmt (gsi);
          phi_arg = PHI_ARG_DEF_FROM_EDGE (phi, entry_e);
          if (phi_arg)
-           add_phi_arg (phi, phi_arg, new_exit_e);     
+           add_phi_arg (phi, phi_arg, new_exit_e,
+                        gimple_phi_arg_location_from_edge (phi, entry_e));     
        }    
 
       redirect_edge_and_branch_force (entry_e, new_loop->header);
@@ -792,11 +796,12 @@ slpeel_tree_duplicate_loop_to_edge_cfg (struct loop *loop, edge e)
 /* 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.  */
 
 static edge
-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;
@@ -809,11 +814,13 @@ slpeel_add_loop_guard (basic_block guard_bb, tree cond, basic_block exit_bb,
   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);
-  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);
@@ -841,7 +848,7 @@ slpeel_can_duplicate_loop_p (const struct loop *loop, const_edge e)
   gimple orig_cond = get_loop_exit_condition (loop);
   gimple_stmt_iterator loop_exit_gsi = gsi_last_bb (exit_e->src);
 
-  if (need_ssa_update_p ())
+  if (need_ssa_update_p (cfun))
     return false;
 
   if (loop->inner
@@ -961,8 +968,9 @@ set_prologue_iterations (basic_block bb_before_first_loop,
     gsi_insert_seq_after (&gsi, stmts, GSI_NEW_STMT);
 
   newphi = create_phi_node (var, bb_before_first_loop);
-  add_phi_arg (newphi, prologue_after_cost_adjust_name, e_fallthru);
-  add_phi_arg (newphi, first_niters, e_false);
+  add_phi_arg (newphi, prologue_after_cost_adjust_name, e_fallthru, 
+              UNKNOWN_LOCATION);
+  add_phi_arg (newphi, first_niters, e_false, UNKNOWN_LOCATION);
 
   first_niters = PHI_RESULT (newphi);
 }
@@ -1011,6 +1019,10 @@ set_prologue_iterations (basic_block bb_before_first_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.
 */
@@ -1019,7 +1031,8 @@ static struct loop*
 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;
@@ -1149,7 +1162,8 @@ slpeel_tree_peel_loop_to_edge (struct loop *loop,
          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.
+        time.  This check is combined with any pre-existing
+        check in COND_EXPR to avoid versioning.
 
          Resulting CFG after prologue peeling would be:
 
@@ -1193,6 +1207,14 @@ slpeel_tree_peel_loop_to_edge (struct loop *loop,
          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.  */  
@@ -1208,6 +1230,7 @@ slpeel_tree_peel_loop_to_edge (struct loop *loop,
     }
 
   skip_e = slpeel_add_loop_guard (bb_before_first_loop, pre_condition,
+                                 cond_expr_stmt_list,
                                   bb_before_second_loop, bb_before_first_loop);
   slpeel_update_phi_nodes_for_guard1 (skip_e, first_loop,
                                      first_loop == new_loop,
@@ -1245,7 +1268,7 @@ slpeel_tree_peel_loop_to_edge (struct loop *loop,
 
   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);
@@ -1303,10 +1326,11 @@ find_loop_location (struct loop *loop)
 
 
 /* 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.  */
 
 static tree
-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;
@@ -1321,8 +1345,13 @@ vect_build_loop_niters (loop_vec_info loop_vinfo)
   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);
+       }
     }
 
   return ni_name;
@@ -1335,13 +1364,15 @@ vect_build_loop_niters (loop_vec_info loop_vinfo)
  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, 
-                                tree *ratio_name_ptr)
+                                tree *ratio_name_ptr,
+                                gimple_seq cond_expr_stmt_list)
 {
 
   edge pe;
@@ -1361,7 +1392,7 @@ vect_generate_tmps_on_preheader (loop_vec_info loop_vinfo,
   /* 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) */
@@ -1374,9 +1405,14 @@ vect_generate_tmps_on_preheader (loop_vec_info loop_vinfo,
 
       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).  */
@@ -1391,9 +1427,14 @@ vect_generate_tmps_on_preheader (loop_vec_info loop_vinfo,
       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;
@@ -1557,7 +1598,8 @@ vect_update_ivs_after_vectorizer (loop_vec_info loop_vinfo, tree niters,
       tree access_fn = NULL;
       tree evolution_part;
       tree init_expr;
-      tree step_expr;
+      tree step_expr, off;
+      tree type;
       tree var, ni, ni_name;
       gimple_stmt_iterator last_gsi;
 
@@ -1587,6 +1629,11 @@ vect_update_ivs_after_vectorizer (loop_vec_info loop_vinfo, tree niters,
 
       access_fn = analyze_scalar_evolution (loop, PHI_RESULT (phi)); 
       gcc_assert (access_fn);
+      /* We can end up with an access_fn like
+           (short int) {(short unsigned int) i_49, +, 1}_1
+        for further analysis we need to strip the outer cast but we
+        need to preserve the original type.  */
+      type = TREE_TYPE (access_fn);
       STRIP_NOPS (access_fn);
       evolution_part =
         unshare_expr (evolution_part_in_loop_num (access_fn, loop->num));
@@ -1599,22 +1646,19 @@ vect_update_ivs_after_vectorizer (loop_vec_info loop_vinfo, tree niters,
       step_expr = evolution_part;
       init_expr = unshare_expr (initial_condition_in_loop_num (access_fn, 
                                                               loop->num));
+      init_expr = fold_convert (type, init_expr);
 
+      off = fold_build2 (MULT_EXPR, TREE_TYPE (step_expr),
+                        fold_convert (TREE_TYPE (step_expr), niters),
+                        step_expr);
       if (POINTER_TYPE_P (TREE_TYPE (init_expr)))
        ni = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (init_expr), 
-                         init_expr, 
-                         fold_convert (sizetype, 
-                                       fold_build2 (MULT_EXPR, TREE_TYPE (niters),
-                                                    niters, step_expr)));
+                         init_expr,
+                         fold_convert (sizetype, off));
       else
        ni = fold_build2 (PLUS_EXPR, TREE_TYPE (init_expr),
-                         fold_build2 (MULT_EXPR, TREE_TYPE (init_expr),
-                                      fold_convert (TREE_TYPE (init_expr),
-                                                    niters),
-                                      step_expr),
-                         init_expr);
-
-
+                         init_expr,
+                         fold_convert (TREE_TYPE (init_expr), off));
 
       var = create_tmp_var (TREE_TYPE (init_expr), "tmp");
       add_referenced_var (var);
@@ -1651,7 +1695,7 @@ conservative_cost_threshold (loop_vec_info loop_vinfo,
     th = (unsigned) min_profitable_iters;
 
   if (th && vect_print_dump_info (REPORT_COST))
-    fprintf (vect_dump, "Vectorization may not be profitable.");
+    fprintf (vect_dump, "Profitability threshold is %u loop iterations.", th);
 
   return th;
 }
@@ -1664,10 +1708,14 @@ conservative_cost_threshold (loop_vec_info loop_vinfo,
    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.  */
 
 void 
-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);
@@ -1690,15 +1738,17 @@ vect_do_peeling_for_loop_bound (loop_vec_info loop_vinfo, tree *ratio)
      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);
 
   loop_num  = loop->num; 
 
   /* If cost model check not done during versioning and 
      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))
+  if (!LOOP_REQUIRES_VERSIONING_FOR_ALIGNMENT (loop_vinfo)
+      && !LOOP_REQUIRES_VERSIONING_FOR_ALIAS (loop_vinfo)
+      && !LOOP_PEELING_FOR_ALIGNMENT (loop_vinfo)
+      && !cond_expr)
     {
       check_profitability = true;
 
@@ -1711,7 +1761,8 @@ vect_do_peeling_for_loop_bound (loop_vec_info loop_vinfo, tree *ratio)
 
   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
@@ -1883,7 +1934,8 @@ vect_update_init_of_dr (struct data_reference *dr, tree niters)
   niters = fold_build2 (MULT_EXPR, sizetype,
                        fold_convert (sizetype, niters),
                        fold_convert (sizetype, DR_STEP (dr)));
-  offset = fold_build2 (PLUS_EXPR, sizetype, offset, niters);
+  offset = fold_build2 (PLUS_EXPR, sizetype,
+                       fold_convert (sizetype, offset), niters);
   DR_OFFSET (dr) = offset;
 }
 
@@ -1926,7 +1978,6 @@ vect_do_peeling_for_alignment (loop_vec_info loop_vinfo)
   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;
 
@@ -1935,28 +1986,20 @@ vect_do_peeling_for_alignment (loop_vec_info loop_vinfo)
 
   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);
   
 
-  /* 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,
-                                  th, check_profitability);
+                                  th, true, NULL_TREE, NULL);
 
   gcc_assert (new_loop);
 #ifdef ENABLE_CHECKING
@@ -2252,10 +2295,10 @@ vect_create_cond_for_alias_checks (loop_vec_info loop_vinfo,
       else
        *cond_expr = part_cond_expr;
     }
-    if (vect_print_dump_info (REPORT_VECTORIZED_LOOPS))
-      fprintf (vect_dump, "created %u versioning for alias checks.\n",
-               VEC_length (ddr_p, may_alias_ddrs));
 
+  if (vect_print_dump_info (REPORT_VECTORIZED_LOCATIONS))
+    fprintf (vect_dump, "created %u versioning for alias checks.\n",
+             VEC_length (ddr_p, may_alias_ddrs));
 }
 
 
@@ -2273,15 +2316,18 @@ vect_create_cond_for_alias_checks (loop_vec_info loop_vinfo,
   
    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.  */
 
 void
-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;
-  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;
@@ -2301,29 +2347,34 @@ vect_loop_versioning (loop_vec_info loop_vinfo)
   th = conservative_cost_threshold (loop_vinfo,
                                    min_profitable_iters);
 
-  cond_expr =
+  *cond_expr =
     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)))
-      vect_create_cond_for_align_checks (loop_vinfo, &cond_expr,
-                                        &cond_expr_stmt_list);
+  if (LOOP_REQUIRES_VERSIONING_FOR_ALIGNMENT (loop_vinfo))
+      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)))
-    vect_create_cond_for_alias_checks (loop_vinfo, &cond_expr, 
-                                      &cond_expr_stmt_list);
+  if (LOOP_REQUIRES_VERSIONING_FOR_ALIAS (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);
+  *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 ();
-  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();
 
@@ -2347,17 +2398,21 @@ vect_loop_versioning (loop_vec_info loop_vinfo)
       new_phi = create_phi_node (SSA_NAME_VAR (PHI_RESULT (orig_phi)),
                                  new_exit_bb);
       arg = PHI_ARG_DEF_FROM_EDGE (orig_phi, e);
-      add_phi_arg (new_phi, arg, new_exit_e);
+      add_phi_arg (new_phi, arg, new_exit_e, 
+                  gimple_phi_arg_location_from_edge (orig_phi, e));
       SET_PHI_ARG_DEF (orig_phi, e->dest_idx, PHI_RESULT (new_phi));
     } 
 
   /* 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);
-      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;
 }