In my backend GCC generates illegal scheduled code.

 After pass sched2, GCC generates:

;;        0-->   486 R1=R3<<0x4                        :IF,ID,AD,RA,EX,WB
;;        1-->   487 A0=R1+`buffer'                    :IF,ID,AD,RA,EX,WB
;;        2-->   766 R0=abs(R7)                        :IF,ID,AD,RA,EX,WB
;;        3-->   456 STATUS=cmp(R3,0x0)                :IF,ID,AD,RA,EX,WB
;;        4-->   767 R0=R0-0x1                         :IF,ID,AD,RA,EX,WB
;;        5-->   465 (!STATUS) [A6]=R7^0x1             
:IF,ID,AD,RA,EX,(WB+one_memory_port)
;;        6-->   469 R6=R6-R2                          :IF,ID,AD,RA,EX,WB
;;        7-->   476 R7=R0 0>>0x1f                     :IF,ID,AD,RA,EX,WB
;;        9-->   488 [A4]=zxn([A0])                    
:IF,ID,(AD+two_memory_ports),RA,EX,(WB+two_memory_ports)
;;       10-->   925 pc=L489                           :IF,ID,AD,RA,EX,WB

 The instructions 465 and 488 have a pipeline hazard, because they need 3 
memory ports at some time, but there are only two ports. The unit reservation 
templates are:
(define_reservation "one_memory_port"  "(MP1 | MP2)")
(define_reservation "two_memory_ports" "(MP1 + MP2)")

 I checked my scheduler description, and I can't find an error. For GCC this 
hazard is ok, because GCC assumes the processor can stall the pipeline.

 But after branch-delay-slots filling the code is:

(insn 1001 767 1002 (sequence [
            (jump_insn 941 767 465 (set (pc)
                    (label_ref 489)) 119 {jump_to_immediate_long} (nil)
                (expr_list:REG_BR_PRED (const_int 14 [0xe])
                    (nil)))
            (insn:HI 465 941 469 (cond_exec (eq (reg:CC 48 STATUS)
                        (const_int 0 [0x0]))
                    (set (mem/s:SI (reg/f:SI 38 A6 [479]) [4 <variable>.MPS+0 
S32 A32])
                        (xor:SI (reg/v:SI 7 R7 [orig:125 bit ] [125])
                            (const_int 1 [0x1])))) 205 {doloop_end+31} (nil)
                (nil))
            (insn:HI 469 465 476 (set (reg/v:SI 6 R6 [orig:124 value ] [124])
                    (minus:SI (reg/v:SI 6 R6 [orig:124 value ] [124])
                        (reg/v:SI 2 R2 [orig:107 0xa60range ] [107]))) 30 
{subsi3_register_internal} (nil)
                (nil))
            (insn:HI 476 469 488 (set (reg/v:SI 7 R7 [orig:125 bit ] [125])
                    (lshiftrt:SI (reg:SI 0 R0 [473])
                        (const_int 31 [0x1f]))) 75 {lshrsi3_const5bit} (nil)
                (nil))
            (insn:HI 488 476 1002 (set (mem/s:SI (reg/f:SI 36 A4 [478]) [4 
<variable>.state+0 S32 A32])
                    (zero_extend:SI (mem/s/u:HI (reg/f:SI 32 A0 [365]) [17 
buffer S16 A16]))) 102 {zero_extendhisi2} (nil)
                (nil))
        ]) -1 (nil)
    (nil))

 The four instructions before the jump are placed into the delay slots, such 
that the delay slots are completely filled; but there is still the pipeline 
hazard, which can't be resolved by inserting NOPs now, because there are no 
free slots.

 Do I have to reorganize the code prior to slot filling? Do I have to make sure 
that some problematic instructions do not appear in slots?

Boris

Reply via email to