From 6f8091fc3ed9d3cfa7a6dee7e9f9a34eb4308b2a Mon Sep 17 00:00:00 2001 From: Jan Hubicka Date: Sat, 20 Sep 2014 08:22:58 +0200 Subject: [PATCH] ipa-utils.h (ipa_polymorphic_call_context): Turn into class; add ctors. * ipa-utils.h (ipa_polymorphic_call_context): Turn into class; add ctors. (possible_polymorphic_call_targets, dump_possible_polymorphic_call_targets, possible_polymorphic_call_target_p, possible_polymorphic_call_target_p): Simplify. (get_dynamic_type): Remove. * ipa-devirt.c (ipa_dummy_polymorphic_call_context): Remove. (clear_speculation): Bring to ipa-deivrt.h (get_class_context): Rename to ... (ipa_polymorphic_call_context::restrict_to_inner_class): ... this one. (contains_type_p): Update. (get_dynamic_type): Rename to ... ipa_polymorphic_call_context::get_dynamic_type(): ... this one. (possible_polymorphic_call_targets): UPdate. * tree-ssa-pre.c (eliminate_dom_walker::before_dom_children): Update. * ipa-prop.c (ipa_analyze_call_uses): Update. From-SVN: r215418 --- gcc/ChangeLog | 17 ++++ gcc/cgraph.c | 16 ++-- gcc/gimple-fold.c | 4 +- gcc/ipa-cp.c | 7 +- gcc/ipa-devirt.c | 256 ++++++++++++++++++++++++++++++----------------------- gcc/ipa-prop.c | 19 ++-- gcc/ipa-utils.h | 84 +++++++++--------- gcc/tree-ssa-pre.c | 9 +- 8 files changed, 222 insertions(+), 190 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 87907fd..87b5e00 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,5 +1,22 @@ 2014-09-19 Jan Hubicka + * ipa-utils.h (ipa_polymorphic_call_context): Turn into class; add ctors. + (possible_polymorphic_call_targets, dump_possible_polymorphic_call_targets, + possible_polymorphic_call_target_p, possible_polymorphic_call_target_p): Simplify. + (get_dynamic_type): Remove. + * ipa-devirt.c (ipa_dummy_polymorphic_call_context): Remove. + (clear_speculation): Bring to ipa-deivrt.h + (get_class_context): Rename to ... + (ipa_polymorphic_call_context::restrict_to_inner_class): ... this one. + (contains_type_p): Update. + (get_dynamic_type): Rename to ... + ipa_polymorphic_call_context::get_dynamic_type(): ... this one. + (possible_polymorphic_call_targets): UPdate. + * tree-ssa-pre.c (eliminate_dom_walker::before_dom_children): Update. + * ipa-prop.c (ipa_analyze_call_uses): Update. + +2014-09-19 Jan Hubicka + * ipa-visibility.c (varpool_node::externally_visible_p): Do not privatize dynamic TLS variables. diff --git a/gcc/cgraph.c b/gcc/cgraph.c index 99e0076..8f04284 100644 --- a/gcc/cgraph.c +++ b/gcc/cgraph.c @@ -884,21 +884,15 @@ cgraph_node::create_indirect_edge (gimple call_stmt, int ecf_flags, && (target = gimple_call_fn (call_stmt)) && virtual_method_call_p (target)) { - tree otr_type; - HOST_WIDE_INT otr_token; - ipa_polymorphic_call_context context; - - get_polymorphic_call_info (decl, - target, - &otr_type, &otr_token, - &context, call_stmt); + ipa_polymorphic_call_context context (decl, target, call_stmt); /* Only record types can have virtual calls. */ - gcc_assert (TREE_CODE (otr_type) == RECORD_TYPE); edge->indirect_info->polymorphic = true; edge->indirect_info->param_index = -1; - edge->indirect_info->otr_token = otr_token; - edge->indirect_info->otr_type = otr_type; + edge->indirect_info->otr_token + = tree_to_uhwi (OBJ_TYPE_REF_TOKEN (target)); + edge->indirect_info->otr_type = obj_type_ref_class (target); + gcc_assert (TREE_CODE (edge->indirect_info->otr_type) == RECORD_TYPE); edge->indirect_info->outer_type = context.outer_type; edge->indirect_info->speculative_outer_type = context.speculative_outer_type; diff --git a/gcc/gimple-fold.c b/gcc/gimple-fold.c index 3d5e3b9..dc2c942 100644 --- a/gcc/gimple-fold.c +++ b/gcc/gimple-fold.c @@ -2563,8 +2563,8 @@ gimple_fold_call (gimple_stmt_iterator *gsi, bool inplace) { if (dump_file && virtual_method_call_p (callee) && !possible_polymorphic_call_target_p - (callee, cgraph_node::get (gimple_call_addr_fndecl - (OBJ_TYPE_REF_EXPR (callee))))) + (callee, stmt, cgraph_node::get (gimple_call_addr_fndecl + (OBJ_TYPE_REF_EXPR (callee))))) { fprintf (dump_file, "Type inheritance inconsistent devirtualization of "); diff --git a/gcc/ipa-cp.c b/gcc/ipa-cp.c index d365634..2ff3b9c 100644 --- a/gcc/ipa-cp.c +++ b/gcc/ipa-cp.c @@ -1618,14 +1618,11 @@ ipa_get_indirect_edge_target_1 (struct cgraph_edge *ie, if (TREE_CODE (t) != TREE_BINFO) { - ipa_polymorphic_call_context context; + ipa_polymorphic_call_context context (t, ie->indirect_info->otr_type, + anc_offset); vec targets; bool final; - if (!get_polymorphic_call_info_from_invariant - (&context, t, ie->indirect_info->otr_type, - anc_offset)) - return NULL_TREE; targets = possible_polymorphic_call_targets (ie->indirect_info->otr_type, ie->indirect_info->otr_token, diff --git a/gcc/ipa-devirt.c b/gcc/ipa-devirt.c index 774275b..af42c6d 100644 --- a/gcc/ipa-devirt.c +++ b/gcc/ipa-devirt.c @@ -2400,41 +2400,43 @@ decl_maybe_in_construction_p (tree base, tree outer_type, } /* Proudce polymorphic call context for call method of instance - that is located within BASE (that is assumed to be a decl) at OFFSET. */ + that is located within BASE (that is assumed to be a decl) at offset OFF. */ -static void -get_polymorphic_call_info_for_decl (ipa_polymorphic_call_context *context, - tree base, HOST_WIDE_INT offset) +void +ipa_polymorphic_call_context::set_by_decl (tree base, HOST_WIDE_INT off) { gcc_assert (DECL_P (base)); - context->outer_type = TYPE_MAIN_VARIANT (TREE_TYPE (base)); - context->offset = offset; - context->speculative_outer_type = NULL; - context->speculative_offset = 0; - context->speculative_maybe_derived_type = true; + outer_type = TYPE_MAIN_VARIANT (TREE_TYPE (base)); + offset = off; + clear_speculation (); /* Make very conservative assumption that all objects may be in construction. TODO: ipa-prop already contains code to tell better. merge it later. */ - context->maybe_in_construction = true; - context->maybe_derived_type = false; + maybe_in_construction = true; + maybe_derived_type = false; } /* CST is an invariant (address of decl), try to get meaningful polymorphic call context for polymorphic call of method - if instance of OTR_TYPE that is located at OFFSET of this invariant. + if instance of OTR_TYPE that is located at offset OFF of this invariant. Return FALSE if nothing meaningful can be found. */ bool -get_polymorphic_call_info_from_invariant (ipa_polymorphic_call_context *context, - tree cst, - tree otr_type, - HOST_WIDE_INT offset) +ipa_polymorphic_call_context::set_by_invariant (tree cst, + tree otr_type, + HOST_WIDE_INT off) { HOST_WIDE_INT offset2, size, max_size; tree base; + invalid = false; + off = 0; + outer_type = NULL; + maybe_in_construction = true; + maybe_derived_type = true; + if (TREE_CODE (cst) != ADDR_EXPR) return false; @@ -2445,10 +2447,13 @@ get_polymorphic_call_info_from_invariant (ipa_polymorphic_call_context *context, /* Only type inconsistent programs can have otr_type that is not part of outer type. */ - if (!contains_type_p (TREE_TYPE (base), offset, otr_type)) - return false; + if (otr_type && !contains_type_p (TREE_TYPE (base), off, otr_type)) + { + invalid = true; + return false; + } - get_polymorphic_call_info_for_decl (context, base, offset); + set_by_decl (base, off); return true; } @@ -2472,34 +2477,46 @@ walk_ssa_copies (tree op) return op; } -/* Given REF call in FNDECL, determine class of the polymorphic - call (OTR_TYPE), its token (OTR_TOKEN) and CONTEXT. - CALL is optional argument giving the actual statement (usually call) where - the context is used. - Return pointer to object described by the context or an declaration if - we found the instance to be stored in the static storage. */ +/* Create polymorphic call context from IP invariant CST. + This is typically &global_var. + OTR_TYPE specify type of polymorphic call or NULL if unknown, OFF + is offset of call. */ -tree -get_polymorphic_call_info (tree fndecl, - tree ref, - tree *otr_type, - HOST_WIDE_INT *otr_token, - ipa_polymorphic_call_context *context, - gimple call) +ipa_polymorphic_call_context::ipa_polymorphic_call_context (tree cst, + tree otr_type, + HOST_WIDE_INT off) +{ + clear_speculation (); + set_by_invariant (cst, otr_type, off); +} + +/* Build context for pointer REF contained in FNDECL at statement STMT. + if INSTANCE is non-NULL, return pointer to the object described by + the context or DECL where context is contained in. */ + +ipa_polymorphic_call_context::ipa_polymorphic_call_context (tree fndecl, + tree ref, + gimple stmt, + tree *instance) { + tree otr_type = NULL; tree base_pointer; - *otr_type = obj_type_ref_class (ref); - *otr_token = tree_to_uhwi (OBJ_TYPE_REF_TOKEN (ref)); + + if (TREE_CODE (ref) == OBJ_TYPE_REF) + { + otr_type = obj_type_ref_class (ref); + base_pointer = OBJ_TYPE_REF_OBJECT (ref); + } + else + base_pointer = ref; /* Set up basic info in case we find nothing interesting in the analysis. */ - context->speculative_outer_type = NULL; - context->speculative_offset = 0; - context->speculative_maybe_derived_type = true; - context->outer_type = TYPE_MAIN_VARIANT (*otr_type); - context->offset = 0; - base_pointer = OBJ_TYPE_REF_OBJECT (ref); - context->maybe_derived_type = true; - context->maybe_in_construction = true; + clear_speculation (); + outer_type = TYPE_MAIN_VARIANT (otr_type); + offset = 0; + maybe_derived_type = true; + maybe_in_construction = true; + invalid = false; /* Walk SSA for outer object. */ do @@ -2522,9 +2539,9 @@ get_polymorphic_call_info (tree fndecl, if (TREE_CODE (base) == MEM_REF) { base_pointer = TREE_OPERAND (base, 0); - context->offset + offset += offset2 + mem_ref_offset (base).to_short_addr () * BITS_PER_UNIT; - context->outer_type = NULL; + outer_type = NULL; } /* We found base object. In this case the outer_type is known. */ @@ -2534,24 +2551,25 @@ get_polymorphic_call_info (tree fndecl, /* Only type inconsistent programs can have otr_type that is not part of outer type. */ - if (!contains_type_p (TREE_TYPE (base), - context->offset + offset2, *otr_type)) + if (otr_type + && !contains_type_p (TREE_TYPE (base), + offset + offset2, otr_type)) { - /* Use OTR_TOKEN = INT_MAX as a marker of probably type inconsistent - code sequences; we arrange the calls to be builtin_unreachable - later. */ - *otr_token = INT_MAX; - return base_pointer; + invalid = true; + if (instance) + *instance = base_pointer; + return; } - get_polymorphic_call_info_for_decl (context, base, - context->offset + offset2); - if (context->maybe_in_construction && call) - context->maybe_in_construction + set_by_decl (base, offset + offset2); + if (maybe_in_construction && stmt) + maybe_in_construction = decl_maybe_in_construction_p (base, - context->outer_type, - call, + outer_type, + stmt, fndecl); - return base; + if (instance) + *instance = base; + return; } else break; @@ -2562,7 +2580,7 @@ get_polymorphic_call_info (tree fndecl, else if (TREE_CODE (base_pointer) == POINTER_PLUS_EXPR && tree_fits_uhwi_p (TREE_OPERAND (base_pointer, 1))) { - context->offset += tree_to_shwi (TREE_OPERAND (base_pointer, 1)) + offset += tree_to_shwi (TREE_OPERAND (base_pointer, 1)) * BITS_PER_UNIT; base_pointer = TREE_OPERAND (base_pointer, 0); } @@ -2580,19 +2598,22 @@ get_polymorphic_call_info (tree fndecl, if (TREE_CODE (TREE_TYPE (fndecl)) == METHOD_TYPE && SSA_NAME_VAR (base_pointer) == DECL_ARGUMENTS (fndecl)) { - context->outer_type + outer_type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (base_pointer))); - gcc_assert (TREE_CODE (context->outer_type) == RECORD_TYPE); + gcc_assert (TREE_CODE (outer_type) == RECORD_TYPE); /* Dynamic casting has possibly upcasted the type in the hiearchy. In this case outer type is less informative than inner type and we should forget about it. */ - if (!contains_type_p (context->outer_type, context->offset, - *otr_type)) + if (otr_type + && !contains_type_p (outer_type, offset, + otr_type)) { - context->outer_type = NULL; - return base_pointer; + outer_type = NULL; + if (instance) + *instance = base_pointer; + return; } /* If the function is constructor or destructor, then @@ -2601,38 +2622,41 @@ get_polymorphic_call_info (tree fndecl, if (DECL_CXX_CONSTRUCTOR_P (fndecl) || DECL_CXX_DESTRUCTOR_P (fndecl)) { - context->maybe_in_construction = true; - context->maybe_derived_type = false; + maybe_in_construction = true; + maybe_derived_type = false; } else { - context->maybe_derived_type = true; - context->maybe_in_construction = false; + maybe_derived_type = true; + maybe_in_construction = false; } - return base_pointer; + if (instance) + *instance = base_pointer; + return; } /* Non-PODs passed by value are really passed by invisible reference. In this case we also know the type of the object. */ if (DECL_BY_REFERENCE (SSA_NAME_VAR (base_pointer))) { - context->outer_type + outer_type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (base_pointer))); - gcc_assert (!POINTER_TYPE_P (context->outer_type)); + gcc_assert (!POINTER_TYPE_P (outer_type)); /* Only type inconsistent programs can have otr_type that is not part of outer type. */ - if (!contains_type_p (context->outer_type, context->offset, - *otr_type)) + if (!contains_type_p (outer_type, offset, + otr_type)) { - /* Use OTR_TOKEN = INT_MAX as a marker of probably type inconsistent - code sequences; we arrange the calls to be builtin_unreachable - later. */ - *otr_token = INT_MAX; - return base_pointer; + invalid = true; + if (instance) + *instance = base_pointer; + return; } - context->maybe_derived_type = false; - context->maybe_in_construction = false; - return base_pointer; + maybe_derived_type = false; + maybe_in_construction = false; + if (instance) + *instance = base_pointer; + return; } } @@ -2642,11 +2666,10 @@ get_polymorphic_call_info (tree fndecl, && SSA_NAME_IS_DEFAULT_DEF (base_pointer) && TREE_CODE (SSA_NAME_VAR (base_pointer)) != PARM_DECL) { - /* Use OTR_TOKEN = INT_MAX as a marker of probably type inconsistent - code sequences; we arrange the calls to be builtin_unreachable - later. */ - *otr_token = INT_MAX; - return base_pointer; + invalid = true; + if (instance) + *instance = base_pointer; + return; } if (TREE_CODE (base_pointer) == SSA_NAME && SSA_NAME_DEF_STMT (base_pointer) @@ -2655,19 +2678,22 @@ get_polymorphic_call_info (tree fndecl, (SSA_NAME_DEF_STMT (base_pointer))); if (POINTER_TYPE_P (base_type) - && contains_type_p (TYPE_MAIN_VARIANT (TREE_TYPE (base_type)), - context->offset, - *otr_type)) + && (otr_type + || !contains_type_p (TYPE_MAIN_VARIANT (TREE_TYPE (base_type)), + offset, + otr_type))) { - context->speculative_outer_type = TYPE_MAIN_VARIANT + speculative_outer_type = TYPE_MAIN_VARIANT (TREE_TYPE (base_type)); - context->speculative_offset = context->offset; - context->speculative_maybe_derived_type = true; + speculative_offset = offset; + speculative_maybe_derived_type = true; } /* TODO: There are multiple ways to derive a type. For instance if BASE_POINTER is passed to an constructor call prior our refernece. We do not make this type of flow sensitive analysis yet. */ - return base_pointer; + if (instance) + *instance = base_pointer; + return; } /* Structure to be passed in between detect_type_change and @@ -3404,9 +3430,6 @@ struct final_warning_record *final_warning_records; temporarily change to one of base types. INCLUDE_DERIVER_TYPES make us to walk the inheritance graph for all derivations. - OTR_TOKEN == INT_MAX is used to mark calls that are provably - undefined and should be redirected to unreachable. - If COMPLETEP is non-NULL, store true if the list is complete. CACHE_TOKEN (if non-NULL) will get stored to an unique ID of entry in the target cache. If user needs to visit every target list @@ -3443,23 +3466,12 @@ possible_polymorphic_call_targets (tree otr_type, otr_type = TYPE_MAIN_VARIANT (otr_type); - /* If ODR is not initialized, return empty incomplete list. */ - if (!odr_hash) + /* If ODR is not initialized or the constext is invalid, return empty + incomplete list. */ + if (!odr_hash || context.invalid) { if (completep) - *completep = false; - if (cache_token) - *cache_token = NULL; - if (speculative_targetsp) - *speculative_targetsp = 0; - return nodes; - } - - /* If we hit type inconsistency, just return empty list of targets. */ - if (otr_token == INT_MAX) - { - if (completep) - *completep = true; + *completep = context.invalid; if (cache_token) *cache_token = NULL; if (speculative_targetsp) @@ -3853,6 +3865,26 @@ possible_polymorphic_call_target_p (tree otr_type, } + +/* Return true if N can be possibly target of a polymorphic call of + OBJ_TYPE_REF expression REF in STMT. */ + +bool +possible_polymorphic_call_target_p (tree ref, + gimple stmt, + struct cgraph_node *n) +{ + ipa_polymorphic_call_context context (current_function_decl, ref, stmt); + tree call_fn = gimple_call_fn (stmt); + + return possible_polymorphic_call_target_p (obj_type_ref_class (call_fn), + tree_to_uhwi + (OBJ_TYPE_REF_TOKEN (call_fn)), + context, + n); +} + + /* After callgraph construction new external nodes may appear. Add them into the graph. */ diff --git a/gcc/ipa-prop.c b/gcc/ipa-prop.c index bbb417d..9223f3a 100644 --- a/gcc/ipa-prop.c +++ b/gcc/ipa-prop.c @@ -2347,14 +2347,13 @@ ipa_analyze_call_uses (struct func_body_info *fbi, gimple call) { tree otr_type; HOST_WIDE_INT otr_token; - ipa_polymorphic_call_context context; tree instance; tree target = gimple_call_fn (call); + ipa_polymorphic_call_context context (current_function_decl, + target, call, &instance); - instance = get_polymorphic_call_info (current_function_decl, - target, - &otr_type, &otr_token, - &context, call); + otr_type = obj_type_ref_class (target); + otr_token = tree_to_uhwi (OBJ_TYPE_REF_TOKEN (target)); if (context.get_dynamic_type (instance, OBJ_TYPE_REF_OBJECT (target), @@ -2609,7 +2608,7 @@ ipa_intraprocedural_devirtualization (gimple call) #ifdef ENABLE_CHECKING if (fndecl) gcc_assert (possible_polymorphic_call_target_p - (otr, cgraph_node::get (fndecl))); + (otr, call, cgraph_node::get (fndecl))); #endif return fndecl; } @@ -3121,14 +3120,12 @@ try_make_edge_direct_virtual_call (struct cgraph_edge *ie, if (TREE_CODE (binfo) != TREE_BINFO) { - ipa_polymorphic_call_context context; + ipa_polymorphic_call_context context (binfo, + ie->indirect_info->otr_type, + ie->indirect_info->offset); vec targets; bool final; - if (!get_polymorphic_call_info_from_invariant - (&context, binfo, ie->indirect_info->otr_type, - ie->indirect_info->offset)) - return NULL; targets = possible_polymorphic_call_targets (ie->indirect_info->otr_type, ie->indirect_info->otr_token, diff --git a/gcc/ipa-utils.h b/gcc/ipa-utils.h index 9c81d5c..c81232c 100644 --- a/gcc/ipa-utils.h +++ b/gcc/ipa-utils.h @@ -53,12 +53,28 @@ public: /* True if speculative outer object may be of derived type. We always speculate that construction does not happen. */ bool speculative_maybe_derived_type; + /* True if the context is invalid and all calls should be redirected + to BUILTIN_UNREACHABLE. */ + bool invalid; /* Build empty "I know nothing" context. */ ipa_polymorphic_call_context (); - /* Build polymorphic call context for indirect call E. */ ipa_polymorphic_call_context (cgraph_edge *e); + /* Build polymorphic call context for IP invariant CST. + If specified, OTR_TYPE specify the type of polymorphic call + that takes CST+OFFSET as a prameter. */ + ipa_polymorphic_call_context (tree cst, tree otr_type = NULL, + HOST_WIDE_INT offset = 0); + /* Build context for pointer REF contained in FNDECL at statement STMT. + if INSTANCE is non-NULL, return pointer to the object described by + the context. */ + ipa_polymorphic_call_context (tree fndecl, tree ref, gimple stmt, + tree *instance = NULL); + + /* Look for vtable stores or constructor calls to work out dynamic type + of memory location. */ + bool get_dynamic_type (tree, tree, tree, gimple); /* Make context non-speculative. */ void clear_speculation (); @@ -67,9 +83,9 @@ public: containing EXPECTED_TYPE as base class. */ bool restrict_to_inner_class (tree expected_type); - /* Look for vtable stores or constructor calls to work out dynamic type - of memory location. */ - bool get_dynamic_type (tree, tree, tree, gimple); +private: + void set_by_decl (tree, HOST_WIDE_INT); + bool set_by_invariant (tree, tree, HOST_WIDE_INT); }; /* Build polymorphic call context for indirect call E. */ @@ -77,6 +93,8 @@ public: inline ipa_polymorphic_call_context::ipa_polymorphic_call_context (cgraph_edge *e) { + gcc_checking_assert (e->indirect_info->polymorphic); + offset = e->indirect_info->offset; speculative_offset = e->indirect_info->speculative_offset; outer_type = e->indirect_info->outer_type; @@ -84,16 +102,22 @@ ipa_polymorphic_call_context::ipa_polymorphic_call_context (cgraph_edge *e) maybe_in_construction = e->indirect_info->maybe_in_construction; maybe_derived_type = e->indirect_info->maybe_derived_type; speculative_maybe_derived_type = e->indirect_info->speculative_maybe_derived_type; + invalid = false; } /* Build empty "I know nothing" context. */ inline ipa_polymorphic_call_context::ipa_polymorphic_call_context () - : offset(0), speculative_offset(0), outer_type(NULL), - speculative_outer_type(NULL), maybe_in_construction(false), - maybe_derived_type(false), speculative_maybe_derived_type(false) { + offset = 0; + speculative_offset = 0; + outer_type = NULL; + speculative_outer_type = NULL; + maybe_in_construction = true; + maybe_derived_type = true; + speculative_maybe_derived_type = false; + invalid = false; } /* Make context non-speculative. */ @@ -131,22 +155,17 @@ void update_type_inheritance_graph (void); vec possible_polymorphic_call_targets (tree, HOST_WIDE_INT, ipa_polymorphic_call_context, - bool *final = NULL, + bool *copletep = NULL, void **cache_token = NULL, int *nonconstruction_targets = NULL); odr_type get_odr_type (tree, bool insert = false); +bool possible_polymorphic_call_target_p (tree ref, gimple stmt, struct cgraph_node *n); void dump_possible_polymorphic_call_targets (FILE *, tree, HOST_WIDE_INT, const ipa_polymorphic_call_context &); bool possible_polymorphic_call_target_p (tree, HOST_WIDE_INT, const ipa_polymorphic_call_context &, struct cgraph_node *); tree method_class_type (const_tree); -tree get_polymorphic_call_info (tree, tree, tree *, - HOST_WIDE_INT *, - ipa_polymorphic_call_context *, - gimple call = NULL); -bool get_polymorphic_call_info_from_invariant (ipa_polymorphic_call_context *, - tree, tree, HOST_WIDE_INT); bool decl_maybe_in_construction_p (tree, tree, gimple, tree); tree vtable_pointer_value_to_binfo (const_tree); bool vtable_pointer_value_to_vtable (const_tree, tree *, unsigned HOST_WIDE_INT *); @@ -155,7 +174,7 @@ bool contains_polymorphic_type_p (const_tree); void register_odr_type (tree); /* Return vector containing possible targets of polymorphic call E. - If FINALP is non-NULL, store true if the list is complette. + If COMPLETEP is non-NULL, store true if the list is complette. CACHE_TOKEN (if non-NULL) will get stored to an unique ID of entry in the target cache. If user needs to visit every target list just once, it can memoize them. @@ -166,16 +185,16 @@ void register_odr_type (tree); inline vec possible_polymorphic_call_targets (struct cgraph_edge *e, - bool *final = NULL, + bool *completep = NULL, void **cache_token = NULL, int *nonconstruction_targets = NULL) { - gcc_checking_assert (e->indirect_info->polymorphic); ipa_polymorphic_call_context context(e); + return possible_polymorphic_call_targets (e->indirect_info->otr_type, e->indirect_info->otr_token, context, - final, cache_token, + completep, cache_token, nonconstruction_targets); } @@ -184,21 +203,16 @@ possible_polymorphic_call_targets (struct cgraph_edge *e, inline vec possible_polymorphic_call_targets (tree ref, gimple call, - bool *final = NULL, + bool *completep = NULL, void **cache_token = NULL) { - tree otr_type; - HOST_WIDE_INT otr_token; - ipa_polymorphic_call_context context; + ipa_polymorphic_call_context context (current_function_decl, ref, call); - get_polymorphic_call_info (current_function_decl, - ref, - &otr_type, &otr_token, &context, call); return possible_polymorphic_call_targets (obj_type_ref_class (ref), tree_to_uhwi (OBJ_TYPE_REF_TOKEN (ref)), context, - final, cache_token); + completep, cache_token); } /* Dump possible targets of a polymorphic call E into F. */ @@ -206,8 +220,8 @@ possible_polymorphic_call_targets (tree ref, inline void dump_possible_polymorphic_call_targets (FILE *f, struct cgraph_edge *e) { - gcc_checking_assert (e->indirect_info->polymorphic); ipa_polymorphic_call_context context(e); + dump_possible_polymorphic_call_targets (f, e->indirect_info->otr_type, e->indirect_info->otr_token, context); @@ -221,26 +235,12 @@ possible_polymorphic_call_target_p (struct cgraph_edge *e, struct cgraph_node *n) { ipa_polymorphic_call_context context(e); + return possible_polymorphic_call_target_p (e->indirect_info->otr_type, e->indirect_info->otr_token, context, n); } -/* Return true if N can be possibly target of a polymorphic call of - OBJ_TYPE_REF expression CALL. */ - -inline bool -possible_polymorphic_call_target_p (tree call, - struct cgraph_node *n) -{ - ipa_polymorphic_call_context context; - return possible_polymorphic_call_target_p (obj_type_ref_class (call), - tree_to_uhwi - (OBJ_TYPE_REF_TOKEN (call)), - context, - n); -} - /* Return true of T is type with One Definition Rule info attached. It means that either it is anonymous type or it has assembler name set. */ diff --git a/gcc/tree-ssa-pre.c b/gcc/tree-ssa-pre.c index 5f32b59..235846f 100644 --- a/gcc/tree-ssa-pre.c +++ b/gcc/tree-ssa-pre.c @@ -4277,16 +4277,11 @@ eliminate_dom_walker::before_dom_children (basic_block b) && flag_devirtualize && virtual_method_call_p (fn)) { - tree otr_type; - HOST_WIDE_INT otr_token; - ipa_polymorphic_call_context context; + tree otr_type = obj_type_ref_class (fn); tree instance; + ipa_polymorphic_call_context context (current_function_decl, fn, stmt, &instance); bool final; - instance = get_polymorphic_call_info (current_function_decl, - fn, - &otr_type, &otr_token, &context, stmt); - context.get_dynamic_type (instance, OBJ_TYPE_REF_OBJECT (fn), otr_type, stmt); vec targets -- 2.7.4