This is the failure of ACATS c94007a at -O2 on SPARC64/Solaris: the compiler
generates wrong code because of a delay slot scheduling (reorg.c) bug. This
is a regression on the 4.6 branch (4.5 branch and mainline are clean).
fill_simple_delay_slots decides to fill the delay slot of a call insn with
another insn that is located about one hundred insns downstream(!); this is
a long sequence of call insns that can throw with handlers that fall thru,
a typical pattern of ACATS tests, without any intervening jumps or labels.
The problem is that fill_simple_delay_slots hoists the insn above such a
call that throws and whose handler falls thru, which makes it effectively a
jump with edges in the CFG. The code handles the regular jump case:
/* Stop our search when seeing an unconditional jump. */
if (JUMP_P (trial_delay))
break;
but overlooks this special jump case. This is a known pattern, whose solution
has been factored into stop_search_p:
/* Return TRUE if this insn should stop the search for insn to fill delay
slots. LABELS_P indicates that labels should terminate the search.
In all cases, jumps terminate the search. */
static int
stop_search_p (rtx insn, int labels_p)
{
if (insn == 0)
return 1;
/* If the insn can throw an exception that is caught within the function,
it may effectively perform a jump from the viewpoint of the function.
Therefore act like for a jump. */
if (can_throw_internal (insn))
return 1;
fill_simple_delay_slots already uses stop_search_p for the backward scan.
The fix is simply to make it use stop_search_p for the forward scan as well.
Bootstrappeg/regtested on SPARC/Solaris and SPARC64/Solaris.
2011-06-21 Eric Botcazou <[email protected]>
* reorg.c (fill_simple_delay_slots): Use stop_search_p to stop the
forward scan as well.
--
Eric Botcazou
Index: reorg.c
===================================================================
--- reorg.c (revision 175090)
+++ reorg.c (working copy)
@@ -2152,7 +2152,7 @@ fill_simple_delay_slots (int non_jumps_p
/* This must be an INSN or CALL_INSN. */
pat = PATTERN (trial);
- /* USE and CLOBBER at this level was just for flow; ignore it. */
+ /* Stand-alone USE and CLOBBER are just for flow. */
if (GET_CODE (pat) == USE || GET_CODE (pat) == CLOBBER)
continue;
@@ -2271,15 +2271,12 @@ fill_simple_delay_slots (int non_jumps_p
}
if (target == 0)
- for (trial = next_nonnote_insn (insn); trial; trial = next_trial)
+ for (trial = next_nonnote_insn (insn); !stop_search_p (trial, 1);
+ trial = next_trial)
{
next_trial = next_nonnote_insn (trial);
- if (LABEL_P (trial)
- || BARRIER_P (trial))
- break;
-
- /* We must have an INSN, JUMP_INSN, or CALL_INSN. */
+ /* This must be an INSN or CALL_INSN. */
pat = PATTERN (trial);
/* Stand-alone USE and CLOBBER are just for flow. */
@@ -2293,7 +2290,7 @@ fill_simple_delay_slots (int non_jumps_p
else
trial_delay = trial;
- /* Stop our search when seeing an unconditional jump. */
+ /* Stop our search when seeing a jump. */
if (JUMP_P (trial_delay))
break;