re PR lto/92674 (ICE in gimple_phi_arg, at gimple.h:4406 since r240291)
authorRichard Biener <rguenther@suse.de>
Wed, 27 Nov 2019 08:52:17 +0000 (08:52 +0000)
committerRichard Biener <rguenth@gcc.gnu.org>
Wed, 27 Nov 2019 08:52:17 +0000 (08:52 +0000)
2019-11-27  Richard Biener  <rguenther@suse.de>

PR middle-end/92674
* tree-inline.c (expand_call_inline): Delay purging EH/abnormal
edges and instead record blocks in bitmap.
(gimple_expand_calls_inline): Adjust.
(fold_marked_statements): Delay EH cleanup until all folding is
done.
(optimize_inline_calls): Do EH/abnormal cleanup for calls after
inlining finished.

From-SVN: r278757

gcc/ChangeLog
gcc/tree-inline.c

index 358602d744e85d1fbfcd48bcabee1a0e23d17969..1235b4411c25cdb6ddf6230a9c8429b2a279a819 100644 (file)
@@ -1,3 +1,14 @@
+2019-11-27  Richard Biener  <rguenther@suse.de>
+
+       PR middle-end/92674
+       * tree-inline.c (expand_call_inline): Delay purging EH/abnormal
+       edges and instead record blocks in bitmap.
+       (gimple_expand_calls_inline): Adjust.
+       (fold_marked_statements): Delay EH cleanup until all folding is
+       done.
+       (optimize_inline_calls): Do EH/abnormal cleanup for calls after
+       inlining finished.
+
 2019-11-27  Bernd Schmidt  <bernds_cb1@t-online.de>
 
        * auto-inc-dec.c (merge_in_block): Allow autoinc in jumps unless
index bdc332dcc23103b5ae89f90ea8ac0641aeaf533c..eecf5c6cf1cf7f291ba13d9c5bb47c7ac8f66d27 100644 (file)
@@ -4623,7 +4623,8 @@ reset_debug_bindings (copy_body_data *id, gimple_stmt_iterator gsi)
 /* If STMT is a GIMPLE_CALL, replace it with its inline expansion.  */
 
 static bool
-expand_call_inline (basic_block bb, gimple *stmt, copy_body_data *id)
+expand_call_inline (basic_block bb, gimple *stmt, copy_body_data *id,
+                   bitmap to_purge)
 {
   tree use_retvar;
   tree fn;
@@ -4768,7 +4769,7 @@ expand_call_inline (basic_block bb, gimple *stmt, copy_body_data *id)
       gimple_call_set_fndecl (stmt, edge->callee->decl);
       update_stmt (stmt);
       id->src_node->remove ();
-      expand_call_inline (bb, stmt, id);
+      expand_call_inline (bb, stmt, id, to_purge);
       maybe_remove_unused_call_args (cfun, stmt);
       return true;
     }
@@ -5156,10 +5157,7 @@ expand_call_inline (basic_block bb, gimple *stmt, copy_body_data *id)
     }
 
   if (purge_dead_abnormal_edges)
-    {
-      gimple_purge_dead_eh_edges (return_block);
-      gimple_purge_dead_abnormal_call_edges (return_block);
-    }
+    bitmap_set_bit (to_purge, return_block->index);
 
   /* If the value of the new expression is ignored, that's OK.  We
      don't warn about this for CALL_EXPRs, so we shouldn't warn about
@@ -5197,7 +5195,8 @@ expand_call_inline (basic_block bb, gimple *stmt, copy_body_data *id)
    in a MODIFY_EXPR.  */
 
 static bool
-gimple_expand_calls_inline (basic_block bb, copy_body_data *id)
+gimple_expand_calls_inline (basic_block bb, copy_body_data *id,
+                           bitmap to_purge)
 {
   gimple_stmt_iterator gsi;
   bool inlined = false;
@@ -5209,7 +5208,7 @@ gimple_expand_calls_inline (basic_block bb, copy_body_data *id)
 
       if (is_gimple_call (stmt)
          && !gimple_call_internal_p (stmt))
-       inlined |= expand_call_inline (bb, stmt, id);
+       inlined |= expand_call_inline (bb, stmt, id, to_purge);
     }
 
   return inlined;
@@ -5222,6 +5221,7 @@ gimple_expand_calls_inline (basic_block bb, copy_body_data *id)
 static void
 fold_marked_statements (int first, hash_set<gimple *> *statements)
 {
+  auto_bitmap to_purge;
   for (; first < last_basic_block_for_fn (cfun); first++)
     if (BASIC_BLOCK_FOR_FN (cfun, first))
       {
@@ -5233,7 +5233,8 @@ fold_marked_statements (int first, hash_set<gimple *> *statements)
          if (statements->contains (gsi_stmt (gsi)))
            {
              gimple *old_stmt = gsi_stmt (gsi);
-             tree old_decl = is_gimple_call (old_stmt) ? gimple_call_fndecl (old_stmt) : 0;
+             tree old_decl
+               = is_gimple_call (old_stmt) ? gimple_call_fndecl (old_stmt) : 0;
 
              if (old_decl && fndecl_built_in_p (old_decl))
                {
@@ -5277,8 +5278,7 @@ fold_marked_statements (int first, hash_set<gimple *> *statements)
                                 is mood anyway.  */
                              if (maybe_clean_or_replace_eh_stmt (old_stmt,
                                                                  new_stmt))
-                               gimple_purge_dead_eh_edges (
-                                 BASIC_BLOCK_FOR_FN (cfun, first));
+                               bitmap_set_bit (to_purge, first);
                              break;
                            }
                          gsi_next (&i2);
@@ -5298,11 +5298,11 @@ fold_marked_statements (int first, hash_set<gimple *> *statements)
                                                       new_stmt);
 
                  if (maybe_clean_or_replace_eh_stmt (old_stmt, new_stmt))
-                   gimple_purge_dead_eh_edges (BASIC_BLOCK_FOR_FN (cfun,
-                                                                   first));
+                   bitmap_set_bit (to_purge, first);
                }
            }
       }
+  gimple_purge_all_dead_eh_edges (to_purge);
 }
 
 /* Expand calls to inline functions in the body of FN.  */
@@ -5348,8 +5348,9 @@ optimize_inline_calls (tree fn)
      will split id->current_basic_block, and the new blocks will
      follow it; we'll trudge through them, processing their CALL_EXPRs
      along the way.  */
+  auto_bitmap to_purge;
   FOR_EACH_BB_FN (bb, cfun)
-    inlined_p |= gimple_expand_calls_inline (bb, &id);
+    inlined_p |= gimple_expand_calls_inline (bb, &id, to_purge);
 
   pop_gimplify_context (NULL);
 
@@ -5369,6 +5370,21 @@ optimize_inline_calls (tree fn)
   fold_marked_statements (last, id.statements_to_fold);
   delete id.statements_to_fold;
 
+  /* Finally purge EH and abnormal edges from the call stmts we inlined.
+     We need to do this after fold_marked_statements since that may walk
+     the SSA use-def chain.  */
+  unsigned i;
+  bitmap_iterator bi;
+  EXECUTE_IF_SET_IN_BITMAP (to_purge, 0, i, bi)
+    {
+      basic_block bb = BASIC_BLOCK_FOR_FN (cfun, i);
+      if (bb)
+       {
+         gimple_purge_dead_eh_edges (bb);
+         gimple_purge_dead_abnormal_call_edges (bb);
+       }
+    }
+
   gcc_assert (!id.debug_stmts.exists ());
 
   /* If we didn't inline into the function there is nothing to do.  */