+ /* 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;
+