diff options
author | Martin Jambor <mjambor@suse.cz> | 2019-01-26 23:19:17 +0100 |
---|---|---|
committer | Martin Jambor <jamborm@gcc.gnu.org> | 2019-01-26 23:19:17 +0100 |
commit | 95a2ed0325864069bb0368d75bcf85a8b22c4127 (patch) | |
tree | 04c852d893bcc50234c3b2bead6edb14dabc70bd /gcc/tree-cfgcleanup.c | |
parent | e4e13e261060dde55de4f7135fe09a816a51f929 (diff) | |
download | gcc-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.c | 75 |
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; +} + |