}
}
\f
-/* Given an insn, INSN, and a pointer to a `struct resource', RES, indicate
- which resources are modified by the insn. If INCLUDE_CALLED_ROUTINE
- is TRUE, also mark resources potentially set by the called routine.
+/* Given X, a part of an insn, and a pointer to a `struct resource', RES,
+ indicate which resources are modified by the insn. If INCLUDE_CALLED_ROUTINE
+ is nonzero, also mark resources potentially set by the called routine.
+
+ If IN_DEST is nonzero, it means we are inside a SET. Otherwise,
+ objects are being referenced instead of set.
We never mark the insn as modifying the condition code unless it explicitly
SETs CC0 even though this is not totally correct. The reason for this is
our computation and thus may be placed in a delay slot. */
static void
-mark_set_resources (insn, res, include_called_routine)
- register rtx insn;
+mark_set_resources (x, res, in_dest, include_called_routine)
+ register rtx x;
register struct resources *res;
+ int in_dest;
int include_called_routine;
{
- register int i;
+ register enum rtx_code code = GET_CODE (x);
+ register int i, j;
+ register char *format_ptr;
- switch (GET_CODE (insn))
+ restart:
+
+ switch (code)
{
case NOTE:
case BARRIER:
case CODE_LABEL:
+ case USE:
+ case CONST_INT:
+ case CONST_DOUBLE:
+ case LABEL_REF:
+ case SYMBOL_REF:
+ case CONST:
+ case PC:
+ case CC0:
/* These don't set any resources. */
return;
if (include_called_routine)
{
- rtx next = NEXT_INSN (insn);
+ rtx next = NEXT_INSN (x);
res->cc = res->memory = 1;
for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
for (; (next && GET_CODE (next) == INSN
&& GET_CODE (PATTERN (next)) == CLOBBER);
next = NEXT_INSN (next))
- mark_referenced_resources (XEXP (PATTERN (next), 0), res, 0);
+ mark_set_resources (XEXP (PATTERN (next), 0), res, 1, 0);
}
/* ... and also what it's RTL says it modifies, if anything. */
case JUMP_INSN:
case INSN:
- {
- register rtx body = PATTERN (insn);
- register rtx note;
-
- /* An insn consisting of just a CLOBBER (or USE) is
- just for flow and doesn't actually do anything, so we don't check
- for it.
-
- If the source of a SET is a CALL, this is actually done by
- the called routine. So only include it if we are to include the
- effects of the calling routine. */
-
- if (GET_CODE (body) == SET
- && (include_called_routine || GET_CODE (SET_SRC (body)) != CALL))
- mark_referenced_resources (SET_DEST (body), res, 0);
- else if (GET_CODE (body) == PARALLEL)
- {
- for (i = 0; i < XVECLEN (body, 0); i++)
- if ((GET_CODE (XVECEXP (body, 0, i)) == SET
- && (include_called_routine
- || GET_CODE (SET_SRC (XVECEXP (body, 0, i))) != CALL))
- || GET_CODE (XVECEXP (body, 0, i)) == CLOBBER)
- mark_referenced_resources (SET_DEST (XVECEXP (body, 0, i)),
- res, 0);
- }
- else if (GET_CODE (body) == SEQUENCE)
- for (i = 0; i < XVECLEN (body, 0); i++)
- if (! (INSN_ANNULLED_BRANCH_P (XVECEXP (body, 0, 0))
- && INSN_FROM_TARGET_P (XVECEXP (body, 0, i))))
- mark_set_resources (XVECEXP (body, 0, i), res,
- include_called_routine);
-
-#ifdef AUTO_INC_DEC
- /* If any register are incremented or decremented in an address,
- they are set here. */
- for (note = REG_NOTES (insn); note; note = XEXP (note, 1))
- if (REG_NOTE_KIND (note) == REG_INC)
- mark_referenced_resources (XEXP (note, 0), res, 0);
-#endif
-#ifdef PUSH_ROUNDING
- /* An insn that has a PRE_DEC on SP will not have a REG_INC note.
- Until we fix this correctly, consider all insns as modifying
- SP on such machines. So far, we don't have delay slot scheduling
- on any machines with PUSH_ROUNDING. */
- SET_HARD_REG_BIT (res->regs, STACK_POINTER_REGNUM);
-#endif
- return;
- }
+ /* An insn consisting of just a CLOBBER (or USE) is just for flow
+ and doesn't actually do anything, so we ignore it. */
- default:
- abort ();
+ x = PATTERN (x);
+ if (GET_CODE (x) != USE && GET_CODE (x) != CLOBBER)
+ goto restart;
+ return;
+
+ case SET:
+ /* If the source of a SET is a CALL, this is actually done by
+ the called routine. So only include it if we are to include the
+ effects of the calling routine. */
+
+ mark_set_resources (SET_DEST (x), res,
+ (include_called_routine
+ || GET_CODE (SET_SRC (x)) != CALL),
+ 0);
+
+ mark_set_resources (SET_SRC (x), res, 0, 0);
+ return;
+
+ case CLOBBER:
+ mark_set_resources (XEXP (x, 0), res, 1, 0);
+ return;
+
+ case SEQUENCE:
+ for (i = 0; i < XVECLEN (x, 0); i++)
+ if (! (INSN_ANNULLED_BRANCH_P (XVECEXP (x, 0, 0))
+ && INSN_FROM_TARGET_P (XVECEXP (x, 0, i))))
+ mark_set_resources (XVECEXP (x, 0, i), res, 0,
+ include_called_routine);
+ return;
+
+ case POST_INC:
+ case PRE_INC:
+ case POST_DEC:
+ case PRE_DEC:
+ mark_set_resources (XEXP (x, 0), res, 1, 0);
+ return;
+
+ case ZERO_EXTRACT:
+ mark_set_resources (XEXP (x, 0), res, in_dest, 0);
+ mark_set_resources (XEXP (x, 1), res, 0, 0);
+ mark_set_resources (XEXP (x, 2), res, 0, 0);
+ return;
+
+ case MEM:
+ if (in_dest)
+ {
+ res->memory = 1;
+ res->volatil = MEM_VOLATILE_P (x);
+ }
+
+ mark_set_resources (XEXP (x, 0), res, 0, 0);
+ goto restart;
+
+ case REG:
+ for (i = 0; i < HARD_REGNO_NREGS (REGNO (x), GET_MODE (x)); i++)
+ SET_HARD_REG_BIT (res->regs, REGNO (x) + i);
+ return;
}
+
+ /* Process each sub-expression and flag what it needs. */
+ format_ptr = GET_RTX_FORMAT (code);
+ for (i = 0; i < GET_RTX_LENGTH (code); i++)
+ switch (*format_ptr++)
+ {
+ case 'e':
+ mark_set_resources (XEXP (x, i), res, in_dest, include_called_routine);
+ break;
+
+ case 'E':
+ for (j = 0; j < XVECLEN (x, i); j++)
+ mark_set_resources (XVECEXP (x, i, j), res, in_dest,
+ include_called_routine);
+ break;
+ }
}
\f
/* Return TRUE if this insn should stop the search for insn to fill delay
struct resources insn_sets;
CLEAR_RESOURCE (&insn_sets);
- mark_set_resources (insn, &insn_sets, include_called_routine);
+ mark_set_resources (insn, &insn_sets, 0, include_called_routine);
return resource_conflicts_p (&insn_sets, res);
}
\f
mark_referenced_resources (next_to_match, &needed, 1);
}
- mark_set_resources (trial, &set, 1);
+ mark_set_resources (trial, &set, 0, 1);
mark_referenced_resources (trial, &needed, 1);
}
CLEAR_RESOURCE (&needed);
CLEAR_RESOURCE (&set);
- mark_set_resources (insn, &set, 1);
+ mark_set_resources (insn, &set, 0, 1);
mark_referenced_resources (insn, &needed, 1);
/* If TARGET is a SEQUENCE, get the main insn. */
}
mark_referenced_resources (insn, &needed, 1);
- mark_set_resources (insn, &set, 1);
+ mark_set_resources (insn, &set, 0, 1);
COPY_HARD_REG_SET (scratch, set.regs);
AND_COMPL_HARD_REG_SET (scratch, needed.regs);
AND_COMPL_HARD_REG_SET (scratch, set.regs);
IOR_HARD_REG_SET (new_resources.regs, scratch);
- mark_set_resources (insn, &set, 1);
+ mark_set_resources (insn, &set, 0, 1);
}
AND_HARD_REG_SET (res->regs, new_resources.regs);
delay_list = 0;
CLEAR_RESOURCE (&needed);
CLEAR_RESOURCE (&set);
- mark_set_resources (insn, &set, 0);
+ mark_set_resources (insn, &set, 0, 0);
mark_referenced_resources (insn, &needed, 0);
for (trial = prev_nonnote_insn (insn); ! stop_search_p (trial, 1);
}
}
- mark_set_resources (trial, &set, 1);
+ mark_set_resources (trial, &set, 0, 1);
mark_referenced_resources (trial, &needed, 1);
}
if (GET_CODE (insn) == CALL_INSN)
{
- mark_set_resources (insn, &set, 1);
+ mark_set_resources (insn, &set, 0, 1);
mark_referenced_resources (insn, &needed, 1);
maybe_never = 1;
}
continue;
}
- mark_set_resources (trial, &set, 1);
+ mark_set_resources (trial, &set, 0, 1);
mark_referenced_resources (trial, &needed, 1);
/* Ensure we don't put insns between the setting of cc and the
}
}
- mark_set_resources (trial, &set, 1);
+ mark_set_resources (trial, &set, 0, 1);
mark_referenced_resources (trial, &needed, 1);
}
/* This insn can't go into a delay slot. */
lose = 1;
- mark_set_resources (trial, &set, 1);
+ mark_set_resources (trial, &set, 0, 1);
mark_referenced_resources (trial, &needed, 1);
/* Ensure we don't put insns between the setting of cc and the comparison