diff options
Diffstat (limited to 'gcc/tree-ssa-pre.c')
-rw-r--r-- | gcc/tree-ssa-pre.c | 40 |
1 files changed, 36 insertions, 4 deletions
diff --git a/gcc/tree-ssa-pre.c b/gcc/tree-ssa-pre.c index 8b4d2badb6f..0e968d5e22c 100644 --- a/gcc/tree-ssa-pre.c +++ b/gcc/tree-ssa-pre.c @@ -64,6 +64,7 @@ along with GCC; see the file COPYING3. If not see #include "domwalk.h" #include "ipa-prop.h" #include "tree-ssa-propagate.h" +#include "ipa-utils.h" /* TODO: @@ -4360,12 +4361,41 @@ eliminate_dom_walker::before_dom_children (basic_block b) { tree fn = gimple_call_fn (stmt); if (fn - && TREE_CODE (fn) == OBJ_TYPE_REF - && TREE_CODE (OBJ_TYPE_REF_EXPR (fn)) == SSA_NAME) + && flag_devirtualize + && virtual_method_call_p (fn)) { - fn = ipa_intraprocedural_devirtualization (stmt); - if (fn && dbg_cnt (devirt)) + tree otr_type; + HOST_WIDE_INT otr_token; + ipa_polymorphic_call_context context; + tree instance; + bool final; + + instance = get_polymorphic_call_info (current_function_decl, + fn, + &otr_type, &otr_token, &context, stmt); + + get_dynamic_type (instance, &context, + OBJ_TYPE_REF_OBJECT (fn), otr_type, stmt); + + vec <cgraph_node *>targets + = possible_polymorphic_call_targets (obj_type_ref_class (fn), + tree_to_uhwi + (OBJ_TYPE_REF_TOKEN (fn)), + context, + &final); + if (dump_enabled_p ()) + dump_possible_polymorphic_call_targets (dump_file, + obj_type_ref_class (fn), + tree_to_uhwi + (OBJ_TYPE_REF_TOKEN (fn)), + context); + if (final && targets.length () <= 1 && dbg_cnt (devirt)) { + tree fn; + if (targets.length () == 1) + fn = targets[0]->decl; + else + fn = builtin_decl_implicit (BUILT_IN_UNREACHABLE); if (dump_enabled_p ()) { location_t loc = gimple_location_safe (stmt); @@ -4377,6 +4407,8 @@ eliminate_dom_walker::before_dom_children (basic_block b) gimple_call_set_fndecl (stmt, fn); gimple_set_modified (stmt, true); } + else + gcc_assert (!ipa_intraprocedural_devirtualization (stmt)); } } |