Hi,

  When analyzing PR 71873 (ICE in push_reload), I found that that code
  in push_reload that recursively calls push_reload for subreg
  expressions doesn't correctly set subreg_in_class for a few cases.

  Specifically, reload_inner_reg_of_subreg returns true if SUBREG_REG(x)
  is CONSTANT_P or if it's code is PLUS. The code that tries to find a
  valid class (before recursively calling push_reload), however, only
  does that if SUBREG_REG is REG_P or if it's a SYMBOL_REF. For the
  other cases, subreg_in_class is set to the default NO_REGS, and this
  triggers the rclass != NO_REGS assert just before find_reusable_reload.

  For PR 71873, reload sees

  (set (reg/f:HI 87)
        (const:HI (plus:HI (symbol_ref:HI ("a")  <var_decl 0x7ff218a11bd0 a>)  
                (const_int 1 [0x1])))) ../test.c:24 83 {*movhi}
     (expr_list:REG_EQUIV (const:HI (plus:HI (symbol_ref:HI ("a")  <var_decl 
0x7ff218a11bd0 a>) 
                (const_int 1 [0x1])))
  and

  (set (mem:QI (post_dec:HI (reg/f:HI 32 __SP_L__)) [0  S1 A8]) 
        (subreg:QI (reg/f:HI 87) 1))

  and decides to replace pseudo reg 87 in the latter insn with the
  REG_EQUIV it found in the former. The resulting RTL expression
   
  (subreg:QI (const:HI (plus:HI (symbol_ref:HI ("a") <var_decl 0x7ffff7ff5bd0 
a>)
            (const_int 1 [0x1]))) 1)

   does not match any of the conditions that handle subregs because
   subreg_low_part is false and the inner expr is not a REG or a SYMBOL_REF.

  Is there a reason why only REG and SYMBOL_REFs get valid
  subreg_in_class? I tried extending it handle constants and PLUS
  expressions, and it fixes PR 71873. It also fixes a another
  bug that was a work around for the reload failure (PR 64452) - that
  had a plus expression instead of the const.

  Reg testing on avr and x86_64 did not show any new failures. Is this
  the right way to fix this?

Regards
Senthil

diff --git gcc/reload.c gcc/reload.c
index 06426d9..f80d849 100644
--- gcc/reload.c
+++ gcc/reload.c
@@ -1141,7 +1141,9 @@ push_reload (rtx in, rtx out, rtx *inloc, rtx *outloc,
                                                   SUBREG_BYTE (in),
                                                   GET_MODE (in)),
                              REGNO (SUBREG_REG (in)));
-      else if (GET_CODE (SUBREG_REG (in)) == SYMBOL_REF)
+      else if (GET_CODE (SUBREG_REG (in)) == SYMBOL_REF
+               || CONSTANT_P (SUBREG_REG (in))
+               || GET_CODE (SUBREG_REG (in)) == PLUS)
        subreg_in_class = find_valid_class_1 (inmode,
                                              GET_MODE (SUBREG_REG (in)),
                                              rclass);

Reply via email to