https://gcc.gnu.org/bugzilla/show_bug.cgi?id=78516
--- Comment #4 from Peter Bergner <bergner at gcc dot gnu.org> --- Created attachment 40317 --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=40317&action=edit Potential fix to spe.md (In reply to Peter Bergner from comment #2) > So we're hitting this code in lra-assigns.c:lra_assign():1612: > > if (flag_checking && !flag_ipa_ra) > for (i = FIRST_PSEUDO_REGISTER; i < max_regno; i++) > if (lra_reg_info[i].nrefs != 0 && reg_renumber[i] >= 0 > && lra_reg_info[i].call_p > && overlaps_hard_reg_set_p (call_used_reg_set, > PSEUDO_REGNO_MODE (i), > reg_renumber[i])) > gcc_unreachable (); > > Our pseudo (i == 184) had been assigned to r9 (a call clobbered reg) and yet > lra_reg_info[184].call_p is true, leading to the assert. > > Looking through the rtl dumps, pseudo 184 is live only over two consecutive > insns, so clearly call_p should not be true here. I'm tracking down where > that is getting set. This ends up being a bug in the spe.md:*mov_sidf_e500_subreg0_2_be pattern's constraints (ditto from some other patterns). The problem RTL is below. We have a call followed later in the same basic block, by a set of pseudo 184 and then its only use closely thereafter: (call_insn 13 10 14 2 (parallel [ (call (mem:SI (symbol_ref:SI ("bar") [flags 0x41] <function_decl 0x3fff821b4600 bar>) [0 barD.1674 S4 A32]) (const_int 0 [0])) (use (const_int 0 [0])) (clobber (reg:SI 65 lr)) ]) "pr78516.i":5 654 {*call_nonlocal_sysvsi} (nil) (nil)) ... (insn 16 15 17 2 (set (reg:SI 184) (subreg:SI (reg:DF 155 [ neg0.0_1 ]) 0)) "pr78516.i":7 1975 {*mov_sidf_e500_subreg0_2_be} (expr_list:REG_DEAD (reg:DF 155 [ neg0.0_1 ]) (nil))) ... (insn 19 18 20 2 (set (reg:CC 167) (compare:CC (reg:SI 184) (const_int 0 [0]))) "pr78516.i":7 678 {*cmpsi_signed} (expr_list:REG_DEAD (reg:SI 184) (nil))) So pseudo 184 (assigned to a call clobber reg) is not live across the call, but lra-lives.c:process_bb_lives() thinks it is, so it triggers the above assert. It seems IRA uses the gcc df infrastructure to determine liveness and this tells IRA is can assign a call clobbered register to pseudo 184 and it does (r9). lra-lives.c has its own liveness analysis code which does not make use of df (should it?) and its analysis finds the pseudo 184's live range extends up to the call and beyond. This is due to lra-lives.c uses an insn's recog data to see what operands are defined and used in an insn and computes liveness from that. The "bug" is that the *mov_sidf_e500_subreg0_2_be pattern has incorrect constraints and the defined pseudo is marked as a OP_INOUT operand, so it what makes pseudo 184 live range extend up to the top of the block and across the call leading to the ICE. The pattern is: (define_insn "*mov_si<mode>_e500_subreg0_2_be" [(set (match_operand:SI 0 "rs6000_nonimmediate_operand" "+r,m") (subreg:SI (match_operand:SPE64TF 1 "register_operand" "+r,&r") 0))] "WORDS_BIG_ENDIAN && ((TARGET_E500_DOUBLE && (<MODE>mode == DFmode || <MODE>mode == TFmode)) || (TARGET_SPE && <MODE>mode != DFmode && <MODE>mode != TFmode))" "@ evmergehi %0,%0,%1 evmergelohi %1,%1,%1\;stw%U0%X0 %1,%0" [(set_attr "length" "4,8")]) There are multiple problems with the first alternative. First, op1 is marked as an input/output operand, but it clearly only an input. Secondly, op0 is also marked as a input/output operand (and this is what leads to our ICE) since it is used as an input to the evmergehi instruction. However, the purpose of the pattern is to simply copy the high word of op1 and place it into the low word of op0. In that case, that case, the source operand %0 here could be any register, since it's value will be unused (since we're writing a SImode reg). That means op0 really should only be an output operand. To simplify things, so changed the instruction for the first alternative to be the same as the second alternative, since they're performing the same function, except that alternative 1 also stores the value to memory. For the second alternative, I moved the earlyclobber constraint modifier to the output operand to quiet the following message I was getting after my changes: /home/bergner/gcc/gcc-fsf-mainline-pr78516/gcc/config/rs6000/spe.md:2561:1: earlyclobber operands may not be read-only in alternative 1 Therefore, the "fixed" pattern which eliminates the ICE, looks like: (define_insn "*mov_si<mode>_e500_subreg0_2_be" - [(set (match_operand:SI 0 "rs6000_nonimmediate_operand" "+r,m") - (subreg:SI (match_operand:SPE64TF 1 "register_operand" "+r,&r") 0))] + [(set (match_operand:SI 0 "rs6000_nonimmediate_operand" "=r,&m") + (subreg:SI (match_operand:SPE64TF 1 "register_operand" "r,r") 0))] "WORDS_BIG_ENDIAN && ((TARGET_E500_DOUBLE && (<MODE>mode == DFmode || <MODE>mode == TFmode)) || (TARGET_SPE && <MODE>mode != DFmode && <MODE>mode != TFmode))" "@ - evmergehi %0,%0,%1 + evmergelohi %0,%1,%1 evmergelohi %1,%1,%1\;stw%U0%X0 %1,%0" [(set_attr "length" "4,8")]) Looking through the spe.md file, I see similar issues with constraints on other patterns, so I fixed them similarly as here. Joseph, can you try the attached patch to see if it works for you, and if so, whether it bootstraps and regtests?