https://gcc.gnu.org/bugzilla/show_bug.cgi?id=91052
Kewen Lin <linkw at gcc dot gnu.org> changed: What |Removed |Added ---------------------------------------------------------------------------- CC| |amodra at gcc dot gnu.org --- Comment #12 from Kewen Lin <linkw at gcc dot gnu.org> --- The insn 59 is deleted and new insn 219 is generated by function combine_and_move_insns, the failure is due to that: Originally insn 59 has the note that the updated reg r121 is REG_UNUSED. Later insn 219 inserted before r184's use, with note directly copied from insn 59, r121 is still REG_UNUSED. So function setup_reg_equiv doesn't filter it out since it's taken as single_set due to REG_UNUSED existence. But the r121 in insn 219 isn't actually REG_UNUSED and gets fixed after live info recalculation as below: 67: NOTE_INSN_BASIC_BLOCK 8 ... 103: NOTE_INSN_DELETED 77: {r191:SF=[sfp:SI-0x18c];r121:SI=sfp:SI-0x18c;} REG_UNUSED r121:SI 60: r122:SI=r127:SI REG_DEAD r127:SI 219: {r184:SF=[sfp:SI-0x190];r121:SI=sfp:SI-0x190;} 61: [r122:SI]=r184:SF REG_DEAD r184:SF 79: [++r122:SI]=r191:SF REG_DEAD r191:SF REG_INC r122:SI Then fix_reg_equiv_init find the insn isn't single_set and assertion fail. The newly generated doesn't look incorrect since some semantic changes as below. * Before combine_and_move_insns, we have: 67: NOTE_INSN_BASIC_BLOCK 8 58: NOTE_INSN_DELETED 63: NOTE_INSN_DELETED 110: NOTE_INSN_DELETED 88: NOTE_INSN_DELETED 76: NOTE_INSN_DELETED 103: NOTE_INSN_DELETED 59: {r184:SF=[sfp:SI-0x190];r121:SI=sfp:SI-0x190;} REG_UNUSED r121:SI 77: {r191:SF=[sfp:SI-0x18c];r121:SI=sfp:SI-0x18c;} 60: r122:SI=r127:SI REG_DEAD r127:SI 61: [r122:SI]=r184:SF REG_DEAD r184:SF 79: [++r122:SI]=r191:SF REG_DEAD r191:SF REG_INC r122:SI 64: r187:SF=[r137:SI+low(`*.LC0')] 99: r198:SF=[++r121:SI] =====> with sp-0x18c+4; REG_INC r121:SI 104: r201:SF=[r137:SI+low(`*.LC0')] 65: [r126:SI]=r187:SF REG_DEAD r187:SF 105: [r126:SI]=r201:SF REG_DEAD r201:SF 101: [++r122:SI]=r198:SF REG_DEAD r198:SF REG_INC r122:SI 114: L114: 113: NOTE_INSN_BASIC_BLOCK 9 * After combine_and_move_insns, we have: 67: NOTE_INSN_BASIC_BLOCK 8 58: NOTE_INSN_DELETED 63: NOTE_INSN_DELETED 110: NOTE_INSN_DELETED 88: NOTE_INSN_DELETED 76: NOTE_INSN_DELETED 103: NOTE_INSN_DELETED 77: {r191:SF=[sfp:SI-0x18c];r121:SI=sfp:SI-0x18c;} REG_UNUSED r121:SI 60: r122:SI=r127:SI REG_DEAD r127:SI 219: {r184:SF=[sfp:SI-0x190];r121:SI=sfp:SI-0x190;} 61: [r122:SI]=r184:SF REG_DEAD r184:SF 79: [++r122:SI]=r191:SF REG_DEAD r191:SF REG_INC r122:SI 64: r187:SF=[r137:SI+low(`*.LC0')] REG_EQUIV [r137:SI+low(`*.LC0')] 99: r198:SF=[++r121:SI] =====> still with sp-0x18c; REG_INC r121:SI 104: r201:SF=[r137:SI+low(`*.LC0')] REG_EQUIV [r137:SI+low(`*.LC0')] 65: [r126:SI]=r187:SF REG_DEAD r187:SF 105: [r126:SI]=r201:SF REG_DEAD r201:SF 101: [++r122:SI]=r198:SF REG_DEAD r198:SF REG_INC r122:SI 114: L114: 113: NOTE_INSN_BASIC_BLOCK 9 As above, I guess we can guard the strict single_set condition for function combine_and_move_insns. @@ -3827,7 +3874,7 @@ combine_and_move_insns (void) /* Move the initialization of the register to just before USE_INSN. Update the flow information. */ - else if (prev_nondebug_insn (use_insn) != def_insn) + else if (prev_nondebug_insn (use_insn) != def_insn && !multiple_sets (def_insn)) { rtx_insn *new_insn; Or any alternative to ensure multiple sets movement doesn't kill usused reg's live range and notes gets updated. ----- Hi @Alan/@Vladimir, What do you think of the issue? Thanks!