diff options
Diffstat (limited to 'gcc-4.6/gcc/cfgloop.c')
-rw-r--r-- | gcc-4.6/gcc/cfgloop.c | 55 |
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); +} |