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:
parent
d7636f5609
commit
9de6f6c3ee
@ -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):
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
@ -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"))
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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.
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
32
gcc/testsuite/g++.dg/torture/pr60315.C
Normal file
32
gcc/testsuite/g++.dg/torture/pr60315.C
Normal 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))();
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user