Hi, I hope DF/middle-end experts will comment about this.
PR target/40710 http://gcc.gnu.org/bugzilla/show_bug.cgi?id=40710 is a wrong code problem on SH. A delayed slot of a conditional branch insn is wrongly filled with an insn changing stack pointer in the failing case. I've tried to see what is going on. Before the dbr optimization, the code looks like as (note 6 1 5 [bb 2] NOTE_INSN_BASIC_BLOCK) ... (jump_insn 13 12 31 fs/ext3/balloc.c:57 (set (pc) (if_then_else (eq (reg:SI 147 t) (const_int 0 [0x0])) (label_ref:SI 129) (pc))) 208 {branch_false} (expr_list:REG_DEAD (reg:SI 147 t) (expr_list:REG_BR_PROB (const_int 184 [0xb8]) (nil)))) (note 31 13 46 [bb 3] NOTE_INSN_BASIC_BLOCK) (note 46 31 32 NOTE_INSN_DELETED) (insn 32 46 35 fs/ext3/balloc.c:66 (parallel [ (asm_operands/v ("") ("") 0 [] [] 2935777) (clobber (mem:BLK (scratch) [0 A8])) ]) -1 (nil)) ... ... (barrier 126 125 129) (code_label 129 126 14 9 "" [1 uses]) (note 14 129 109 [bb 8] NOTE_INSN_BASIC_BLOCK) (insn 109 14 15 fs/ext3/balloc.c:58 (set (reg/f:SI 1 r1 [176]) (mem/u/c:SI (label_ref 146) [0 S4 A32])) 172 {movsi_ie} (expr_list:REG_EQUIV (symbol_ref:SI ("ext3_error") [flags 0x41] <function_decl 0xb7a28d80 ext3_error>) (nil))) (insn 15 109 24 fs/ext3/balloc.c:58 (set (reg/f:SI 15 r15) (plus:SI (reg/f:SI 15 r15) (const_int -4 [0xfffffffffffffffc]))) 35 {*addsi3_compact} (nil)) reorg.c:fill_slots_from_thread fills that delay slot of insn 13 with insn 15 from bb 8. Since r15 is the stack pointer register for SH, this fill makes it wrong when the conditional jmp isn't taken. fill_slots_from_thread computes the resource set for the follow-through block of that jmp insn with mark_target_live_regs (get_insns (), opposite_thread, &opposite_needed); and mark_target_live_regs uses df_get_live_in to get live regs for the basic block including the opposite_thread insn which is insn 32. gdb shows the resulting opposite_needed is $1 = {memory = 0x1, unch_memory = 0x0, volatil = 0x0, cc = 0x0, regs = {0xf6, 0x0, 0x0, 0x0, 0x40000}} i.e. it seems that df_get_live_in doesn't count r15 as an live register and fill_slots_from_thread picks insn 15 up as an eligible insn to fill that delayed slot. Is this the expected behavior of df_get_live_in? If so, is there something problematic in the target? I thought that the stack pointer register should be live here. The first part of DF dump in .compgotos which is the last dump before dbr pass is: ;; Start of basic block ( 0) -> 2 ;; bb 2 artificial_defs: { } ;; bb 2 artificial_uses: { u-1(15){ }} ;; lr in 4 [r4] 5 [r5] 6 [r6] 15 [r15] 146 [pr] 151 [] ;; lr use 4 [r4] 5 [r5] 15 [r15] 146 [pr] ;; lr def 1 [r1] 2 [r2] 3 [r3] 15 [r15] 147 [t] ;; live in 4 [r4] 5 [r5] 6 [r6] 146 [pr] ;; live gen 1 [r1] 2 [r2] 3 [r3] 15 [r15] 147 [t] ;; live kill ... ;; End of basic block 2 -> ( 8 3) ;; lr out 1 [r1] 2 [r2] 3 [r3] 4 [r4] 5 [r5] 6 [r6] 15 [r15] 151 [] ;; live out 1 [r1] 2 [r2] 3 [r3] 4 [r4] 5 [r5] 6 [r6] 15 [r15] ... ;; Start of basic block ( 2) -> 3 ;; bb 3 artificial_defs: { } ;; bb 3 artificial_uses: { u-1(15){ }} ;; lr in 1 [r1] 2 [r2] 4 [r4] 5 [r5] 6 [r6] 15 [r15] 151 [] ;; lr use 1 [r1] 2 [r2] 5 [r5] 15 [r15] ;; lr def 0 [r0] 1 [r1] 2 [r2] 3 [r3] 7 [r7] 147 [t] ;; live in 1 [r1] 2 [r2] 4 [r4] 5 [r5] 6 [r6] 15 [r15] ;; live gen 0 [r0] 1 [r1] 2 [r2] 3 [r3] 7 [r7] 147 [t] ;; live kill ... ;; End of basic block 3 -> ( 9 4) ;; lr out 1 [r1] 2 [r2] 4 [r4] 5 [r5] 6 [r6] 7 [r7] 15 [r15] 151 [] ;; live out 1 [r1] 2 [r2] 4 [r4] 5 [r5] 6 [r6] 7 [r7] 15 [r15] Regards, kaz