aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Kenner <kenner@gcc.gnu.org>1992-04-11 20:30:30 -0400
committerRichard Kenner <kenner@gcc.gnu.org>1992-04-11 20:30:30 -0400
commit916f14f12b114faba1d7fe94076bae5ff6be1d71 (patch)
tree7e9c98b040d0c7134cb36d3d6bcee3a2f058f091
parentaf929c62a22d6efb5da698ccae85d566416a44f0 (diff)
downloadgcc-916f14f12b114faba1d7fe94076bae5ff6be1d71.zip
gcc-916f14f12b114faba1d7fe94076bae5ff6be1d71.tar.gz
gcc-916f14f12b114faba1d7fe94076bae5ff6be1d71.tar.bz2
*** empty log message ***
From-SVN: r727
-rw-r--r--gcc/caller-save.c2
-rw-r--r--gcc/combine.c101
2 files changed, 93 insertions, 10 deletions
diff --git a/gcc/caller-save.c b/gcc/caller-save.c
index 6e16711..dfca1e7 100644
--- a/gcc/caller-save.c
+++ b/gcc/caller-save.c
@@ -472,7 +472,7 @@ restore_referenced_regs (x, insn, insn_mode)
insn, insn_mode);
else if (regno >= FIRST_PSEUDO_REGISTER
&& reg_equiv_address[regno] != 0)
- restore_referenced_regs (XEXP (reg_equiv_address[regno], 0),
+ restore_referenced_regs (reg_equiv_address[regno],
insn, insn_mode);
/* Otherwise if this is a hard register, restore any piece of it that
diff --git a/gcc/combine.c b/gcc/combine.c
index 3878846..bee3287 100644
--- a/gcc/combine.c
+++ b/gcc/combine.c
@@ -1150,7 +1150,7 @@ try_combine (i3, i2, i1)
i1dest_in_i1src = i1 && reg_overlap_mentioned_p (i1dest, i1src);
i2dest_in_i1src = i1 && reg_overlap_mentioned_p (i2dest, i1src);
- /* See if I1 directly feeds into I3. It does if I1dest is not used
+ /* See if I1 directly feeds into I3. It does if I1DEST is not used
in I2SRC. */
i1_feeds_i3 = i1 && ! reg_overlap_mentioned_p (i1dest, i2src);
@@ -1352,9 +1352,13 @@ try_combine (i3, i2, i1)
previous_num_undos = undobuf.num_undo;
}
- /* Fail if an autoincrement side-effect has been duplicated. */
- if ((i2_is_used > 1 && FIND_REG_INC_NOTE (i2, 0) != 0)
- || (i1 != 0 && n_occurrences > 1 && FIND_REG_INC_NOTE (i1, 0) != 0)
+ /* Fail if an autoincrement side-effect has been duplicated. Be careful
+ to count all the ways that I2SRC and I1SRC can be used. */
+ if ((FIND_REG_INC_NOTE (i2, 0) != 0
+ && i2_is_used + added_sets_2 > 1)
+ || (i1 != 0 && FIND_REG_INC_NOTE (i1, 0) != 0
+ && (n_occurrences + added_sets_1 + (added_sets_2 && ! i1_feeds_i3)
+ > 1))
/* Fail if we tried to make a new register (we used to abort, but there's
really no reason to). */
|| max_reg_num () != maxreg
@@ -1453,16 +1457,41 @@ try_combine (i3, i2, i1)
/* If we were combining three insns and the result is a simple SET
with no ASM_OPERANDS that wasn't recognized, try to split it into two
- insns. */
+ insns. There are two ways to do this. It can be split using a
+ machine-specific method (like when you have an addition of a large
+ constant) or by combine in the function find_split_point. */
+
if (i1 && insn_code_number < 0 && GET_CODE (newpat) == SET
&& asm_noperands (newpat) < 0)
{
- rtx *split = find_split_point (&newpat);
+ rtx m_split, *split;
+
+ /* See if the MD file can split NEWPAT. If it can't, see if letting it
+ use I2DEST as a scratch register will help. */
+
+ m_split = split_insns (newpat, i3);
+ if (m_split == 0)
+ m_split = split_insns (gen_rtx (PARALLEL, VOIDmode,
+ gen_rtvec (2, newpat,
+ gen_rtx (CLOBBER, VOIDmode,
+ i2dest))),
+ i3);
+
+ if (m_split && GET_CODE (m_split) == SEQUENCE
+ && XVECLEN (m_split, 0) == 2)
+ {
+ newi2pat = PATTERN (XVECEXP (m_split, 0, 0));
+ newpat = PATTERN (XVECEXP (m_split, 0, 1));
+
+ 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 we can split it and use I2DEST, go ahead and see if that
helps things be recognized. Verify that none of the registers
are set between I2 and I3. */
- if (split
+ else if ((split = find_split_point (&newpat)) != 0
#ifdef HAVE_cc0
&& GET_CODE (i2dest) == REG
#endif
@@ -1909,8 +1938,8 @@ find_split_point (loc)
#endif
return find_split_point (&SUBREG_REG (x));
-#ifdef HAVE_lo_sum
case MEM:
+#ifdef HAVE_lo_sum
/* If we have (mem (const ..)) or (mem (symbol_ref ...)), split it
using LO_SUM and HIGH. */
if (GET_CODE (XEXP (x, 0)) == CONST
@@ -1922,9 +1951,63 @@ find_split_point (loc)
XEXP (x, 0)));
return &XEXP (XEXP (x, 0), 0);
}
- break;
#endif
+ /* If we have a PLUS whose second operand is a constant and the
+ address is not valid, perhaps will can split it up using
+ the machine-specific way to split large constants. We use
+ the first psuedo-reg (one of the virtual regs) as a placeholder;
+ it will not remain in the result. */
+ if (GET_CODE (XEXP (x, 0)) == PLUS
+ && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT
+ && ! memory_address_p (GET_MODE (x), XEXP (x, 0)))
+ {
+ rtx reg = regno_reg_rtx[FIRST_PSEUDO_REGISTER];
+ rtx seq = split_insns (gen_rtx (SET, VOIDmode, reg, XEXP (x, 0)),
+ subst_insn);
+
+ /* This should have produced two insns, each of which sets our
+ placeholder. If the source of the second is a valid address,
+ we can make put both sources together and make a split point
+ in the middle. */
+
+ if (seq && XVECLEN (seq, 0) == 2
+ && GET_CODE (XVECEXP (seq, 0, 0)) == INSN
+ && GET_CODE (PATTERN (XVECEXP (seq, 0, 0))) == SET
+ && SET_DEST (PATTERN (XVECEXP (seq, 0, 0))) == reg
+ && ! reg_mentioned_p (reg,
+ SET_SRC (PATTERN (XVECEXP (seq, 0, 0))))
+ && GET_CODE (XVECEXP (seq, 0, 1)) == INSN
+ && GET_CODE (PATTERN (XVECEXP (seq, 0, 1))) == SET
+ && SET_DEST (PATTERN (XVECEXP (seq, 0, 1))) == reg
+ && memory_address_p (GET_MODE (x),
+ SET_SRC (PATTERN (XVECEXP (seq, 0, 1)))))
+ {
+ rtx src1 = SET_SRC (PATTERN (XVECEXP (seq, 0, 0)));
+ rtx src2 = SET_SRC (PATTERN (XVECEXP (seq, 0, 1)));
+
+ /* Replace the placeholder in SRC2 with SRC1. If we can
+ find where in SRC2 it was placed, that can become our
+ split point and we can replace this address with SRC2.
+ Just try two obvious places. */
+
+ src2 = replace_rtx (src2, reg, src1);
+ split = 0;
+ if (XEXP (src2, 0) == src1)
+ split = &XEXP (src2, 0);
+ else if (GET_RTX_FORMAT (GET_CODE (XEXP (src2, 0)))[0] == 'e'
+ && XEXP (XEXP (src2, 0), 0) == src1)
+ split = &XEXP (XEXP (src2, 0), 0);
+
+ if (split)
+ {
+ SUBST (XEXP (x, 0), src2);
+ return split;
+ }
+ }
+ }
+ break;
+
case SET:
#ifdef HAVE_cc0
/* If SET_DEST is CC0 and SET_SRC is not an operand, a COMPARE, or a