cse.c (set_nonvarying_address_components): New function.

* cse.c (set_nonvarying_address_components): New function.
	(invalidate): Use set_nonvarying_address_components instead of
	computing them.
	(refers_to_mem_p): Likewise.  Simplify checks for conflicting
	memory accesses.  Make static.

From-SVN: r3703
This commit is contained in:
Jeff Law 1993-03-11 05:46:36 -07:00
parent 6f9c49e07d
commit f451db8990
1 changed files with 86 additions and 108 deletions

194
gcc/cse.c
View File

@ -603,8 +603,10 @@ static rtx use_related_value PROTO((rtx, struct table_elt *));
static int canon_hash PROTO((rtx, enum machine_mode));
static int safe_hash PROTO((rtx, enum machine_mode));
static int exp_equiv_p PROTO((rtx, rtx, int, int));
static void set_nonvarying_address_components PROTO((rtx, int, rtx *,
int *, int *));
static int refers_to_p PROTO((rtx, rtx));
int refers_to_mem_p PROTO((rtx, rtx, HOST_WIDE_INT,
static int refers_to_mem_p PROTO((rtx, rtx, HOST_WIDE_INT,
HOST_WIDE_INT));
static int cse_rtx_addr_varies_p PROTO((rtx));
static rtx canon_reg PROTO((rtx, rtx));
@ -1451,8 +1453,8 @@ invalidate (x)
{
register int i;
register struct table_elt *p;
register rtx base;
register HOST_WIDE_INT start, end;
rtx base;
HOST_WIDE_INT start, end;
/* If X is a register, dependencies on its contents
are recorded through the qty number mechanism.
@ -1531,38 +1533,10 @@ invalidate (x)
if (GET_CODE (x) != MEM)
abort ();
base = XEXP (x, 0);
start = 0;
/* Registers with nonvarying addresses usually have constant equivalents;
but the frame pointer register is also possible. */
if (GET_CODE (base) == REG
&& REGNO_QTY_VALID_P (REGNO (base))
&& qty_mode[reg_qty[REGNO (base)]] == GET_MODE (base)
&& qty_const[reg_qty[REGNO (base)]] != 0)
base = qty_const[reg_qty[REGNO (base)]];
else if (GET_CODE (base) == PLUS
&& GET_CODE (XEXP (base, 1)) == CONST_INT
&& GET_CODE (XEXP (base, 0)) == REG
&& REGNO_QTY_VALID_P (REGNO (XEXP (base, 0)))
&& (qty_mode[reg_qty[REGNO (XEXP (base, 0))]]
== GET_MODE (XEXP (base, 0)))
&& qty_const[reg_qty[REGNO (XEXP (base, 0))]])
{
start = INTVAL (XEXP (base, 1));
base = qty_const[reg_qty[REGNO (XEXP (base, 0))]];
}
set_nonvarying_address_components (XEXP (x, 0), GET_MODE_SIZE (GET_MODE (x)),
&base, &start, &end);
if (GET_CODE (base) == CONST)
base = XEXP (base, 0);
if (GET_CODE (base) == PLUS
&& GET_CODE (XEXP (base, 1)) == CONST_INT)
{
start += INTVAL (XEXP (base, 1));
base = XEXP (base, 0);
}
end = start + GET_MODE_SIZE (GET_MODE (x));
for (i = 0; i < NBUCKETS; i++)
{
register struct table_elt *next;
@ -2212,20 +2186,87 @@ refers_to_p (x, y)
return 0;
}
/* Given ADDR and SIZE (a memory address, and the size of the memory reference),
set PBASE, PSTART, and PEND which correspond to the base of the address,
the starting offset, and ending offset respectively.
ADDR is known to be a nonvarying address.
cse_address_varies_p returns zero for nonvarying addresses. */
static void
set_nonvarying_address_components (addr, size, pbase, pstart, pend)
rtx addr;
int size;
rtx *pbase;
int *pstart, *pend;
{
rtx base;
int start, end;
base = addr;
start = 0;
end = 0;
/* Registers with nonvarying addresses usually have constant equivalents;
but the frame pointer register is also possible. */
if (GET_CODE (base) == REG
&& qty_const != 0
&& REGNO_QTY_VALID_P (REGNO (base))
&& qty_mode[reg_qty[REGNO (base)]] == GET_MODE (base)
&& qty_const[reg_qty[REGNO (base)]] != 0)
base = qty_const[reg_qty[REGNO (base)]];
else if (GET_CODE (base) == PLUS
&& GET_CODE (XEXP (base, 1)) == CONST_INT
&& GET_CODE (XEXP (base, 0)) == REG
&& qty_const != 0
&& REGNO_QTY_VALID_P (REGNO (XEXP (base, 0)))
&& (qty_mode[reg_qty[REGNO (XEXP (base, 0))]]
== GET_MODE (XEXP (base, 0)))
&& qty_const[reg_qty[REGNO (XEXP (base, 0))]])
{
start = INTVAL (XEXP (base, 1));
base = qty_const[reg_qty[REGNO (XEXP (base, 0))]];
}
/* By definition, operand1 of a LO_SUM is the associated constant
address. Use the associated constant address as the base instead. */
if (GET_CODE (base) == LO_SUM)
base = XEXP (base, 1);
/* Strip off CONST. */
if (GET_CODE (base) == CONST)
base = XEXP (base, 0);
if (GET_CODE (base) == PLUS
&& GET_CODE (XEXP (base, 1)) == CONST_INT)
{
start += INTVAL (XEXP (base, 1));
base = XEXP (base, 0);
}
end = start + size;
/* Set the return values. */
*pbase = base;
*pstart = start;
*pend = end;
}
/* Return 1 iff any subexpression of X refers to memory
at an address of BASE plus some offset
such that any of the bytes' offsets fall between START (inclusive)
and END (exclusive).
The value is undefined if X is a varying address.
This function is not used in such cases.
The value is undefined if X is a varying address (as determined by
cse_rtx_addr_varies_p). This function is not used in such cases.
When used in the cse pass, `qty_const' is nonzero, and it is used
to treat an address that is a register with a known constant value
as if it were that constant value.
In the loop pass, `qty_const' is zero, so this is not done. */
int
static int
refers_to_mem_p (x, base, start, end)
rtx x, base;
HOST_WIDE_INT start, end;
@ -2249,83 +2290,20 @@ refers_to_mem_p (x, base, start, end)
if (code == MEM)
{
register rtx addr = XEXP (x, 0); /* Get the address. */
int myend;
rtx mybase;
int mystart, myend;
i = 0;
if (GET_CODE (addr) == REG
/* qty_const is 0 when outside the cse pass;
at such times, this info is not available. */
&& qty_const != 0
&& REGNO_QTY_VALID_P (REGNO (addr))
&& GET_MODE (addr) == qty_mode[reg_qty[REGNO (addr)]]
&& qty_const[reg_qty[REGNO (addr)]] != 0)
addr = qty_const[reg_qty[REGNO (addr)]];
else if (GET_CODE (addr) == PLUS
&& GET_CODE (XEXP (addr, 1)) == CONST_INT
&& GET_CODE (XEXP (addr, 0)) == REG
&& qty_const != 0
&& REGNO_QTY_VALID_P (REGNO (XEXP (addr, 0)))
&& (GET_MODE (XEXP (addr, 0))
== qty_mode[reg_qty[REGNO (XEXP (addr, 0))]])
&& qty_const[reg_qty[REGNO (XEXP (addr, 0))]])
{
i = INTVAL (XEXP (addr, 1));
addr = qty_const[reg_qty[REGNO (XEXP (addr, 0))]];
}
set_nonvarying_address_components (addr, GET_MODE_SIZE (GET_MODE (x)),
&mybase, &mystart, &myend);
check_addr:
if (GET_CODE (addr) == CONST)
addr = XEXP (addr, 0);
/* If ADDR is BASE, or BASE plus an integer, put
the integer in I. */
if (GET_CODE (addr) == PLUS
&& XEXP (addr, 0) == base
&& GET_CODE (XEXP (addr, 1)) == CONST_INT)
i += INTVAL (XEXP (addr, 1));
else if (GET_CODE (addr) == LO_SUM)
{
if (GET_CODE (base) != LO_SUM)
return 1;
/* The REG component of the LO_SUM is known by the
const value in the XEXP part. */
addr = XEXP (addr, 1);
base = XEXP (base, 1);
i = 0;
if (GET_CODE (base) == CONST)
base = XEXP (base, 0);
if (GET_CODE (base) == PLUS
&& GET_CODE (XEXP (base, 1)) == CONST_INT)
{
HOST_WIDE_INT tem = INTVAL (XEXP (base, 1));
start += tem;
end += tem;
base = XEXP (base, 0);
}
goto check_addr;
}
else if (GET_CODE (base) == LO_SUM)
{
base = XEXP (base, 1);
if (GET_CODE (base) == CONST)
base = XEXP (base, 0);
if (GET_CODE (base) == PLUS
&& GET_CODE (XEXP (base, 1)) == CONST_INT)
{
HOST_WIDE_INT tem = INTVAL (XEXP (base, 1));
start += tem;
end += tem;
base = XEXP (base, 0);
}
goto check_addr;
}
else if (GET_CODE (addr) == CONST_INT && base == const0_rtx)
i = INTVAL (addr);
else if (addr != base)
/* refers_to_mem_p is never called with varying addresses.
If the base addresses are not equal, there is no chance
of the memory addresses conflicting. */
if (mybase != base)
return 0;
myend = i + GET_MODE_SIZE (GET_MODE (x));
return myend > start && i < end;
return myend > start && mystart < end;
}
/* X does not match, so try its subexpressions. */