parent
e932039036
commit
5089e22e27
153
gcc/combine.c
153
gcc/combine.c
|
@ -114,7 +114,7 @@ static int combine_successes;
|
|||
static int total_attempts, total_merges, total_extras, total_successes;
|
||||
|
||||
/* Vector mapping INSN_UIDs to cuids.
|
||||
The cuids are like uids but increase monononically always.
|
||||
The cuids are like uids but increase monotonically always.
|
||||
Combine always uses cuids so that it can compare them.
|
||||
But actually renumbering the uids, which we used to do,
|
||||
proves to be a bad idea because it makes it hard to compare
|
||||
|
@ -174,7 +174,7 @@ static int previous_num_undos;
|
|||
|
||||
/* The next group of arrays allows the recording of the last value assigned
|
||||
to (hard or pseudo) register n. We use this information to see if a
|
||||
operation being processed is redundant given the a prior operation peformed
|
||||
operation being processed is redundant given a prior operation performed
|
||||
on the register. For example, an `and' with a constant is redundant if
|
||||
all the zero bits are already known to be turned off.
|
||||
|
||||
|
@ -517,7 +517,7 @@ combine_instructions (f, nregs)
|
|||
|
||||
/* Finally, see if any of the insns that this insn links to
|
||||
explicitly references CC0. If so, try this insn, that insn,
|
||||
and its prececessor if it sets CC0. */
|
||||
and its predecessor if it sets CC0. */
|
||||
for (links = LOG_LINKS (insn); links; links = XEXP (links, 1))
|
||||
if (GET_CODE (XEXP (links, 0)) == INSN
|
||||
&& GET_CODE (PATTERN (XEXP (links, 0))) == SET
|
||||
|
@ -576,7 +576,7 @@ set_significant (x, set)
|
|||
return;
|
||||
|
||||
/* If this is a complex assignment, see if we can convert it into a
|
||||
simple assignent. */
|
||||
simple assignment. */
|
||||
set = expand_field_assignment (set);
|
||||
if (SET_DEST (set) == x)
|
||||
reg_significant[REGNO (x)]
|
||||
|
@ -682,9 +682,16 @@ can_combine_p (insn, i3, pred, succ, pdest, psrc)
|
|||
It can worsen register allocation, and can even make invalid reload
|
||||
insns, since the reg inside may need to be copied from in the
|
||||
outside mode, and that may be invalid if it is an fp reg copied in
|
||||
integer mode. */
|
||||
integer mode. As a special exception, we can allow this if
|
||||
I3 is simply copying DEST, a REG, to CC0. */
|
||||
|| (GET_CODE (src) == SUBREG
|
||||
&& ! MODES_TIEABLE_P (GET_MODE (src), GET_MODE (SUBREG_REG (src))))
|
||||
&& ! MODES_TIEABLE_P (GET_MODE (src), GET_MODE (SUBREG_REG (src)))
|
||||
#ifdef HAVE_cc0
|
||||
&& ! (GET_CODE (i3) == INSN && GET_CODE (PATTERN (i3)) == SET
|
||||
&& SET_DEST (PATTERN (i3)) == cc0_rtx
|
||||
&& GET_CODE (dest) == REG && dest == SET_SRC (PATTERN (i3)))
|
||||
#endif
|
||||
)
|
||||
/* If we couldn't eliminate a field assignment, we can't combine. */
|
||||
|| GET_CODE (dest) == ZERO_EXTRACT || GET_CODE (dest) == STRICT_LOW_PART
|
||||
/* Don't combine with an insn that sets a register to itself if it has
|
||||
|
@ -1031,29 +1038,56 @@ try_combine (i3, i2, i1)
|
|||
&& find_reg_note (i3, REG_DEAD, SET_SRC (PATTERN (i3)))
|
||||
&& GET_CODE (PATTERN (i2)) == PARALLEL
|
||||
&& ! side_effects_p (SET_DEST (PATTERN (i3)))
|
||||
/* If the dest of I3 is a ZERO_EXTRACT or STRICT_LOW_PART, the code
|
||||
below would need to check what is inside (and reg_overlap_mentioned_p
|
||||
doesn't support those codes anyway). Don't allow those destinations;
|
||||
the resulting insn isn't likely to be recognized anyway. */
|
||||
&& GET_CODE (SET_DEST (PATTERN (i3))) != ZERO_EXTRACT
|
||||
&& GET_CODE (SET_DEST (PATTERN (i3))) != STRICT_LOW_PART
|
||||
&& ! reg_overlap_mentioned_p (SET_SRC (PATTERN (i3)),
|
||||
SET_DEST (PATTERN (i3)))
|
||||
&& next_real_insn (i2) == i3)
|
||||
for (i = 0; i < XVECLEN (PATTERN (i2), 0); i++)
|
||||
if (SET_DEST (XVECEXP (PATTERN (i2), 0, i)) == SET_SRC (PATTERN (i3)))
|
||||
{
|
||||
combine_merges++;
|
||||
{
|
||||
rtx p2 = PATTERN (i2);
|
||||
|
||||
subst_insn = i3;
|
||||
subst_low_cuid = INSN_CUID (i2);
|
||||
/* Make sure that the destination of I3,
|
||||
which we are going to substitute into one output of I2,
|
||||
is not used within another output of I2. We must avoid making this:
|
||||
(parallel [(set (mem (reg 69)) ...)
|
||||
(set (reg 69) ...)])
|
||||
which is not well-defined as to order of actions.
|
||||
(Besides, reload can't handle output reloads for this.)
|
||||
|
||||
added_sets_2 = 0;
|
||||
i2dest = SET_SRC (PATTERN (i3));
|
||||
The problem can also happen if the dest of I3 is a memory ref,
|
||||
if another dest in I2 is an indirect memory ref. */
|
||||
for (i = 0; i < XVECLEN (p2, 0); i++)
|
||||
if (GET_CODE (XVECEXP (p2, 0, i)) == SET
|
||||
&& reg_overlap_mentioned_p (SET_DEST (PATTERN (i3)),
|
||||
SET_DEST (XVECEXP (p2, 0, i))))
|
||||
break;
|
||||
|
||||
/* Replace the dest in I2 with our dest and make the resulting
|
||||
insn the new pattern for I3. Then skip to where we
|
||||
validate the pattern. Everything was set up above. */
|
||||
SUBST (SET_DEST (XVECEXP (PATTERN (i2), 0, i)),
|
||||
SET_DEST (PATTERN (i3)));
|
||||
if (i == XVECLEN (p2, 0))
|
||||
for (i = 0; i < XVECLEN (p2, 0); i++)
|
||||
if (SET_DEST (XVECEXP (p2, 0, i)) == SET_SRC (PATTERN (i3)))
|
||||
{
|
||||
combine_merges++;
|
||||
|
||||
newpat = PATTERN (i2);
|
||||
goto validate_replacement;
|
||||
}
|
||||
subst_insn = i3;
|
||||
subst_low_cuid = INSN_CUID (i2);
|
||||
|
||||
added_sets_2 = 0;
|
||||
i2dest = SET_SRC (PATTERN (i3));
|
||||
|
||||
/* Replace the dest in I2 with our dest and make the resulting
|
||||
insn the new pattern for I3. Then skip to where we
|
||||
validate the pattern. Everything was set up above. */
|
||||
SUBST (SET_DEST (XVECEXP (p2, 0, i)),
|
||||
SET_DEST (PATTERN (i3)));
|
||||
|
||||
newpat = p2;
|
||||
goto validate_replacement;
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef HAVE_cc0
|
||||
/* If we have no I1 and I2 looks like:
|
||||
|
@ -1134,7 +1168,7 @@ try_combine (i3, i2, i1)
|
|||
output operand. However, that exception can give rise to insns like
|
||||
mov r3,(r3)+
|
||||
which is a famous insn on the PDP-11 where the value of r3 used as the
|
||||
source was model-dependant. Avoid this sort of thing. */
|
||||
source was model-dependent. Avoid this sort of thing. */
|
||||
|
||||
#if 0
|
||||
if (!(GET_CODE (PATTERN (i3)) == SET
|
||||
|
@ -1175,7 +1209,7 @@ try_combine (i3, i2, i1)
|
|||
|
||||
/* If the set in I2 needs to be kept around, we must make a copy of
|
||||
PATTERN (I2), so that when we substitute I1SRC for I1DEST in
|
||||
PATTERN (I2), we are only substituing for the original I1DEST, not into
|
||||
PATTERN (I2), we are only substituting for the original I1DEST, not into
|
||||
an already-substituted copy. This also prevents making self-referential
|
||||
rtx. If I2 is a PARALLEL, we just need the piece that assigns I2SRC to
|
||||
I2DEST. */
|
||||
|
@ -1517,6 +1551,50 @@ try_combine (i3, i2, i1)
|
|||
i2_code_number = recog_for_combine (&newi2pat, i2, &new_i2_notes);
|
||||
if (i2_code_number >= 0)
|
||||
insn_code_number = recog_for_combine (&newpat, i3, &new_i3_notes);
|
||||
|
||||
if (insn_code_number >= 0)
|
||||
{
|
||||
rtx insn;
|
||||
rtx link;
|
||||
|
||||
/* If we will be able to accept this, we have made a change to the
|
||||
destination of I3. This can invalidate a LOG_LINKS pointing
|
||||
to I3. No other part of combine.c makes such a transformation.
|
||||
|
||||
The new I3 will have a destination that was previously the
|
||||
destination of I1 or I2 and which was used in i2 or I3. Call
|
||||
distribute_links to make a LOG_LINK from the next use of
|
||||
that destination. */
|
||||
|
||||
PATTERN (i3) = newpat;
|
||||
distribute_links (gen_rtx (INSN_LIST, VOIDmode, i3, 0));
|
||||
|
||||
/* I3 now uses what used to be its destination and which is
|
||||
now I2's destination. That means we need a LOG_LINK from
|
||||
I3 to I2. But we used to have one, so we still will.
|
||||
|
||||
However, some later insn might be using I2's dest and have
|
||||
a LOG_LINK pointing at I3. We must remove this link.
|
||||
The simplest way to remove the link is to point it at I1,
|
||||
which we know will be a NOTE. */
|
||||
|
||||
for (insn = NEXT_INSN (i3);
|
||||
insn && GET_CODE (insn) != CODE_LABEL
|
||||
&& GET_CODE (PREV_INSN (insn)) != JUMP_INSN;
|
||||
insn = NEXT_INSN (insn))
|
||||
{
|
||||
if (GET_RTX_CLASS (GET_CODE (insn)) == 'i'
|
||||
&& reg_referenced_p (SET_DEST (newi2pat), PATTERN (insn)))
|
||||
{
|
||||
for (link = LOG_LINKS (insn); link;
|
||||
link = XEXP (link, 1))
|
||||
if (XEXP (link, 0) == i3)
|
||||
XEXP (link, 0) = i1;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Similarly, check for a case where we have a PARALLEL of two independent
|
||||
|
@ -1620,7 +1698,7 @@ try_combine (i3, i2, i1)
|
|||
|
||||
/* Ensure that we do not have something that should not be shared but
|
||||
occurs multiple times in the new insns. Check this by first
|
||||
restting all the `used' flags and then copying anything is shared. */
|
||||
resetting all the `used' flags and then copying anything is shared. */
|
||||
|
||||
reset_used_flags (i3notes);
|
||||
reset_used_flags (i2notes);
|
||||
|
@ -2082,7 +2160,7 @@ find_split_point (loc)
|
|||
|
||||
IN_DEST is non-zero if we are processing the SET_DEST of a SET.
|
||||
|
||||
UNIQUE_COPY is non-zero if each substition must be unique. We do this
|
||||
UNIQUE_COPY is non-zero if each substitution must be unique. We do this
|
||||
by copying if `n_occurrences' is non-zero. */
|
||||
|
||||
static rtx
|
||||
|
@ -4435,7 +4513,8 @@ make_field_assignment (x)
|
|||
/* Shift OTHER right POS places and make it the source, restricting it
|
||||
to the proper length and mode. */
|
||||
|
||||
src = force_to_mode (simplify_shift_const (0, LSHIFTRT, mode, other, pos),
|
||||
src = force_to_mode (simplify_shift_const (0, LSHIFTRT, GET_MODE (src),
|
||||
other, pos),
|
||||
mode, len, dest);
|
||||
|
||||
return gen_rtx_combine (SET, VOIDmode, assign, src);
|
||||
|
@ -6253,7 +6332,7 @@ gen_unary (code, mode, op0)
|
|||
|
||||
It is possible that we might detect that a comparison is either always
|
||||
true or always false. However, we do not perform general constant
|
||||
folding in combine, so this knowlege isn't useful. Such tautologies
|
||||
folding in combine, so this knowledge isn't useful. Such tautologies
|
||||
should have been detected earlier. Hence we ignore all such cases. */
|
||||
|
||||
static enum rtx_code
|
||||
|
@ -6685,7 +6764,7 @@ simplify_comparison (code, pop0, pop1)
|
|||
|
||||
case PLUS:
|
||||
/* (eq (plus X C1) C2) -> (eq X (minus C2 C1)). We can only do
|
||||
this for equality comparisons due to pathalogical cases involving
|
||||
this for equality comparisons due to pathological cases involving
|
||||
overflows. */
|
||||
if (equality_comparison_p && GET_CODE (XEXP (op0, 1)) == CONST_INT
|
||||
&& (tem = simplify_binary_operation (MINUS, mode, op1,
|
||||
|
@ -7576,9 +7655,9 @@ reg_bitfield_target_p (reg, body)
|
|||
|
||||
if (GET_CODE (body) == SET)
|
||||
return ((GET_CODE (SET_DEST (body)) == ZERO_EXTRACT
|
||||
&& reg == XEXP (SET_DEST (body), 0))
|
||||
&& rtx_equal_p (reg, XEXP (SET_DEST (body), 0)))
|
||||
|| (GET_CODE (SET_DEST (body)) == STRICT_LOW_PART
|
||||
&& reg == SUBREG_REG (XEXP (SET_DEST (body), 0))));
|
||||
&& rtx_equal_p (reg, SUBREG_REG (XEXP (SET_DEST (body), 0)))));
|
||||
|
||||
else if (GET_CODE (body) == PARALLEL)
|
||||
for (i = XVECLEN (body, 0) - 1; i >= 0; i--)
|
||||
|
@ -7742,7 +7821,11 @@ distribute_notes (notes, from_insn, i3, i2, elim_i2, elim_i1)
|
|||
{
|
||||
rtx set = single_set (tem);
|
||||
|
||||
if (set != 0 && ! side_effects_p (SET_SRC (set)))
|
||||
/* Verify that it was the set, and not a clobber that
|
||||
modified the register. */
|
||||
|
||||
if (set != 0 && ! side_effects_p (SET_SRC (set))
|
||||
&& rtx_equal_p (XEXP (note, 0), SET_DEST (set)))
|
||||
{
|
||||
/* Move the notes and links of TEM elsewhere.
|
||||
This might delete other dead insns recursively.
|
||||
|
@ -7830,6 +7913,7 @@ distribute_notes (notes, from_insn, i3, i2, elim_i2, elim_i1)
|
|||
= emit_insn_before (gen_rtx (USE, VOIDmode, piece),
|
||||
place);
|
||||
|
||||
all_used = 0;
|
||||
REG_NOTES (use_insn)
|
||||
= gen_rtx (EXPR_LIST, REG_DEAD, piece,
|
||||
REG_NOTES (use_insn));
|
||||
|
@ -7878,7 +7962,8 @@ distribute_notes (notes, from_insn, i3, i2, elim_i2, elim_i1)
|
|||
}
|
||||
|
||||
/* Similarly to above, distribute the LOG_LINKS that used to be present on
|
||||
I3, I2, and I1 to new locations. */
|
||||
I3, I2, and I1 to new locations. This is also called in one case to
|
||||
add a link pointing at I3 when I3's destination is changed. */
|
||||
|
||||
static void
|
||||
distribute_links (links)
|
||||
|
@ -7921,7 +8006,7 @@ distribute_links (links)
|
|||
when we reach a set of the register or the end of the basic block.
|
||||
|
||||
Note that this correctly handles the link that used to point from
|
||||
I3 to I2. Also note that not much seaching is typically done here
|
||||
I3 to I2. Also note that not much searching is typically done here
|
||||
since most links don't point very far away. */
|
||||
|
||||
for (insn = NEXT_INSN (XEXP (link, 0));
|
||||
|
|
|
@ -43,7 +43,7 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
|
|||
/* -m68881 is the default */
|
||||
#define CPP_SPEC \
|
||||
"%{!msoft-float:%{mfpa:-D__HAVE_FPA__ }%{!mfpa:-D__HAVE_68881__ }}\
|
||||
%{m68000:-D__mc68010__}%{mc68000:-D__mc68010__}%{!mc68000:%{!m68000:-D__mc68020__}}} \
|
||||
%{m68000:-D__mc68010__}%{mc68000:-D__mc68010__}%{!mc68000:%{!m68000:-D__mc68020__}} \
|
||||
%{!ansi:%{m68000:-Dmc68010}%{mc68000:-Dmc68010}%{!mc68000:%{!m68000:-Dmc68020}}}"
|
||||
|
||||
#else
|
||||
|
@ -51,7 +51,7 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
|
|||
/* -msoft-float is the default */
|
||||
#define CPP_SPEC \
|
||||
"%{m68881:-D__HAVE_68881__ }%{mfpa:-D__HAVE_FPA__ }\
|
||||
%{m68000:-D__mc68010__}%{mc68000:-D__mc68010__}%{!mc68000:%{!m68000:-D__mc68020__}}} \
|
||||
%{m68000:-D__mc68010__}%{mc68000:-D__mc68010__}%{!mc68000:%{!m68000:-D__mc68020__}} \
|
||||
%{!ansi:%{m68000:-Dmc68010}%{mc68000:-Dmc68010}%{!mc68000:%{!m68000:-Dmc68020}}}"
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Reference in New Issue