Hi, As PR91052's comments show, commit r272731 exposed one issue in function combine_and_move_insns. Function combine_and_move_insns perform the below unexpected transformation.
** Before: ** 67: NOTE_INSN_BASIC_BLOCK 8 ... 59: {r184:SF=[sfp:SI-0x190];r121:SI=sfp:SI-0x190;} ==> move object 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: ** 67: NOTE_INSN_BASIC_BLOCK 8 ... 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;} ==> moved here but update origin r121. 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] =====> with sp-0x18c; inconsistent from above. 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 The insn 59 is special with multiple_sets, its movement alters the live interval of r121 from insn 77 to insn 99 and update r121 with unexpected value. Bootstrapped/regtested on powerpc64le-linux-gnu (LE) and ppc64-redhat-linux (BE). Is it ok for trunk? BR, Kewen ------- gcc/ChangeLog 2020-02-11 Kewen Lin <li...@gcc.gnu.org> * ira.c (combine_and_move_insns): Skip multiple_sets def_insn.
diff --git a/gcc/ira.c b/gcc/ira.c index c8b5f86..a655ae1 100644 --- a/gcc/ira.c +++ b/gcc/ira.c @@ -3784,6 +3784,11 @@ combine_and_move_insns (void) if (can_throw_internal (def_insn)) continue; + /* Instructions with multiple sets can only be moved if DF analysis is + performed for all of the registers set. See PR91052. */ + if (multiple_sets (def_insn)) + continue; + basic_block use_bb = BLOCK_FOR_INSN (use_insn); basic_block def_bb = BLOCK_FOR_INSN (def_insn); if (bb_loop_depth (use_bb) > bb_loop_depth (def_bb))