+/* Record that REG is being set to a value with the mode of REG. */
+
+static void
+move2add_record_mode (rtx reg)
+{
+ int regno, nregs;
+ machine_mode mode = GET_MODE (reg);
+
+ if (GET_CODE (reg) == SUBREG)
+ {
+ regno = subreg_regno (reg);
+ nregs = subreg_nregs (reg);
+ }
+ else if (REG_P (reg))
+ {
+ regno = REGNO (reg);
+ nregs = REG_NREGS (reg);
+ }
+ else
+ gcc_unreachable ();
+ for (int i = nregs - 1; i > 0; i--)
+ reg_mode[regno + i] = BLKmode;
+ reg_mode[regno] = mode;
+}
+
+/* Record that REG is being set to the sum of SYM and OFF. */
+
+static void
+move2add_record_sym_value (rtx reg, rtx sym, rtx off)
+{
+ int regno = REGNO (reg);
+
+ move2add_record_mode (reg);
+ reg_set_luid[regno] = move2add_luid;
+ reg_base_reg[regno] = -1;
+ reg_symbol_ref[regno] = sym;
+ reg_offset[regno] = INTVAL (off);
+}
+
+/* Check if REGNO contains a valid value in MODE. */
+
+static bool
+move2add_valid_value_p (int regno, machine_mode mode)
+{
+ if (reg_set_luid[regno] <= move2add_last_label_luid)
+ return false;
+
+ if (mode != reg_mode[regno])
+ {
+ if (!MODES_OK_FOR_MOVE2ADD (mode, reg_mode[regno]))
+ return false;
+ /* The value loaded into regno in reg_mode[regno] is also valid in
+ mode after truncation only if (REG:mode regno) is the lowpart of
+ (REG:reg_mode[regno] regno). Now, for big endian, the starting
+ regno of the lowpart might be different. */
+ int s_off = subreg_lowpart_offset (mode, reg_mode[regno]);
+ s_off = subreg_regno_offset (regno, reg_mode[regno], s_off, mode);
+ if (s_off != 0)
+ /* We could in principle adjust regno, check reg_mode[regno] to be
+ BLKmode, and return s_off to the caller (vs. -1 for failure),
+ but we currently have no callers that could make use of this
+ information. */
+ return false;
+ }
+
+ for (int i = hard_regno_nregs[regno][mode] - 1; i > 0; i--)
+ if (reg_mode[regno + i] != BLKmode)
+ return false;
+ return true;
+}
+