return found_barrier;
}
+/* If the instruction INSN is implemented by a special function, and we can
+ positively find the register that is used to call the sfunc, and this
+ register is not used anywhere else in this instruction - except as the
+ destination of a set, return this register; else, return 0. */
+static rtx
+sfunc_uses_reg (insn)
+ rtx insn;
+{
+ int i;
+ rtx pattern, part, reg_part, reg;
+
+ if (GET_CODE (insn) != INSN)
+ return 0;
+ pattern = PATTERN (insn);
+ if (GET_CODE (pattern) != PARALLEL || get_attr_type (insn) != TYPE_SFUNC)
+ return 0;
+
+ for (reg_part = 0, i = XVECLEN (pattern, 0) - 1; i >= 1; i--)
+ {
+ part = XVECEXP (pattern, 0, i);
+ if (GET_CODE (part) == USE)
+ reg_part = part;
+ }
+ if (! reg_part)
+ return 0;
+ reg = XEXP (reg_part, 0);
+ for (i = XVECLEN (pattern, 0) - 1; i >= 0; i--)
+ {
+ part = XVECEXP (pattern, 0, i);
+ if (part == reg_part)
+ continue;
+ if (reg_mentioned_p (reg, ((GET_CODE (part) == SET
+ && GET_CODE (SET_DEST (part)) == REG)
+ ? SET_SRC (part) : part)))
+ return 0;
+ }
+ return reg;
+}
+
/* See if the only way in which INSN uses REG is by calling it, or by
setting it while calling it. Set *SET to a SET rtx if the register
is set by INSN. */
rtx insn;
rtx *set;
{
- rtx pattern;
+ rtx pattern, reg2;
*set = NULL_RTX;
+ reg2 = sfunc_uses_reg (insn);
+ if (reg2 && REGNO (reg2) == REGNO (reg))
+ {
+ pattern = single_set (insn);
+ if (pattern
+ && GET_CODE (SET_DEST (pattern)) == REG
+ && REGNO (reg) == REGNO (SET_DEST (pattern)))
+ *set = pattern;
+ return 0;
+ }
if (GET_CODE (insn) != CALL_INSN)
{
/* We don't use rtx_equal_p because we don't care if the mode is
&& GET_CODE (SET_DEST (pattern)) == REG
&& REGNO (reg) == REGNO (SET_DEST (pattern)))
{
+ rtx par, part;
+ int i;
+
*set = pattern;
- return 0;
+ par = PATTERN (insn);
+ if (GET_CODE (par) == PARALLEL)
+ for (i = XVECLEN (par, 0) - 1; i >= 0; i--)
+ {
+ part = XVECEXP (par, 0, i);
+ if (GET_CODE (part) != SET && reg_mentioned_p (reg, part))
+ return 1;
+ }
+ return reg_mentioned_p (reg, SET_SRC (pattern));
}
return 1;
rtx pattern, reg, link, set, scan, dies, label;
int rescan = 0, foundinsn = 0;
- if (GET_CODE (insn) != CALL_INSN)
- continue;
+ if (GET_CODE (insn) == CALL_INSN)
+ {
+ pattern = PATTERN (insn);
- pattern = PATTERN (insn);
+ if (GET_CODE (pattern) == PARALLEL)
+ pattern = XVECEXP (pattern, 0, 0);
+ if (GET_CODE (pattern) == SET)
+ pattern = SET_SRC (pattern);
- if (GET_CODE (pattern) == PARALLEL)
- pattern = XVECEXP (pattern, 0, 0);
- if (GET_CODE (pattern) == SET)
- pattern = SET_SRC (pattern);
+ if (GET_CODE (pattern) != CALL
+ || GET_CODE (XEXP (pattern, 0)) != MEM)
+ continue;
- if (GET_CODE (pattern) != CALL
- || GET_CODE (XEXP (pattern, 0)) != MEM)
- continue;
+ reg = XEXP (XEXP (pattern, 0), 0);
+ }
+ else
+ {
+ reg = sfunc_uses_reg (insn);
+ if (! reg)
+ continue;
+ }
- reg = XEXP (XEXP (pattern, 0), 0);
if (GET_CODE (reg) != REG)
continue;
if (scan == insn)
foundinsn = 1;
- if (scan != insn && GET_CODE (scan) == CALL_INSN)
+ if (scan != insn
+ && (GET_CODE (scan) == CALL_INSN || sfunc_uses_reg (scan)))
{
/* There is a function call to this register other
than the one we are checking. If we optimize
scan = link;
do
{
+ rtx reg2;
+
scan = NEXT_INSN (scan);
if (scan != insn
- && GET_CODE (scan) == CALL_INSN
- && reg_mentioned_p (reg, scan))
+ && ((GET_CODE (scan) == CALL_INSN
+ && reg_mentioned_p (reg, scan))
+ || ((reg2 = sfunc_uses_reg (scan))
+ && REGNO (reg2) == REGNO (reg))))
REG_NOTES (scan) = gen_rtx (EXPR_LIST, REG_LABEL,
label, REG_NOTES (scan));
}
pattern = XVECEXP (pattern, 0, 0);
if (GET_CODE (pattern) == CALL
|| (GET_CODE (pattern) == SET
- && GET_CODE (SET_SRC (pattern)) == CALL))
+ && (GET_CODE (SET_SRC (pattern)) == CALL
+ || get_attr_type (insn) == TYPE_SFUNC)))
fprintf (asm_out_file, "\t.uses L%d\n",
CODE_LABEL_NUMBER (XEXP (note, 0)));
else if (GET_CODE (pattern) == SET)