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!

Reply via email to