+ scan_rtx (insn, &XVECEXP (x, i, j), cl, action, type);
+ }
+}
+
+/* Hide operands of the current insn (of which there are N_OPS) by
+ substituting cc0 for them.
+ Previous values are stored in the OLD_OPERANDS and OLD_DUPS.
+ If INOUT_ONLY is set, we only do this for OP_INOUT type operands. */
+
+static void
+hide_operands (int n_ops, rtx *old_operands, rtx *old_dups,
+ bool inout_only)
+{
+ int i;
+ for (i = 0; i < n_ops; i++)
+ {
+ old_operands[i] = recog_data.operand[i];
+ /* Don't squash match_operator or match_parallel here, since
+ we don't know that all of the contained registers are
+ reachable by proper operands. */
+ if (recog_data.constraints[i][0] == '\0')
+ continue;
+ if (!inout_only || recog_data.operand_type[i] == OP_INOUT)
+ *recog_data.operand_loc[i] = cc0_rtx;
+ }
+ for (i = 0; i < recog_data.n_dups; i++)
+ {
+ int opn = recog_data.dup_num[i];
+ old_dups[i] = *recog_data.dup_loc[i];
+ if (!inout_only || recog_data.operand_type[opn] == OP_INOUT)
+ *recog_data.dup_loc[i] = cc0_rtx;
+ }
+}
+
+/* Undo the substitution performed by hide_operands. INSN is the insn we
+ are processing; the arguments are the same as in hide_operands. */
+
+static void
+restore_operands (rtx insn, int n_ops, rtx *old_operands, rtx *old_dups)
+{
+ int i;
+ for (i = 0; i < recog_data.n_dups; i++)
+ *recog_data.dup_loc[i] = old_dups[i];
+ for (i = 0; i < n_ops; i++)
+ *recog_data.operand_loc[i] = old_operands[i];
+ if (recog_data.n_dups)
+ df_insn_rescan (insn);
+}
+
+/* For each output operand of INSN, call scan_rtx to create a new
+ open chain. */
+
+static void
+record_out_operands (rtx insn)
+{
+ int n_ops = recog_data.n_operands;
+ int alt = which_alternative;
+
+ int i;
+
+ for (i = 0; i < n_ops + recog_data.n_dups; i++)
+ {
+ int opn = i < n_ops ? i : recog_data.dup_num[i - n_ops];
+ rtx *loc = (i < n_ops
+ ? recog_data.operand_loc[opn]
+ : recog_data.dup_loc[i - n_ops]);
+ rtx op = *loc;
+ enum reg_class cl = recog_op_alt[opn][alt].cl;
+
+ struct du_head *prev_open;
+
+ if (recog_data.operand_type[opn] != OP_OUT)
+ continue;
+
+ prev_open = open_chains;
+ scan_rtx (insn, loc, cl, mark_write, OP_OUT);
+
+ /* ??? Many targets have output constraints on the SET_DEST
+ of a call insn, which is stupid, since these are certainly
+ ABI defined hard registers. For these, and for asm operands
+ that originally referenced hard registers, we must record that
+ the chain cannot be renamed. */
+ if (CALL_P (insn)
+ || (asm_noperands (PATTERN (insn)) > 0
+ && REG_P (op)
+ && REGNO (op) == ORIGINAL_REGNO (op)))
+ {
+ if (prev_open != open_chains)
+ open_chains->first->cl = NO_REGS;
+ }