cfgloop.h (DLTHE_FLAG_COMPLETTE_PEEL): New flag.
authorJan Hubicka <jh@suse.cz>
Wed, 3 Aug 2005 13:34:49 +0000 (15:34 +0200)
committerJan Hubicka <hubicka@gcc.gnu.org>
Wed, 3 Aug 2005 13:34:49 +0000 (13:34 +0000)
* cfgloop.h (DLTHE_FLAG_COMPLETTE_PEEL): New flag.
* cfgloopmanip.c (duplicate_loop_to_header_edge): Special case
profile updating for complette unrolling.
* loop-unroll.c (peel_loop_completely): Use it.
* tree-ssa-loop-ivcanon.c (try_unroll_loop_completely): Likewise.
(tree_unroll_loops_completely): Disable code growing unrolling of cold
loops.

* update-conroll.c: New testcase.
* update-conroll-2.c: New testcase.

From-SVN: r102687

gcc/ChangeLog
gcc/cfgloop.h
gcc/cfgloopmanip.c
gcc/loop-unroll.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/tree-prof/update-cunroll-2.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/tree-ssa/update-cunroll.c [new file with mode: 0644]
gcc/tree-ssa-loop-ivcanon.c

index fb1cf3fd7cc5d32ce0a237eba2685504746a2d07..21d87f21c64ba0fc19a2c7c4e30138b9a0c9a567 100644 (file)
@@ -1,3 +1,13 @@
+2005-08-03  Jan Hubicka  <jh@suse.cz>
+
+       * cfgloop.h (DLTHE_FLAG_COMPLETTE_PEEL): New flag.
+       * cfgloopmanip.c (duplicate_loop_to_header_edge): Special case
+       profile updating for complette unrolling.
+       * loop-unroll.c (peel_loop_completely): Use it.
+       * tree-ssa-loop-ivcanon.c (try_unroll_loop_completely): Likewise.
+       (tree_unroll_loops_completely): Disable code growing unrolling of cold
+       loops.
+
 2005-08-03  Paul Brook  <paul@codesourcery.com>
 
        * combine.c (can_change_dest_mode): New function.
index 34cebe2ce3ce5544abd8f60c648939edcd2fecf0..0bfb8d87a9ead64c079c7a5e75b8befbd180c924 100644 (file)
@@ -298,6 +298,8 @@ extern bool can_duplicate_loop_p (struct loop *loop);
                                           duplicate_loop_to_header_edge.  */
 #define DLTHE_RECORD_COPY_NUMBER 2     /* Record copy number in the aux
                                           field of newly create BB.  */
+#define DLTHE_FLAG_COMPLETTE_PEEL 4    /* Update frequencies expecting
+                                          a complette peeling. */
 
 extern struct loop * duplicate_loop (struct loops *, struct loop *,
                                     struct loop *);
