* 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
+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.
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 *);
? 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
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);
+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.
--- /dev/null
+
+/* { 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" } } */
--- /dev/null
+/* { 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" } } */
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 ();
}
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++)
{
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);