/* Analyze RTL for C-Compiler
- Copyright (C) 1987, 88, 92-98, 1999 Free Software Foundation, Inc.
+ Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
+ 1999, 2000 Free Software Foundation, Inc.
This file is part of GNU CC.
#include "system.h"
#include "rtl.h"
-static int rtx_addr_can_trap_p PROTO((rtx));
-static void reg_set_p_1 PROTO((rtx, rtx, void *));
-static void reg_set_last_1 PROTO((rtx, rtx, void *));
+static int rtx_addr_can_trap_p PARAMS ((rtx));
+static void reg_set_p_1 PARAMS ((rtx, rtx, void *));
+static void reg_set_last_1 PARAMS ((rtx, rtx, void *));
/* Forward declarations */
-static int jmp_uses_reg_or_mem PROTO((rtx));
+static int jmp_uses_reg_or_mem PARAMS ((rtx));
/* Bit flags that specify the machine subtype we are compiling for.
Bits are tested using macros TARGET_... defined in the tm.h file
case CALL:
case USE:
+ case IF_THEN_ELSE:
return reg_overlap_mentioned_p (x, body);
case TRAP_IF:
return 1;
return 0;
+ case CLOBBER:
+ if (GET_CODE (XEXP (body, 0)) == MEM)
+ if (reg_overlap_mentioned_p (x, XEXP (XEXP (body, 0), 0)))
+ return 1;
+ return 0;
+
+ case COND_EXEC:
+ if (reg_overlap_mentioned_p (x, COND_EXEC_TEST (body)))
+ return 1;
+ return reg_referenced_p (x, COND_EXEC_CODE (body));
+
default:
return 0;
}
if (fmt[i] == 'e' && modified_between_p (XEXP (x, i), start, end))
return 1;
- if (fmt[i] == 'E')
+ else if (fmt[i] == 'E')
for (j = XVECLEN (x, i) - 1; j >= 0; j--)
if (modified_between_p (XVECEXP (x, i, j), start, end))
return 1;
if (fmt[i] == 'e' && modified_in_p (XEXP (x, i), insn))
return 1;
- if (fmt[i] == 'E')
+ else if (fmt[i] == 'E')
for (j = XVECLEN (x, i) - 1; j >= 0; j--)
if (modified_in_p (XVECEXP (x, i, j), insn))
return 1;
else if (GET_CODE (PATTERN (insn)) == PARALLEL)
{
for (i = 0, set = 0; i < XVECLEN (PATTERN (insn), 0); i++)
- if (GET_CODE (XVECEXP (PATTERN (insn), 0, i)) == SET
- && (! find_reg_note (insn, REG_UNUSED,
- SET_DEST (XVECEXP (PATTERN (insn), 0, i)))
- || side_effects_p (XVECEXP (PATTERN (insn), 0, i))))
- {
- if (set)
+ {
+ rtx sub = XVECEXP (PATTERN (insn), 0, i);
+
+ switch (GET_CODE (sub))
+ {
+ case USE:
+ case CLOBBER:
+ break;
+
+ case SET:
+ if (! find_reg_note (insn, REG_UNUSED, SET_DEST (sub))
+ || side_effects_p (sub))
+ {
+ if (set)
+ return 0;
+ else
+ set = sub;
+ }
+ break;
+
+ default:
return 0;
- else
- set = XVECEXP (PATTERN (insn), 0, i);
- }
+ }
+ }
return set;
}
return 0;
}
\f
-/* Return the last thing that X was assigned from before *PINSN. Verify that
- the object is not modified up to VALID_TO. If it was, if we hit
- a partial assignment to X, or hit a CODE_LABEL first, return X. If we
- found an assignment, update *PINSN to point to it.
- ALLOW_HWREG is set to 1 if hardware registers are allowed to be the src. */
+/* Return the last thing that X was assigned from before *PINSN. If VALID_TO
+ is not NULL_RTX then verify that the object is not modified up to VALID_TO.
+ If the object was modified, if we hit a partial assignment to X, or hit a
+ CODE_LABEL first, return X. If we found an assignment, update *PINSN to
+ point to it. ALLOW_HWREG is set to 1 if hardware registers are allowed to
+ be the src. */
rtx
find_last_value (x, pinsn, valid_to, allow_hwreg)
if (note && GET_CODE (XEXP (note, 0)) != EXPR_LIST)
src = XEXP (note, 0);
- if (! modified_between_p (src, PREV_INSN (p), valid_to)
+ if ((valid_to == NULL_RTX
+ || ! modified_between_p (src, PREV_INSN (p), valid_to))
/* Reject hard registers because we don't usually want
to use them; we'd rather use a pseudo. */
&& (! (GET_CODE (src) == REG
int
refers_to_regno_p (regno, endregno, x, loc)
- int regno, endregno;
+ unsigned int regno, endregno;
rtx x;
rtx *loc;
{
- register int i;
- register RTX_CODE code;
- register const char *fmt;
+ int i;
+ unsigned int x_regno;
+ RTX_CODE code;
+ const char *fmt;
repeat:
/* The contents of a REG_NONNEG note is always zero, so we must come here
switch (code)
{
case REG:
- i = REGNO (x);
+ x_regno = REGNO (x);
/* If we modifying the stack, frame, or argument pointer, it will
clobber a virtual register. In fact, we could be more precise,
but it isn't worth it. */
- if ((i == STACK_POINTER_REGNUM
+ if ((x_regno == STACK_POINTER_REGNUM
#if FRAME_POINTER_REGNUM != ARG_POINTER_REGNUM
- || i == ARG_POINTER_REGNUM
+ || x_regno == ARG_POINTER_REGNUM
#endif
- || i == FRAME_POINTER_REGNUM)
+ || x_regno == FRAME_POINTER_REGNUM)
&& regno >= FIRST_VIRTUAL_REGISTER && regno <= LAST_VIRTUAL_REGISTER)
return 1;
- return (endregno > i
- && regno < i + (i < FIRST_PSEUDO_REGISTER
- ? HARD_REGNO_NREGS (i, GET_MODE (x))
+ return (endregno > x_regno
+ && regno < x_regno + (x_regno < FIRST_PSEUDO_REGISTER
+ ? HARD_REGNO_NREGS (x_regno, GET_MODE (x))
: 1));
case SUBREG:
if (GET_CODE (SUBREG_REG (x)) == REG
&& REGNO (SUBREG_REG (x)) < FIRST_PSEUDO_REGISTER)
{
- int inner_regno = REGNO (SUBREG_REG (x)) + SUBREG_WORD (x);
- int inner_endregno
+ unsigned int inner_regno = REGNO (SUBREG_REG (x)) + SUBREG_WORD (x);
+ unsigned int inner_endregno
= inner_regno + (inner_regno < FIRST_PSEUDO_REGISTER
? HARD_REGNO_NREGS (regno, GET_MODE (x)) : 1);
reg_overlap_mentioned_p (x, in)
rtx x, in;
{
- int regno, endregno;
+ unsigned int regno, endregno;
/* Overly conservative. */
if (GET_CODE (x) == STRICT_LOW_PART)
/* If either argument is a constant, then modifying X can not affect IN. */
if (CONSTANT_P (x) || CONSTANT_P (in))
return 0;
- else if (GET_CODE (x) == SUBREG)
+
+ switch (GET_CODE (x))
{
+ case SUBREG:
regno = REGNO (SUBREG_REG (x));
if (regno < FIRST_PSEUDO_REGISTER)
regno += SUBREG_WORD (x);
- }
- else if (GET_CODE (x) == REG)
- regno = REGNO (x);
- else if (GET_CODE (x) == MEM)
- {
- const char *fmt;
- int i;
+ goto do_reg;
- if (GET_CODE (in) == MEM)
- return 1;
+ case REG:
+ regno = REGNO (x);
+ do_reg:
+ endregno = regno + (regno < FIRST_PSEUDO_REGISTER
+ ? HARD_REGNO_NREGS (regno, GET_MODE (x)) : 1);
+ return refers_to_regno_p (regno, endregno, in, NULL_PTR);
- fmt = GET_RTX_FORMAT (GET_CODE (in));
+ case MEM:
+ {
+ const char *fmt;
+ int i;
- for (i = GET_RTX_LENGTH (GET_CODE (in)) - 1; i >= 0; i--)
- if (fmt[i] == 'e' && reg_overlap_mentioned_p (x, XEXP (in, i)))
+ if (GET_CODE (in) == MEM)
return 1;
- return 0;
- }
- else if (GET_CODE (x) == SCRATCH || GET_CODE (x) == PC
- || GET_CODE (x) == CC0)
- return reg_mentioned_p (x, in);
- else if (GET_CODE (x) == PARALLEL
- && GET_MODE (x) == BLKmode)
- {
- register int i;
+ fmt = GET_RTX_FORMAT (GET_CODE (in));
+ for (i = GET_RTX_LENGTH (GET_CODE (in)) - 1; i >= 0; i--)
+ if (fmt[i] == 'e' && reg_overlap_mentioned_p (x, XEXP (in, i)))
+ return 1;
- /* If any register in here refers to it
- we return true. */
- for (i = XVECLEN (x, 0) - 1; i >= 0; i--)
- if (reg_overlap_mentioned_p (SET_DEST (XVECEXP (x, 0, i)), in))
- return 1;
- return 0;
- }
- else
- abort ();
+ return 0;
+ }
+
+ case SCRATCH:
+ case PC:
+ case CC0:
+ return reg_mentioned_p (x, in);
+
+ case PARALLEL:
+ if (GET_MODE (x) == BLKmode)
+ {
+ register int i;
- endregno = regno + (regno < FIRST_PSEUDO_REGISTER
- ? HARD_REGNO_NREGS (regno, GET_MODE (x)) : 1);
+ /* If any register in here refers to it we return true. */
+ for (i = XVECLEN (x, 0) - 1; i >= 0; i--)
+ if (reg_overlap_mentioned_p (SET_DEST (XVECEXP (x, 0, i)), in))
+ return 1;
+ return 0;
+ }
+ break;
- return refers_to_regno_p (regno, endregno, in, NULL_PTR);
+ default:
+ break;
+ }
+
+ abort ();
}
\f
/* Used for communications between the next few functions. */
static int reg_set_last_unknown;
static rtx reg_set_last_value;
-static int reg_set_last_first_regno, reg_set_last_last_regno;
+static unsigned int reg_set_last_first_regno, reg_set_last_last_regno;
/* Called via note_stores from reg_set_last. */
rtx pat;
void *data ATTRIBUTE_UNUSED;
{
- int first, last;
+ unsigned int first, last;
/* If X is not a register, or is not one in the range we care
about, ignore. */
return 0;
}
\f
-/* This is 1 until after the rtl generation pass. */
-int rtx_equal_function_value_matters;
-
-/* Return 1 if X and Y are identical-looking rtx's.
- This is the Lisp function EQUAL for rtx arguments. */
-
-int
-rtx_equal_p (x, y)
- rtx x, y;
-{
- register int i;
- register int j;
- register enum rtx_code code;
- register const char *fmt;
-
- if (x == y)
- return 1;
- if (x == 0 || y == 0)
- return 0;
-
- code = GET_CODE (x);
- /* Rtx's of different codes cannot be equal. */
- if (code != GET_CODE (y))
- return 0;
-
- /* (MULT:SI x y) and (MULT:HI x y) are NOT equivalent.
- (REG:SI x) and (REG:HI x) are NOT equivalent. */
-
- if (GET_MODE (x) != GET_MODE (y))
- return 0;
-
- /* REG, LABEL_REF, and SYMBOL_REF can be compared nonrecursively. */
-
- if (code == REG)
- /* Until rtl generation is complete, don't consider a reference to the
- return register of the current function the same as the return from a
- called function. This eases the job of function integration. Once the
- distinction is no longer needed, they can be considered equivalent. */
- return (REGNO (x) == REGNO (y)
- && (! rtx_equal_function_value_matters
- || REG_FUNCTION_VALUE_P (x) == REG_FUNCTION_VALUE_P (y)));
- else if (code == LABEL_REF)
- return XEXP (x, 0) == XEXP (y, 0);
- else if (code == SYMBOL_REF)
- return XSTR (x, 0) == XSTR (y, 0);
- else if (code == SCRATCH || code == CONST_DOUBLE)
- return 0;
-
- /* Compare the elements. If any pair of corresponding elements
- fail to match, return 0 for the whole things. */
-
- fmt = GET_RTX_FORMAT (code);
- for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
- {
- switch (fmt[i])
- {
- case 'w':
- if (XWINT (x, i) != XWINT (y, i))
- return 0;
- break;
-
- case 'n':
- case 'i':
- if (XINT (x, i) != XINT (y, i))
- return 0;
- break;
-
- case 'V':
- case 'E':
- /* Two vectors must have the same length. */
- if (XVECLEN (x, i) != XVECLEN (y, i))
- return 0;
-
- /* And the corresponding elements must match. */
- for (j = 0; j < XVECLEN (x, i); j++)
- if (rtx_equal_p (XVECEXP (x, i, j), XVECEXP (y, i, j)) == 0)
- return 0;
- break;
-
- case 'e':
- if (rtx_equal_p (XEXP (x, i), XEXP (y, i)) == 0)
- return 0;
- break;
-
- case 'S':
- case 's':
- if (strcmp (XSTR (x, i), XSTR (y, i)))
- return 0;
- break;
-
- case 'u':
- /* These are just backpointers, so they don't matter. */
- break;
-
- case '0':
- case 't':
- break;
-
- /* It is believed that rtx's at this level will never
- contain anything but integers and other rtx's,
- except for within LABEL_REFs and SYMBOL_REFs. */
- default:
- abort ();
- }
- }
- return 1;
-}
-\f
/* Call FUN on each register or MEM that is stored into or clobbered by X.
(X would be the pattern of an insn).
FUN receives two arguments:
void
note_stores (x, fun, data)
register rtx x;
- void (*fun) PROTO ((rtx, rtx, void *));
+ void (*fun) PARAMS ((rtx, rtx, void *));
void *data;
{
- if ((GET_CODE (x) == SET || GET_CODE (x) == CLOBBER))
+ if (GET_CODE (x) == COND_EXEC)
+ x = COND_EXEC_CODE (x);
+ if (GET_CODE (x) == SET || GET_CODE (x) == CLOBBER)
{
register rtx dest = SET_DEST (x);
while ((GET_CODE (dest) == SUBREG
for (i = XVECLEN (x, 0) - 1; i >= 0; i--)
{
register rtx y = XVECEXP (x, 0, i);
+ if (GET_CODE (y) == COND_EXEC)
+ y = COND_EXEC_CODE (y);
if (GET_CODE (y) == SET || GET_CODE (y) == CLOBBER)
{
register rtx dest = SET_DEST (y);
&& GET_MODE (dest) == BLKmode)
{
register int i;
+
for (i = XVECLEN (dest, 0) - 1; i >= 0; i--)
(*fun) (SET_DEST (XVECEXP (dest, 0, i)), y, data);
}
rtx insn;
rtx x;
{
- register int regno, last_regno;
- register int i;
+ unsigned int regno, last_regno;
+ unsigned int i;
/* Can't use cc0_rtx below since this file is used by genattrtab.c. */
if (GET_CODE (x) == CC0)
int
dead_or_set_regno_p (insn, test_regno)
rtx insn;
- int test_regno;
+ unsigned int test_regno;
{
- int regno, endregno;
- rtx link;
+ unsigned int regno, endregno;
+ rtx link, pattern;
/* See if there is a death note for something that includes
TEST_REGNO. */
&& find_regno_fusage (insn, CLOBBER, test_regno))
return 1;
- if (GET_CODE (PATTERN (insn)) == SET)
+ pattern = PATTERN (insn);
+
+ if (GET_CODE (pattern) == COND_EXEC)
+ pattern = COND_EXEC_CODE (pattern);
+
+ if (GET_CODE (pattern) == SET)
{
rtx dest = SET_DEST (PATTERN (insn));
return (test_regno >= regno && test_regno < endregno);
}
- else if (GET_CODE (PATTERN (insn)) == PARALLEL)
+ else if (GET_CODE (pattern) == PARALLEL)
{
register int i;
- for (i = XVECLEN (PATTERN (insn), 0) - 1; i >= 0; i--)
+ for (i = XVECLEN (pattern, 0) - 1; i >= 0; i--)
{
- rtx body = XVECEXP (PATTERN (insn), 0, i);
+ rtx body = XVECEXP (pattern, 0, i);
+
+ if (GET_CODE (body) == COND_EXEC)
+ body = COND_EXEC_CODE (body);
if (GET_CODE (body) == SET || GET_CODE (body) == CLOBBER)
{
find_regno_note (insn, kind, regno)
rtx insn;
enum reg_note kind;
- int regno;
+ unsigned int regno;
{
register rtx link;
}
else
{
- register int regno = REGNO (datum);
+ unsigned int regno = REGNO (datum);
/* CALL_INSN_FUNCTION_USAGE information cannot contain references
to pseudo registers, so don't bother checking. */
if (regno < FIRST_PSEUDO_REGISTER)
{
- int end_regno = regno + HARD_REGNO_NREGS (regno, GET_MODE (datum));
- int i;
+ unsigned int end_regno
+ = regno + HARD_REGNO_NREGS (regno, GET_MODE (datum));
+ unsigned int i;
for (i = regno; i < end_regno; i++)
if (find_regno_fusage (insn, code, i))
find_regno_fusage (insn, code, regno)
rtx insn;
enum rtx_code code;
- int regno;
+ unsigned int regno;
{
register rtx link;
for (link = CALL_INSN_FUNCTION_USAGE (insn); link; link = XEXP (link, 1))
{
- register int regnote;
- register rtx op, reg;
+ unsigned int regnote;
+ rtx op, reg;
if (GET_CODE (op = XEXP (link, 0)) == code
&& GET_CODE (reg = XEXP (op, 0)) == REG
if (volatile_insn_p (XEXP (x, i)))
return 1;
}
- if (fmt[i] == 'E')
+ else if (fmt[i] == 'E')
{
register int j;
for (j = 0; j < XVECLEN (x, i); j++)
if (volatile_refs_p (XEXP (x, i)))
return 1;
}
- if (fmt[i] == 'E')
+ else if (fmt[i] == 'E')
{
register int j;
for (j = 0; j < XVECLEN (x, i); j++)
if (side_effects_p (XEXP (x, i)))
return 1;
}
- if (fmt[i] == 'E')
+ else if (fmt[i] == 'E')
{
register int j;
for (j = 0; j < XVECLEN (x, i); j++)
replace_regs (x, reg_map, nregs, replace_dest)
rtx x;
rtx *reg_map;
- int nregs;
+ unsigned int nregs;
int replace_dest;
{
register enum rtx_code code;
{
if (fmt[i] == 'e')
XEXP (x, i) = replace_regs (XEXP (x, i), reg_map, nregs, replace_dest);
- if (fmt[i] == 'E')
+ else if (fmt[i] == 'E')
{
register int j;
for (j = 0; j < XVECLEN (x, i); j++)
&& jmp_uses_reg_or_mem (XEXP (x, i)))
return 1;
- if (fmt[i] == 'E')
+ else if (fmt[i] == 'E')
for (j = 0; j < XVECLEN (x, i); j++)
if (jmp_uses_reg_or_mem (XVECEXP (x, i, j)))
return 1;
rtx
regno_use_in (regno, x)
- int regno;
+ unsigned int regno;
rtx x;
{
register const char *fmt;