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
This commit is contained in:
Jan Hubicka 2014-03-26 03:11:57 +01:00 committed by Jan Hubicka
parent d7636f5609
commit 9de6f6c3ee
10 changed files with 105 additions and 13 deletions

View File

@ -1,3 +1,23 @@
2014-03-25 Jan Hubicka <hubicka@ucw.cz>
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.
2014-03-25 Jan Hubicka <hubicka@ucw.cz>
* ipa-pure-const.c (propagate_pure_const, propagate_nothrow):

View File

@ -2612,6 +2612,12 @@ verify_edge_corresponds_to_fndecl (struct cgraph_edge *e, tree decl)
|| node->in_other_partition
|| e->callee->in_other_partition)
return false;
/* Optimizers can redirect unreachable calls or calls triggering undefined
behaviour to builtin_unreachable. */
if (DECL_BUILT_IN_CLASS (e->callee->decl) == BUILT_IN_NORMAL
&& DECL_FUNCTION_CODE (e->callee->decl) == BUILT_IN_UNREACHABLE)
return false;
node = cgraph_function_or_thunk_node (node, NULL);
if (e->callee->former_clone_of != node->decl

View File

@ -238,8 +238,12 @@ cgraph_clone_node (struct cgraph_node *n, tree decl, gcov_type count, int freq,
FOR_EACH_VEC_ELT (redirect_callers, i, e)
{
/* Redirect calls to the old version node to point to its new
version. */
cgraph_redirect_edge_callee (e, new_node);
version. The only exception is when the edge was proved to
be unreachable during the clonning procedure. */
if (!e->callee
|| DECL_BUILT_IN_CLASS (e->callee->decl) != BUILT_IN_NORMAL
|| DECL_FUNCTION_CODE (e->callee->decl) != BUILT_IN_UNREACHABLE)
cgraph_redirect_edge_callee (e, new_node);
}

View File

@ -127,3 +127,7 @@ DEFCIFCODE(USES_COMDAT_LOCAL, CIF_FINAL_NORMAL,
/* We can't inline because of mismatched caller/callee attributes. */
DEFCIFCODE(ATTRIBUTE_MISMATCH, CIF_FINAL_NORMAL,
N_("function attribute mismatch"))
/* We proved that the call is unreachable. */
DEFCIFCODE(UNREACHABLE, CIF_FINAL_NORMAL,
N_("unreachable"))

View File

@ -2811,9 +2811,7 @@ create_specialized_node (struct cgraph_node *node,
if (aggvals)
ipa_dump_agg_replacement_values (dump_file, aggvals);
}
gcc_checking_assert (ipa_node_params_vector.exists ()
&& (ipa_node_params_vector.length ()
> (unsigned) cgraph_max_uid));
ipa_check_create_node_params ();
update_profiling_info (node, new_node);
new_info = IPA_NODE_REF (new_node);
new_info->ipcp_orig_node = node;

View File

@ -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;
}
}
}

View File

@ -1685,7 +1685,7 @@ inline_small_functions (void)
edge = (struct cgraph_edge *) fibheap_extract_min (edge_heap);
gcc_assert (edge->aux);
edge->aux = NULL;
if (!edge->inline_failed)
if (!edge->inline_failed || !edge->callee->analyzed)
continue;
/* Be sure that caches are maintained consistent.

View File

@ -285,7 +285,8 @@ static inline int
estimate_edge_growth (struct cgraph_edge *edge)
{
#ifdef ENABLE_CHECKING
gcc_checking_assert (inline_edge_summary (edge)->call_stmt_size);
gcc_checking_assert (inline_edge_summary (edge)->call_stmt_size
|| !edge->callee->analyzed);
#endif
return (estimate_edge_size (edge)
- inline_edge_summary (edge)->call_stmt_size);

View File

@ -1,3 +1,8 @@
2014-03-25 Jan Hubicka <hubicka@ucw.cz>
PR ipa/60315
* testsuite/g++.dg/torture/pr60315.C: New testcase.
2014-03-25 Martin Jambor <mjambor@suse.cz>
PR ipa/60600

View File

@ -0,0 +1,32 @@
// { dg-do compile }
struct Base {
virtual int f() = 0;
};
struct Derived : public Base {
virtual int f() final override {
return 42;
}
};
extern Base* b;
int main() {
return (static_cast<Derived*>(b)->*(&Derived::f))();
}
// { dg-do compile }
struct Base {
virtual int f() = 0;
};
struct Derived : public Base {
virtual int f() final override {
return 42;
}
};
extern Base* b;
int main() {
return (static_cast<Derived*>(b)->*(&Derived::f))();
}