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 <[email protected]>
* 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))