aboutsummaryrefslogtreecommitdiff
path: root/gcc/tree-cfg.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/tree-cfg.c')
-rw-r--r--gcc/tree-cfg.c55
1 files changed, 55 insertions, 0 deletions
diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c
index be7ee56b..c9a8e31 100644
--- a/gcc/tree-cfg.c
+++ b/gcc/tree-cfg.c
@@ -959,6 +959,30 @@ cleanup_tree_cfg (void)
}
+/* Cleanup cfg and repair loop structures. */
+
+void
+cleanup_tree_cfg_loop (void)
+{
+ bitmap changed_bbs = BITMAP_ALLOC (NULL);
+
+ cleanup_tree_cfg ();
+
+ fix_loop_structure (current_loops, changed_bbs);
+ calculate_dominance_info (CDI_DOMINATORS);
+
+ /* 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);
+
+ BITMAP_FREE (changed_bbs);
+
+#ifdef ENABLE_CHECKING
+ verify_loop_structure (current_loops);
+#endif
+}
+
/* Cleanup useless labels in basic blocks. This is something we wish
to do early because it allows us to group case labels before creating
the edges for the CFG, and it speeds up block statement iterators in
@@ -1277,6 +1301,11 @@ tree_can_merge_blocks_p (basic_block a, basic_block b)
return false;
}
+ /* Protect the loop latches. */
+ if (current_loops
+ && b->loop_father->latch == b)
+ return false;
+
return true;
}
@@ -2045,6 +2074,20 @@ remove_bb (basic_block bb)
}
}
+ /* If we remove the header or the latch of a loop, mark the loop for
+ removal by setting its header and latch to NULL. */
+ if (current_loops)
+ {
+ struct loop *loop = bb->loop_father;
+
+ if (loop->latch == bb
+ || loop->header == bb)
+ {
+ loop->latch = NULL;
+ loop->header = NULL;
+ }
+ }
+
/* Remove all the instructions in the block. */
for (i = bsi_start (bb); !bsi_end_p (i);)
{
@@ -4099,6 +4142,18 @@ tree_forwarder_block_p (basic_block bb, bool phi_wanted)
if (find_edge (ENTRY_BLOCK_PTR, bb))
return false;
+ if (current_loops)
+ {
+ basic_block dest;
+ /* Protect loop latches, headers and preheaders. */
+ if (bb->loop_father->header == bb)
+ return false;
+ dest = EDGE_SUCC (bb, 0)->dest;
+
+ if (dest->loop_father->header == dest)
+ return false;
+ }
+
return true;
}