https://gcc.gnu.org/bugzilla/show_bug.cgi?id=119099

            Bug ID: 119099
           Summary: Compile-time hang in DCE
           Product: gcc
           Version: 15.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: rtl-optimization
          Assignee: unassigned at gcc dot gnu.org
          Reporter: alexey.merzlyakov at samsung dot com
  Target Milestone: ---

Created attachment 60644
  --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=60644&action=edit
Reduced test-case

The following code c-reduced from csmith generated testcase, causes GCC to hang
at -O2 during the compile-time:
  int a, b;

  void func2(short);

  void func1() {
    while (1) {
      int loc = 8;
      while (1) {
        func2(loc);
        if (a)
          loc = 3;
        else if (b)
          break;
        loc |= a;
      }
    }
  }

The hang appears on trunk and affects at least RISC-V 64/32, ARM 64/32,
powerpc64, MRISC32 targets.
Here is the example link on godbolt for RV64: https://godbolt.org/z/eWxfW3q1K

GCC hangs in ext-dce pass, where the "df_worklist_dataflow_doublequeue()" loops
forwever on the following basic blocks taken from double-worklists queue:

  BB7->BB6->BB4->BB3->BB5->worklists swap->BB7->BB6->BB4->BB3->BB5->worklists
swap ...

Dataflow solver algorithm will serve each BB node while BB sets are still
changing. The key point for solver in deciding whether to continue or not - is
"changed" variable state, which is set by "con_fun_n" function. This function
takes a pointer to "ext_dce_rd_transfer_n()" for ext-dce case. It initializes
"livenow" variables bitmap by "livein[]" states, processes it and finally emits
back "livenow" to the "livein[current BB]". For the selected basic block,
"livein" state flip-flops each time when loop returns back to this BB
processing. E.g. in the example above for the BB=4:

  Breakpoint 1, ext_dce_rd_transfer_n (bb_index=4) at ext-dce.cc:980
  980         return true;
  (gdb) p/x (&livein[bb_index])->first->next->bits
  $8 = {0xf000030f0000000, 0xff0}
  Continuing...
  worklist <-> pedning swap
  Breakpoint 2, df_worklist_dataflow_doublequeue (...) at df-core.cc:1097
  1097        std::swap (pending, worklist);
  Continuing...
  (gdb) p/x (&livein[bb_index])->first->next->bits
  $11 = {0xf000070f0000000, 0xff0}
  Continuing...

So livein[4] bits flip 0xf000030f0000000 -> 0xf000070f0000000 ->
0xf000030f0000000 -> ... states forever.

In other words, ext-dce + df-core could be treated as finite-state machine,
whose states acting on "livenow" and "livein" bitmaps. On the given testcase
machine loops forever, flipping/flopping or widening/narrowing "livein" states
with "livenow". Dataflow solver algorith will never come to the null-worklist
state in this case.

The cornerstone place for all of the described above seems to be "livein"
state, which could be changed in two directions (widen or narrowed) and thus
allowing machine to loop forever. If so, the solution could be to allow
changing of "livein" bitmap state only in one direction: in our case - to
expand. It will cause "ext_dce_rd_transfer_n()" function to also guarantee the
dataflow solver algorithm to converge to its final state.

The proposed solution could be as follows below:
  @@ -1094,8 +1094,13 @@ ext_dce_rd_transfer_n (int bb_index)
        the generic dataflow code that something changed.  */
     if (!bitmap_equal_p (&livein[bb_index], livenow))
       {
  -      bitmap_copy (&livein[bb_index], livenow);
  -      return true;
  +      bitmap tmp = BITMAP_ALLOC (NULL);
  +      bitmap_and (tmp, &livein[bb_index], livenow);
  +      if (!bitmap_equal_p (tmp, livenow))
  +     {
  +       bitmap_ior_into (&livein[bb_index], livenow);
  +       return true;
  +     }
       }

     return false;

It allows "livein[bb_index]" to be only widened and returns true only if it is
being really changed.
The patch works for me locally, and passed simple internal GCC testing. But if
this idea to be considered positively to accept, I will to go with more serious
testing on different targets and prepare its final version ready for mail-list.

Reply via email to