GCC Middle and Back End API Reference
ipa-polymorphic-call.cc File Reference
#include "config.h"
#include "system.h"
#include "coretypes.h"
#include "backend.h"
#include "rtl.h"
#include "tree.h"
#include "gimple.h"
#include "tree-pass.h"
#include "tree-ssa-operands.h"
#include "streamer-hooks.h"
#include "cgraph.h"
#include "data-streamer.h"
#include "diagnostic.h"
#include "alias.h"
#include "fold-const.h"
#include "calls.h"
#include "ipa-utils.h"
#include "tree-dfa.h"
#include "gimple-pretty-print.h"
#include "tree-into-ssa.h"
#include "alloc-pool.h"
#include "symbol-summary.h"
#include "symtab-thunks.h"
Include dependency graph for ipa-polymorphic-call.cc:

Data Structures

struct  type_change_info
 

Functions

static bool contains_type_p (tree, HOST_WIDE_INT, tree, bool consider_placement_new=true, bool consider_bases=true)
 
bool contains_polymorphic_type_p (const_tree type)
 
bool possible_placement_new (tree type, tree expected_type, HOST_WIDE_INT cur_offset)
 
tree polymorphic_ctor_dtor_p (tree fn, bool check_clones)
 
tree inlined_polymorphic_ctor_dtor_block_p (tree block, bool check_clones)
 
bool decl_maybe_in_construction_p (tree base, tree outer_type, gimple *call, tree function)
 
static tree walk_ssa_copies (tree op, hash_set< tree > **global_visited=NULL)
 
static bool noncall_stmt_may_be_vtbl_ptr_store (gimple *stmt)
 
static tree extr_type_from_vtbl_ptr_store (gimple *stmt, struct type_change_info *tci, HOST_WIDE_INT *type_offset)
 
static void record_known_type (struct type_change_info *tci, tree type, HOST_WIDE_INT offset)
 
static bool csftc_abort_walking_p (unsigned speculative)
 
static bool check_stmt_for_type_change (ao_ref *ao, tree vdef, void *data)
 

Function Documentation

◆ check_stmt_for_type_change()

◆ contains_polymorphic_type_p()

◆ contains_type_p()

static bool contains_type_p ( tree outer_type,
HOST_WIDE_INT offset,
tree otr_type,
bool consider_placement_new = true,
bool consider_bases = true )
static
Analysis of polymorphic call context.
   Copyright (C) 2013-2024 Free Software Foundation, Inc.
   Contributed by Jan Hubicka

This file is part of GCC.

GCC is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 3, or (at your option) any later
version.

GCC is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
for more details.

You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING3.  If not see
<http://www.gnu.org/licenses/>.   
Return true when TYPE contains an polymorphic type and thus is interesting
for devirtualization machinery.   
Return true if OUTER_TYPE contains OTR_TYPE at OFFSET.
CONSIDER_PLACEMENT_NEW makes function to accept cases where OTR_TYPE can
be built within OUTER_TYPE by means of placement new.  CONSIDER_BASES makes
function to accept cases where OTR_TYPE appears as base of OUTER_TYPE or as
base of one of fields of OUTER_TYPE.   

References ipa_polymorphic_call_context::dynamic, ipa_polymorphic_call_context::maybe_derived_type, ipa_polymorphic_call_context::offset, offset, ipa_polymorphic_call_context::outer_type, ipa_polymorphic_call_context::restrict_to_inner_class(), and TYPE_MAIN_VARIANT.

Referenced by ipa_polymorphic_call_context::combine_speculation_with(), ipa_polymorphic_call_context::combine_with(), ipa_polymorphic_call_context::ipa_polymorphic_call_context(), ipa_polymorphic_call_context::meet_speculation_with(), ipa_polymorphic_call_context::meet_with(), ipa_polymorphic_call_context::set_by_invariant(), and ipa_polymorphic_call_context::speculation_consistent_p().

◆ csftc_abort_walking_p()

static bool csftc_abort_walking_p ( unsigned speculative)
inlinestatic
The maximum number of may-defs we visit when looking for a must-def
that changes the dynamic type in check_stmt_for_type_change.  Tuned
after the PR12392 testcase which unlimited spends 40% time within
these alias walks and 8% with the following limit.   

References true.

Referenced by check_stmt_for_type_change().

◆ decl_maybe_in_construction_p()

bool decl_maybe_in_construction_p ( tree base,
tree outer_type,
gimple * call,
tree function )
We know that the instance is stored in variable or parameter
(not dynamically allocated) and we want to disprove the fact
that it may be in construction at invocation of CALL.

BASE represents memory location where instance is stored.
If BASE is NULL, it is assumed to be global memory.
OUTER_TYPE is known type of the instance or NULL if not
known.

For the variable to be in construction we actually need to
be in constructor of corresponding global variable or
the inline stack of CALL must contain the constructor.
Check this condition.  This check works safely only before
IPA passes, because inline stacks may become out of date
later.   

References auto_var_in_fn_p(), BLOCK_SUPERCONTEXT, DECL_ABSTRACT_ORIGIN, DECL_CXX_CONSTRUCTOR_P, DECL_CXX_DESTRUCTOR_P, DECL_P, DECL_STRUCT_FUNCTION, ECF_CONST, ECF_PURE, flags_from_decl_or_type(), gcc_assert, gimple_block(), inlined_polymorphic_ctor_dtor_block_p(), is_global_var(), polymorphic_type_binfo_p(), TREE_CODE, TREE_TYPE, TYPE_BINFO, TYPE_MAIN_VARIANT, TYPE_METHOD_BASETYPE, types_odr_comparable(), types_same_for_odr(), and VAR_P.

