aboutsummaryrefslogtreecommitdiff
path: root/gcc/tree-cfgcleanup.c
diff options
context:
space:
mode:
authorMartin Jambor <mjambor@suse.cz>2019-01-26 23:19:17 +0100
committerMartin Jambor <jamborm@gcc.gnu.org>2019-01-26 23:19:17 +0100
commit95a2ed0325864069bb0368d75bcf85a8b22c4127 (patch)
tree04c852d893bcc50234c3b2bead6edb14dabc70bd /gcc/tree-cfgcleanup.c
parente4e13e261060dde55de4f7135fe09a816a51f929 (diff)
downloadgcc-95a2ed0325864069bb0368d75bcf85a8b22c4127.zip
gcc-95a2ed0325864069bb0368d75bcf85a8b22c4127.tar.gz
gcc-95a2ed0325864069bb0368d75bcf85a8b22c4127.tar.bz2
[PR ipa/88933] Careful CFG cleanup in IPA-CP function transformation
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
Diffstat (limited to 'gcc/tree-cfgcleanup.c')
-rw-r--r--gcc/tree-cfgcleanup.c75
1 files changed, 74 insertions, 1 deletions
diff --git a/gcc/tree-cfgcleanup.c b/gcc/tree-cfgcleanup.c
index 2adb395..f2e8b96 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;
+}
+