[PR ipa/88933] Careful CFG cleanup in IPA-CP function transformation
authorMartin Jambor <mjambor@suse.cz>
Sat, 26 Jan 2019 22:19:17 +0000 (23:19 +0100)
committerMartin Jambor <jamborm@gcc.gnu.org>
Sat, 26 Jan 2019 22:19:17 +0000 (23:19 +0100)
2019-01-26  Martin Jambor  <mjambor@suse.cz>

PR ipa/88933
* tree-inline.c: Include tree-cfgcleanup.h.
(delete_unreachable_blocks_update_callgraph): Move...
* tree-cfgcleanup.c (delete_unreachable_blocks_update_callgraph):
...here, make externally visible, make second argument bool, adjust
all callers.
* tree-cfgcleanup.c: Include cgraph.h.
* tree-cfgcleanup.h (delete_unreachable_blocks_update_callgraph):
Declare.
* ipa-prop.c: Include tree-cfgcleanup.h.
(ipcp_transform_function): Call
delete_unreachable_blocks_update_callgraph instead of cleaning uo CFG.

testsuite/
* gfortran.dg/gomp/pr88933.f90: New test.

From-SVN: r268305

gcc/ChangeLog
gcc/ipa-prop.c
gcc/testsuite/ChangeLog
gcc/testsuite/gfortran.dg/gomp/pr88933.f90 [new file with mode: 0644]
gcc/tree-cfgcleanup.c
gcc/tree-cfgcleanup.h
gcc/tree-inline.c

index 0518053ad856a4f772e6d1cfc161f0a51c518bb3..269b6652249ea46e04f1c64f21eb02a2c746097e 100644 (file)
@@ -1,3 +1,18 @@
+2019-01-26  Martin Jambor  <mjambor@suse.cz>
+
+       PR ipa/88933
+       * tree-inline.c: Include tree-cfgcleanup.h.
+       (delete_unreachable_blocks_update_callgraph): Move...
+       * tree-cfgcleanup.c (delete_unreachable_blocks_update_callgraph):
+       ...here, make externally visible, make second argument bool, adjust
+       all callers.
+       * tree-cfgcleanup.c: Include cgraph.h.
+       * tree-cfgcleanup.h (delete_unreachable_blocks_update_callgraph):
+       Declare.
+       * ipa-prop.c: Include tree-cfgcleanup.h.
+       (ipcp_transform_function): Call
+       delete_unreachable_blocks_update_callgraph instead of cleaning uo CFG.
+
 2019-01-25  Vladimir Makarov  <vmakarov@redhat.com>
 
        PR rtl-optimization/88846
index 40ab130b750f0ceb9f5840e755af6555f021006a..d86c2f3db5528f5fe3c67e46cecd2f3bb761a212 100644 (file)
@@ -52,6 +52,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "dbgcnt.h"
 #include "domwalk.h"
 #include "builtins.h"
+#include "tree-cfgcleanup.h"
 
 /* Function summary where the parameter infos are actually stored. */
 ipa_node_params_t *ipa_node_params_sum = NULL;
@@ -5173,10 +5174,11 @@ ipcp_transform_function (struct cgraph_node *node)
 
   if (!something_changed)
     return 0;
-  else if (cfg_changed)
-    return TODO_update_ssa_only_virtuals | TODO_cleanup_cfg;
-  else
-    return TODO_update_ssa_only_virtuals;
+
+  if (cfg_changed)
+    delete_unreachable_blocks_update_callgraph (node, false);
+
+  return TODO_update_ssa_only_virtuals;
 }
 
 #include "gt-ipa-prop.h"
index f1e89d56010e2237b6fb6046f6db522f5f6619cd..9fe74a08600f029d86706bea3c3f4b83d2c7dd32 100644 (file)
@@ -1,3 +1,8 @@
+2019-01-26  Martin Jambor  <mjambor@suse.cz>
+
+       PR ipa/88933
+       * gfortran.dg/gomp/pr88933.f90: New test.
+
 2019-01-26  Iain Buclaw  <ibuclaw@gdcproject.org>
 
        PR d/89042
