[backport gcc-4.9/trunk r199449, second fix for PR57439 regression on m68k from PR56833 patch ] gcc/ 2013-05-30 Joern Rennecke PR rtl-optimization/57439 * postreload.c (move2add_valid_value_p): Check that we have a zero subreg_regno_offset when accessing the register in the requested mode. --- gcc-4.8.1/gcc/postreload.c.~1~ 2013-06-01 11:33:10.201765796 +0200 +++ gcc-4.8.1/gcc/postreload.c 2013-06-01 11:35:11.421841862 +0200 @@ -1720,10 +1720,27 @@ move2add_record_sym_value (rtx reg, rtx static bool move2add_valid_value_p (int regno, enum machine_mode mode) { - if (reg_set_luid[regno] <= move2add_last_label_luid - || !MODES_OK_FOR_MOVE2ADD (mode, reg_mode[regno])) + 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;