+static void mark_set_regs (rtx, const_rtx, void *);
+static void mark_referenced_regs (rtx);
+static int insert_save (struct insn_chain *, int, int, HARD_REG_SET *,
+ enum machine_mode *);
+static int insert_restore (struct insn_chain *, int, int, int,
+ enum machine_mode *);
+static struct insn_chain *insert_one_insn (struct insn_chain *, int, int,
+ rtx);
+static void add_stored_regs (rtx, const_rtx, void *);
+\f
+static GTY(()) rtx savepat;
+static GTY(()) rtx restpat;
+static GTY(()) rtx test_reg;
+static GTY(()) rtx test_mem;
+static GTY(()) rtx saveinsn;
+static GTY(()) rtx restinsn;
+
+/* Return the INSN_CODE used to save register REG in mode MODE. */
+static int
+reg_save_code (int reg, enum machine_mode mode)
+{
+ bool ok;
+ if (cached_reg_save_code[reg][mode])
+ return cached_reg_save_code[reg][mode];
+ if (!HARD_REGNO_MODE_OK (reg, mode))
+ {
+ cached_reg_save_code[reg][mode] = -1;
+ cached_reg_restore_code[reg][mode] = -1;
+ return -1;
+ }
+
+ /* Update the register number and modes of the register
+ and memory operand. */
+ SET_REGNO (test_reg, reg);
+ PUT_MODE (test_reg, mode);
+ PUT_MODE (test_mem, mode);
+
+ /* Force re-recognition of the modified insns. */
+ INSN_CODE (saveinsn) = -1;
+ INSN_CODE (restinsn) = -1;
+
+ cached_reg_save_code[reg][mode] = recog_memoized (saveinsn);
+ cached_reg_restore_code[reg][mode] = recog_memoized (restinsn);
+
+ /* Now extract both insns and see if we can meet their
+ constraints. */
+ ok = (cached_reg_save_code[reg][mode] != -1
+ && cached_reg_restore_code[reg][mode] != -1);
+ if (ok)
+ {
+ extract_insn (saveinsn);
+ ok = constrain_operands (1);
+ extract_insn (restinsn);
+ ok &= constrain_operands (1);
+ }