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

Richard Biener <rguenth at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |rguenth at gcc dot gnu.org

--- Comment #3 from Richard Biener <rguenth at gcc dot gnu.org> ---
On GIMPLE I see

  <bb 2> [local count: 1073741825]:
  if (d_3(D) < max_4(D))
    goto <bb 3>; [50.00%]
  else
    goto <bb 4>; [50.00%]

  <bb 3> [local count: 536870912]:
  _1 = -max_4(D);
  _6 = _1 < d_3(D);

  <bb 4> [local count: 1073741825]:
  # iftmp.0_2 = PHI <_6(3), 0(2)>

generated by late phiopt which means phiopt could iteratively arrive at
the solution if it handled the above.

phiopt first value-replaces

  if (_1 < d_3(D))
    goto <bb 5>; [50.00%]
  else
    goto <bb 4>; [50.00%]

  <bb 4> [local count: 268435456]:

  <bb 5> [local count: 1073741825]:
  # iftmp.0_2 = PHI <0(4), 1(3), 0(2)>

not sure why that only happens in the last phiopt pass.  Ah, because
the main phiopt pass sees the following:

  <bb 2> [local count: 1073741825]:
  if (d_3(D) < max_4(D))
    goto <bb 3>; [50.00%]
  else
    goto <bb 4>; [50.00%]

  <bb 3> [local count: 536870912]:
  _1 = -max_4(D);
  if (_1 < d_3(D))
    goto <bb 5>; [50.00%]
  else
    goto <bb 4>; [50.00%]

  <bb 4> [local count: 805306368]:

  <bb 5> [local count: 1073741825]:
  # iftmp.0_2 = PHI <1(3), 0(4)>

oddly enough the forwarder is removed by veclower?!  Ah, I guess this
is the first cfg-cleanup run that happens since nobody else touches
the code and veclower runs it unconditionally.  Heh.  No, it looks like
the forwarding is somehow triggered by PRE splitting critical edges
and _then_ only veclower runs cfg-cleanup.

Hmm.  CCP runs CFG cleanup which removes one forwarder but then
has to keep the other one because we need at least one forwarder
due to the different PHI arg values.  So it looks like we should
somehow prefer to eliminate the other forwarder (for phiopts sake
only?).  That's sth to investigate - make CFG cleanup apply a
more consistent decision here rather than eliminating the forwarders
simply in BB index order.

The course of action is probably to detect the

remove_forwarder_block (basic_block bb)
{
...
  /* If there are phi nodes in DEST, and some of the blocks that are
     predecessors of BB are also predecessors of DEST, check that the
     phi node arguments match.  */
  if (!gimple_seq_empty_p (phi_nodes (dest)))
    {
      FOR_EACH_EDGE (e, ei, bb->preds)
        {
          s = find_edge (e->src, dest);
          if (!s)
            continue;

          if (!phi_alternatives_equal (dest, succ, s))
            return false;

situation and then decide whether to re-create a forwarder on the
other edge to create a more canonical CFG (when BB has multiple
predecessors, that is, though in that case we're introducing another
copy).

Reply via email to