diff options
author | Diego Novillo <dnovillo@gcc.gnu.org> | 2004-05-13 02:41:07 -0400 |
---|---|---|
committer | Diego Novillo <dnovillo@gcc.gnu.org> | 2004-05-13 02:41:07 -0400 |
commit | 6de9cd9a886ea695aa892c3c7c07818a7b7e9e6f (patch) | |
tree | a2568888a519c077427b133de9ece5879a8484a5 /gcc/cfgloopmanip.c | |
parent | ac1a20aec53364d77f3bdff94a2a0a06840e0fe9 (diff) | |
download | gcc-6de9cd9a886ea695aa892c3c7c07818a7b7e9e6f.zip gcc-6de9cd9a886ea695aa892c3c7c07818a7b7e9e6f.tar.gz gcc-6de9cd9a886ea695aa892c3c7c07818a7b7e9e6f.tar.bz2 |
Merge tree-ssa-20020619-branch into mainline.
From-SVN: r81764
Diffstat (limited to 'gcc/cfgloopmanip.c')
-rw-r--r-- | gcc/cfgloopmanip.c | 96 |
1 files changed, 96 insertions, 0 deletions
diff --git a/gcc/cfgloopmanip.c b/gcc/cfgloopmanip.c index e380780..9e10d8e 100644 --- a/gcc/cfgloopmanip.c +++ b/gcc/cfgloopmanip.c @@ -1242,3 +1242,99 @@ loop_split_edge_with (edge e, rtx insns) return new_bb; } + +/* Uses the natural loop discovery to recreate loop notes. */ +void +create_loop_notes (void) +{ + rtx insn, head, end; + struct loops loops; + struct loop *loop; + basic_block *first, *last, bb, pbb; + struct loop **stack, **top; + +#ifdef ENABLE_CHECKING + /* Verify that there really are no loop notes. */ + for (insn = get_insns (); insn; insn = NEXT_INSN (insn)) + if (GET_CODE (insn) == NOTE + && NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_BEG) + abort (); +#endif + + flow_loops_find (&loops, LOOP_TREE); + free_dominance_info (CDI_DOMINATORS); + if (loops.num > 1) + { + last = xcalloc (loops.num, sizeof (basic_block)); + + FOR_EACH_BB (bb) + { + for (loop = bb->loop_father; loop->outer; loop = loop->outer) + last[loop->num] = bb; + } + + first = xcalloc (loops.num, sizeof (basic_block)); + stack = xcalloc (loops.num, sizeof (struct loop *)); + top = stack; + + FOR_EACH_BB (bb) + { + for (loop = bb->loop_father; loop->outer; loop = loop->outer) + { + if (!first[loop->num]) + { + *top++ = loop; + first[loop->num] = bb; + } + + if (bb == last[loop->num]) + { + /* Prevent loops from overlapping. */ + while (*--top != loop) + last[(*top)->num] = EXIT_BLOCK_PTR; + + /* If loop starts with jump into it, place the note in + front of the jump. */ + insn = PREV_INSN (BB_HEAD (first[loop->num])); + if (insn + && GET_CODE (insn) == BARRIER) + insn = PREV_INSN (insn); + + if (insn + && GET_CODE (insn) == JUMP_INSN + && any_uncondjump_p (insn) + && onlyjump_p (insn)) + { + pbb = BLOCK_FOR_INSN (insn); + if (!pbb || !pbb->succ || pbb->succ->succ_next) + abort (); + + if (!flow_bb_inside_loop_p (loop, pbb->succ->dest)) + insn = BB_HEAD (first[loop->num]); + } + else + insn = BB_HEAD (first[loop->num]); + + head = BB_HEAD (first[loop->num]); + emit_note_before (NOTE_INSN_LOOP_BEG, insn); + BB_HEAD (first[loop->num]) = head; + + /* Position the note correctly wrto barrier. */ + insn = BB_END (last[loop->num]); + if (NEXT_INSN (insn) + && GET_CODE (NEXT_INSN (insn)) == BARRIER) + insn = NEXT_INSN (insn); + + end = BB_END (last[loop->num]); + emit_note_after (NOTE_INSN_LOOP_END, insn); + BB_END (last[loop->num]) = end; + } + } + } + + free (first); + free (last); + free (stack); + } + flow_loops_free (&loops); +} |