re PR tree-optimization/79347 (vect_do_peeling is messing up profile)
authorBin Cheng <bin.cheng@arm.com>
Wed, 15 Feb 2017 17:16:29 +0000 (17:16 +0000)
committerBin Cheng <amker@gcc.gnu.org>
Wed, 15 Feb 2017 17:16:29 +0000 (17:16 +0000)
PR tree-optimization/79347
* tree-vect-loop-manip.c (vect_do_peeling): Maintain profile
counters during peeling.

gcc/testsuite
* gcc.dg/vect/pr79347.c: New test.

From-SVN: r245490

gcc/ChangeLog
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/vect/pr79347.c [new file with mode: 0644]
gcc/tree-vect-loop-manip.c

index fa0b01ce1849cb35ea247d1c3dbf025840245567..b3f479646edafb80415d129471ffae100e07f2e3 100644 (file)
@@ -1,3 +1,9 @@
+2017-02-15  Bin Cheng  <bin.cheng@arm.com>
+
+       PR tree-optimization/79347
+       * tree-vect-loop-manip.c (vect_do_peeling): Maintain profile
+       counters during peeling.
+
 2017-02-15  Thomas Schwinge  <thomas@codesourcery.com>
 
        * Makefile.in (site.exp): Remove "set ISLVER".
index f749fb7dbc9785057f9fa6bfd4cffab4404fe3d5..42ec70d0d3e64aaf3087c5a09193a6dddb9add2d 100644 (file)
@@ -1,3 +1,8 @@
+2017-02-15  Bin Cheng  <bin.cheng@arm.com>
+
+       PR tree-optimization/79347
+       * gcc.dg/vect/pr79347.c: New test.
+
 2017-02-15  Jakub Jelinek  <jakub@redhat.com>
 
        PR c++/79301
diff --git a/gcc/testsuite/gcc.dg/vect/pr79347.c b/gcc/testsuite/gcc.dg/vect/pr79347.c
new file mode 100644 (file)
index 0000000..586c638
--- /dev/null
@@ -0,0 +1,13 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target vect_int } */
+/* { dg-additional-options "-fdump-tree-vect-all" } */
+
+short *a;
+int c;
+void n(void)
+{
+  for (int i = 0; i<c;i++)
+    a[i]++;
+}
+
+/* { dg-final { scan-tree-dump-times "Invalid sum of " 2 "vect" } } */
index f29449c37fdfc272dd2a8ab3ff027d0b229f0b73..5ee2c38e0484406c8afacc06a2d657f0b1a46f93 100644 (file)
@@ -1690,7 +1690,19 @@ vect_do_peeling (loop_vec_info loop_vinfo, tree niters, tree nitersm1,
      may be preferred.  */
   basic_block anchor = loop_preheader_edge (loop)->src;
   if (skip_vector)
-    split_edge (loop_preheader_edge (loop));
+    {
+      split_edge (loop_preheader_edge (loop));
+
+      /* Due to the order in which we peel prolog and epilog, we first
+        propagate probability to the whole loop.  The purpose is to
+        avoid adjusting probabilities of both prolog and vector loops
+        separately.  Note in this case, the probability of epilog loop
+        needs to be scaled back later.  */
+      basic_block bb_before_loop = loop_preheader_edge (loop)->src;
+      scale_bbs_frequencies_int (&bb_before_loop, 1, prob_vector,
+                                REG_BR_PROB_BASE);
+      scale_loop_profile (loop, prob_vector, bound);
+    }
 
   tree niters_prolog = build_int_cst (type, 0);
   source_location loop_loc = find_loop_location (loop);
@@ -1727,6 +1739,7 @@ vect_do_peeling (loop_vec_info loop_vinfo, tree niters, tree nitersm1,
          guard_cond = fold_build2 (EQ_EXPR, boolean_type_node,
                                    niters_prolog, build_int_cst (type, 0));
          guard_bb = loop_preheader_edge (prolog)->src;
+         basic_block bb_after_prolog = loop_preheader_edge (loop)->src;
          guard_to = split_edge (loop_preheader_edge (loop));
          guard_e = slpeel_add_loop_guard (guard_bb, guard_cond,
                                           guard_to, guard_bb,
@@ -1734,6 +1747,9 @@ vect_do_peeling (loop_vec_info loop_vinfo, tree niters, tree nitersm1,
          e = EDGE_PRED (guard_to, 0);
          e = (e != guard_e ? e : EDGE_PRED (guard_to, 1));
          slpeel_update_phi_nodes_for_guard1 (prolog, loop, guard_e, e);
+
+         scale_bbs_frequencies_int (&bb_after_prolog, 1, prob_prolog,
+                                    REG_BR_PROB_BASE);
          scale_loop_profile (prolog, prob_prolog, bound_prolog);
        }
       /* Update init address of DRs.  */
@@ -1796,9 +1812,18 @@ vect_do_peeling (loop_vec_info loop_vinfo, tree niters, tree nitersm1,
          e = EDGE_PRED (guard_to, 0);
          e = (e != guard_e ? e : EDGE_PRED (guard_to, 1));
          slpeel_update_phi_nodes_for_guard1 (first_loop, epilog, guard_e, e);
-         scale_loop_profile (epilog, prob_vector, bound_scalar);
+
+         /* Simply propagate profile info from guard_bb to guard_to which is
+            a merge point of control flow.  */
+         guard_to->frequency = guard_bb->frequency;
+         guard_to->count = guard_bb->count;
+         single_succ_edge (guard_to)->count = guard_to->count;
+         /* Scale probability of epilog loop back.  */
+         int scale_up = REG_BR_PROB_BASE * REG_BR_PROB_BASE / prob_vector;
+         scale_loop_frequencies (epilog, scale_up, REG_BR_PROB_BASE);
        }
 
+      basic_block bb_before_epilog = loop_preheader_edge (epilog)->src;
       tree niters_vector_mult_vf;
       /* If loop is peeled for non-zero constant times, now niters refers to
         orig_niters - prolog_peeling, it won't overflow even the orig_niters
@@ -1826,6 +1851,16 @@ vect_do_peeling (loop_vec_info loop_vinfo, tree niters, tree nitersm1,
                                           inverse_probability (prob_epilog));
          slpeel_update_phi_nodes_for_guard2 (loop, epilog, guard_e,
                                              single_exit (epilog));
+         /* Only need to handle basic block before epilog loop if it's not
+            the guard_bb, which is the case when skip_vector is true.  */
+         if (guard_bb != bb_before_epilog)
+           {
+             prob_epilog = (combine_probabilities (prob_vector, prob_epilog)
+                            + inverse_probability (prob_vector));
+
+             scale_bbs_frequencies_int (&bb_before_epilog, 1, prob_epilog,
+                                        REG_BR_PROB_BASE);
+           }
          scale_loop_profile (epilog, prob_epilog, bound);
        }
       else