https://gcc.gnu.org/bugzilla/show_bug.cgi?id=78516
Peter Bergner <bergner at gcc dot gnu.org> changed:
What |Removed |Added
----------------------------------------------------------------------------
CC| |vmakarov at gcc dot gnu.org
--- Comment #8 from Peter Bergner <bergner at gcc dot gnu.org> ---
Adding Vlad as this seems like it may be a LRA bug...or we at least need his
input about what we should be doing.
We have the following "fixed" pattern from the updated fix patch attached
above:
(define_insn "*mov_si<mode>_e500_subreg0_2_be"
[(set (match_operand:SI 0 "int_reg_or_mem_operand" "=r,m")
(subreg:SI (match_operand:SPE64TF 1 "gpc_reg_operand" "+r,&r") 0))]
"WORDS_BIG_ENDIAN
&& ((TARGET_E500_DOUBLE && (<MODE>mode == DFmode || <MODE>mode == TFmode))
|| (TARGET_SPE && <MODE>mode != DFmode && <MODE>mode != TFmode))"
"@
evmergelohi %0,%1,%1
evmergelohi %1,%1,%1\;stw%U0%X0 %1,%0"
[(set_attr "length" "4,8")])
After IRA, we have the following rtl dump results, with pseudo 192 not getting
a color and pseudo 283 getting assigned to the CTR (hard reg 66 ...ick!):
(insn 223 222 51 2 (set (reg/v:DF 192 [ tD.1744 ])
(mem/u/c:DF (reg/f:SI 339) [1 S8 A64])) "q.i":28 2031
{*movdf_e500_double}
(expr_list:REG_DEAD (reg/f:SI 339)
(expr_list:REG_EQUIV (const_double:DF 0.0 [0x0.0p+0])
(nil))))
...
(insn 113 97 234 2 (set (reg:SI 283)
(subreg:SI (reg/v:DF 192 [ tD.1744 ]) 0)) "q.i":9 1975
{*mov_sidf_e500_subreg0_2_be}
(nil))
...
(insn 111 107 116 2 (set (reg:DF 278)
(mult:DF (reg/v:DF 192 [ tD.1744 ])
(reg:DF 279))) "q.i":28 2038 {spe_muldf3}
(expr_list:REG_DEAD (reg:DF 279)
(expr_list:REG_DEAD (reg/v:DF 192 [ tD.1744 ])
(nil))))
In lra-constraints.c:check_and_process_move() with curr_insn == insn 113, we
end up modifying insn 113 and emitting an insn before 113 that looks like:
(insn 273 97 113 2 (set (reg:SI 345)
(subreg:SI (reg/v:DF 192 [ t ]) 0)) "q.i":9 1975
{*mov_sidf_e500_subreg0_2_be}
(nil))
(insn 113 273 234 2 (set (reg:SI 283)
(reg:SI 345)) "q.i":9 1975 {*mov_sidf_e500_subreg0_2_be}
(nil))
Notice that the new insn 273 looks just like the old insn 113 and now insn 113
is invalid since this is a SImode reg to SImode reg copy without the subreg
which won't match the mov_sidf_e500_subreg0_2_be pattern, which leads us to
SEGV during check_rtl()'s call to constrain_operands() via
extract_constrain_insn().
The invalid insn 113 modification occurs due to the following code near the
bottom of check_and_process_move():
if (new_reg != NULL_RTX)
SET_SRC (curr_insn_set) = new_reg;
In this case, new_reg was created by:
if (secondary_class != NO_REGS)
new_reg = lra_create_new_reg_with_unique_value (GET_MODE (src), NULL_RTX,
secondary_class,
"secondary");
where "src" is the subreg:SI ..., so the new_reg mode will be SImode and we
then replace the whole SET_SRC (curr_insn_set) which is the subreg:SI (reg:DF
...) which doesn't seem correct.
Vlad, should we have never got this far into check_and_process_move() with this
type of insn? Adding an ugly hack that creates an early out for this insn (ie,
set (reg:SI) (subreg:SI (reg:DF))) seems to make us compile.
If we are supposed to still process this insn, then how about something like
the following patch that creates a new_reg with the mode of the src register
and not the subreg and then replacing that instead of the entire subreg src?
This too eliminates the SEGV/ICE.
Joseph, in the mean time, can you try the patch below to see if you get farther
into your glibc build?
Index: lra-constraints.c
===================================================================
--- lra-constraints.c (revision 243444)
+++ lra-constraints.c (working copy)
@@ -1237,12 +1237,12 @@ check_and_process_move (bool *change_p,
*change_p = true;
new_reg = NULL_RTX;
if (secondary_class != NO_REGS)
- new_reg = lra_create_new_reg_with_unique_value (GET_MODE (src), NULL_RTX,
+ new_reg = lra_create_new_reg_with_unique_value (GET_MODE (sreg), NULL_RTX,
secondary_class,
"secondary");
start_sequence ();
if (sri.icode == CODE_FOR_nothing)
- lra_emit_move (new_reg, src);
+ lra_emit_move (new_reg, sreg);
else
{
enum reg_class scratch_class;
@@ -1259,7 +1259,12 @@ check_and_process_move (bool *change_p,
end_sequence ();
lra_process_new_insns (curr_insn, before, NULL, "Inserting the move");
if (new_reg != NULL_RTX)
- SET_SRC (curr_insn_set) = new_reg;
+ {
+ if (SUBREG_P (src))
+ SUBREG_REG (SET_SRC (curr_insn_set)) = new_reg;
+ else
+ SET_SRC (curr_insn_set) = new_reg;
+ }
else
{
if (lra_dump_file != NULL)