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

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

           What    |Removed                     |Added
----------------------------------------------------------------------------
   Target Milestone|---                         |7.4

--- Comment #2 from Richard Biener <rguenth at gcc dot gnu.org> ---
OK, so the issue is that there's a missed CFG cleanup run somewhere (eventually
done by one of the passes you disable).  We have


  # j = PHI<1>
 if (j == 0)
   loop!
 else
   loop exit

and we happily if-convert single-argument PHIs (boo).  if-conversion then
will do the CFG cleanup and that scraps the fallback loop while the
if-converted loop now looks like

  j = 1;
  if (j == 0)
    ....

which CFG cleanup doesn't "handle".

-> Kaboom.

I'd say "doctor it hurts", but of course we should cleanup the CFG properly.
This time the offender is VRP which performs jump-threading and then
CFG cleanup but with SSA not updated.  This then runs into

gimple_can_merge_blocks_p (a=<basic_block 0x7ffff68986e8 (7)>, 
    b=<basic_block 0x7ffff6898340 (4)>) at /tmp/trunk/gcc/tree-cfg.c:1883
1939      for (gphi_iterator gsi = gsi_start_phis (b); !gsi_end_p (gsi);
1940           gsi_next (&gsi))
1941        {
1942          gphi *phi = gsi.phi ();
1943          /* Technically only new names matter.  */
1944          if (name_registered_for_update_p (PHI_RESULT (phi)))
1945            return false;
1946        }

and so not merging two blocks which would propagate out the single-arg PHI.
I also believe the comment is wrong and we cannot propagate the PHI out.
But we could in theory simply create a copy (which of course wouldn't solve
the issue at hand).

So one solution might be to force a phi-only-cprop pass before
tree-if-conversion but then if you disable that manually you're screwed again
;)

Or try re-organizing TODO processing to "interleave" update-SSA and
cleanup-CFG.  We basically need cleanup_control_flow_pre () be performed
first, then update-SSA if required and then continue.

static void
execute_function_todo (function *fn, void *data)
{
  bool from_ipa_pass = (cfun == NULL);
  unsigned int flags = (size_t)data;
  flags &= ~fn->last_verified;
  if (!flags)
    return;

  push_cfun (fn);

  /* Always cleanup the CFG before trying to update SSA.  */
  if (flags & TODO_cleanup_cfg)
    {
      cleanup_tree_cfg ();

...

  if (flags & TODO_update_ssa_any)
    {
      unsigned update_flags = flags & TODO_update_ssa_any;
      update_ssa (update_flags);


anyhow this seems low-priority and certainly I don't think CFG cleanup
(or loop fixup) should in any way be forced to kill LOOP_VECTORIZED IFN calls.

Reply via email to