mirror of git://gcc.gnu.org/git/gcc.git
integrate.c (try_constants, [...]): Remove.
* integrate.c (try_constants, subst_constants, mark_stores): Remove. * integrate.h: Remove the prototype for try_constants. From-SVN: r88787
This commit is contained in:
parent
6dcc04b060
commit
2a9772e3f8
|
|
@ -1,3 +1,9 @@
|
|||
2004-10-08 Kazu Hirata <kazu@cs.umass.edu>
|
||||
|
||||
* integrate.c (try_constants, subst_constants, mark_stores):
|
||||
Remove.
|
||||
* integrate.h: Remove the prototype for try_constants.
|
||||
|
||||
2004-10-08 Joseph S. Myers <jsm@polyomino.org.uk>
|
||||
|
||||
* c-typeck.c (enum impl_conv): Add ic_argpass_nonproto.
|
||||
|
|
|
|||
439
gcc/integrate.c
439
gcc/integrate.c
|
|
@ -61,10 +61,8 @@ typedef struct initial_value_struct GTY(()) {
|
|||
initial_value_pair * GTY ((length ("%h.num_entries"))) entries;
|
||||
} initial_value_struct;
|
||||
|
||||
static void subst_constants (rtx *, rtx, struct inline_remap *, int);
|
||||
static void set_block_origin_self (tree);
|
||||
static void set_block_abstract_flags (tree, int);
|
||||
static void mark_stores (rtx, rtx, void *);
|
||||
|
||||
/* Returns the Ith entry in the label_map contained in MAP. If the
|
||||
Ith entry has not yet been set, return a fresh label. This function
|
||||
|
|
@ -583,443 +581,6 @@ copy_rtx_and_substitute (rtx orig, struct inline_remap *map, int for_lhs)
|
|||
return copy;
|
||||
}
|
||||
|
||||
/* Substitute known constant values into INSN, if that is valid. */
|
||||
|
||||
void
|
||||
try_constants (rtx insn, struct inline_remap *map)
|
||||
{
|
||||
int i;
|
||||
|
||||
map->num_sets = 0;
|
||||
|
||||
/* First try just updating addresses, then other things. This is
|
||||
important when we have something like the store of a constant
|
||||
into memory and we can update the memory address but the machine
|
||||
does not support a constant source. */
|
||||
subst_constants (&PATTERN (insn), insn, map, 1);
|
||||
apply_change_group ();
|
||||
subst_constants (&PATTERN (insn), insn, map, 0);
|
||||
apply_change_group ();
|
||||
|
||||
/* Enforce consistency between the addresses in the regular insn flow
|
||||
and the ones in CALL_INSN_FUNCTION_USAGE lists, if any. */
|
||||
if (CALL_P (insn) && CALL_INSN_FUNCTION_USAGE (insn))
|
||||
{
|
||||
subst_constants (&CALL_INSN_FUNCTION_USAGE (insn), insn, map, 1);
|
||||
apply_change_group ();
|
||||
}
|
||||
|
||||
/* Show we don't know the value of anything stored or clobbered. */
|
||||
note_stores (PATTERN (insn), mark_stores, NULL);
|
||||
map->last_pc_value = 0;
|
||||
#ifdef HAVE_cc0
|
||||
map->last_cc0_value = 0;
|
||||
#endif
|
||||
|
||||
/* Set up any constant equivalences made in this insn. */
|
||||
for (i = 0; i < map->num_sets; i++)
|
||||
{
|
||||
if (REG_P (map->equiv_sets[i].dest))
|
||||
{
|
||||
int regno = REGNO (map->equiv_sets[i].dest);
|
||||
|
||||
MAYBE_EXTEND_CONST_EQUIV_VARRAY (map, regno);
|
||||
if (VARRAY_CONST_EQUIV (map->const_equiv_varray, regno).rtx == 0
|
||||
/* Following clause is a hack to make case work where GNU C++
|
||||
reassigns a variable to make cse work right. */
|
||||
|| ! rtx_equal_p (VARRAY_CONST_EQUIV (map->const_equiv_varray,
|
||||
regno).rtx,
|
||||
map->equiv_sets[i].equiv))
|
||||
SET_CONST_EQUIV_DATA (map, map->equiv_sets[i].dest,
|
||||
map->equiv_sets[i].equiv, map->const_age);
|
||||
}
|
||||
else if (map->equiv_sets[i].dest == pc_rtx)
|
||||
map->last_pc_value = map->equiv_sets[i].equiv;
|
||||
#ifdef HAVE_cc0
|
||||
else if (map->equiv_sets[i].dest == cc0_rtx)
|
||||
map->last_cc0_value = map->equiv_sets[i].equiv;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/* Substitute known constants for pseudo regs in the contents of LOC,
|
||||
which are part of INSN.
|
||||
If INSN is zero, the substitution should always be done (this is used to
|
||||
update DECL_RTL).
|
||||
These changes are taken out by try_constants if the result is not valid.
|
||||
|
||||
Note that we are more concerned with determining when the result of a SET
|
||||
is a constant, for further propagation, than actually inserting constants
|
||||
into insns; cse will do the latter task better.
|
||||
|
||||
This function is also used to adjust address of items previously addressed
|
||||
via the virtual stack variable or virtual incoming arguments registers.
|
||||
|
||||
If MEMONLY is nonzero, only make changes inside a MEM. */
|
||||
|
||||
static void
|
||||
subst_constants (rtx *loc, rtx insn, struct inline_remap *map, int memonly)
|
||||
{
|
||||
rtx x = *loc;
|
||||
int i, j;
|
||||
enum rtx_code code;
|
||||
const char *format_ptr;
|
||||
int num_changes = num_validated_changes ();
|
||||
rtx new = 0;
|
||||
enum machine_mode op0_mode = MAX_MACHINE_MODE;
|
||||
|
||||
code = GET_CODE (x);
|
||||
|
||||
switch (code)
|
||||
{
|
||||
case PC:
|
||||
case CONST_INT:
|
||||
case CONST_DOUBLE:
|
||||
case CONST_VECTOR:
|
||||
case SYMBOL_REF:
|
||||
case CONST:
|
||||
case LABEL_REF:
|
||||
case ADDRESS:
|
||||
return;
|
||||
|
||||
#ifdef HAVE_cc0
|
||||
case CC0:
|
||||
if (! memonly)
|
||||
validate_change (insn, loc, map->last_cc0_value, 1);
|
||||
return;
|
||||
#endif
|
||||
|
||||
case USE:
|
||||
case CLOBBER:
|
||||
/* The only thing we can do with a USE or CLOBBER is possibly do
|
||||
some substitutions in a MEM within it. */
|
||||
if (MEM_P (XEXP (x, 0)))
|
||||
subst_constants (&XEXP (XEXP (x, 0), 0), insn, map, 0);
|
||||
return;
|
||||
|
||||
case REG:
|
||||
/* Substitute for parms and known constants. Don't replace
|
||||
hard regs used as user variables with constants. */
|
||||
if (! memonly)
|
||||
{
|
||||
int regno = REGNO (x);
|
||||
struct const_equiv_data *p;
|
||||
|
||||
if (! (regno < FIRST_PSEUDO_REGISTER && REG_USERVAR_P (x))
|
||||
&& (size_t) regno < VARRAY_SIZE (map->const_equiv_varray)
|
||||
&& (p = &VARRAY_CONST_EQUIV (map->const_equiv_varray, regno),
|
||||
p->rtx != 0)
|
||||
&& p->age >= map->const_age)
|
||||
validate_change (insn, loc, p->rtx, 1);
|
||||
}
|
||||
return;
|
||||
|
||||
case SUBREG:
|
||||
/* SUBREG applied to something other than a reg
|
||||
should be treated as ordinary, since that must
|
||||
be a special hack and we don't know how to treat it specially.
|
||||
Consider for example mulsidi3 in m68k.md.
|
||||
Ordinary SUBREG of a REG needs this special treatment. */
|
||||
if (! memonly && REG_P (SUBREG_REG (x)))
|
||||
{
|
||||
rtx inner = SUBREG_REG (x);
|
||||
rtx new = 0;
|
||||
|
||||
/* We can't call subst_constants on &SUBREG_REG (x) because any
|
||||
constant or SUBREG wouldn't be valid inside our SUBEG. Instead,
|
||||
see what is inside, try to form the new SUBREG and see if that is
|
||||
valid. We handle two cases: extracting a full word in an
|
||||
integral mode and extracting the low part. */
|
||||
subst_constants (&inner, NULL_RTX, map, 0);
|
||||
new = simplify_gen_subreg (GET_MODE (x), inner,
|
||||
GET_MODE (SUBREG_REG (x)),
|
||||
SUBREG_BYTE (x));
|
||||
|
||||
if (new)
|
||||
validate_change (insn, loc, new, 1);
|
||||
else
|
||||
cancel_changes (num_changes);
|
||||
|
||||
return;
|
||||
}
|
||||
break;
|
||||
|
||||
case MEM:
|
||||
subst_constants (&XEXP (x, 0), insn, map, 0);
|
||||
|
||||
/* If a memory address got spoiled, change it back. */
|
||||
if (! memonly && insn != 0 && num_validated_changes () != num_changes
|
||||
&& ! memory_address_p (GET_MODE (x), XEXP (x, 0)))
|
||||
cancel_changes (num_changes);
|
||||
return;
|
||||
|
||||
case SET:
|
||||
{
|
||||
/* Substitute constants in our source, and in any arguments to a
|
||||
complex (e..g, ZERO_EXTRACT) destination, but not in the destination
|
||||
itself. */
|
||||
rtx *dest_loc = &SET_DEST (x);
|
||||
rtx dest = *dest_loc;
|
||||
rtx src, tem;
|
||||
enum machine_mode compare_mode = VOIDmode;
|
||||
|
||||
/* If SET_SRC is a COMPARE which subst_constants would turn into
|
||||
COMPARE of 2 VOIDmode constants, note the mode in which comparison
|
||||
is to be done. */
|
||||
if (GET_CODE (SET_SRC (x)) == COMPARE)
|
||||
{
|
||||
src = SET_SRC (x);
|
||||
if (GET_MODE_CLASS (GET_MODE (src)) == MODE_CC
|
||||
|| CC0_P (dest))
|
||||
{
|
||||
compare_mode = GET_MODE (XEXP (src, 0));
|
||||
if (compare_mode == VOIDmode)
|
||||
compare_mode = GET_MODE (XEXP (src, 1));
|
||||
}
|
||||
}
|
||||
|
||||
subst_constants (&SET_SRC (x), insn, map, memonly);
|
||||
src = SET_SRC (x);
|
||||
|
||||
while (GET_CODE (*dest_loc) == ZERO_EXTRACT
|
||||
|| GET_CODE (*dest_loc) == SUBREG
|
||||
|| GET_CODE (*dest_loc) == STRICT_LOW_PART)
|
||||
{
|
||||
if (GET_CODE (*dest_loc) == ZERO_EXTRACT)
|
||||
{
|
||||
subst_constants (&XEXP (*dest_loc, 1), insn, map, memonly);
|
||||
subst_constants (&XEXP (*dest_loc, 2), insn, map, memonly);
|
||||
}
|
||||
dest_loc = &XEXP (*dest_loc, 0);
|
||||
}
|
||||
|
||||
/* Do substitute in the address of a destination in memory. */
|
||||
if (MEM_P (*dest_loc))
|
||||
subst_constants (&XEXP (*dest_loc, 0), insn, map, 0);
|
||||
|
||||
/* Check for the case of DEST a SUBREG, both it and the underlying
|
||||
register are less than one word, and the SUBREG has the wider mode.
|
||||
In the case, we are really setting the underlying register to the
|
||||
source converted to the mode of DEST. So indicate that. */
|
||||
if (GET_CODE (dest) == SUBREG
|
||||
&& GET_MODE_SIZE (GET_MODE (dest)) <= UNITS_PER_WORD
|
||||
&& GET_MODE_SIZE (GET_MODE (SUBREG_REG (dest))) <= UNITS_PER_WORD
|
||||
&& (GET_MODE_SIZE (GET_MODE (SUBREG_REG (dest)))
|
||||
<= GET_MODE_SIZE (GET_MODE (dest)))
|
||||
&& (tem = gen_lowpart_if_possible (GET_MODE (SUBREG_REG (dest)),
|
||||
src)))
|
||||
src = tem, dest = SUBREG_REG (dest);
|
||||
|
||||
/* If storing a recognizable value save it for later recording. */
|
||||
if ((map->num_sets < MAX_RECOG_OPERANDS)
|
||||
&& (CONSTANT_P (src)
|
||||
|| (REG_P (src)
|
||||
&& (REGNO (src) == VIRTUAL_INCOMING_ARGS_REGNUM
|
||||
|| REGNO (src) == VIRTUAL_STACK_VARS_REGNUM))
|
||||
|| (GET_CODE (src) == PLUS
|
||||
&& REG_P (XEXP (src, 0))
|
||||
&& (REGNO (XEXP (src, 0)) == VIRTUAL_INCOMING_ARGS_REGNUM
|
||||
|| REGNO (XEXP (src, 0)) == VIRTUAL_STACK_VARS_REGNUM)
|
||||
&& CONSTANT_P (XEXP (src, 1)))
|
||||
|| GET_CODE (src) == COMPARE
|
||||
|| CC0_P (dest)
|
||||
|| (dest == pc_rtx
|
||||
&& (src == pc_rtx || GET_CODE (src) == RETURN
|
||||
|| GET_CODE (src) == LABEL_REF))))
|
||||
{
|
||||
/* Normally, this copy won't do anything. But, if SRC is a COMPARE
|
||||
it will cause us to save the COMPARE with any constants
|
||||
substituted, which is what we want for later. */
|
||||
rtx src_copy = copy_rtx (src);
|
||||
map->equiv_sets[map->num_sets].equiv = src_copy;
|
||||
map->equiv_sets[map->num_sets++].dest = dest;
|
||||
if (compare_mode != VOIDmode
|
||||
&& GET_CODE (src) == COMPARE
|
||||
&& (GET_MODE_CLASS (GET_MODE (src)) == MODE_CC
|
||||
|| CC0_P (dest))
|
||||
&& GET_MODE (XEXP (src, 0)) == VOIDmode
|
||||
&& GET_MODE (XEXP (src, 1)) == VOIDmode)
|
||||
{
|
||||
map->compare_src = src_copy;
|
||||
map->compare_mode = compare_mode;
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
format_ptr = GET_RTX_FORMAT (code);
|
||||
|
||||
/* If the first operand is an expression, save its mode for later. */
|
||||
if (*format_ptr == 'e')
|
||||
op0_mode = GET_MODE (XEXP (x, 0));
|
||||
|
||||
for (i = 0; i < GET_RTX_LENGTH (code); i++)
|
||||
{
|
||||
switch (*format_ptr++)
|
||||
{
|
||||
case '0':
|
||||
break;
|
||||
|
||||
case 'e':
|
||||
if (XEXP (x, i))
|
||||
subst_constants (&XEXP (x, i), insn, map, memonly);
|
||||
break;
|
||||
|
||||
case 'u':
|
||||
case 'i':
|
||||
case 's':
|
||||
case 'w':
|
||||
case 'n':
|
||||
case 't':
|
||||
case 'B':
|
||||
break;
|
||||
|
||||
case 'E':
|
||||
if (XVEC (x, i) != NULL && XVECLEN (x, i) != 0)
|
||||
for (j = 0; j < XVECLEN (x, i); j++)
|
||||
subst_constants (&XVECEXP (x, i, j), insn, map, memonly);
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
abort ();
|
||||
}
|
||||
}
|
||||
|
||||
/* If this is a commutative operation, move a constant to the second
|
||||
operand unless the second operand is already a CONST_INT. */
|
||||
if (! memonly
|
||||
&& (GET_RTX_CLASS (code) == RTX_COMM_ARITH
|
||||
|| GET_RTX_CLASS (code) == RTX_COMM_COMPARE)
|
||||
&& CONSTANT_P (XEXP (x, 0)) && GET_CODE (XEXP (x, 1)) != CONST_INT)
|
||||
{
|
||||
rtx tem = XEXP (x, 0);
|
||||
validate_change (insn, &XEXP (x, 0), XEXP (x, 1), 1);
|
||||
validate_change (insn, &XEXP (x, 1), tem, 1);
|
||||
}
|
||||
|
||||
/* Simplify the expression in case we put in some constants. */
|
||||
if (! memonly)
|
||||
switch (GET_RTX_CLASS (code))
|
||||
{
|
||||
case RTX_UNARY:
|
||||
if (op0_mode == MAX_MACHINE_MODE)
|
||||
abort ();
|
||||
new = simplify_unary_operation (code, GET_MODE (x),
|
||||
XEXP (x, 0), op0_mode);
|
||||
break;
|
||||
|
||||
case RTX_COMPARE:
|
||||
case RTX_COMM_COMPARE:
|
||||
{
|
||||
enum machine_mode op_mode = GET_MODE (XEXP (x, 0));
|
||||
|
||||
if (op_mode == VOIDmode)
|
||||
op_mode = GET_MODE (XEXP (x, 1));
|
||||
|
||||
new = simplify_relational_operation (code, GET_MODE (x), op_mode,
|
||||
XEXP (x, 0), XEXP (x, 1));
|
||||
break;
|
||||
}
|
||||
|
||||
case RTX_BIN_ARITH:
|
||||
case RTX_COMM_ARITH:
|
||||
new = simplify_binary_operation (code, GET_MODE (x),
|
||||
XEXP (x, 0), XEXP (x, 1));
|
||||
break;
|
||||
|
||||
case RTX_BITFIELD_OPS:
|
||||
case RTX_TERNARY:
|
||||
if (op0_mode == MAX_MACHINE_MODE)
|
||||
abort ();
|
||||
|
||||
if (code == IF_THEN_ELSE)
|
||||
{
|
||||
rtx op0 = XEXP (x, 0);
|
||||
|
||||
if (COMPARISON_P (op0)
|
||||
&& GET_MODE (op0) == VOIDmode
|
||||
&& ! side_effects_p (op0)
|
||||
&& XEXP (op0, 0) == map->compare_src
|
||||
&& GET_MODE (XEXP (op0, 1)) == VOIDmode)
|
||||
{
|
||||
/* We have compare of two VOIDmode constants for which
|
||||
we recorded the comparison mode. */
|
||||
rtx tem =
|
||||
simplify_gen_relational (GET_CODE (op0), GET_MODE (op0),
|
||||
map->compare_mode, XEXP (op0, 0),
|
||||
XEXP (op0, 1));
|
||||
|
||||
if (GET_CODE (tem) != CONST_INT)
|
||||
new = simplify_ternary_operation (code, GET_MODE (x),
|
||||
op0_mode, tem, XEXP (x, 1),
|
||||
XEXP (x, 2));
|
||||
else if (tem == const0_rtx)
|
||||
new = XEXP (x, 2);
|
||||
else
|
||||
new = XEXP (x, 1);
|
||||
}
|
||||
}
|
||||
if (!new)
|
||||
new = simplify_ternary_operation (code, GET_MODE (x), op0_mode,
|
||||
XEXP (x, 0), XEXP (x, 1),
|
||||
XEXP (x, 2));
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (new)
|
||||
validate_change (insn, loc, new, 1);
|
||||
}
|
||||
|
||||
/* Show that register modified no longer contain known constants. We are
|
||||
called from note_stores with parts of the new insn. */
|
||||
|
||||
static void
|
||||
mark_stores (rtx dest, rtx x ATTRIBUTE_UNUSED, void *data ATTRIBUTE_UNUSED)
|
||||
{
|
||||
int regno = -1;
|
||||
enum machine_mode mode = VOIDmode;
|
||||
|
||||
/* DEST is always the innermost thing set, except in the case of
|
||||
SUBREGs of hard registers. */
|
||||
|
||||
if (REG_P (dest))
|
||||
regno = REGNO (dest), mode = GET_MODE (dest);
|
||||
else if (GET_CODE (dest) == SUBREG && REG_P (SUBREG_REG (dest)))
|
||||
{
|
||||
regno = REGNO (SUBREG_REG (dest));
|
||||
if (regno < FIRST_PSEUDO_REGISTER)
|
||||
regno += subreg_regno_offset (REGNO (SUBREG_REG (dest)),
|
||||
GET_MODE (SUBREG_REG (dest)),
|
||||
SUBREG_BYTE (dest),
|
||||
GET_MODE (dest));
|
||||
mode = GET_MODE (SUBREG_REG (dest));
|
||||
}
|
||||
|
||||
if (regno >= 0)
|
||||
{
|
||||
unsigned int uregno = regno;
|
||||
unsigned int last_reg = (uregno >= FIRST_PSEUDO_REGISTER ? uregno
|
||||
: uregno + hard_regno_nregs[uregno][mode] - 1);
|
||||
unsigned int i;
|
||||
|
||||
/* Ignore virtual stack var or virtual arg register since those
|
||||
are handled separately. */
|
||||
if (uregno != VIRTUAL_INCOMING_ARGS_REGNUM
|
||||
&& uregno != VIRTUAL_STACK_VARS_REGNUM)
|
||||
for (i = uregno; i <= last_reg; i++)
|
||||
if ((size_t) i < VARRAY_SIZE (global_const_equiv_varray))
|
||||
VARRAY_CONST_EQUIV (global_const_equiv_varray, i).rtx = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Given a pointer to some BLOCK node, if the BLOCK_ABSTRACT_ORIGIN for the
|
||||
given BLOCK node is NULL, set the BLOCK_ABSTRACT_ORIGIN for the node so
|
||||
that it points to the node itself, thus indicating that the node is its
|
||||
|
|
|
|||
|
|
@ -142,8 +142,6 @@ extern tree copy_decl_for_inlining (tree, tree, tree);
|
|||
true otherwise. */
|
||||
extern bool function_attribute_inlinable_p (tree);
|
||||
|
||||
extern void try_constants (rtx, struct inline_remap *);
|
||||
|
||||
/* Return the label indicated. */
|
||||
extern rtx get_label_from_map (struct inline_remap *, int);
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue