summaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorrakdver <rakdver@138bc75d-0d04-0410-961f-82ee72b054a4>2007-04-09 06:51:43 +0000
committerrakdver <rakdver@138bc75d-0d04-0410-961f-82ee72b054a4>2007-04-09 06:51:43 +0000
commitd8a0d6b8af37fd836425e5d8e2f510c7e8753bd5 (patch)
treef5af72013d20563b8340bcf3462e935b8ad07bef /gcc
parent85c11f8971a88d45613596396aa8215103fbdd1c (diff)
downloadgcc-d8a0d6b8af37fd836425e5d8e2f510c7e8753bd5.tar.gz
* cfgloopmanip.c (create_preheader): Do not use loop_preheader_edge.
(create_preheaders): Check that loops are available. (fix_loop_structure): Clean up, improve comments. * tree-ssa-loop-manip.c (rewrite_into_loop_closed_ssa): Check that loops are available. Set LOOP_CLOSED_SSA to the loops state flags. * tree-scalar-evolution.c (scev_finalize): Clear scalar_evolution_info. * predict.c (tree_estimate_probability): Do not call calculate_dominance_info. Call create_preheaders. * tree-cfgcleanup.c (cleanup_tree_cfg_loop): Only call rewrite_into_loop_closed_ssa if LOOP_CLOSED_SSA is set in loops state flags. * cfgloop.c (loop_preheader_edge): Assert that loops have preheaders. * cfgloop.h (LOOP_CLOSED_SSA): New constant. * tree-cfg.c (tree_split_edge): Make an assert more precise. * tree-ssa-threadedge.c (thread_across_edge): Comment the function arguments. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@123670 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog20
-rw-r--r--gcc/cfgloop.c2
-rw-r--r--gcc/cfgloop.h3
-rw-r--r--gcc/cfgloopmanip.c79
-rw-r--r--gcc/predict.c4
-rw-r--r--gcc/tree-cfg.c2
-rw-r--r--gcc/tree-cfgcleanup.c5
-rw-r--r--gcc/tree-scalar-evolution.c1
-rw-r--r--gcc/tree-ssa-loop-manip.c12
-rw-r--r--gcc/tree-ssa-threadedge.c14
10 files changed, 109 insertions, 33 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 6542dc83882..0309e9fa92f 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,23 @@
+2007-04-09 Zdenek Dvorak <dvorakz@suse.cz>
+
+ * cfgloopmanip.c (create_preheader): Do not use loop_preheader_edge.
+ (create_preheaders): Check that loops are available.
+ (fix_loop_structure): Clean up, improve comments.
+ * tree-ssa-loop-manip.c (rewrite_into_loop_closed_ssa):
+ Check that loops are available. Set LOOP_CLOSED_SSA to the loops
+ state flags.
+ * tree-scalar-evolution.c (scev_finalize): Clear scalar_evolution_info.
+ * predict.c (tree_estimate_probability): Do not call
+ calculate_dominance_info. Call create_preheaders.
+ * tree-cfgcleanup.c (cleanup_tree_cfg_loop): Only call
+ rewrite_into_loop_closed_ssa if LOOP_CLOSED_SSA is set in loops state
+ flags.
+ * cfgloop.c (loop_preheader_edge): Assert that loops have preheaders.
+ * cfgloop.h (LOOP_CLOSED_SSA): New constant.
+ * tree-cfg.c (tree_split_edge): Make an assert more precise.
+ * tree-ssa-threadedge.c (thread_across_edge): Comment the function
+ arguments.
+
2007-04-08 Jan Hubicka <jh@suse.cz>
* tree.h (maybe_fold_offset_to_component_ref): Declare.
diff --git a/gcc/cfgloop.c b/gcc/cfgloop.c
index 12ce92cdd9e..b30e3527a6c 100644
--- a/gcc/cfgloop.c
+++ b/gcc/cfgloop.c
@@ -1548,6 +1548,8 @@ loop_preheader_edge (const struct loop *loop)
edge e;
edge_iterator ei;
+ gcc_assert ((current_loops->state & LOOPS_HAVE_PREHEADERS) != 0);
+
FOR_EACH_EDGE (e, ei, loop->header->preds)
if (e->src != loop->latch)
break;
diff --git a/gcc/cfgloop.h b/gcc/cfgloop.h
index cbad81d27f0..15d55890f6a 100644
--- a/gcc/cfgloop.h
+++ b/gcc/cfgloop.h
@@ -169,7 +169,8 @@ enum
LOOPS_HAVE_SIMPLE_LATCHES = 2,
LOOPS_HAVE_MARKED_IRREDUCIBLE_REGIONS = 4,
LOOPS_HAVE_RECORDED_EXITS = 8,
- LOOPS_MAY_HAVE_MULTIPLE_LATCHES = 16
+ LOOPS_MAY_HAVE_MULTIPLE_LATCHES = 16,
+ LOOP_CLOSED_SSA = 32
};
#define LOOPS_NORMAL (LOOPS_HAVE_PREHEADERS | LOOPS_HAVE_SIMPLE_LATCHES \
diff --git a/gcc/cfgloopmanip.c b/gcc/cfgloopmanip.c
index 9ca3947a0c6..0e876e566e1 100644
--- a/gcc/cfgloopmanip.c
+++ b/gcc/cfgloopmanip.c
@@ -1105,7 +1105,7 @@ create_preheader (struct loop *loop, int flags)
int nentry = 0;
bool irred = false;
bool latch_edge_was_fallthru;
- edge one_succ_pred = 0;
+ edge one_succ_pred = NULL, single_entry = NULL;
edge_iterator ei;
FOR_EACH_EDGE (e, ei, loop->header->preds)
@@ -1114,21 +1114,20 @@ create_preheader (struct loop *loop, int flags)
continue;
irred |= (e->flags & EDGE_IRREDUCIBLE_LOOP) != 0;
nentry++;
+ single_entry = e;
if (single_succ_p (e->src))
one_succ_pred = e;
}
gcc_assert (nentry);
if (nentry == 1)
{
- e = loop_preheader_edge (loop);
-
if (/* We do not allow entry block to be the loop preheader, since we
cannot emit code there. */
- e->src != ENTRY_BLOCK_PTR
+ single_entry->src != ENTRY_BLOCK_PTR
/* If we want simple preheaders, also force the preheader to have
just a single successor. */
&& !((flags & CP_SIMPLE_PREHEADERS)
- && !single_succ_p (e->src)))
+ && !single_succ_p (single_entry->src)))
return NULL;
}
@@ -1177,6 +1176,9 @@ create_preheaders (int flags)
loop_iterator li;
struct loop *loop;
+ if (!current_loops)
+ return;
+
FOR_EACH_LOOP (li, loop, 0)
create_preheader (loop, flags);
current_loops->state |= LOOPS_HAVE_PREHEADERS;
@@ -1380,19 +1382,33 @@ fix_loop_structure (bitmap changed_bbs)
basic_block bb;
struct loop *loop, *ploop;
loop_iterator li;
+ bool record_exits = false;
+ struct loop **superloop = XNEWVEC (struct loop *, number_of_loops ());
- /* Remove the old bb -> loop mapping. */
+ gcc_assert (current_loops->state & LOOPS_HAVE_SIMPLE_LATCHES);
+
+ /* Remove the old bb -> loop mapping. Remember the depth of the blocks in
+ the loop hierarchy, so that we can recognize blocks whose loop nesting
+ relationship has changed. */
FOR_EACH_BB (bb)
{
- bb->aux = (void *) (size_t) bb->loop_father->depth;
+ if (changed_bbs)
+ bb->aux = (void *) (size_t) bb->loop_father->depth;
bb->loop_father = current_loops->tree_root;
}
- /* Remove the dead loops from structures. */
- current_loops->tree_root->num_nodes = n_basic_blocks;
- FOR_EACH_LOOP (li, loop, 0)
+ if (current_loops->state & LOOPS_HAVE_RECORDED_EXITS)
+ {
+ release_recorded_exits ();
+ record_exits = true;
+ }
+
+ /* Remove the dead loops from structures. We start from the innermost
+ loops, so that when we remove the loops, we know that the loops inside
+ are preserved, and do not waste time relinking loops that will be
+ removed later. */
+ FOR_EACH_LOOP (li, loop, LI_FROM_INNERMOST)
{
- loop->num_nodes = 0;
if (loop->header)
continue;
@@ -1407,39 +1423,52 @@ fix_loop_structure (bitmap changed_bbs)
delete_loop (loop);
}
- /* Rescan the bodies of loops, starting from the outermost. */
+ /* Rescan the bodies of loops, starting from the outermost ones. We assume
+ that no optimization interchanges the order of the loops, i.e., it cannot
+ happen that L1 was superloop of L2 before and it is subloop of L2 now
+ (without explicitly updating loop information). At the same time, we also
+ determine the new loop structure. */
+ current_loops->tree_root->num_nodes = n_basic_blocks;
FOR_EACH_LOOP (li, loop, 0)
{
+ superloop[loop->num] = loop->header->loop_father;
loop->num_nodes = flow_loop_nodes_find (loop->header, loop);
}
/* Now fix the loop nesting. */
FOR_EACH_LOOP (li, loop, 0)
{
- bb = loop_preheader_edge (loop)->src;
- if (bb->loop_father != loop->outer)
+ ploop = superloop[loop->num];
+ if (ploop != loop->outer)
{
flow_loop_tree_node_remove (loop);
- flow_loop_tree_node_add (bb->loop_father, loop);
+ flow_loop_tree_node_add (ploop, loop);
}
}
+ free (superloop);
/* Mark the blocks whose loop has changed. */
- FOR_EACH_BB (bb)
+ if (changed_bbs)
{
- if (changed_bbs
- && (void *) (size_t) bb->loop_father->depth != bb->aux)
- bitmap_set_bit (changed_bbs, bb->index);
+ FOR_EACH_BB (bb)
+ {
+ if ((void *) (size_t) bb->loop_father->depth != bb->aux)
+ bitmap_set_bit (changed_bbs, bb->index);
- bb->aux = NULL;
+ bb->aux = NULL;
+ }
}
+ if (current_loops->state & LOOPS_HAVE_PREHEADERS)
+ create_preheaders (CP_SIMPLE_PREHEADERS);
+
if (current_loops->state & LOOPS_HAVE_MARKED_IRREDUCIBLE_REGIONS)
mark_irreducible_loops ();
- if (current_loops->state & LOOPS_HAVE_RECORDED_EXITS)
- {
- release_recorded_exits ();
- record_loop_exits ();
- }
+ if (record_exits)
+ record_loop_exits ();
+
+#ifdef ENABLE_CHECKING
+ verify_loop_structure ();
+#endif
}
diff --git a/gcc/predict.c b/gcc/predict.c
index 097cfb86070..7cae1b720ed 100644
--- a/gcc/predict.c
+++ b/gcc/predict.c
@@ -1290,7 +1290,9 @@ tree_estimate_probability (void)
add_noreturn_fake_exit_edges ();
connect_infinite_loops_to_exit ();
- calculate_dominance_info (CDI_DOMINATORS);
+ /* We use loop_niter_by_eval, which requires that the loops have
+ preheaders. */
+ create_preheaders (CP_SIMPLE_PREHEADERS);
calculate_dominance_info (CDI_POST_DOMINATORS);
tree_bb_level_predictions ();
diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c
index fa4800e00c2..a0af80442e8 100644
--- a/gcc/tree-cfg.c
+++ b/gcc/tree-cfg.c
@@ -3118,7 +3118,7 @@ tree_split_edge (edge edge_in)
new_edge->count = edge_in->count;
e = redirect_edge_and_branch (edge_in, new_bb);
- gcc_assert (e);
+ gcc_assert (e == edge_in);
reinstall_phi_args (new_edge, e);
return new_bb;
diff --git a/gcc/tree-cfgcleanup.c b/gcc/tree-cfgcleanup.c
index 8cf66cb4a27..39dcfe7c3ab 100644
--- a/gcc/tree-cfgcleanup.c
+++ b/gcc/tree-cfgcleanup.c
@@ -599,7 +599,7 @@ cleanup_tree_cfg_loop (void)
{
bool changed = cleanup_tree_cfg ();
- if (changed)
+ if (changed && current_loops != NULL)
{
bitmap changed_bbs = BITMAP_ALLOC (NULL);
calculate_dominance_info (CDI_DOMINATORS);
@@ -608,7 +608,8 @@ cleanup_tree_cfg_loop (void)
/* This usually does nothing. But sometimes parts of cfg that originally
were inside a loop get out of it due to edge removal (since they
become unreachable by back edges from latch). */
- rewrite_into_loop_closed_ssa (changed_bbs, TODO_update_ssa);
+ if ((current_loops->state & LOOP_CLOSED_SSA) != 0)
+ rewrite_into_loop_closed_ssa (changed_bbs, TODO_update_ssa);
BITMAP_FREE (changed_bbs);
diff --git a/gcc/tree-scalar-evolution.c b/gcc/tree-scalar-evolution.c
index 846d27414d5..955240b6895 100644
--- a/gcc/tree-scalar-evolution.c
+++ b/gcc/tree-scalar-evolution.c
@@ -2862,6 +2862,7 @@ scev_finalize (void)
{
htab_delete (scalar_evolution_info);
BITMAP_FREE (already_instantiated);
+ scalar_evolution_info = NULL;
}
/* Replace ssa names for that scev can prove they are constant by the
diff --git a/gcc/tree-ssa-loop-manip.c b/gcc/tree-ssa-loop-manip.c
index bce9890d6a4..30f853469fc 100644
--- a/gcc/tree-ssa-loop-manip.c
+++ b/gcc/tree-ssa-loop-manip.c
@@ -355,10 +355,16 @@ find_uses_to_rename (bitmap changed_bbs, bitmap *use_blocks, bitmap need_phis)
void
rewrite_into_loop_closed_ssa (bitmap changed_bbs, unsigned update_flag)
{
- bitmap loop_exits = get_loops_exits ();
+ bitmap loop_exits;
bitmap *use_blocks;
unsigned i, old_num_ssa_names;
- bitmap names_to_rename = BITMAP_ALLOC (NULL);
+ bitmap names_to_rename;
+
+ if (!current_loops)
+ return;
+
+ loop_exits = get_loops_exits ();
+ names_to_rename = BITMAP_ALLOC (NULL);
/* If the pass has caused the SSA form to be out-of-date, update it
now. */
@@ -383,6 +389,8 @@ rewrite_into_loop_closed_ssa (bitmap changed_bbs, unsigned update_flag)
/* Fix up all the names found to be used outside their original
loops. */
update_ssa (TODO_update_ssa);
+
+ current_loops->state |= LOOP_CLOSED_SSA;
}
/* Check invariants of the loop closed ssa form for the USE in BB. */
diff --git a/gcc/tree-ssa-threadedge.c b/gcc/tree-ssa-threadedge.c
index 777685af652..86b26562754 100644
--- a/gcc/tree-ssa-threadedge.c
+++ b/gcc/tree-ssa-threadedge.c
@@ -488,7 +488,19 @@ simplify_control_stmt_condition (edge e,
Note it is quite common for the first block inside a loop to
end with a conditional which is either always true or always
false when reached via the loop backedge. Thus we do not want
- to blindly disable threading across a loop backedge. */
+ to blindly disable threading across a loop backedge.
+
+ DUMMY_COND is a shared cond_expr used by condition simplification as scratch,
+ to avoid allocating memory.
+
+ HANDLE_DOMINATING_ASSERTS is true if we should try to replace operands of
+ the simplified condition with left-hand sides of ASSERT_EXPRs they are
+ used in.
+
+ STACK is used to undo temporary equivalences created during the walk of
+ E->dest.
+
+ SIMPLIFY is a pass-specific function used to simplify statements. */
void
thread_across_edge (tree dummy_cond,