Commit 9fc37b2b by Richard Sandiford Committed by Richard Sandiford

rtl.def (ADDRESS): Turn operand into a HOST_WIDE_INT.

gcc/
	* rtl.def (ADDRESS): Turn operand into a HOST_WIDE_INT.
	* alias.c (reg_base_value): Expand and update comment.
	(arg_base_value): New variable.
	(unique_id): Move up file.
	(unique_base_value, unique_base_value_p, known_base_value_p): New.
	(find_base_value): Use arg_base_value and known_base_value_p.
	(record_set): Document REG_NOALIAS handling.  Use unique_base_value.
	(find_base_term): Use known_base_value_p.
	(base_alias_check): Use unique_base_value_p.
	(init_alias_target): Initialize arg_base_value.  Use unique_base_value.
	(init_alias_analysis): Use 1 as the first id for REG_NOALIAS bases.

From-SVN: r186540
parent ac9ce934
2012-04-17 Richard Sandiford <rdsandiford@googlemail.com>
* rtl.def (ADDRESS): Turn operand into a HOST_WIDE_INT.
* alias.c (reg_base_value): Expand and update comment.
(arg_base_value): New variable.
(unique_id): Move up file.
(unique_base_value, unique_base_value_p, known_base_value_p): New.
(find_base_value): Use arg_base_value and known_base_value_p.
(record_set): Document REG_NOALIAS handling. Use unique_base_value.
(find_base_term): Use known_base_value_p.
(base_alias_check): Use unique_base_value_p.
(init_alias_target): Initialize arg_base_value. Use unique_base_value.
(init_alias_analysis): Use 1 as the first id for REG_NOALIAS bases.
2012-04-17 Pat Haugen <pthaugen@us.ibm.com> 2012-04-17 Pat Haugen <pthaugen@us.ibm.com>
* config/rs6000/rs6000.h (SLOW_UNALIGNED_ACCESS): Remove DImode. * config/rs6000/rs6000.h (SLOW_UNALIGNED_ACCESS): Remove DImode.
......
...@@ -187,21 +187,42 @@ static void memory_modified_1 (rtx, const_rtx, void *); ...@@ -187,21 +187,42 @@ static void memory_modified_1 (rtx, const_rtx, void *);
of the first set. of the first set.
A base address can be an ADDRESS, SYMBOL_REF, or LABEL_REF. ADDRESS A base address can be an ADDRESS, SYMBOL_REF, or LABEL_REF. ADDRESS
expressions represent certain special values: function arguments and expressions represent three types of base:
the stack, frame, and argument pointers.
The contents of an ADDRESS is not normally used, the mode of the 1. incoming arguments. There is just one ADDRESS to represent all
ADDRESS determines whether the ADDRESS is a function argument or some arguments, since we do not know at this level whether accesses
other special value. Pointer equality, not rtx_equal_p, determines whether based on different arguments can alias. The ADDRESS has id 0.
two ADDRESS expressions refer to the same base address.
The only use of the contents of an ADDRESS is for determining if the 2. stack_pointer_rtx, frame_pointer_rtx, hard_frame_pointer_rtx
current function performs nonlocal memory memory references for the (if distinct from frame_pointer_rtx) and arg_pointer_rtx.
purposes of marking the function as a constant function. */ Each of these rtxes has a separate ADDRESS associated with it,
each with a negative id.
GCC is (and is required to be) precise in which register it
chooses to access a particular region of stack. We can therefore
assume that accesses based on one of these rtxes do not alias
accesses based on another of these rtxes.
3. bases that are derived from malloc()ed memory (REG_NOALIAS).
Each such piece of memory has a separate ADDRESS associated
with it, each with an id greater than 0.
Accesses based on one ADDRESS do not alias accesses based on other
ADDRESSes. Accesses based on ADDRESSes in groups (2) and (3) do not
alias globals either; the ADDRESSes have Pmode to indicate this.
The ADDRESS in group (1) _may_ alias globals; it has VOIDmode to
indicate this. */
static GTY(()) VEC(rtx,gc) *reg_base_value; static GTY(()) VEC(rtx,gc) *reg_base_value;
static rtx *new_reg_base_value; static rtx *new_reg_base_value;
/* The single VOIDmode ADDRESS that represents all argument bases.
It has id 0. */
static GTY(()) rtx arg_base_value;
/* Used to allocate unique ids to each REG_NOALIAS ADDRESS. */
static int unique_id;
/* We preserve the copy of old array around to avoid amount of garbage /* We preserve the copy of old array around to avoid amount of garbage
produced. About 8% of garbage produced were attributed to this produced. About 8% of garbage produced were attributed to this
array. */ array. */
...@@ -993,6 +1014,43 @@ get_frame_alias_set (void) ...@@ -993,6 +1014,43 @@ get_frame_alias_set (void)
return frame_set; return frame_set;
} }
/* Create a new, unique base with id ID. */
static rtx
unique_base_value (HOST_WIDE_INT id)
{
return gen_rtx_ADDRESS (Pmode, id);
}
/* Return true if accesses based on any other base value cannot alias
those based on X. */
static bool
unique_base_value_p (rtx x)
{
return GET_CODE (x) == ADDRESS && GET_MODE (x) == Pmode;
}
/* Return true if X is known to be a base value. */
static bool
known_base_value_p (rtx x)
{
switch (GET_CODE (x))
{
case LABEL_REF:
case SYMBOL_REF:
return true;
case ADDRESS:
/* Arguments may or may not be bases; we don't know for sure. */
return GET_MODE (x) != VOIDmode;
default:
return false;
}
}
/* Inside SRC, the source of a SET, find a base address. */ /* Inside SRC, the source of a SET, find a base address. */
static rtx static rtx
...@@ -1049,7 +1107,7 @@ find_base_value (rtx src) ...@@ -1049,7 +1107,7 @@ find_base_value (rtx src)
&& (XEXP (src, 0) == arg_pointer_rtx && (XEXP (src, 0) == arg_pointer_rtx
|| (GET_CODE (XEXP (src, 0)) == PLUS || (GET_CODE (XEXP (src, 0)) == PLUS
&& XEXP (XEXP (src, 0), 0) == arg_pointer_rtx))) && XEXP (XEXP (src, 0), 0) == arg_pointer_rtx)))
return gen_rtx_ADDRESS (VOIDmode, src); return arg_base_value;
return 0; return 0;
case CONST: case CONST:
...@@ -1090,18 +1148,10 @@ find_base_value (rtx src) ...@@ -1090,18 +1148,10 @@ find_base_value (rtx src)
/* If either base is named object or a special address /* If either base is named object or a special address
(like an argument or stack reference), then use it for the (like an argument or stack reference), then use it for the
base term. */ base term. */
if (src_0 != 0 if (src_0 != 0 && known_base_value_p (src_0))
&& (GET_CODE (src_0) == SYMBOL_REF
|| GET_CODE (src_0) == LABEL_REF
|| (GET_CODE (src_0) == ADDRESS
&& GET_MODE (src_0) != VOIDmode)))
return src_0; return src_0;
if (src_1 != 0 if (src_1 != 0 && known_base_value_p (src_1))
&& (GET_CODE (src_1) == SYMBOL_REF
|| GET_CODE (src_1) == LABEL_REF
|| (GET_CODE (src_1) == ADDRESS
&& GET_MODE (src_1) != VOIDmode)))
return src_1; return src_1;
/* Guess which operand is the base address: /* Guess which operand is the base address:
...@@ -1169,16 +1219,14 @@ find_base_value (rtx src) ...@@ -1169,16 +1219,14 @@ find_base_value (rtx src)
return 0; return 0;
} }
/* Called from init_alias_analysis indirectly through note_stores. */ /* Called from init_alias_analysis indirectly through note_stores,
or directly if DEST is a register with a REG_NOALIAS note attached.
SET is null in the latter case. */
/* While scanning insns to find base values, reg_seen[N] is nonzero if /* While scanning insns to find base values, reg_seen[N] is nonzero if
register N has been set in this function. */ register N has been set in this function. */
static char *reg_seen; static char *reg_seen;
/* Addresses which are known not to alias anything else are identified
by a unique integer. */
static int unique_id;
static void static void
record_set (rtx dest, const_rtx set, void *data ATTRIBUTE_UNUSED) record_set (rtx dest, const_rtx set, void *data ATTRIBUTE_UNUSED)
{ {
...@@ -1223,14 +1271,14 @@ record_set (rtx dest, const_rtx set, void *data ATTRIBUTE_UNUSED) ...@@ -1223,14 +1271,14 @@ record_set (rtx dest, const_rtx set, void *data ATTRIBUTE_UNUSED)
} }
else else
{ {
/* There's a REG_NOALIAS note against DEST. */
if (reg_seen[regno]) if (reg_seen[regno])
{ {
new_reg_base_value[regno] = 0; new_reg_base_value[regno] = 0;
return; return;
} }
reg_seen[regno] = 1; reg_seen[regno] = 1;
new_reg_base_value[regno] = gen_rtx_ADDRESS (Pmode, new_reg_base_value[regno] = unique_base_value (unique_id++);
GEN_INT (unique_id++));
return; return;
} }
...@@ -1666,18 +1714,10 @@ find_base_term (rtx x) ...@@ -1666,18 +1714,10 @@ find_base_term (rtx x)
/* If either base term is named object or a special address /* If either base term is named object or a special address
(like an argument or stack reference), then use it for the (like an argument or stack reference), then use it for the
base term. */ base term. */
if (tmp1 != 0 if (tmp1 != 0 && known_base_value_p (tmp1))
&& (GET_CODE (tmp1) == SYMBOL_REF
|| GET_CODE (tmp1) == LABEL_REF
|| (GET_CODE (tmp1) == ADDRESS
&& GET_MODE (tmp1) != VOIDmode)))
return tmp1; return tmp1;
if (tmp2 != 0 if (tmp2 != 0 && known_base_value_p (tmp2))
&& (GET_CODE (tmp2) == SYMBOL_REF
|| GET_CODE (tmp2) == LABEL_REF
|| (GET_CODE (tmp2) == ADDRESS
&& GET_MODE (tmp2) != VOIDmode)))
return tmp2; return tmp2;
/* We could not determine which of the two operands was the /* We could not determine which of the two operands was the
...@@ -1762,12 +1802,7 @@ base_alias_check (rtx x, rtx y, enum machine_mode x_mode, ...@@ -1762,12 +1802,7 @@ base_alias_check (rtx x, rtx y, enum machine_mode x_mode,
if (GET_CODE (x_base) != ADDRESS && GET_CODE (y_base) != ADDRESS) if (GET_CODE (x_base) != ADDRESS && GET_CODE (y_base) != ADDRESS)
return 0; return 0;
/* If one address is a stack reference there can be no alias: if (unique_base_value_p (x_base) || unique_base_value_p (y_base))
stack references using different base registers do not alias,
a stack reference can not alias a parameter, and a stack reference
can not alias a global. */
if ((GET_CODE (x_base) == ADDRESS && GET_MODE (x_base) == Pmode)
|| (GET_CODE (y_base) == ADDRESS && GET_MODE (y_base) == Pmode))
return 0; return 0;
return 1; return 1;
...@@ -2686,6 +2721,9 @@ init_alias_target (void) ...@@ -2686,6 +2721,9 @@ init_alias_target (void)
{ {
int i; int i;
if (!arg_base_value)
arg_base_value = gen_rtx_ADDRESS (VOIDmode, 0);
memset (static_reg_base_value, 0, sizeof static_reg_base_value); memset (static_reg_base_value, 0, sizeof static_reg_base_value);
for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
...@@ -2694,18 +2732,13 @@ init_alias_target (void) ...@@ -2694,18 +2732,13 @@ init_alias_target (void)
numbers, so translate if necessary due to register windows. */ numbers, so translate if necessary due to register windows. */
if (FUNCTION_ARG_REGNO_P (OUTGOING_REGNO (i)) if (FUNCTION_ARG_REGNO_P (OUTGOING_REGNO (i))
&& HARD_REGNO_MODE_OK (i, Pmode)) && HARD_REGNO_MODE_OK (i, Pmode))
static_reg_base_value[i] static_reg_base_value[i] = arg_base_value;
= gen_rtx_ADDRESS (VOIDmode, gen_rtx_REG (Pmode, i));
static_reg_base_value[STACK_POINTER_REGNUM] = unique_base_value (-1);
static_reg_base_value[STACK_POINTER_REGNUM] static_reg_base_value[ARG_POINTER_REGNUM] = unique_base_value (-2);
= gen_rtx_ADDRESS (Pmode, stack_pointer_rtx); static_reg_base_value[FRAME_POINTER_REGNUM] = unique_base_value (-3);
static_reg_base_value[ARG_POINTER_REGNUM]
= gen_rtx_ADDRESS (Pmode, arg_pointer_rtx);
static_reg_base_value[FRAME_POINTER_REGNUM]
= gen_rtx_ADDRESS (Pmode, frame_pointer_rtx);
#if !HARD_FRAME_POINTER_IS_FRAME_POINTER #if !HARD_FRAME_POINTER_IS_FRAME_POINTER
static_reg_base_value[HARD_FRAME_POINTER_REGNUM] static_reg_base_value[HARD_FRAME_POINTER_REGNUM] = unique_base_value (-4);
= gen_rtx_ADDRESS (Pmode, hard_frame_pointer_rtx);
#endif #endif
} }
...@@ -2791,8 +2824,8 @@ init_alias_analysis (void) ...@@ -2791,8 +2824,8 @@ init_alias_analysis (void)
changed = 0; changed = 0;
/* We want to assign the same IDs each iteration of this loop, so /* We want to assign the same IDs each iteration of this loop, so
start counting from zero each iteration of the loop. */ start counting from one each iteration of the loop. */
unique_id = 0; unique_id = 1;
/* We're at the start of the function each iteration through the /* We're at the start of the function each iteration through the
loop, so we're copying arguments. */ loop, so we're copying arguments. */
......
...@@ -109,8 +109,8 @@ DEF_RTL_EXPR(INSN_LIST, "insn_list", "ue", RTX_EXTRA) ...@@ -109,8 +109,8 @@ DEF_RTL_EXPR(INSN_LIST, "insn_list", "ue", RTX_EXTRA)
`emit_insn' takes the SEQUENCE apart and makes separate insns. */ `emit_insn' takes the SEQUENCE apart and makes separate insns. */
DEF_RTL_EXPR(SEQUENCE, "sequence", "E", RTX_EXTRA) DEF_RTL_EXPR(SEQUENCE, "sequence", "E", RTX_EXTRA)
/* Refers to the address of its argument. This is only used in alias.c. */ /* Represents a non-global base address. This is only used in alias.c. */
DEF_RTL_EXPR(ADDRESS, "address", "e", RTX_MATCH) DEF_RTL_EXPR(ADDRESS, "address", "w", RTX_EXTRA)
/* ---------------------------------------------------------------------- /* ----------------------------------------------------------------------
Expression types used for things in the instruction chain. Expression types used for things in the instruction chain.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment