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)