Scheduling fix (fixes gcc.c-torture/execute/980506-1.c on ppc)

Geoff Keating geoffk@ozemail.com.au
Tue Aug 25 00:28:00 GMT 1998


The testcase, under '-O -fsched-verbose-9 -fschedule-insns', generates
RTL like the following:

;; Function clear_modes

...

;; Start of basic block 2, registers live: 1 [1] 31 [31] 81 84
(code_label 16 15 18 2 ("blah"))

(note 18 16 19 "" NOTE_INSN_DELETED)

(jump_insn 19 18 0 (set (pc)
        (if_then_else (ne (reg:CC 84)
                (const_int 0))
            (label_ref 11)
            (pc))) 634 {jump-4} (nil)
    (nil))
;; End of basic block 2


;; Function main

...


Now, basic block 2 has two exits.  One exit goes back to basic block
1.  The other goes off the edge of the procedure.  Unfortunately,
haifa only notices the first one, because the second exit doesn't go
to any basic block, and thinks basic block 2 has only one exit; so the
branch must be taken with 100% probability:

;;   ------------ REGIONS ----------

;;      rgn 0 nr_blocks 2:
;;      bb/block:  0/2  1/1 

;;      rgn 1 nr_blocks 1:
;;      bb/block:  0/0 

;;  bb_prob(1, 1) = 100

For the test case, the branch is actually 0% probability, and haifa
then mis-schedules the procedure.

If the fix below is not acceptable, then you must go through
haifa-sched.c and fix every place where it examines the flow graph
(that is, everywhere in haifa-sched.c) to allow for blocks like block
2 in the above.  The immediate problem is in compute_dom_prob_ps.

-- 
Geoffrey Keating <geoffk@ozemail.com.au>

===File ~/patches/egcs-5.diff===============================
Tue Aug 25 10:52:31 1998  Geoff Keating  <geoffk@ozemail.com.au>

	* flow.c (find_basic_blocks): Ensure the last basic block
	in a function has no other exits.

--- gcc/flow.c~	Thu Jul  9 07:15:55 1998
+++ gcc/flow.c	Tue Aug 25 10:52:58 1998
@@ -307,6 +307,16 @@
   rtx nonlocal_label_list = nonlocal_label_rtx_list ();
   int in_libcall_block = 0;
 
+  /* If the very last insn of the function is a jump, add a NOTE after it.
+     This way it is always true that either a block has successors
+     only inside the function or it has no successors (inside the function).
+     The Haifa scheduler relies on this.  */
+
+  for (insn = f; NEXT_INSN (insn); insn = NEXT_INSN (insn))
+    ;
+  if (GET_CODE (insn) == JUMP_INSN)
+    emit_note_after (NOTE_INSN_DELETED, insn);
+
   /* Count the basic blocks.  Also find maximum insn uid value used.  */
 
   {
============================================================



More information about the Gcc-patches mailing list