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 = &reg_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

Reply via email to