-/* If all INSN does is set the pc, delete it,
- and delete the insn that set the condition codes for it
- if that's what the previous thing was. */
-
-void
-delete_jump (insn)
- rtx insn;
-{
- rtx set = single_set (insn);
-
- if (set && GET_CODE (SET_DEST (set)) == PC)
- delete_computation (insn);
-}
-
-/* Verify INSN is a BARRIER and delete it. */
-
-void
-delete_barrier (insn)
- rtx insn;
-{
- if (GET_CODE (insn) != BARRIER)
- abort ();
-
- delete_insn (insn);
-}
-
-/* Recursively delete prior insns that compute the value (used only by INSN
- which the caller is deleting) stored in the register mentioned by NOTE
- which is a REG_DEAD note associated with INSN. */
-
-static void
-delete_prior_computation (note, insn)
- rtx note;
- rtx insn;
-{
- rtx our_prev;
- rtx reg = XEXP (note, 0);
-
- for (our_prev = prev_nonnote_insn (insn);
- our_prev && (GET_CODE (our_prev) == INSN
- || GET_CODE (our_prev) == CALL_INSN);
- our_prev = prev_nonnote_insn (our_prev))
- {
- rtx pat = PATTERN (our_prev);
-
- /* If we reach a CALL which is not calling a const function
- or the callee pops the arguments, then give up. */
- if (GET_CODE (our_prev) == CALL_INSN
- && (! CONST_OR_PURE_CALL_P (our_prev)
- || GET_CODE (pat) != SET || GET_CODE (SET_SRC (pat)) != CALL))
- break;
-
- /* If we reach a SEQUENCE, it is too complex to try to
- do anything with it, so give up. We can be run during
- and after reorg, so SEQUENCE rtl can legitimately show
- up here. */
- if (GET_CODE (pat) == SEQUENCE)
- break;
-
- if (GET_CODE (pat) == USE
- && GET_CODE (XEXP (pat, 0)) == INSN)
- /* reorg creates USEs that look like this. We leave them
- alone because reorg needs them for its own purposes. */
- break;
-
- if (reg_set_p (reg, pat))
- {
- if (side_effects_p (pat) && GET_CODE (our_prev) != CALL_INSN)
- break;
-
- if (GET_CODE (pat) == PARALLEL)
- {
- /* If we find a SET of something else, we can't
- delete the insn. */
-
- int i;
-
- for (i = 0; i < XVECLEN (pat, 0); i++)
- {
- rtx part = XVECEXP (pat, 0, i);
-
- if (GET_CODE (part) == SET
- && SET_DEST (part) != reg)
- break;
- }
-
- if (i == XVECLEN (pat, 0))
- delete_computation (our_prev);
- }
- else if (GET_CODE (pat) == SET
- && GET_CODE (SET_DEST (pat)) == REG)
- {
- int dest_regno = REGNO (SET_DEST (pat));
- int dest_endregno
- = (dest_regno
- + (dest_regno < FIRST_PSEUDO_REGISTER
- ? HARD_REGNO_NREGS (dest_regno,
- GET_MODE (SET_DEST (pat))) : 1));
- int regno = REGNO (reg);
- int endregno
- = (regno
- + (regno < FIRST_PSEUDO_REGISTER
- ? HARD_REGNO_NREGS (regno, GET_MODE (reg)) : 1));
-
- if (dest_regno >= regno
- && dest_endregno <= endregno)
- delete_computation (our_prev);
-
- /* We may have a multi-word hard register and some, but not
- all, of the words of the register are needed in subsequent
- insns. Write REG_UNUSED notes for those parts that were not
- needed. */
- else if (dest_regno <= regno
- && dest_endregno >= endregno)
- {
- int i;
-
- REG_NOTES (our_prev)
- = gen_rtx_EXPR_LIST (REG_UNUSED, reg,
- REG_NOTES (our_prev));
-
- for (i = dest_regno; i < dest_endregno; i++)
- if (! find_regno_note (our_prev, REG_UNUSED, i))
- break;
-
- if (i == dest_endregno)
- delete_computation (our_prev);
- }
- }
-
- break;
- }
-
- /* If PAT references the register that dies here, it is an
- additional use. Hence any prior SET isn't dead. However, this
- insn becomes the new place for the REG_DEAD note. */
- if (reg_overlap_mentioned_p (reg, pat))
- {
- XEXP (note, 1) = REG_NOTES (our_prev);
- REG_NOTES (our_prev) = note;
- break;
- }
- }
-}
-
-/* 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.
-
- On machines with CC0, if CC0 is used in this insn, we may be able to
- delete the insn that set it. */
-
-static void
-delete_computation (insn)
- rtx insn;
-{
- rtx note, next;
-
-#ifdef HAVE_cc0
- if (reg_referenced_p (cc0_rtx, PATTERN (insn)))
- {
- rtx prev = prev_nonnote_insn (insn);
- /* We assume that at this stage
- CC's are always set explicitly
- and always immediately before the jump that
- will use them. So if the previous insn
- exists to set the CC's, delete it
- (unless it performs auto-increments, etc.). */
- if (prev && GET_CODE (prev) == INSN
- && sets_cc0_p (PATTERN (prev)))
- {
- if (sets_cc0_p (PATTERN (prev)) > 0
- && ! side_effects_p (PATTERN (prev)))
- delete_computation (prev);
- else
- /* Otherwise, show that cc0 won't be used. */
- REG_NOTES (prev) = gen_rtx_EXPR_LIST (REG_UNUSED,
- cc0_rtx, REG_NOTES (prev));
- }
- }
-#endif
-
- for (note = REG_NOTES (insn); note; note = next)
- {
- next = XEXP (note, 1);
-
- if (REG_NOTE_KIND (note) != REG_DEAD
- /* Verify that the REG_NOTE is legitimate. */
- || GET_CODE (XEXP (note, 0)) != REG)
- continue;
-
- delete_prior_computation (note, insn);
- }
-
- delete_related_insns (insn);
-}