aboutsummaryrefslogtreecommitdiffstats
path: root/gcc-4.6/gcc/cfgloop.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc-4.6/gcc/cfgloop.c')
-rw-r--r--gcc-4.6/gcc/cfgloop.c55
1 files changed, 55 insertions, 0 deletions
diff --git a/gcc-4.6/gcc/cfgloop.c b/gcc-4.6/gcc/cfgloop.c
index 3f14551..28701d7 100644
--- a/gcc-4.6/gcc/cfgloop.c
+++ b/gcc-4.6/gcc/cfgloop.c
@@ -1640,3 +1640,58 @@ loop_exits_from_bb_p (struct loop *loop, basic_block bb)
return false;
}
+
+/* Return location corresponding to the loop control condition if possible. */
+
+location_t
+get_loop_location (struct loop *loop)
+{
+ rtx insn = NULL;
+ struct niter_desc *desc = NULL;
+ edge exit;
+
+ /* For a for or while loop, we would like to return the location
+ * of the for or while statement, if possible. To do this, look
+ * for the branch guarding the loop back-edge.
+ */
+
+ /* If this is a simple loop with an in_edge, then the loop control
+ * branch is typically at the end of its source.
+ */
+ desc = get_simple_loop_desc (loop);
+ if (desc->in_edge)
+ {
+ FOR_BB_INSNS_REVERSE (desc->in_edge->src, insn)
+ {
+ if (INSN_P (insn))
+ return RTL_LOCATION (insn);
+ }
+ }
+ /* If loop has a single exit, then the loop control branch
+ * must be at the end of its source.
+ */
+ if ((exit = single_exit(loop)))
+ {
+ FOR_BB_INSNS_REVERSE (exit->src, insn)
+ {
+ if (INSN_P (insn))
+ return RTL_LOCATION (insn);
+ }
+ }
+ /* Next check the latch, to see if it is non-empty. */
+ FOR_BB_INSNS_REVERSE (loop->latch, insn)
+ {
+ if (INSN_P (insn))
+ return RTL_LOCATION (insn);
+ }
+ /* Finally, if none of the above identifies the loop control branch,
+ * return the first location in the loop header.
+ */
+ FOR_BB_INSNS (loop->header, insn)
+ {
+ if (INSN_P (insn))
+ return RTL_LOCATION (insn);
+ }
+ /* If all else fails, simply return the current function location. */
+ return DECL_SOURCE_LOCATION (current_function_decl);
+}