OSDN Git Service

2012-02-02 Vladimir Makarov <vmakarov@redhat.com>
[pf3gnuchains/gcc-fork.git] / gcc / tree-vect-loop-manip.c
index 7619d74..7ac3f67 100644 (file)
@@ -1,5 +1,5 @@
 /* Vectorizer Specific Loop Manipulations
-   Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
+   Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2012
    Free Software Foundation, Inc.
    Contributed by Dorit Naishlos <dorit@il.ibm.com>
    and Ira Rosen <irar@il.ibm.com>
@@ -1037,7 +1037,7 @@ slpeel_verify_cfg_after_peeling (struct loop *first_loop,
 
 static void
 set_prologue_iterations (basic_block bb_before_first_loop,
-                        tree first_niters,
+                        tree *first_niters,
                         struct loop *loop,
                         unsigned int th)
 {
@@ -1100,40 +1100,11 @@ set_prologue_iterations (basic_block bb_before_first_loop,
   newphi = create_phi_node (var, bb_before_first_loop);
   add_phi_arg (newphi, prologue_after_cost_adjust_name, e_fallthru,
               UNKNOWN_LOCATION);
-  add_phi_arg (newphi, first_niters, e_false, UNKNOWN_LOCATION);
+  add_phi_arg (newphi, *first_niters, e_false, UNKNOWN_LOCATION);
 
-  first_niters = PHI_RESULT (newphi);
+  *first_niters = PHI_RESULT (newphi);
 }
 
-
-/* Remove dead assignments from loop NEW_LOOP.  */
-
-static void
-remove_dead_stmts_from_loop (struct loop *new_loop)
-{
-  basic_block *bbs = get_loop_body (new_loop);
-  unsigned i;
-  for (i = 0; i < new_loop->num_nodes; ++i)
-    {
-      gimple_stmt_iterator gsi;
-      for (gsi = gsi_start_bb (bbs[i]); !gsi_end_p (gsi);)
-       {
-         gimple stmt = gsi_stmt (gsi);
-         if (is_gimple_assign (stmt)
-             && TREE_CODE (gimple_assign_lhs (stmt)) == SSA_NAME
-             && has_zero_uses (gimple_assign_lhs (stmt)))
-           {
-             gsi_remove (&gsi, true);
-             release_defs (stmt);
-           }
-         else
-           gsi_next (&gsi);
-       }
-    }
-  free (bbs);
-}
-
-
 /* Function slpeel_tree_peel_loop_to_edge.
 
    Peel the first (last) iterations of LOOP into a new prolog (epilog) loop
@@ -1187,7 +1158,7 @@ remove_dead_stmts_from_loop (struct loop *new_loop)
 
 static struct loop*
 slpeel_tree_peel_loop_to_edge (struct loop *loop,
-                              edge e, tree first_niters,
+                              edge e, tree *first_niters,
                               tree niters, bool update_first_loop_count,
                               unsigned int th, bool check_profitability,
                               tree cond_expr, gimple_seq cond_expr_stmt_list)
@@ -1357,8 +1328,8 @@ slpeel_tree_peel_loop_to_edge (struct loop *loop,
   if (!update_first_loop_count)
     {
       pre_condition =
-       fold_build2 (LE_EXPR, boolean_type_node, first_niters,
-                    build_int_cst (TREE_TYPE (first_niters), 0));
+       fold_build2 (LE_EXPR, boolean_type_node, *first_niters,
+                    build_int_cst (TREE_TYPE (*first_niters), 0));
       if (check_profitability)
        {
          tree scalar_loop_iters
@@ -1389,8 +1360,8 @@ slpeel_tree_peel_loop_to_edge (struct loop *loop,
                                 loop, th);
 
       pre_condition =
-       fold_build2 (LE_EXPR, boolean_type_node, first_niters,
-                    build_int_cst (TREE_TYPE (first_niters), 0));
+       fold_build2 (LE_EXPR, boolean_type_node, *first_niters,
+                    build_int_cst (TREE_TYPE (*first_niters), 0));
     }
 
   skip_e = slpeel_add_loop_guard (bb_before_first_loop, pre_condition,
@@ -1431,7 +1402,7 @@ slpeel_tree_peel_loop_to_edge (struct loop *loop,
   bb_after_second_loop = split_edge (single_exit (second_loop));
 
   pre_condition =
-       fold_build2 (EQ_EXPR, boolean_type_node, first_niters, niters);
+       fold_build2 (EQ_EXPR, boolean_type_node, *first_niters, niters);
   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,
@@ -1440,18 +1411,11 @@ slpeel_tree_peel_loop_to_edge (struct loop *loop,
   /* 4. Make first-loop iterate FIRST_NITERS times, if requested.
    */
   if (update_first_loop_count)
-    slpeel_make_loop_iterate_ntimes (first_loop, first_niters);
+    slpeel_make_loop_iterate_ntimes (first_loop, *first_niters);
 
   BITMAP_FREE (definitions);
   delete_update_ssa ();
 
