/* Perform instruction reorganizations for delay slot filling.
Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
- 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
+ 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
Free Software Foundation, Inc.
Contributed by Richard Kenner (kenner@vlsi1.ultra.nyu.edu).
Hacked by Michael Tiemann (tiemann@cygnus.com).
#include "system.h"
#include "coretypes.h"
#include "tm.h"
-#include "toplev.h"
+#include "diagnostic-core.h"
#include "rtl.h"
#include "tm_p.h"
#include "expr.h"
for (trial = PREV_INSN (target),
insns_to_search = MAX_DELAY_SLOT_INSN_SEARCH;
trial && insns_to_search > 0;
- trial = PREV_INSN (trial), --insns_to_search)
+ trial = PREV_INSN (trial))
{
if (LABEL_P (trial))
return 0;
- if (! INSN_P (trial))
+ if (!NONDEBUG_INSN_P (trial))
continue;
+ --insns_to_search;
pat = PATTERN (trial);
if (GET_CODE (pat) == USE || GET_CODE (pat) == CLOBBER)
for (trial = PREV_INSN (target),
insns_to_search = MAX_DELAY_SLOT_INSN_SEARCH;
trial && !LABEL_P (trial) && insns_to_search > 0;
- trial = PREV_INSN (trial), --insns_to_search)
+ trial = PREV_INSN (trial))
{
- if (!INSN_P (trial))
+ if (!NONDEBUG_INSN_P (trial))
continue;
+ --insns_to_search;
pat = PATTERN (trial);
if (GET_CODE (pat) == USE || GET_CODE (pat) == CLOBBER)
/* If this is a constant adjustment, use the same code with
the negated constant. Otherwise, reverse the sense of the
arithmetic. */
- if (GET_CODE (other) == CONST_INT)
+ if (CONST_INT_P (other))
new_arith = gen_rtx_fmt_ee (GET_CODE (src), GET_MODE (src), dest,
negate_rtx (GET_MODE (src), other));
else
/* Delete INSN and recursively delete insns that compute values used only
by INSN. This uses the REG_DEAD notes computed during flow analysis.
- If we are running before flow.c, we need do nothing since flow.c will
- delete dead code. We also can't know if the registers being used are
- dead or not at this point.
- Otherwise, look at all our REG_DEAD notes. If a previous insn does
- nothing other than set a register that dies in this insn, we can delete
- that insn as well.
+ Look at all our REG_DEAD notes. If a previous insn does nothing other
+ than set a register that dies in this insn, we can delete that insn
+ as well.
On machines with CC0, if CC0 is used in this insn, we may be able to
delete the insn that set it. */
We do this by deleting the INSN containing the SEQUENCE, then
re-emitting the insns separately, and then deleting the RETURN.
This allows the count of the jump target to be properly
- decremented. */
+ decremented.
- /* Clear the from target bit, since these insns are no longer
+ Note that we need to change the INSN_UID of the re-emitted insns
+ since it is used to hash the insns for mark_target_live_regs and
+ the re-emitted insns will no longer be wrapped up in a SEQUENCE.
+
+ Clear the from target bit, since these insns are no longer
in delay slots. */
for (i = 0; i < XVECLEN (pat, 0); i++)
INSN_FROM_TARGET_P (XVECEXP (pat, 0, i)) = 0;
trial = PREV_INSN (insn);
delete_related_insns (insn);
gcc_assert (GET_CODE (pat) == SEQUENCE);
- after = trial;
- for (i = 0; i < XVECLEN (pat, 0); i++)
- {
- rtx this_insn = XVECEXP (pat, 0, i);
- add_insn_after (this_insn, after, NULL);
- after = this_insn;
- }
+ add_insn_after (delay_insn, trial, NULL);
+ after = delay_insn;
+ for (i = 1; i < XVECLEN (pat, 0); i++)
+ after = emit_copy_of_insn_after (XVECEXP (pat, 0, i), after);
delete_scheduled_jump (delay_insn);
continue;
}
}
/* If the first insn at TARGET_LABEL is redundant with a previous
- insn, redirect the jump to the following insn process again. */
- trial = next_active_insn (target_label);
+ insn, redirect the jump to the following insn and process again.
+ We use next_real_insn instead of next_active_insn so we
+ don't skip USE-markers, or we'll end up with incorrect
+ liveness info. */
+ trial = next_real_insn (target_label);
if (trial && GET_CODE (PATTERN (trial)) != SEQUENCE
&& redundant_insn (trial, insn, 0)
&& ! can_throw_internal (trial))
We do this by deleting the INSN containing the SEQUENCE, then
re-emitting the insns separately, and then deleting the jump.
This allows the count of the jump target to be properly
- decremented. */
+ decremented.
- /* Clear the from target bit, since these insns are no longer
+ Note that we need to change the INSN_UID of the re-emitted insns
+ since it is used to hash the insns for mark_target_live_regs and
+ the re-emitted insns will no longer be wrapped up in a SEQUENCE.
+
+ Clear the from target bit, since these insns are no longer
in delay slots. */
for (i = 0; i < XVECLEN (pat, 0); i++)
INSN_FROM_TARGET_P (XVECEXP (pat, 0, i)) = 0;
trial = PREV_INSN (insn);
delete_related_insns (insn);
gcc_assert (GET_CODE (pat) == SEQUENCE);
- after = trial;
- for (i = 0; i < XVECLEN (pat, 0); i++)
- {
- rtx this_insn = XVECEXP (pat, 0, i);
- add_insn_after (this_insn, after, NULL);
- after = this_insn;
- }
+ add_insn_after (delay_insn, trial, NULL);
+ after = delay_insn;
+ for (i = 1; i < XVECLEN (pat, 0); i++)
+ after = emit_copy_of_insn_after (XVECEXP (pat, 0, i), after);
delete_scheduled_jump (delay_insn);
continue;
}
INSN_FROM_TARGET_P (insn) = 0;
/* Skip vector tables. We can't get attributes for them. */
- if (JUMP_P (insn)
- && (GET_CODE (PATTERN (insn)) == ADDR_VEC
- || GET_CODE (PATTERN (insn)) == ADDR_DIFF_VEC))
+ if (JUMP_TABLE_DATA_P (insn))
continue;
if (num_delay_slots (insn) > 0)