Referenced by symbol_table::create_edge(), and ipa_polymorphic_call_context::ipa_polymorphic_call_context().

◆ extr_type_from_vtbl_ptr_store()

static tree extr_type_from_vtbl_ptr_store ( gimple * stmt,
struct type_change_info * tci,
HOST_WIDE_INT * type_offset )
static
If STMT can be proved to be an assignment to the virtual method table
pointer of ANALYZED_OBJ and the type associated with the new table
identified, return the type.  Otherwise return NULL_TREE if type changes
in unknown way or ERROR_MARK_NODE if type is unchanged.   

References BINFO_OFFSET, DECL_CONTEXT, DECL_P, DECL_VIRTUAL_P, dump_file, error_mark_node, get_ref_base_and_extent(), gimple_assign_lhs(), gimple_assign_rhs1(), gimple_assign_single_p(), type_change_info::instance, integer_zerop(), known_gt, known_le, NULL, NULL_TREE, offset, type_change_info::offset, operand_equal_p(), POINTER_SIZE, print_dec(), print_generic_expr(), subbinfo_with_vtable_at_offset(), TDF_SLIM, TREE_CODE, tree_fits_shwi_p(), TREE_OPERAND, tree_to_shwi(), TYPE_BINFO, vtable_pointer_value_to_vtable(), and type_change_info::vtbl_ptr_ref.

Referenced by check_stmt_for_type_change().

◆ inlined_polymorphic_ctor_dtor_block_p()

tree inlined_polymorphic_ctor_dtor_block_p ( tree block,
bool check_clones )
Return a FUNCTION_DECL if BLOCK represents a constructor or destructor.
If CHECK_CLONES is true, also check for clones of ctor/dtors.   

References block_ultimate_origin(), NULL, NULL_TREE, polymorphic_ctor_dtor_p(), and TREE_CODE.

Referenced by decl_maybe_in_construction_p(), noncall_stmt_may_be_vtbl_ptr_store(), param_type_may_change_p(), and remove_unused_scope_block_p().

◆ noncall_stmt_may_be_vtbl_ptr_store()

static bool noncall_stmt_may_be_vtbl_ptr_store ( gimple * stmt)
static
Return true if STMT is not call and can modify a virtual method table pointer.
We take advantage of fact that vtable stores must appear within constructor
and destructor functions.   

References AGGREGATE_TYPE_P, BLOCK_ABSTRACT_ORIGIN, BLOCK_SUPERCONTEXT, block_ultimate_origin(), cfun, current_function_decl, DECL_CXX_CONSTRUCTOR_P, DECL_CXX_DESTRUCTOR_P, DECL_VIRTUAL_P, gimple_assign_lhs(), gimple_block(), gimple_clobber_p(), inlined_polymorphic_ctor_dtor_block_p(), is_gimple_assign(), POINTER_TYPE_P, TREE_CODE, TREE_OPERAND, and TREE_TYPE.

Referenced by check_stmt_for_type_change().

◆ polymorphic_ctor_dtor_p()

tree polymorphic_ctor_dtor_p ( tree fn,
bool check_clones )
Return a FUNCTION_DECL if FN represent a constructor or destructor.
If CHECK_CLONES is true, also check for clones of ctor/dtors.   

References DECL_ABSTRACT_ORIGIN, DECL_CXX_CONSTRUCTOR_P, DECL_CXX_DESTRUCTOR_P, ECF_CONST, ECF_PURE, flags_from_decl_or_type(), NULL_TREE, TREE_CODE, and TREE_TYPE.

Referenced by inlined_polymorphic_ctor_dtor_block_p(), and remove_unused_locals().

◆ possible_placement_new()

bool possible_placement_new ( tree type,
tree expected_type,
HOST_WIDE_INT cur_offset )
Return true if it seems valid to use placement new to build EXPECTED_TYPE
at position CUR_OFFSET within TYPE.

POD can be changed to an instance of a polymorphic type by
placement new.  Here we play safe and assume that any
non-polymorphic type is POD.   

References POINTER_SIZE, polymorphic_type_binfo_p(), TREE_CODE, tree_fits_shwi_p(), tree_to_uhwi(), TYPE_BINFO, and TYPE_SIZE.

Referenced by ipa_polymorphic_call_context::restrict_to_inner_class().

◆ record_known_type()

◆ walk_ssa_copies()

static tree walk_ssa_copies ( tree op,
hash_set< tree > ** global_visited = NULL )
static
See if OP is SSA name initialized as a copy or by single assignment.
If so, walk the SSA graph up.  Because simple PHI conditional is considered
copy, GLOBAL_VISITED may be used to avoid infinite loop walking the SSA
graph.   

References gimple_assign_load_p(), gimple_assign_rhs1(), gimple_assign_single_p(), gimple_phi_arg_def(), gimple_phi_num_args(), integer_zerop(), name_registered_for_update_p(), NULL, SSA_NAME_DEF_STMT, SSA_NAME_IS_DEFAULT_DEF, STRIP_NOPS, TREE_CODE, and visited.

Referenced by check_stmt_for_type_change(), ipa_polymorphic_call_context::get_dynamic_type(), and ipa_polymorphic_call_context::ipa_polymorphic_call_context().