aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog15
-rw-r--r--gcc/tree-flow.h4
-rw-r--r--gcc/tree-ssa-loop-manip.c121
3 files changed, 93 insertions, 47 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 7b37633..607cbb0 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,10 @@
+2007-01-10 Zdenek Dvorak <dvorakz@suse.cz>
+
+ * tree-ssa-loop-manip.c (tree_unroll_loop): Make it a wrapper over ...
+ (tree_transform_and_unroll_loop): New.
+ * tree-flow.h (transform_callback, tree_transform_and_unroll_loop):
+ Declare.
+
2007-01-10 Robert Kennedy <jimbob@google.com>
* fold-const.c (fold_comparison): Fold comparisons like (x *
@@ -24,11 +31,11 @@
* config/bfin/t-bfin, config/bfin/t-bfin-elf: Remove GCC_CFLAGS.
2007-01-10 Razya Ladelsky <razya@il.ibm.com>
-
- * function.c (get_last_funcdef_no): New function.
+
+ * function.c (get_last_funcdef_no): New function.
* function.h (get_last_funcdef_no): Declare.
- * tree-inline.c (initialize_cfun): Add initialization.
- (tree_function_versioning): Cleanup.
+ * tree-inline.c (initialize_cfun): Add initialization.
+ (tree_function_versioning): Cleanup.
2007-01-10 Jan Hubicka <jh@suse.cz>
diff --git a/gcc/tree-flow.h b/gcc/tree-flow.h
index 82dae23..5bd07dc 100644
--- a/gcc/tree-flow.h
+++ b/gcc/tree-flow.h
@@ -908,6 +908,10 @@ bool can_unroll_loop_p (struct loop *loop, unsigned factor,
struct tree_niter_desc *niter);
void tree_unroll_loop (struct loop *, unsigned,
edge, struct tree_niter_desc *);
+typedef void (*transform_callback)(struct loop *, void *);
+void tree_transform_and_unroll_loop (struct loop *, unsigned,
+ edge, struct tree_niter_desc *,
+ transform_callback, void *);
bool contains_abnormal_ssa_name_p (tree);
/* In tree-ssa-threadedge.c */
diff --git a/gcc/tree-ssa-loop-manip.c b/gcc/tree-ssa-loop-manip.c
index f224aa0..53280b9 100644
--- a/gcc/tree-ssa-loop-manip.c
+++ b/gcc/tree-ssa-loop-manip.c
@@ -803,14 +803,20 @@ determine_exit_conditions (struct loop *loop, struct tree_niter_desc *desc,
if (st)
break;
post;
- } */
+ }
+
+ Before the loop is unrolled, TRANSFORM is called for it (only for the
+ unrolled loop, but not for its versioned copy). DATA is passed to
+ TRANSFORM. */
/* Probability in % that the unrolled loop is entered. Just a guess. */
#define PROB_UNROLLED_LOOP_ENTERED 90
void
-tree_unroll_loop (struct loop *loop, unsigned factor,
- edge exit, struct tree_niter_desc *desc)
+tree_transform_and_unroll_loop (struct loop *loop, unsigned factor,
+ edge exit, struct tree_niter_desc *desc,
+ transform_callback transform,
+ void *data)
{
tree dont_exit, exit_if, ctr_before, ctr_after;
tree enter_main_cond, exit_base, exit_step, exit_bound;
@@ -859,24 +865,7 @@ tree_unroll_loop (struct loop *loop, unsigned factor,
gcc_assert (new_loop != NULL);
update_ssa (TODO_update_ssa);
- /* Unroll the loop and remove the old exits. */
- dont_exit = ((exit->flags & EDGE_TRUE_VALUE)
- ? boolean_false_node
- : boolean_true_node);
- exit_if = last_stmt (exit->src);
- COND_EXPR_COND (exit_if) = dont_exit;
- update_stmt (exit_if);
-
- wont_exit = sbitmap_alloc (factor);
- sbitmap_ones (wont_exit);
- ok = tree_duplicate_loop_to_header_edge
- (loop, loop_latch_edge (loop), factor - 1,
- wont_exit, exit, NULL, DLTHE_FLAG_UPDATE_FREQ);
- free (wont_exit);
- gcc_assert (ok);
- update_ssa (TODO_update_ssa);
-
- /* Determine the probability of the exit edge. */
+ /* Determine the probability of the exit edge of the unrolled loop. */
new_est_niter = est_niter / factor;
/* Without profile feedback, loops for that we do not know a better estimate
@@ -892,31 +881,24 @@ tree_unroll_loop (struct loop *loop, unsigned factor,
new_est_niter = 5;
}
- /* Ensure that the frequencies in the loop match the new estimated
- number of iterations. */
- freq_h = loop->header->frequency;
- freq_e = EDGE_FREQUENCY (loop_preheader_edge (loop));
- if (freq_h != 0)
- scale_loop_frequencies (loop, freq_e * new_est_niter, freq_h);
-
/* Prepare the cfg and update the phi nodes. */
rest = loop_preheader_edge (new_loop)->src;
precond_edge = single_pred_edge (rest);
split_edge (loop_latch_edge (loop));
exit_bb = single_pred (loop->latch);
+ /* For the moment, make it appear that the new exit edge cannot
+ be taken. */
+ bsi = bsi_last (exit_bb);
+ exit_if = build_if_stmt (boolean_true_node,
+ tree_block_label (loop->latch),
+ tree_block_label (rest));
+ bsi_insert_after (&bsi, exit_if, BSI_NEW_STMT);
new_exit = make_edge (exit_bb, rest, EDGE_FALSE_VALUE | irr);
- new_exit->count = loop_preheader_edge (loop)->count;
- new_exit->probability = REG_BR_PROB_BASE / new_est_niter;
-
- rest->count += new_exit->count;
- rest->frequency += EDGE_FREQUENCY (new_exit);
-
+ new_exit->count = 0;
+ new_exit->probability = 0;
new_nonexit = single_pred_edge (loop->latch);
new_nonexit->flags = EDGE_TRUE_VALUE;
- new_nonexit->probability = REG_BR_PROB_BASE - new_exit->probability;
- scale_bbs_frequencies_int (&loop->latch, 1, new_nonexit->probability,
- REG_BR_PROB_BASE);
old_entry = loop_preheader_edge (loop);
new_entry = loop_preheader_edge (new_loop);
@@ -954,16 +936,57 @@ tree_unroll_loop (struct loop *loop, unsigned factor,
SET_USE (op, new_init);
}
+ /* Transform the loop. */
+ if (transform)
+ (*transform) (loop, data);
+
+ /* Unroll the loop and remove the old exits. */
+ dont_exit = ((exit->flags & EDGE_TRUE_VALUE)
+ ? boolean_false_node
+ : boolean_true_node);
+ exit_if = last_stmt (exit->src);
+ COND_EXPR_COND (exit_if) = dont_exit;
+ update_stmt (exit_if);
+
+ wont_exit = sbitmap_alloc (factor);
+ sbitmap_ones (wont_exit);
+ ok = tree_duplicate_loop_to_header_edge
+ (loop, loop_latch_edge (loop), factor - 1,
+ wont_exit, exit, NULL, DLTHE_FLAG_UPDATE_FREQ);
+ free (wont_exit);
+ gcc_assert (ok);
+ update_ssa (TODO_update_ssa);
+
+ /* Ensure that the frequencies in the loop match the new estimated
+ number of iterations, and change the probability of the new
+ exit edge. */
+ freq_h = loop->header->frequency;
+ freq_e = EDGE_FREQUENCY (loop_preheader_edge (loop));
+ if (freq_h != 0)
+ scale_loop_frequencies (loop, freq_e * (new_est_niter + 1), freq_h);
+
+ exit_bb = single_pred (loop->latch);
+ new_exit = find_edge (exit_bb, rest);
+ new_exit->count = loop_preheader_edge (loop)->count;
+ new_exit->probability = REG_BR_PROB_BASE / (new_est_niter + 1);
+
+ rest->count += new_exit->count;
+ rest->frequency += EDGE_FREQUENCY (new_exit);
+
+ new_nonexit = single_pred_edge (loop->latch);
+ new_nonexit->probability = REG_BR_PROB_BASE - new_exit->probability;
+ scale_bbs_frequencies_int (&loop->latch, 1, new_nonexit->probability,
+ REG_BR_PROB_BASE);
+
/* Finally create the new counter for number of iterations and add the new
exit instruction. */
bsi = bsi_last (exit_bb);
+ exit_if = bsi_stmt (bsi);
create_iv (exit_base, exit_step, NULL_TREE, loop,
- &bsi, true, &ctr_before, &ctr_after);
- exit_if = build_if_stmt (build2 (exit_cmp, boolean_type_node, ctr_after,
- exit_bound),
- tree_block_label (loop->latch),
- tree_block_label (rest));
- bsi_insert_after (&bsi, exit_if, BSI_NEW_STMT);
+ &bsi, false, &ctr_before, &ctr_after);
+ COND_EXPR_COND (exit_if) = build2 (exit_cmp, boolean_type_node, ctr_after,
+ exit_bound);
+ update_stmt (exit_if);
#ifdef ENABLE_CHECKING
verify_flow_info ();
@@ -972,3 +995,15 @@ tree_unroll_loop (struct loop *loop, unsigned factor,
verify_loop_closed_ssa ();
#endif
}
+
+/* Wrapper over tree_transform_and_unroll_loop for case we do not
+ want to transform the loop before unrolling. The meaning
+ of the arguments is the same as for tree_transform_and_unroll_loop. */
+
+void
+tree_unroll_loop (struct loop *loop, unsigned factor,
+ edge exit, struct tree_niter_desc *desc)
+{
+ tree_transform_and_unroll_loop (loop, factor, exit, desc,
+ NULL, NULL);
+}