+ 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.
+ For every bit set in DO_NOT_HIDE, we leave the operand alone.
+ If INOUT_AND_EC_ONLY is set, we only do this for OP_INOUT type operands
+ and earlyclobbers. */
+
+static void
+hide_operands (int n_ops, rtx *old_operands, rtx *old_dups,
+ unsigned HOST_WIDE_INT do_not_hide, bool inout_and_ec_only)
+{
+ int i;
+ int alt = which_alternative;
+ 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 (do_not_hide & (1 << i))
+ continue;
+ if (!inout_and_ec_only || recog_data.operand_type[i] == OP_INOUT
+ || recog_op_alt[i][alt].earlyclobber)
+ *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 (do_not_hide & (1 << opn))
+ continue;
+ if (!inout_and_ec_only || recog_data.operand_type[opn] == OP_INOUT
+ || recog_op_alt[opn][alt].earlyclobber)
+ *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. Do this only for normal or earlyclobber outputs,
+ depending on EARLYCLOBBER. */
+
+static void
+record_out_operands (rtx insn, bool earlyclobber)
+{
+ 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
+ || recog_op_alt[opn][alt].earlyclobber != earlyclobber)
+ 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->cannot_rename = 1;
+ }