diff --git a/gcc/testsuite/gfortran.dg/gomp/pr88933.f90 b/gcc/testsuite/gfortran.dg/gomp/pr88933.f90
new file mode 100644 (file)
index 0000000..e4f30ae
--- /dev/null
@@ -0,0 +1,39 @@
+! PR ipa/88933
+! { dg-do compile }
+! { dg-options "-O1 -fexceptions -fipa-cp -fnon-call-exceptions -fopenmp -fno-inline-functions-called-once" }
+
+!$omp parallel  
+!$omp single
+  call a
+!$omp end single
+!$omp end parallel
+contains
+  subroutine b (c, d, e, f, g, h, i, j, k, m)
+    character (*) c
+    character  d
+    integer, dimension (m) :: e
+    integer, dimension (m) :: f
+    character  g
+    character  h
+    real, dimension (:, :, :) :: i
+    double precision, dimension (:, :, :) :: j
+    integer, dimension (:, :, :) :: k
+     
+    integer, dimension (m) :: l
+!$omp task firstprivate (k) firstprivate (l)
+    !$omp end task
+  c = ''
+  end  
+  subroutine a
+    character  c
+    character  d
+    integer, dimension (7) :: e
+    integer, dimension (7) :: f
+    character g
+    character h
+    real, dimension (5, 6, 7) :: i
+    double precision, dimension (6, 6, 7) :: j
+    integer, dimension (5, 7, 6) :: k
+    call b (c, d, e, f, g, h, i, j, k, 7)
+  end  
+end
index 2adb3953d6bea9482ccbfc54838a3d5a802f0260..f2e8b96ee8ef556e955d8c38b9b9afc1b68d5108 100644 (file)
@@ -43,7 +43,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "gimple-match.h"
 #include "gimple-fold.h"
 #include "tree-ssa-loop-niter.h"
-
+#include "cgraph.h"
 
 /* The set of blocks in that at least one of the following changes happened:
    -- the statement at the end of the block was changed
@@ -1380,3 +1380,76 @@ make_pass_cleanup_cfg_post_optimizing (gcc::context *ctxt)
 }
 
 
+/* Delete all unreachable basic blocks and update callgraph.
+   Doing so is somewhat nontrivial because we need to update all clones and
+   remove inline function that become unreachable.  */
+
+bool
+delete_unreachable_blocks_update_callgraph (cgraph_node *dst_node,
+                                           bool update_clones)
+{
+  bool changed = false;
+  basic_block b, next_bb;
+
+  find_unreachable_blocks ();
+
+  /* Delete all unreachable basic blocks.  */
+
+  for (b = ENTRY_BLOCK_PTR_FOR_FN (cfun)->next_bb; b
+       != EXIT_BLOCK_PTR_FOR_FN (cfun); b = next_bb)
+    {
+      next_bb = b->next_bb;
+
+      if (!(b->flags & BB_REACHABLE))
+       {
+          gimple_stmt_iterator bsi;
+
+          for (bsi = gsi_start_bb (b); !gsi_end_p (bsi); gsi_next (&bsi))
+           {
+             struct cgraph_edge *e;
+             struct cgraph_node *node;
+
+             dst_node->remove_stmt_references (gsi_stmt (bsi));
+
+             if (gimple_code (gsi_stmt (bsi)) == GIMPLE_CALL
+                 &&(e = dst_node->get_edge (gsi_stmt (bsi))) != NULL)
+               {
+                 if (!e->inline_failed)
+                   e->callee->remove_symbol_and_inline_clones (dst_node);
+                 else
+                   e->remove ();
+               }
+             if (update_clones && dst_node->clones)
+               for (node = dst_node->clones; node != dst_node;)
+                 {
+                   node->remove_stmt_references (gsi_stmt (bsi));
+                   if (gimple_code (gsi_stmt (bsi)) == GIMPLE_CALL
+                       && (e = node->get_edge (gsi_stmt (bsi))) != NULL)
+                     {
+                       if (!e->inline_failed)
+                         e->callee->remove_symbol_and_inline_clones (dst_node);
+                       else
+                         e->remove ();
+                     }
+
+                   if (node->clones)
+                     node = node->clones;
+                   else if (node->next_sibling_clone)
+                     node = node->next_sibling_clone;
+                   else
+                     {
+                       while (node != dst_node && !node->next_sibling_clone)
+                         node = node->clone_of;
+                       if (node != dst_node)
+                         node = node->next_sibling_clone;
+                     }
+                 }
+           }
+         delete_basic_block (b);
+         changed = true;
+       }
+    }
+
+  return changed;
+}
+
index e133bbdfbec681e189b5f80bc2f7df5369096769..bd27505fd5c8092611bcfc3800be24818807a3de 100644 (file)
@@ -24,5 +24,7 @@ along with GCC; see the file COPYING3.  If not see
 extern bitmap cfgcleanup_altered_bbs;
 extern bool cleanup_tree_cfg (void);
 extern bool fixup_noreturn_call (gimple *stmt);
+extern bool delete_unreachable_blocks_update_callgraph (cgraph_node *dst_node,
+                                                       bool update_clones);
 
 #endif /* GCC_TREE_CFGCLEANUP_H */
