Dne 2019-01-25 19:10, Martin Jambor napsal:
Hi,

the following patch fixes a verification ICE because of mismatching BB
and cgraph_edge counts arising as a consequence of cleaning-up CFG after
IPA-CP transformation, which is currently done as if it was a normal
tree pass, and which IPA passes should not attempt exaclty because of
this reason.

Fixed (hopefully) exactly as I was told by Honza in Bugzilla, by
resorting to calling delete_unreachable_blocks_update_callgraph
instead.  The aforementioned function had to be made public and in the
process was moved to a more suitable file.

Bootstrapped and tested on x86_64-linux.  OK for trunk?

OK,
Honza

Thanks,

Martin



2019-01-25  Martin Jambor  <mjam...@suse.cz>

        * 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.
---
 gcc/ipa-prop.c                             | 10 +--
 gcc/testsuite/gfortran.dg/gomp/pr88933.f90 | 39 +++++++++++
 gcc/tree-cfgcleanup.c                      | 75 +++++++++++++++++++-
 gcc/tree-cfgcleanup.h                      |  2 +
 gcc/tree-inline.c                          | 80 ++--------------------
 5 files changed, 125 insertions(+), 81 deletions(-)
 create mode 100644 gcc/testsuite/gfortran.dg/gomp/pr88933.f90

diff --git a/gcc/ipa-prop.c b/gcc/ipa-prop.c
index 40ab130b750..d86c2f3db55 100644
--- a/gcc/ipa-prop.c
+++ b/gcc/ipa-prop.c
@@ -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"
diff --git a/gcc/testsuite/gfortran.dg/gomp/pr88933.f90
b/gcc/testsuite/gfortran.dg/gomp/pr88933.f90
new file mode 100644
index 00000000000..e4f30ae9f3e
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/gomp/pr88933.f90
@@ -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
diff --git a/gcc/tree-cfgcleanup.c b/gcc/tree-cfgcleanup.c
index 2adb3953d6b..f2e8b96ee8e 100644
--- a/gcc/tree-cfgcleanup.c
+++ b/gcc/tree-cfgcleanup.c
@@ -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;
+}
+
diff --git a/gcc/tree-cfgcleanup.h b/gcc/tree-cfgcleanup.h
index e133bbdfbec..bd27505fd5c 100644
--- a/gcc/tree-cfgcleanup.h
+++ b/gcc/tree-cfgcleanup.h
@@ -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 */
diff --git a/gcc/tree-inline.c b/gcc/tree-inline.c
index 29f119ade77..d8bed50d78e 100644
--- a/gcc/tree-inline.c
+++ b/gcc/tree-inline.c
@@ -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
@@ -5123,7 +5123,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 ();

@@ -5707,79 +5708,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
@@ -6093,7 +6021,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))

Reply via email to