-  /* Remove all pattern statements from the loop copy.  They will confuse
-     the expander if DCE is disabled.
-     ???  The pattern recognizer should be split into an analysis and
-     a transformation phase that is then run only on the loop that is
-     going to be transformed.  */
-  remove_dead_stmts_from_loop (new_loop);
-
   adjust_vec_debug_stmts ();
 
   return new_loop;
@@ -1551,7 +1515,7 @@ vect_generate_tmps_on_preheader (loop_vec_info loop_vinfo,
   edge pe;
   basic_block new_bb;
   gimple_seq stmts;
-  tree ni_name;
+  tree ni_name, ni_minus_gap_name;
   tree var;
   tree ratio_name;
   tree ratio_mult_vf_name;
@@ -1568,9 +1532,39 @@ vect_generate_tmps_on_preheader (loop_vec_info 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));
 
+  /* If epilogue loop is required because of data accesses with gaps, we
+     subtract one iteration from the total number of iterations here for
+     correct calculation of RATIO.  */
+  if (LOOP_VINFO_PEELING_FOR_GAPS (loop_vinfo))
+    {
+      ni_minus_gap_name = fold_build2 (MINUS_EXPR, TREE_TYPE (ni_name),
+                                      ni_name,
+                                      build_one_cst (TREE_TYPE (ni_name)));
+      if (!is_gimple_val (ni_minus_gap_name))
+       {
+         var = create_tmp_var (TREE_TYPE (ni), "ni_gap");
+          add_referenced_var (var);
+
+          stmts = NULL;
+          ni_minus_gap_name = force_gimple_operand (ni_minus_gap_name, &stmts,
+                                                   true, var);
+          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);
+            }
+        }
+    }
+  else
+    ni_minus_gap_name = ni_name;
+
   /* Create: ratio = ni >> log2(vf) */
 
-  ratio_name = fold_build2 (RSHIFT_EXPR, TREE_TYPE (ni_name), ni_name, log_vf);
+  ratio_name = fold_build2 (RSHIFT_EXPR, TREE_TYPE (ni_minus_gap_name),
+                           ni_minus_gap_name, log_vf);
   if (!is_gimple_val (ratio_name))
     {
       var = create_tmp_var (TREE_TYPE (ni), "bnd");
@@ -1825,9 +1819,7 @@ vect_update_ivs_after_vectorizer (loop_vec_info loop_vinfo, tree niters,
                         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, off));
+       ni = fold_build_pointer_plus (init_expr, off);
       else
        ni = fold_build2 (PLUS_EXPR, TREE_TYPE (init_expr),
                          init_expr,
@@ -1933,7 +1925,7 @@ 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,
+                                            &ratio_mult_vf_name, ni_name, false,
                                             th, check_profitability,
                                            cond_expr, cond_expr_stmt_list);
   gcc_assert (new_loop);