index eb5073c5f6124c956e8c0db91162e26d4ace155f..5c0c4c5ab91da61e6b8b74045f6840e4dc4b5a2a 100644 (file)
@@ -60,6 +60,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "stringpool.h"
 #include "attribs.h"
 #include "sreal.h"
+#include "tree-cfgcleanup.h"
 
 /* I'm not real happy about this, but we need to handle gimple and
    non-gimple trees.  */
@@ -132,7 +133,6 @@ static tree copy_decl_to_var (tree, copy_body_data *);
 static tree copy_result_decl_to_var (tree, copy_body_data *);
 static tree copy_decl_maybe_to_var (tree, copy_body_data *);
 static gimple_seq remap_gimple_stmt (gimple *, copy_body_data *);
-static bool delete_unreachable_blocks_update_callgraph (copy_body_data *id);
 static void insert_init_stmt (copy_body_data *, basic_block, gimple *);
 
 /* Insert a tree->tree mapping for ID.  Despite the name suggests
@@ -5124,7 +5124,8 @@ optimize_inline_calls (tree fn)
   /* Renumber the lexical scoping (non-code) blocks consecutively.  */
   number_blocks (fn);
 
-  delete_unreachable_blocks_update_callgraph (&id);
+  delete_unreachable_blocks_update_callgraph (id.dst_node, false);
+
   if (flag_checking)
     id.dst_node->verify ();
 
@@ -5708,79 +5709,6 @@ tree_versionable_function_p (tree fndecl)
          && copy_forbidden (DECL_STRUCT_FUNCTION (fndecl)) == NULL);
 }
 
-/* Delete all unreachable basic blocks and update callgraph.
-   Doing so is somewhat nontrivial because we need to update all clones and
-   remove inline function that become unreachable.  */
-
-static bool
-delete_unreachable_blocks_update_callgraph (copy_body_data *id)
-{
-  bool changed = false;
-  basic_block b, next_bb;
-
-  find_unreachable_blocks ();
-
-  /* Delete all unreachable basic blocks.  */
-
-  for (b = ENTRY_BLOCK_PTR_FOR_FN (cfun)->next_bb; b
-       != EXIT_BLOCK_PTR_FOR_FN (cfun); b = next_bb)
-    {
-      next_bb = b->next_bb;
-
-      if (!(b->flags & BB_REACHABLE))
-       {
-          gimple_stmt_iterator bsi;
-
-          for (bsi = gsi_start_bb (b); !gsi_end_p (bsi); gsi_next (&bsi))
-           {
-             struct cgraph_edge *e;
-             struct cgraph_node *node;
-
-             id->dst_node->remove_stmt_references (gsi_stmt (bsi));
-
-             if (gimple_code (gsi_stmt (bsi)) == GIMPLE_CALL
-                 &&(e = id->dst_node->get_edge (gsi_stmt (bsi))) != NULL)
-               {
-                 if (!e->inline_failed)
-                   e->callee->remove_symbol_and_inline_clones (id->dst_node);
-                 else
-                   e->remove ();
-               }
-             if (id->transform_call_graph_edges == CB_CGE_MOVE_CLONES
-                 && id->dst_node->clones)
-               for (node = id->dst_node->clones; node != id->dst_node;)
-                 {
-                   node->remove_stmt_references (gsi_stmt (bsi));
-                   if (gimple_code (gsi_stmt (bsi)) == GIMPLE_CALL
-                       && (e = node->get_edge (gsi_stmt (bsi))) != NULL)
-                     {
-                       if (!e->inline_failed)
-                         e->callee->remove_symbol_and_inline_clones (id->dst_node);
-                       else
-                         e->remove ();
-                     }
-
-                   if (node->clones)
-                     node = node->clones;
-                   else if (node->next_sibling_clone)
-                     node = node->next_sibling_clone;
-                   else
-                     {
-                       while (node != id->dst_node && !node->next_sibling_clone)
-                         node = node->clone_of;
-                       if (node != id->dst_node)
-                         node = node->next_sibling_clone;
-                     }
-                 }
-           }
-         delete_basic_block (b);
-         changed = true;
-       }
-    }
-
-  return changed;
-}
-
 /* Update clone info after duplication.  */
 
 static void
@@ -6094,7 +6022,7 @@ tree_function_versioning (tree old_decl, tree new_decl,
   update_max_bb_count ();
   fold_marked_statements (0, id.statements_to_fold);
   delete id.statements_to_fold;
-  delete_unreachable_blocks_update_callgraph (&id);
+  delete_unreachable_blocks_update_callgraph (id.dst_node, update_clones);
   if (id.dst_node->definition)
     cgraph_edge::rebuild_references ();
   if (loops_state_satisfies_p (LOOPS_NEED_FIXUP))