summaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorhubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4>2005-08-03 13:34:49 +0000
committerhubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4>2005-08-03 13:34:49 +0000
commitfb54ef7ccb98fc1c10a1662869dab0a3ab52a35a (patch)
tree1a926b9bc202452ffb1c89f9db59da5c72ea357e /gcc
parent136305f40bec39c518bec801bcb454cf483005f3 (diff)
downloadgcc-fb54ef7ccb98fc1c10a1662869dab0a3ab52a35a.tar.gz
* 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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@102687 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog10
-rw-r--r--gcc/cfgloop.h2
-rw-r--r--gcc/cfgloopmanip.c23
-rw-r--r--gcc/loop-unroll.c1
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/gcc.dg/tree-prof/update-cunroll-2.c21
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/update-cunroll.c13
-rw-r--r--gcc/tree-ssa-loop-ivcanon.c25
8 files changed, 96 insertions, 4 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index fb1cf3fd7cc..21d87f21c64 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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.
diff --git a/gcc/cfgloop.h b/gcc/cfgloop.h
index 34cebe2ce3c..0bfb8d87a9e 100644
--- a/gcc/cfgloop.h
+++ b/gcc/cfgloop.h
@@ -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 *);
diff --git a/gcc/cfgloopmanip.c b/gcc/cfgloopmanip.c
index 648e8372ff8..1e364279403 100644
--- a/gcc/cfgloopmanip.c
+++ b/gcc/cfgloopmanip.c
@@ -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
diff --git a/gcc/loop-unroll.c b/gcc/loop-unroll.c
index deeca2da8d6..8293448f5cf 100644
--- a/gcc/loop-unroll.c
+++ b/gcc/loop-unroll.c
@@ -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);
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 4db6413d193..e571c94ecab 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -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
index 00000000000..d559b924535
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-prof/update-cunroll-2.c
@@ -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
index 00000000000..7a114ea3a9c
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/update-cunroll.c
@@ -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" } } */
diff --git a/gcc/tree-ssa-loop-ivcanon.c b/gcc/tree-ssa-loop-ivcanon.c
index e8a94d66e6c..4ac20039f4c 100644
--- a/gcc/tree-ssa-loop-ivcanon.c
+++ b/gcc/tree-ssa-loop-ivcanon.c
@@ -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);