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);