https://gcc.gnu.org/bugzilla/show_bug.cgi?id=78516
--- Comment #19 from Peter Bergner <bergner at gcc dot gnu.org> --- (In reply to Peter Bergner from comment #18) > With the patch Vlad attached minus the one unwanted line/typo, I'm getting > an ICE on a powerpc64le-linux bootstrap. Looking into it. Here's a minimal test case: bergner@genoa:~/gcc/BUGS/PR78516$ cat libgcc2.i float fn1 (__int128 a) { if ((unsigned)a == a) return a; } bergner@genoa:~/gcc/BUGS/PR78516$ /home/bergner/gcc/build/gcc-fsf-mainline-pr78516/./gcc/xgcc -B/home/bergner/gcc/build/gcc-fsf-mainline-pr78516/./gcc/ -O2 -S libgcc2.i libgcc2.i: In function ‘fn1’: libgcc2.i:6:1: internal compiler error: in lra_set_insn_recog_data, at lra.c:965 } ^ 0x10a8eaaf lra_set_insn_recog_data(rtx_insn*) /home/bergner/gcc/gcc-fsf-mainline-pr78516/gcc/lra.c:963 We have the following insn after IRA: (insn 13 12 31 4 (set (reg:SF 157 [ <retval> ]) (float:SF (subreg:DI (reg/v:TI 158 [ aD.2516 ]) 0))) "libgcc2.i":5 407 {floatdisf2_fcfids} (expr_list:REG_DEAD (reg/v:TI 158 [ aD.2516 ]) (nil))) With pseudo 157 being assigned to fp reg fr1 and pseudo 158 being assigned to r3. The floatdisf2_fcfids pattern looks like: (define_insn "floatdisf2_fcfids" [(set (match_operand:SF 0 "gpc_reg_operand" "=f,wy") (float:SF (match_operand:DI 1 "gpc_reg_operand" "d,wi")))] "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_SINGLE_FLOAT && TARGET_DOUBLE_FLOAT && TARGET_FCFIDS" "@ fcfids %0,%1 xscvsxdsp %x0,%x1" [(set_attr "type" "fp")]) ...so pseudo 158 does not match the pattern's constraints. check_and_process_move() doesn't handle this type of insn, so it returns false and eventually, we generate the following two insns (haven't tracked down where they come from yet): (insn 38 12 13 4 (set (reg:DI 165) (subreg:DI (reg/v:TI 158 [ a ]) 0)) "libgcc2.i":5 582 {*movdi_internal64} (nil)) (insn 13 38 31 4 (set (reg:SF 157 [ <retval> ]) (float:SF (reg:DI 165))) "libgcc2.i":5 407 {floatdisf2_fcfids} (expr_list:REG_DEAD (reg/v:TI 158 [ a ]) (nil))) This maybe looks ok (?), except for the REG_DEAD on insn 13 should have been removed and added to the new insn 38. Later, check_and_process_move() is called again, this time for the new insn 38 and this is where we end up ICEing. We end up seeing: (gdb) pr dest (reg:DI 165) (gdb) pr dreg (reg:DI 165) (gdb) p dclass $54 = FLOAT_REGS (gdb) p dregno $55 = 165 (gdb) pr src (subreg:DI (reg/v:TI 158 [ a ]) 0) (gdb) pr sreg (reg/v:TI 158 [ a ]) (gdb) p sregno $56 = -1 (gdb) p sclass $57 = BASE_REGS (gdb) p secondary_class $58 = NO_REGS Due to the above, new_reg == NULL_RTX and sri.icode == CODE_FOR_reload_vsx_from_gprti. This pushes us down the else clause of the following if: if (sri.icode == CODE_FOR_nothing) lra_emit_move (new_reg, sreg); else { enum reg_class scratch_class; scratch_class = (reg_class_from_constraints (insn_data[sri.icode].operand[2].constraint)); scratch_reg = (lra_create_new_reg_with_unique_value (insn_data[sri.icode].operand[2].mode, NULL_RTX, scratch_class, "scratch")); emit_insn (GEN_FCN (sri.icode) (new_reg != NULL_RTX ? new_reg : dest, new_reg != NULL_RTX ? sreg : src, scratch_reg)); } We then up calling gen_reload_vsx_from_gprti() via the emit_insn() with: op0, op1 and op2 as: (gdb) pr operand0 (reg:DI 165) (gdb) pr operand1 (subreg:DI (reg/v:TI 158 [ a ]) 0) (gdb) pr operand2 (reg:IF 166) That subreg for operand1 does not look correct to me.