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