Hi,

I am doing a private port in GCC 4.5.1. For the my target i see some
strange behavior in delay slot scheduling. For my target the
instruction in the delay slots gets executed irrespective of whether
the branch is taken or not. I have generated the following code after
commenting out the call to 'relax_delay_slots' in the function
'dbr_schedule'.

RTL:

(insn 97 42 51 del1.c:19 (sequence [
            (jump_insn 61 42 38 del1.c:19 (set (pc)
                    (if_then_else (ne (reg:CCF 34 CC)
                            (const_int 0 [0x0]))
                        (label_ref:PQI 86)
                        (pc))) 56 {conditional_branch}
(expr_list:REG_BR_PRED (const_int 5 [0x5])
                    (expr_list:REG_DEAD (reg:CCF 34 CC)
                        (expr_list:REG_BR_PROB (const_int 5000 [0x1388])
                            (nil))))
             -> 86)
            (insn 38 61 43 (set (mem/s/j:QI (reg/f:PQI 28 a0 [orig:62
D.1955 ] [62]) [0 bytes S1 A32])
                    (reg:QI 1 g1 [orig:65 D.1938 ] [65])) 7 {movqi_op} (nil))
            (insn 43 38 51 (set (reg:QI 1 g1 [75])
                    (ior:QI (reg:QI 1 g1 [orig:65 D.1938 ] [65])
                        (reg:QI 3 g3 [77]))) 31 {iorqi3}
(expr_list:REG_EQUAL (ior:QI (reg:QI 1 g1 [orig:65 D.1938 ] [65])
                        (const_int 128 [0x80]))
                    (nil)))
        ]) -1 (nil))

(code_label 51 97 52 1 "" [2 uses])

(note 52 51 73 [bb 4] NOTE_INSN_BASIC_BLOCK)

(jump_insn 73 52 72 (return) 72 {return_rts} (expr_list:REG_BR_PRED
(const_int 12 [0xc])
        (nil)))

(barrier 72 73 86)

(code_label 86 72 41 5 "" [1 uses])

(note 41 86 45 [bb 5] NOTE_INSN_BASIC_BLOCK)

(insn 45 41 44 del1.c:20 (set (reg:QI 2 g2 [orig:68 ivtmp.7 ] [68])
        (plus:QI (reg:QI 2 g2 [orig:68 ivtmp.7 ] [68])
            (const_int 1 [0x1]))) 13 {addqi3} (nil))

(insn 44 45 101 del1.c:20 (set (mem/s/j:QI (reg/f:PQI 28 a0 [orig:62
D.1955 ] [62]) [0 bytes S1 A32])
        (reg:QI 1 g1 [75])) 7 {movqi_op} (expr_list:REG_DEAD
(reg/f:PQI 28 a0 [orig:62 D.1955 ] [62])
        (expr_list:REG_DEAD (reg:QI 1 g1 [75])
            (nil))))

(code_label 101 44 79 7 "" [1 uses])


Corresponding code:

        jmp.ne  .L5;
        st      [a0], g1;             (INSN 38)
        or      g1, g1, g3;          (INSN 43)
.L1:
        rts;
        nop;
        nop;
.L5:
        add   g2, g2, 1;           (INSN 45)
        st      [a0], g1;            (INSN 44)  -> deleted
.L7:



You can see that INSN 44 and INSN 38 are identical. In
'relax_delay_slots' while processing INSN 97, the second call to
'try_merge_delay_insns' deletes the INSN 44 because of which
unexpected result is generated.

      /* If we own the thread opposite the way this insn branches, see if we
         can merge its delay slots with following insns.  */
      if (INSN_FROM_TARGET_P (XVECEXP (pat, 0, 1))
          && own_thread_p (NEXT_INSN (insn), 0, 1))
        try_merge_delay_insns (insn, next);
      else if (! INSN_FROM_TARGET_P (XVECEXP (pat, 0, 1))
               && own_thread_p (target_label, target_label, 0))
        try_merge_delay_insns (insn, next_active_insn (target_label));

Deleting the INSN 44 would have been proper if the 2nd delay slot insn
had not modified G1. But looking at the comments from the function
'try_merge_delay_insns'

/* Try merging insns starting at THREAD which match exactly the insns in
   INSN's delay list.

   If all insns were matched and the insn was previously annulling, the
   annul bit will be cleared.

   For each insn that is merged, if the branch is or will be non-annulling,
   we delete the merged insn.  */

I think REGOUT dependency of g1 between instructions 38 and 43 in the
delay slot is not being considered by 'try_merge_delay_insns'.

Is this a bug?

Regards,
Shafi

Reply via email to