@@ -1996,8 +1988,7 @@ vect_do_peeling_for_loop_bound (loop_vec_info loop_vinfo, tree *ratio,
    use TYPE_VECTOR_SUBPARTS.  */
 
 static tree
-vect_gen_niters_for_prolog_loop (loop_vec_info loop_vinfo, tree loop_niters,
-                                tree *wide_prolog_niters)
+vect_gen_niters_for_prolog_loop (loop_vec_info loop_vinfo, tree loop_niters)
 {
   struct data_reference *dr = LOOP_VINFO_UNALIGNED_DR (loop_vinfo);
   struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
@@ -2081,19 +2072,6 @@ vect_gen_niters_for_prolog_loop (loop_vec_info loop_vinfo, tree loop_niters,
   add_referenced_var (var);
   stmts = NULL;
   iters_name = force_gimple_operand (iters, &stmts, false, var);
-  if (types_compatible_p (sizetype, niters_type))
-    *wide_prolog_niters = iters_name;
-  else
-    {
-      gimple_seq seq = NULL;
-      tree wide_iters = fold_convert (sizetype, iters);
-      var = create_tmp_var (sizetype, "prolog_loop_niters");
-      add_referenced_var (var);
-      *wide_prolog_niters = force_gimple_operand (wide_iters, &seq, false,
-                                                 var);
-      if (seq)
-       gimple_seq_add_seq (&stmts, seq);
-    }
 
   /* Insert stmt on loop preheader edge.  */
   if (stmts)
@@ -2175,9 +2153,8 @@ vect_do_peeling_for_alignment (loop_vec_info loop_vinfo)
   initialize_original_copy_tables ();
 
   ni_name = vect_build_loop_niters (loop_vinfo, NULL);
-  niters_of_prolog_loop = vect_gen_niters_for_prolog_loop (loop_vinfo, ni_name,
-                                                          &wide_prolog_niters);
-
+  niters_of_prolog_loop = vect_gen_niters_for_prolog_loop (loop_vinfo,
+                                                          ni_name);
 
   /* Get profitability threshold for vectorized loop.  */
   min_profitable_iters = LOOP_VINFO_COST_MODEL_MIN_ITERS (loop_vinfo);
@@ -2187,7 +2164,7 @@ vect_do_peeling_for_alignment (loop_vec_info loop_vinfo)
   /* 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,
+                                  &niters_of_prolog_loop, ni_name, true,
                                   th, true, NULL_TREE, NULL);
 
   gcc_assert (new_loop);
@@ -2200,6 +2177,25 @@ vect_do_peeling_for_alignment (loop_vec_info loop_vinfo)
   LOOP_VINFO_NITERS (loop_vinfo) = fold_build2 (MINUS_EXPR,
                TREE_TYPE (n_iters), n_iters, niters_of_prolog_loop);
 
+  if (types_compatible_p (sizetype, TREE_TYPE (niters_of_prolog_loop)))
+    wide_prolog_niters = niters_of_prolog_loop;
+  else
+    {
+      gimple_seq seq = NULL;
+      edge pe = loop_preheader_edge (loop);
+      tree wide_iters = fold_convert (sizetype, niters_of_prolog_loop);
+      tree var = create_tmp_var (sizetype, "prolog_loop_adjusted_niters");
+      add_referenced_var (var);
+      wide_prolog_niters = force_gimple_operand (wide_iters, &seq, false,
+                                                 var);
+      if (seq)
+       {
+         /* Insert stmt on loop preheader edge.  */
+          basic_block new_bb = gsi_insert_seq_on_edge_immediate (pe, seq);
+          gcc_assert (!new_bb);
+        }
+    }
+
   /* Update the init conditions of the access functions of all data refs.  */
   vect_update_inits_of_drs (loop_vinfo, wide_prolog_niters);
 
@@ -2362,9 +2358,14 @@ static tree
 vect_vfa_segment_size (struct data_reference *dr, tree length_factor)
 {
   tree segment_length;
-  segment_length = size_binop (MULT_EXPR,
-                              fold_convert (sizetype, DR_STEP (dr)),
-                              fold_convert (sizetype, length_factor));
+
+  if (!compare_tree_int (DR_STEP (dr), 0))
+    segment_length = TYPE_SIZE_UNIT (TREE_TYPE (DR_REF (dr)));
+  else
+    segment_length = size_binop (MULT_EXPR,
+                                 fold_convert (sizetype, DR_STEP (dr)),
+                                 fold_convert (sizetype, length_factor));
+
   if (vect_supportable_dr_alignment (dr, false)
         == dr_explicit_realign_optimized)
     {
@@ -2415,13 +2416,13 @@ vect_create_cond_for_alias_checks (loop_vec_info loop_vinfo,
   tree part_cond_expr, length_factor;
 
   /* Create expression
-     ((store_ptr_0 + store_segment_length_0) < load_ptr_0)
-     || (load_ptr_0 + load_segment_length_0) < store_ptr_0))
+     ((store_ptr_0 + store_segment_length_0) <= load_ptr_0)
+     || (load_ptr_0 + load_segment_length_0) <= store_ptr_0))
      &&
      ...
      &&
-     ((store_ptr_n + store_segment_length_n) < load_ptr_n)
-     || (load_ptr_n + load_segment_length_n) < store_ptr_n))  */
+     ((store_ptr_n + store_segment_length_n) <= load_ptr_n)
+     || (load_ptr_n + load_segment_length_n) <= store_ptr_n))  */
 
   if (VEC_empty (ddr_p, may_alias_ddrs))
     return;
@@ -2477,21 +2478,19 @@ vect_create_cond_for_alias_checks (loop_vec_info loop_vinfo,
        }
 
       seg_a_min = addr_base_a;
-      seg_a_max = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (addr_base_a), 
-                              addr_base_a, segment_length_a);
+      seg_a_max = fold_build_pointer_plus (addr_base_a, segment_length_a);
       if (tree_int_cst_compare (DR_STEP (dr_a), size_zero_node) < 0)
        seg_a_min = seg_a_max, seg_a_max = addr_base_a;
 
       seg_b_min = addr_base_b;
-      seg_b_max = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (addr_base_b),
-                              addr_base_b, segment_length_b);
+      seg_b_max = fold_build_pointer_plus (addr_base_b, segment_length_b);
       if (tree_int_cst_compare (DR_STEP (dr_b), size_zero_node) < 0)
        seg_b_min = seg_b_max, seg_b_max = addr_base_b;
 
       part_cond_expr =
        fold_build2 (TRUTH_OR_EXPR, boolean_type_node,
-         fold_build2 (LT_EXPR, boolean_type_node, seg_a_max, seg_b_min),
-         fold_build2 (LT_EXPR, boolean_type_node, seg_b_max, seg_a_min));
+         fold_build2 (LE_EXPR, boolean_type_node, seg_a_max, seg_b_min),
+         fold_build2 (LE_EXPR, boolean_type_node, seg_b_max, seg_a_min));
 
       if (*cond_expr)
        *cond_expr = fold_build2 (TRUTH_AND_EXPR, boolean_type_node,