-/* This is used by find_single_use to locate an rtx that contains exactly one
- use of DEST, which is typically either a REG or CC0. It returns a
- pointer to the innermost rtx expression containing DEST. Appearances of
- DEST that are being used to totally replace it are not counted. */
-
-static rtx *
-find_single_use_1 (rtx dest, rtx *loc)
-{
- rtx x = *loc;
- enum rtx_code code = GET_CODE (x);
- rtx *result = 0;
- rtx *this_result;
- int i;
- const char *fmt;
-
- switch (code)
- {
- case CONST_INT:
- case CONST:
- case LABEL_REF:
- case SYMBOL_REF:
- case CONST_DOUBLE:
- case CONST_VECTOR:
- case CLOBBER:
- return 0;
-
- case SET:
- /* If the destination is anything other than CC0, PC, a REG or a SUBREG
- of a REG that occupies all of the REG, the insn uses DEST if
- it is mentioned in the destination or the source. Otherwise, we
- need just check the source. */
- if (GET_CODE (SET_DEST (x)) != CC0
- && GET_CODE (SET_DEST (x)) != PC
- && !REG_P (SET_DEST (x))
- && ! (GET_CODE (SET_DEST (x)) == SUBREG
- && REG_P (SUBREG_REG (SET_DEST (x)))
- && (((GET_MODE_SIZE (GET_MODE (SUBREG_REG (SET_DEST (x))))
- + (UNITS_PER_WORD - 1)) / UNITS_PER_WORD)
- == ((GET_MODE_SIZE (GET_MODE (SET_DEST (x)))
- + (UNITS_PER_WORD - 1)) / UNITS_PER_WORD))))
- break;
-
- return find_single_use_1 (dest, &SET_SRC (x));
-
- case MEM:
- case SUBREG:
- return find_single_use_1 (dest, &XEXP (x, 0));
-
- default:
- break;
- }
-
- /* If it wasn't one of the common cases above, check each expression and
- vector of this code. Look for a unique usage of DEST. */
-
- fmt = GET_RTX_FORMAT (code);
- for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
- {
- if (fmt[i] == 'e')
- {
- if (dest == XEXP (x, i)
- || (REG_P (dest) && REG_P (XEXP (x, i))
- && REGNO (dest) == REGNO (XEXP (x, i))))
- this_result = loc;
- else
- this_result = find_single_use_1 (dest, &XEXP (x, i));
-
- if (result == 0)
- result = this_result;
- else if (this_result)
- /* Duplicate usage. */
- return 0;
- }
- else if (fmt[i] == 'E')
- {
- int j;
-
- for (j = XVECLEN (x, i) - 1; j >= 0; j--)
- {
- if (XVECEXP (x, i, j) == dest
- || (REG_P (dest)
- && REG_P (XVECEXP (x, i, j))
- && REGNO (XVECEXP (x, i, j)) == REGNO (dest)))
- this_result = loc;
- else
- this_result = find_single_use_1 (dest, &XVECEXP (x, i, j));
-
- if (result == 0)
- result = this_result;
- else if (this_result)
- return 0;
- }
- }
- }
-
- return result;
-}
-\f
-/* See if DEST, produced in INSN, is used only a single time in the
- sequel. If so, return a pointer to the innermost rtx expression in which
- it is used.
-
- If PLOC is nonzero, *PLOC is set to the insn containing the single use.
-
- This routine will return usually zero either before flow is called (because
- there will be no LOG_LINKS notes) or after reload (because the REG_DEAD
- note can't be trusted).
-
- If DEST is cc0_rtx, we look only at the next insn. In that case, we don't
- care about REG_DEAD notes or LOG_LINKS.
-
- Otherwise, we find the single use by finding an insn that has a
- LOG_LINKS pointing at INSN and has a REG_DEAD note for DEST. If DEST is
- only referenced once in that insn, we know that it must be the first
- and last insn referencing DEST. */
-
-rtx *
-find_single_use (rtx dest, rtx insn, rtx *ploc)
-{
- rtx next;
- rtx *result;
- rtx link;
-
-#ifdef HAVE_cc0
- if (dest == cc0_rtx)
- {
- next = NEXT_INSN (insn);
- if (next == 0
- || (!NONJUMP_INSN_P (next) && !JUMP_P (next)))
- return 0;
-
- result = find_single_use_1 (dest, &PATTERN (next));
- if (result && ploc)
- *ploc = next;
- return result;
- }
-#endif
-
- if (reload_completed || reload_in_progress || !REG_P (dest))
- return 0;
-
- for (next = next_nonnote_insn (insn);
- next != 0 && !LABEL_P (next);
- next = next_nonnote_insn (next))
- if (INSN_P (next) && dead_or_set_p (next, dest))
- {
- for (link = LOG_LINKS (next); link; link = XEXP (link, 1))
- if (XEXP (link, 0) == insn)
- break;
-
- if (link)
- {
- result = find_single_use_1 (dest, &PATTERN (next));
- if (ploc)
- *ploc = next;
- return result;
- }
- }
-
- return 0;
-}
-\f