index 648e8372ff88829d25afb82dfed93fe7881cf893..1e364279403f5af27fd3fa00dfd7f8373a678ad5 100644 (file)
@@ -913,7 +913,28 @@ duplicate_loop_to_header_edge (struct loop *loop, edge e, struct loops *loops,
                                ? prob_pass_wont_exit
                                : prob_pass_thru;
 
-      if (is_latch)
+      /* Complette peeling is special as the probability of exit in last
+         copy becomes 1.  */
+      if (flags & DLTHE_FLAG_COMPLETTE_PEEL)
+       {
+         int wanted_freq = EDGE_FREQUENCY (e);
+
+         if (wanted_freq > freq_in)
+           wanted_freq = freq_in;
+
+         gcc_assert (!is_latch);
+         /* First copy has frequency of incomming edge.  Each subseqeuent
+            frequency should be reduced by prob_pass_wont_exit.  Caller
+            should've managed the flags so all except for original loop
+            has won't exist set.  */
+         scale_act = RDIV (wanted_freq * REG_BR_PROB_BASE, freq_in);
+         /* Now simulate the duplication adjustments and compute header
+            frequency of the last copy.  */
+         for (i = 0; i < ndupl; i++)
+            wanted_freq = RDIV (wanted_freq * scale_step[i], REG_BR_PROB_BASE);
+         scale_main = RDIV (wanted_freq * REG_BR_PROB_BASE, freq_in);
+       }
+      else if (is_latch)
        {
          prob_pass_main = TEST_BIT (wont_exit, 0)
                                ? prob_pass_wont_exit
index deeca2da8d6a0d4888d718c98e28566de6510f92..8293448f5cff7ed77be9c19ed5dc8db1ed7bb1ce 100644 (file)
@@ -520,6 +520,7 @@ peel_loop_completely (struct loops *loops, struct loop *loop)
                                          wont_exit, desc->out_edge,
                                          remove_edges, &n_remove_edges,
                                          DLTHE_FLAG_UPDATE_FREQ
+                                         | DLTHE_FLAG_COMPLETTE_PEEL
                                          | (opt_info
                                             ? DLTHE_RECORD_COPY_NUMBER : 0));
       gcc_assert (ok);
index 4db6413d193cd0dc0cd40febf78a33389aa39b9c..e571c94ecab10a0111d70ba4c20b282e3e4158c3 100644 (file)
@@ -1,3 +1,8 @@
+2005-08-03  Jan Hubicka  <jh@suse.cz>
+
+       * update-conroll.c: New testcase.
+       * update-conroll-2.c: New testcase.
+
 2005-08-02  David Edelsohn  <edelsohn@gnu.org>
 
        * gfortran.dg/constant_substring.f: New test.
diff --git a/gcc/testsuite/gcc.dg/tree-prof/update-cunroll-2.c b/gcc/testsuite/gcc.dg/tree-prof/update-cunroll-2.c
new file mode 100644 (file)
index 0000000..d559b92
--- /dev/null
@@ -0,0 +1,21 @@
+
+/* { dg-options "-O2 -fdump-tree-optimized-blocks" } */
+int a[8];
+__attribute__ ((noinline))
+int t()
+{
+       int i;
+       for (i = 0; i < 3; i++)
+               if (a[i])
+                       break;
+       return i;
+}
+main ()
+{
+  int i;
+  for (i = 0; i < 1000; i++)
+    t ();
+  return 0;
+}
+/* { dg-final-use { scan-tree-dump-not "Invalid sum" "optimized"} } */
+/* { dg-final-use { cleanup-tree-dump "optimized" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/update-cunroll.c b/gcc/testsuite/gcc.dg/tree-ssa/update-cunroll.c
new file mode 100644 (file)
index 0000000..7a114ea
--- /dev/null
@@ -0,0 +1,13 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+int a[8];
+int t()
+{
+       int i;
+       for (i = 0; i < 3; i++)
+               if (a[i])
+                       break;
+       return i;
+}
+/* { dg-final { scan-tree-dump-times ".optimized" 0 "Invalid sum"} } */
+/* { dg-final { cleanup-tree-dump "optimized" } } */
index e8a94d66e6ce3bb6dddbebeb649d5630216467c6..4ac20039f4c5ef1258ec7529eaff1b17ee90053c 100644 (file)
@@ -223,20 +223,35 @@ try_unroll_loop_completely (struct loops *loops ATTRIBUTE_UNUSED,
     
   if (n_unroll)
     {
+      sbitmap wont_exit;
+      edge *edges_to_remove = xmalloc (sizeof (edge *) * n_unroll);
+      unsigned int n_to_remove = 0;
+
       old_cond = COND_EXPR_COND (cond);
       COND_EXPR_COND (cond) = dont_exit;
       update_stmt (cond);
       initialize_original_copy_tables ();
 
+      wont_exit = sbitmap_alloc (n_unroll + 1);
+      sbitmap_ones (wont_exit);
+      RESET_BIT (wont_exit, 0);
+
       if (!tree_duplicate_loop_to_header_edge (loop, loop_preheader_edge (loop),
-                                              loops, n_unroll, NULL,
-                                              NULL, NULL, NULL, 0))
+                                              loops, n_unroll, wont_exit,
+                                              exit, edges_to_remove,
+                                              &n_to_remove,
+                                              DLTHE_FLAG_UPDATE_FREQ
+                                              | DLTHE_FLAG_COMPLETTE_PEEL))
        {
          COND_EXPR_COND (cond) = old_cond;
          update_stmt (cond);
           free_original_copy_tables ();
+         free (wont_exit);
+         free (edges_to_remove);
          return false;
        }
+      free (wont_exit);
+      free (edges_to_remove);
       free_original_copy_tables ();
     }
   
@@ -350,7 +365,7 @@ tree_unroll_loops_completely (struct loops *loops, bool may_increase_size)
   unsigned i;
   struct loop *loop;
   bool changed = false;
-  enum unroll_level ul = may_increase_size ? UL_ALL : UL_NO_GROWTH;
+  enum unroll_level ul;
 
   for (i = 1; i < loops->num; i++)
     {
@@ -359,6 +374,10 @@ tree_unroll_loops_completely (struct loops *loops, bool may_increase_size)
       if (!loop)
        continue;
 
+      if (may_increase_size && maybe_hot_bb_p (loop->header))
+       ul = UL_ALL;
+      else
+       ul = UL_NO_GROWTH;
       changed |= canonicalize_loop_induction_variables (loops, loop,
                                                        false, ul,
                                                        !flag_tree_loop_ivcanon);