aboutsummaryrefslogtreecommitdiff
path: root/gcc/tree-ssa-loop-niter.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/tree-ssa-loop-niter.c')
-rw-r--r--gcc/tree-ssa-loop-niter.c83
1 files changed, 83 insertions, 0 deletions
diff --git a/gcc/tree-ssa-loop-niter.c b/gcc/tree-ssa-loop-niter.c
index 21bfce89a2a..25a9082d448 100644
--- a/gcc/tree-ssa-loop-niter.c
+++ b/gcc/tree-ssa-loop-niter.c
@@ -1395,3 +1395,86 @@ free_numbers_of_iterations_estimates (struct loops *loops)
free_numbers_of_iterations_estimates_loop (loop);
}
}
+
+
+/* APPLE LOCAL begin lno */
+/*
+
+ Removal of loops in DCE.
+
+*/
+
+/* If we are able to prove that the LOOP always exits, turn off the
+ EDGE_DFS_BACK flag from its latch edge. */
+
+static void
+unmark_surely_finite_loop (struct loop *loop)
+{
+ edge *exits;
+ unsigned i, n_exits;
+ struct tree_niter_desc niter_desc;
+
+ exits = get_loop_exit_edges (loop, &n_exits);
+ for (i = 0; i < n_exits; i++)
+ if (number_of_iterations_exit (loop, exits[i], &niter_desc))
+ {
+ loop_latch_edge (loop)->flags &= ~EDGE_DFS_BACK;
+ return;
+ }
+}
+
+/* Emit special statements preventing removal of possibly infinite loops in
+ CD_DCE to the latches of LOOPS for that we are not able to prove that they
+ iterate just finite number of times. */
+
+void
+mark_maybe_infinite_loops (struct loops *loops)
+{
+ unsigned i;
+ struct loop *loop;
+ basic_block bb;
+ edge e;
+ tree stmt;
+ bool inserted = false;
+ block_stmt_iterator bsi;
+
+ mark_dfs_back_edges ();
+
+ for (i = 1; i < loops->num; i++)
+ {
+ loop = loops->parray[i];
+ if (loop)
+ unmark_surely_finite_loop (loop);
+ }
+
+ FOR_EACH_BB (bb)
+ {
+ edge_iterator ei;
+ FOR_EACH_EDGE (e, ei, bb->succs)
+ if (e->flags & EDGE_DFS_BACK)
+ {
+ stmt = build_function_call_expr (built_in_decls[BUILT_IN_MAYBE_INFINITE_LOOP],
+ NULL);
+
+ if (!(e->flags & EDGE_ABNORMAL))
+ {
+ bsi_insert_on_edge (e, stmt);
+ inserted = true;
+ continue;
+ }
+
+ /* We cannot insert on abnormal edge, so insert to the basic block
+ at its start. */
+ bsi = bsi_last (e->src);
+ if (!bsi_end_p (bsi)
+ && stmt_ends_bb_p (bsi_stmt (bsi)))
+ bsi_insert_before (&bsi, stmt, BSI_NEW_STMT);
+ else
+ bsi_insert_after (&bsi, stmt, BSI_NEW_STMT);
+ }
+ }
+
+ if (inserted)
+ loop_commit_inserts ();
+}
+/* APPLE LOCAL end lno */