mark_set_resources (insn, &insn_sets, 0, include_delayed_effects);
return resource_conflicts_p (&insn_sets, res);
}
+
+/* Return TRUE if INSN is a return, possibly with a filled delay slot. */
+
+static bool
+return_insn_p (rtx insn)
+{
+ if (GET_CODE (insn) == JUMP_INSN && GET_CODE (PATTERN (insn)) == RETURN)
+ return true;
+
+ if (GET_CODE (insn) == INSN && GET_CODE (PATTERN (insn)) == SEQUENCE)
+ return return_insn_p (XVECEXP (PATTERN (insn), 0, 0));
+
+ return false;
+}
\f
/* Find a label at the end of the function or before a RETURN. If there is
none, make one. */
/* When a target threads its epilogue we might already have a
suitable return insn. If so put a label before it for the
end_of_function_label. */
- if (GET_CODE (insn) == BARRIER
- && GET_CODE (PREV_INSN (insn)) == JUMP_INSN
- && GET_CODE (PATTERN (PREV_INSN (insn))) == RETURN)
+ if (GET_CODE (insn) == BARRIER && return_insn_p (PREV_INSN (insn)))
{
rtx temp = PREV_INSN (PREV_INSN (insn));
end_of_function_label = gen_label_rtx ();
LABEL_NUSES (end_of_function_label) = 0;
- /* Put the label before an USE insns that may proceed the RETURN insn. */
+ /* Put the label before an USE insn that may precede the RETURN insn. */
while (GET_CODE (temp) == USE)
temp = PREV_INSN (temp);
/* If the basic block reorder pass moves the return insn to
some other place try to locate it again and put our
end_of_function_label there. */
- while (insn && ! (GET_CODE (insn) == JUMP_INSN
- && (GET_CODE (PATTERN (insn)) == RETURN)))
+ while (insn && ! return_insn_p (insn))
insn = PREV_INSN (insn);
if (insn)
{
rtx trial, seq_insn, seq, prev;
rtx delay_list = 0;
int i;
+ int had_barrier = 0;
/* We first must find the insn containing the SEQUENCE with INSN in its
delay slot. Do this by finding an insn, TRIAL, where
seq_insn = PREV_INSN (NEXT_INSN (trial));
seq = PATTERN (seq_insn);
+ if (NEXT_INSN (seq_insn) && GET_CODE (NEXT_INSN (seq_insn)) == BARRIER)
+ had_barrier = 1;
+
/* Create a delay list consisting of all the insns other than the one
we are deleting (unless we were the only one). */
if (XVECLEN (seq, 0) > 2)
delete_related_insns (seq_insn);
add_insn_after (trial, prev);
- if (GET_CODE (trial) == JUMP_INSN
- && (simplejump_p (trial) || GET_CODE (PATTERN (trial)) == RETURN))
+ /* If there was a barrier after the old SEQUENCE, remit it. */
+ if (had_barrier)
emit_barrier_after (trial);
/* If there are any delay insns, remit them. Otherwise clear the
next = XEXP (link, 1);
if (REG_NOTE_KIND (link) != REG_DEAD
- || GET_CODE (XEXP (link, 0)) != REG)
+ || !REG_P (XEXP (link, 0)))
continue;
if (reg_referenced_p (XEXP (link, 0), PATTERN (insn)))
next = XEXP (link, 1);
if (REG_NOTE_KIND (link) != REG_DEAD
- || GET_CODE (XEXP (link, 0)) != REG)
+ || !REG_P (XEXP (link, 0)))
continue;
if (reg_set_p (XEXP (link, 0), PATTERN (start_insn)))
next = XEXP (link, 1);
if (REG_NOTE_KIND (link) != REG_UNUSED
- || GET_CODE (XEXP (link, 0)) != REG)
+ || !REG_P (XEXP (link, 0)))
continue;
if (! find_regno_note (redundant_insn, REG_UNUSED,
&& eligible_for_delay (insn, slots_filled, next_trial, flags)
&& ! can_throw_internal (trial))
{
- rtx new_label = next_active_insn (next_trial);
+ /* See comment in relax_delay_slots about necessity of using
+ next_real_insn here. */
+ rtx new_label = next_real_insn (next_trial);
if (new_label != 0)
new_label = get_label_before (new_label);
destination. Overlap may happen for larger-than-register-size modes. */
if (GET_CODE (trial) == INSN && GET_CODE (pat) == SET
- && GET_CODE (SET_SRC (pat)) == REG
- && GET_CODE (SET_DEST (pat)) == REG
+ && REG_P (SET_SRC (pat))
+ && REG_P (SET_DEST (pat))
&& !reg_overlap_mentioned_p (SET_DEST (pat), SET_SRC (pat)))
{
rtx next = next_nonnote_insn (trial);
&& (condjump_p (insn) || condjump_in_parallel_p (insn))
&& (target_label = JUMP_LABEL (insn)) != 0)
{
- target_label = follow_jumps (target_label);
- target_label = prev_label (next_active_insn (target_label));
-
+ target_label = skip_consecutive_labels (follow_jumps (target_label));
if (target_label == 0)
target_label = find_end_label ();
/* See if we have a RETURN insn with a filled delay slot followed
by a RETURN insn with an unfilled a delay slot. If so, we can delete
- the first RETURN (but not it's delay insn). This gives the same
+ the first RETURN (but not its delay insn). This gives the same
effect in fewer instructions.
Only do so if optimizing for size since this results in slower, but
{
/* If this jump goes to another unconditional jump, thread it, but
don't convert a jump into a RETURN here. */
- trial = follow_jumps (target_label);
- /* We use next_real_insn instead of next_active_insn, so that
- the special USE insns emitted by reorg won't be ignored.
- If they are ignored, then they will get deleted if target_label
- is now unreachable, and that would cause mark_target_live_regs
- to fail. */
- trial = prev_label (next_real_insn (trial));
- if (trial == 0 && target_label != 0)
+ trial = skip_consecutive_labels (follow_jumps (target_label));
+ if (trial == 0)
trial = find_end_label ();
if (trial != target_label
{
target_label = JUMP_LABEL (XVECEXP (PATTERN (trial), 0, 0));
if (target_label == 0)
- target_label = find_end_label ();
+ {
+ target_label = find_end_label ();
+ /* The following condition may be true if TRIAL contains
+ the unique RETURN. In this case, threading would be
+ a nop and we would enter an infinite loop if we did it. */
+ if (next_active_insn (target_label) == trial)
+ target_label = 0;
+ }
- if (redirect_with_delay_slots_safe_p (delay_insn, target_label,
- insn))
+ if (target_label
+ && redirect_with_delay_slots_safe_p (delay_insn, target_label,
+ insn))
{
reorg_redirect_jump (delay_insn, target_label);
next = insn;
if (GET_CODE (insn) == JUMP_INSN
&& (condjump_p (insn) || condjump_in_parallel_p (insn))
&& JUMP_LABEL (insn) != 0
- && ((target = prev_label (next_active_insn (JUMP_LABEL (insn))))
+ && ((target = skip_consecutive_labels (JUMP_LABEL (insn)))
!= JUMP_LABEL (insn)))
redirect_jump (insn, target, 1);
}