aboutsummaryrefslogtreecommitdiff
path: root/gcc/ipa-inline-analysis.c
diff options
context:
space:
mode:
authorJan Hubicka <hubicka@ucw.cz>2014-03-26 03:11:57 +0100
committerJan Hubicka <hubicka@gcc.gnu.org>2014-03-26 02:11:57 +0000
commit9de6f6c3eed463e8c41b95a28ad7f2186e379fff (patch)
tree58c27722a6391d91e8bbfcb902c1edc28e754d14 /gcc/ipa-inline-analysis.c
parentd7636f5609dc4325d145b82adc9dd977d079303e (diff)
downloadgcc-9de6f6c3eed463e8c41b95a28ad7f2186e379fff.zip
gcc-9de6f6c3eed463e8c41b95a28ad7f2186e379fff.tar.gz
gcc-9de6f6c3eed463e8c41b95a28ad7f2186e379fff.tar.bz2
re PR ipa/60315 (template constructor switch optimization)
PR ipa/60315 * cif-code.def (UNREACHABLE) New code. * ipa-inline.c (inline_small_functions): Skip edges to __builtlin_unreachable. (estimate_edge_growth): Allow edges to __builtlin_unreachable. * ipa-inline-analysis.c (edge_set_predicate): Redirect edges with false predicate to __bulitin_unreachable. (set_cond_stmt_execution_predicate): Fix issue when invert_tree_comparison returns ERROR_MARK. * ipa-pure-const.c (propagate_pure_const, propagate_nothrow): Do not propagate to inline clones. * cgraph.c (verify_edge_corresponds_to_fndecl): Allow redirection to unreachable. * ipa-cp.c (create_specialized_node): Be ready for new node to appear. * cgraphclones.c (cgraph_clone_node): If call destination is already ureachable, do not redirect it back. * tree-inline.c (fold_marked_statements): Hanlde calls becoming unreachable. From-SVN: r208831
Diffstat (limited to 'gcc/ipa-inline-analysis.c')
-rw-r--r--gcc/ipa-inline-analysis.c34
1 files changed, 28 insertions, 6 deletions
diff --git a/gcc/ipa-inline-analysis.c b/gcc/ipa-inline-analysis.c
index 98f42ef..ebc46a9 100644
--- a/gcc/ipa-inline-analysis.c
+++ b/gcc/ipa-inline-analysis.c
@@ -746,6 +746,20 @@ static void
edge_set_predicate (struct cgraph_edge *e, struct predicate *predicate)
{
struct inline_edge_summary *es = inline_edge_summary (e);
+
+ /* If the edge is determined to be never executed, redirect it
+ to BUILTIN_UNREACHABLE to save inliner from inlining into it. */
+ if (predicate && false_predicate_p (predicate) && e->callee)
+ {
+ struct cgraph_node *callee = !e->inline_failed ? e->callee : NULL;
+
+ cgraph_redirect_edge_callee (e,
+ cgraph_get_create_node
+ (builtin_decl_implicit (BUILT_IN_UNREACHABLE)));
+ e->inline_failed = CIF_UNREACHABLE;
+ if (callee)
+ cgraph_remove_node_and_inline_clones (callee, NULL);
+ }
if (predicate && !true_predicate_p (predicate))
{
if (!es->predicate)
@@ -1724,12 +1738,20 @@ set_cond_stmt_execution_predicate (struct ipa_node_params *info,
FOR_EACH_EDGE (e, ei, bb->succs)
{
- struct predicate p = add_condition (summary, index, &aggpos,
- e->flags & EDGE_TRUE_VALUE
- ? code : inverted_code,
- gimple_cond_rhs (last));
- e->aux = pool_alloc (edge_predicate_pool);
- *(struct predicate *) e->aux = p;
+ enum tree_code this_code = (e->flags & EDGE_TRUE_VALUE
+ ? code : inverted_code);
+ /* invert_tree_comparison will return ERROR_MARK on FP
+ comparsions that are not EQ/NE instead of returning proper
+ unordered one. Be sure it is not confused with NON_CONSTANT. */
+ if (this_code != ERROR_MARK)
+ {
+ struct predicate p = add_condition (summary, index, &aggpos,
+ e->flags & EDGE_TRUE_VALUE
+ ? code : inverted_code,
+ gimple_cond_rhs (last));
+ e->aux = pool_alloc (edge_predicate_pool);
+ *(struct predicate *) e->aux = p;
+ }
}
}