+
+ /* Look for a single-word load into an integer register. */
+ else if (sparc_fix_ut699
+ && NONJUMP_INSN_P (insn)
+ && (set = single_set (insn)) != NULL_RTX
+ && GET_MODE_SIZE (GET_MODE (SET_SRC (set))) <= 4
+ && mem_ref (SET_SRC (set)) != NULL_RTX
+ && REG_P (SET_DEST (set))
+ && REGNO (SET_DEST (set)) < 32)
+ {
+ /* There is no problem if the second memory access has a data
+ dependency on the first single-cycle load. */
+ rtx x = SET_DEST (set);
+
+ next = next_active_insn (insn);
+ if (!next)
+ break;
+ /* If the insn is a branch, then it cannot be problematic. */
+ if (!NONJUMP_INSN_P (next) || GET_CODE (PATTERN (next)) == SEQUENCE)
+ continue;
+
+ /* Look for a second memory access to/from an integer register. */
+ if ((set = single_set (next)) != NULL_RTX)
+ {
+ rtx src = SET_SRC (set);
+ rtx dest = SET_DEST (set);
+ rtx mem;
+
+ /* LDD is affected. */
+ if ((mem = mem_ref (src)) != NULL_RTX
+ && REG_P (dest)
+ && REGNO (dest) < 32
+ && !reg_mentioned_p (x, XEXP (mem, 0)))
+ insert_nop = true;
+
+ /* STD is *not* affected. */
+ else if (MEM_P (dest)
+ && GET_MODE_SIZE (GET_MODE (dest)) <= 4
+ && (src == CONST0_RTX (GET_MODE (dest))
+ || (REG_P (src)
+ && REGNO (src) < 32
+ && REGNO (src) != REGNO (x)))
+ && !reg_mentioned_p (x, XEXP (dest, 0)))
+ insert_nop = true;
+ }
+ }
+
+ /* Look for a single-word load/operation into an FP register. */
+ else if (sparc_fix_ut699
+ && NONJUMP_INSN_P (insn)
+ && (set = single_set (insn)) != NULL_RTX
+ && GET_MODE_SIZE (GET_MODE (SET_SRC (set))) == 4
+ && REG_P (SET_DEST (set))
+ && REGNO (SET_DEST (set)) > 31)
+ {
+ /* Number of instructions in the problematic window. */
+ const int n_insns = 4;
+ /* The problematic combination is with the sibling FP register. */
+ const unsigned int x = REGNO (SET_DEST (set));
+ const unsigned int y = x ^ 1;
+ rtx_insn *after;
+ int i;
+
+ next = next_active_insn (insn);
+ if (!next)
+ break;
+ /* If the insn is a branch, then it cannot be problematic. */
+ if (!NONJUMP_INSN_P (next) || GET_CODE (PATTERN (next)) == SEQUENCE)
+ continue;
+
+ /* Look for a second load/operation into the sibling FP register. */
+ if (!((set = single_set (next)) != NULL_RTX
+ && GET_MODE_SIZE (GET_MODE (SET_SRC (set))) == 4
+ && REG_P (SET_DEST (set))
+ && REGNO (SET_DEST (set)) == y))
+ continue;
+
+ /* Look for a (possible) store from the FP register in the next N
+ instructions, but bail out if it is again modified or if there
+ is a store from the sibling FP register before this store. */
+ for (after = next, i = 0; i < n_insns; i++)
+ {
+ bool branch_p;
+
+ after = next_active_insn (after);
+ if (!after)
+ break;
+
+ /* This is a branch with an empty delay slot. */
+ if (!NONJUMP_INSN_P (after))
+ {
+ if (++i == n_insns)
+ break;
+ branch_p = true;
+ after = NULL;
+ }
+ /* This is a branch with a filled delay slot. */
+ else if (rtx_sequence *seq =
+ dyn_cast <rtx_sequence *> (PATTERN (after)))
+ {
+ if (++i == n_insns)
+ break;
+ branch_p = true;
+ after = seq->insn (1);
+ }
+ /* This is a regular instruction. */
+ else
+ branch_p = false;
+
+ if (after && (set = single_set (after)) != NULL_RTX)
+ {
+ const rtx src = SET_SRC (set);
+ const rtx dest = SET_DEST (set);
+ const unsigned int size = GET_MODE_SIZE (GET_MODE (dest));
+
+ /* If the FP register is again modified before the store,
+ then the store isn't affected. */
+ if (REG_P (dest)
+ && (REGNO (dest) == x
+ || (REGNO (dest) == y && size == 8)))
+ break;
+
+ if (MEM_P (dest) && REG_P (src))
+ {
+ /* If there is a store from the sibling FP register
+ before the store, then the store is not affected. */
+ if (REGNO (src) == y || (REGNO (src) == x && size == 8))
+ break;
+
+ /* Otherwise, the store is affected. */
+ if (REGNO (src) == x && size == 4)
+ {
+ insert_nop = true;
+ break;
+ }
+ }
+ }
+
+ /* If we have a branch in the first M instructions, then we
+ cannot see the (M+2)th instruction so we play safe. */
+ if (branch_p && i <= (n_insns - 2))
+ {
+ insert_nop = true;
+ break;
+ }
+ }
+ }
+