The current code in reg_nonzero_bits_for_combine allows using the reg_stat info when last_set_mode is a different integer mode. This is completely wrong for non-pseudos. For example, as in the PR, a value in a DImode hard register is set by eight writes to its constituent QImode parts. The value written to the DImode is not the same as that written to the lowest-numbered QImode!
This patch fixes it. Committing. Will backport later, too. Segher 2018-07-26 Segher Boessenkool <seg...@kernel.crashing.org> PR rtl-optimization/85805 * combine.c (reg_nonzero_bits_for_combine): Only use the last set value for hard registers if that was written in the same mode. --- gcc/combine.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/gcc/combine.c b/gcc/combine.c index 09cbad4..fe71f3a 100644 --- a/gcc/combine.c +++ b/gcc/combine.c @@ -10186,7 +10186,8 @@ reg_nonzero_bits_for_combine (const_rtx x, scalar_int_mode xmode, rsp = ®_stat[REGNO (x)]; if (rsp->last_set_value != 0 && (rsp->last_set_mode == mode - || (GET_MODE_CLASS (rsp->last_set_mode) == MODE_INT + || (REGNO (x) >= FIRST_PSEUDO_REGISTER + && GET_MODE_CLASS (rsp->last_set_mode) == MODE_INT && GET_MODE_CLASS (mode) == MODE_INT)) && ((rsp->last_set_label >= label_tick_ebb_start && rsp->last_set_label < label_tick) -- 1.8.3.1