This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
split_edge improvement
- To: gcc-patches at gcc dot gnu dot org
- Subject: split_edge improvement
- From: Jeffrey A Law <law at cygnus dot com>
- Date: Wed, 17 Nov 1999 23:43:38 -0700
- Reply-To: law at cygnus dot com
I should have checked for this when we originally integrated the split_edge
code -- I ran into the same problem with my optimistic critical edge
splitting experiments.
Basically if we are not careful when we split an edge, we can easily confuse
the loop optimizer.
If loop finds a NOTE_INSN_LOOP_BEGIN that is not immediately followed by a
code label, then it assumes the loop isn't well behaved/phony.
So consider what happens when we want to insert an instruction on the
edge that passes control to the start of a loop such as the edge from 0 -> 1
in this example.
E
|
0
/ \
+->1-->2--->E
| |
+--+
We end up creating something like:
(jump_insn (set (pc)
(if_then_else (geu (reg:CCUNS 89)
(const_int 0 [0x0]))
(label_ref 38)
(pc))) 681 {jump-4} (nil)
(nil))
(note "" NOTE_INSN_LOOP_BEG)
(note [bb 1] NOTE_INSN_BASIC_BLOCK)
(insn (set (reg:SI 90)
(plus:SI (reg/v:SI 82)
(const_int 5 [0x5]))) -1 (nil)
(nil))
(insn (set (reg/s:SI 85)
(reg:SI 90)) -1 (nil)
(nil))
(code_label 6 "" "" [num uses: 1])
Egad. We would be much better off creating:
jump_insn 53 52 69 (set (pc)
(if_then_else (geu (reg:CCUNS 89)
(const_int 0 [0x0]))
(label_ref 38)
(pc))) 681 {jump-4} (nil)
(nil))
(note 69 53 68 [bb 1] NOTE_INSN_BASIC_BLOCK)
(insn 68 69 70 (set (reg:SI 90)
(plus:SI (reg/v:SI 82)
(const_int 5 [0x5]))) -1 (nil)
(nil))
(insn 70 68 15 (set (reg/s:SI 85)
(reg:SI 90)) -1 (nil)
(nil))
(note 15 70 23 "" NOTE_INSN_LOOP_BEG)
(code_label 23 15 58 6 "" "" [num uses: 1])
Anyway, this fixes the problem. At least the loops I'm looking at are now
being recognized as loops.
* flow.c (split_edge): Take looping structure into account when
determining where to put the new block note.
Index: flow.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/flow.c,v
retrieving revision 1.188
diff -c -3 -p -r1.188 flow.c
*** flow.c 1999/11/16 04:51:28 1.188
--- flow.c 1999/11/18 06:42:01
*************** split_edge (edge_in)
*** 1422,1429 ****
BASIC_BLOCK (i) = bb;
bb->index = i;
! /* Create the basic block note. */
! if (old_succ != EXIT_BLOCK_PTR)
bb_note = emit_note_before (NOTE_INSN_BASIC_BLOCK, old_succ->head);
else
bb_note = emit_note_after (NOTE_INSN_BASIC_BLOCK, get_last_insn ());
--- 1422,1452 ----
BASIC_BLOCK (i) = bb;
bb->index = i;
! /* Create the basic block note.
!
! Where we place the note can have a noticable impact on the generated
! code. Consider this cfg:
!
!
! E
! |
! 0
! / \
! +->1-->2--->E
! | |
! +--+
!
! If we need to insert an insn on the edge from block 0 to block 1,
! we want to ensure the instructions we insert are outside of any
! loop notes that physically sit between block 0 and block 1. Otherwise
! we confuse the loop optimizer into thinking the loop is a phony. */
! if (old_succ != EXIT_BLOCK_PTR
! && PREV_INSN (old_succ->head)
! && GET_CODE (PREV_INSN (old_succ->head)) == NOTE
! && NOTE_LINE_NUMBER (PREV_INSN (old_succ->head)) == NOTE_INSN_LOOP_BEG)
! bb_note = emit_note_before (NOTE_INSN_BASIC_BLOCK,
! PREV_INSN (old_succ->head));
! else if (old_succ != EXIT_BLOCK_PTR)
bb_note = emit_note_before (NOTE_INSN_BASIC_BLOCK, old_succ->head);
else
bb_note = emit_note_after (NOTE_INSN_BASIC_BLOCK, get_last_insn ());