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

--- Comment #2 from Richard Biener <rguenth at gcc dot gnu.org> ---
So the copyprop iteration figures out half of the function is unreachable
and thus registers a copy from a value defined in a region that is also
dead (but we figure that out only during substitution and folding via
a match.pd pattern looking at defs).  Then cfgcleanup comes along and
processes BBs in random order, removing the wrong unreachable region
(with the def we propagated) first and then another unreachable region
part where a basic-block merging opportunity then causes the propagated
but removed def being a source for propagating out a PHI ...

One fix is to _not_ do remove_edge_and_dominated_blocks in CFG cleanup
but only remove edges and remove unreachable blocks later (which causes
more work of course).  Or trying to paper over the issue by checking
for released SSA names (propagating them out anyway) or delaying SSA
name release via registering them for SSA update.

CFG cleanup ordering patch:

Index: gcc/tree-cfgcleanup.c
===================================================================
--- gcc/tree-cfgcleanup.c       (revision 231101)
+++ gcc/tree-cfgcleanup.c       (working copy)
@@ -67,7 +67,7 @@ remove_fallthru_edge (vec<edge, va_gc> *
        if (e->flags & EDGE_COMPLEX)
          e->flags &= ~EDGE_FALLTHRU;
        else
-         remove_edge_and_dominated_blocks (e);
+         remove_edge (e);
        return true;
       }
   return false;
@@ -134,7 +134,7 @@ cleanup_control_expr_graph (basic_block

              taken_edge->probability += e->probability;
              taken_edge->count += e->count;
-             remove_edge_and_dominated_blocks (e);
+             remove_edge (e);
              retval = true;
            }
          else
@@ -218,7 +218,7 @@ cleanup_control_flow_bb (basic_block bb)
       for (ei = ei_start (bb->succs); (e = ei_safe_edge (ei)); )
        {
          if (e->dest != target_block)
-           remove_edge_and_dominated_blocks (e);
+           remove_edge (e);
          else
            {
              /* Turn off the EDGE_ABNORMAL flag.  */
@@ -717,7 +717,13 @@ cleanup_tree_cfg_noloop (void)
       changed = false;
     }

-  changed |= cleanup_tree_cfg_1 ();
+  if (cleanup_tree_cfg_1 ())
+    {
+      changed = true;
+      delete_unreachable_blocks ();
+      free_dominance_info (CDI_DOMINATORS);
+      calculate_dominance_info (CDI_DOMINATORS);
+    }

   gcc_assert (dom_info_available_p (CDI_DOMINATORS));
   compact_blocks ();


"Hack" to detect the situation and not ICE (could also be applied to
may_propagate_copy)

Index: gcc/tree-cfg.c
===================================================================
--- gcc/tree-cfg.c      (revision 231101)
+++ gcc/tree-cfg.c      (working copy)
@@ -1865,6 +1865,8 @@ gimple_merge_blocks (basic_block a, basi
       tree def = gimple_phi_result (phi), use = gimple_phi_arg_def (phi, 0);
       gimple *copy;
       bool may_replace_uses = (virtual_operand_p (def)
+                              || (TREE_CODE (use) == SSA_NAME
+                                  && SSA_NAME_IN_FREE_LIST (use))
                               || may_propagate_copy (def, use));

       /* In case we maintain loop closed ssa form, do not propagate arguments

Reply via email to