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

--- Comment #2 from Richard Biener <rguenth at gcc dot gnu.org> ---
(In reply to Richard Biener from comment #1)
> We hit
> 
>               if (e->flags & EDGE_ABNORMAL
>                   // This is like path_crosses_loops in profitable_path_p but
>                   // more restrictive to avoid peeling off loop iterations
> (see
>                   // tree-ssa/pr14341.c for an example).
>                   // ???  Note this restriction only applied when visiting an
>                   // interesting PHI with the former resolve_phi.
>                   || (!interesting_phis.is_empty ()
>                       && m_path[0]->loop_father != e->src->loop_father))
>                 continue;
> 
> in find_paths_to_names.  I guess we might want to defer this check and
> only disallow when the path exit condition resolves to not exiting the
> loop.  That is, the above tries to prevent peeling the first iteration
> for the case the exit test would be, say, i != 8 when the condition
> would resolve to know to stay inside the loop.  The above point of
> rejection is premature.
> 
> I suppose for policy rejection (rather than profitability rejection)
> m_registry.register_path would be responsible.  But maybe there's a similar
> enough check in the profitable_path_p that could be enhanced.
> 
> Let me give it a stab.

And then:

  // The backwards thread copier cannot copy blocks that do not belong
  // to the same loop, so when the new source of the path entry no
  // longer belongs to it we don't need to search further.
  else if (m_path[0]->loop_father != bb->loop_father)
    ;     

that would need to read "unless the threading does not duplicate the loop".
Aka, m_path[0]->loop_father would need to be the loop father of the
destination of the taken edge of the branch at the path exit.

We then get

maybe_register_phi_relation in bb5: Registering killing_def (path_oracle) i_1
 Registering value_relation (path_oracle) (i_8 == i_1) (root: bb2)
Checking profitability of path (backwards):
  [4] Registering jump thread: (2, 4) incoming edge;  (4, 5) normal (5, 6)
nocopy;  
path: 2->4->5->6 SUCCESS
Checking profitability of path (backwards):  bb:5 (4 insns) bb:7 (latch)
  Control statement insns: 2
  Overall: 2 insns

but fail the "subloop" sanity check in duplicate_thread_path.  Fixing that
makes the path threaded in thread2.  The subloop check prevents peeling
in this case.  But for the following both thread2 and threadfull2 would
peel one iteration:

volatile unsigned sink;

void
f (int flag, unsigned n)
{
  unsigned i = /*flag*/ 1 ? 0 : n;
  do
    {
      sink = i;
      i += 4;
    }
  while (i != 128);
}

Reply via email to