GCC Middle and Back End API Reference
ipa.cc File Reference
#include "config.h"
#include "system.h"
#include "coretypes.h"
#include "backend.h"
#include "target.h"
#include "tree.h"
#include "gimple.h"
#include "alloc-pool.h"
#include "tree-pass.h"
#include "stringpool.h"
#include "cgraph.h"
#include "gimplify.h"
#include "tree-iterator.h"
#include "ipa-utils.h"
#include "symbol-summary.h"
#include "tree-vrp.h"
#include "sreal.h"
#include "ipa-cp.h"
#include "ipa-prop.h"
#include "ipa-fnsummary.h"
#include "dbgcnt.h"
#include "debug.h"
#include "attribs.h"
Include dependency graph for ipa.cc:

Macros

#define BOTTOM   ((cgraph_node *)(size_t) 2)
 

Functions

static bool has_addr_references_p (struct cgraph_node *node, void *)
 
static bool is_indirect_call_target_p (struct cgraph_node *node, void *)
 
static void update_inlined_to_pointer (struct cgraph_node *node, struct cgraph_node *inlined_to)
 
static void enqueue_node (symtab_node *node, symtab_node **first, hash_set< symtab_node * > *reachable)
 
static bool possible_inline_candidate_p (symtab_node *node)
 
static void process_references (symtab_node *snode, symtab_node **first, hash_set< symtab_node * > *reachable)
 
static void walk_polymorphic_call_targets (hash_set< void * > *reachable_call_targets, struct cgraph_edge *edge, symtab_node **first, hash_set< symtab_node * > *reachable)
 
void process_references (varpool_node *vnode, bool *written, bool *address_taken, bool *read, bool *explicit_refs)
 
bool set_readonly_bit (varpool_node *vnode, void *data)
 
bool set_writeonly_bit (varpool_node *vnode, void *data)
 
bool clear_addressable_bit (varpool_node *vnode, void *data)
 
bool ipa_discover_variable_flags (void)
 
static tree cgraph_build_static_cdtor_1 (char which, tree body, int priority, bool final, tree optimization, tree target)
 
void cgraph_build_static_cdtor (char which, tree body, int priority)
 
static void record_cdtor_fn (struct cgraph_node *node, vec< tree > *ctors, vec< tree > *dtors)
 
static void build_cdtor (bool ctor_p, const vec< tree > &cdtors)
 
static tree build_cxa_atexit_decl ()
 
static tree build_dso_handle_decl ()
 
static void build_cxa_dtor_registrations (const vec< tree > &dtors, vec< tree > *ctors)
 
static int compare_ctor (const void *p1, const void *p2)
 
static int compare_dtor (const void *p1, const void *p2)
 
static int compare_cdtor_tu_order (const void *p1, const void *p2)
 
static void build_cdtor_fns (vec< tree > *ctors, vec< tree > *dtors)
 
static void build_cxa_atexit_fns (vec< tree > *ctors, vec< tree > *dtors)
 
static unsigned int ipa_cdtor_merge (void)
 
ipa_opt_pass_dmake_pass_ipa_cdtor_merge (gcc::context *ctxt)
 
cgraph_nodemeet (cgraph_node *function, varpool_node *var, hash_map< varpool_node *, cgraph_node * > &single_user_map)
 
cgraph_nodepropagate_single_user (varpool_node *vnode, cgraph_node *function, hash_map< varpool_node *, cgraph_node * > &single_user_map)
 
static unsigned int ipa_single_use (void)
 
ipa_opt_pass_dmake_pass_ipa_single_use (gcc::context *ctxt)
 

Macro Definition Documentation

◆ BOTTOM

#define BOTTOM   ((cgraph_node *)(size_t) 2)
Invalid pointer representing BOTTOM for single user dataflow.   

Referenced by ipa_single_use(), meet(), and propagate_single_user().

Function Documentation

◆ build_cdtor()

static void build_cdtor ( bool ctor_p,
const vec< tree > & cdtors )
static
Define global constructors/destructor functions for the CDTORS, of
which they are LEN.  The CDTORS are sorted by initialization
priority.  If CTOR_P is true, these are constructors; otherwise,
they are destructors.   

References append_to_statement_list(), build_call_expr(), cgraph_build_static_cdtor_1(), DECL_FINI_PRIORITY, DECL_FUNCTION_SPECIFIC_OPTIMIZATION, DECL_FUNCTION_SPECIFIC_TARGET, DECL_INIT_PRIORITY, DECL_STATIC_CONSTRUCTOR, DECL_STATIC_DESTRUCTOR, gcc_assert, ggc_alloc(), i, NULL_TREE, targetm, and TREE_SIDE_EFFECTS.

Referenced by build_cdtor_fns(), and build_cxa_atexit_fns().

◆ build_cdtor_fns()

static void build_cdtor_fns ( vec< tree > * ctors,
vec< tree > * dtors )
static
Generate functions to call static constructors and destructors
for targets that do not support .ctors/.dtors sections.  These
functions have magic names which are detected by collect2.   

References build_cdtor(), compare_ctor(), compare_dtor(), gcc_assert, ggc_alloc(), and targetm.

Referenced by ipa_cdtor_merge().

◆ build_cxa_atexit_decl()

◆ build_cxa_atexit_fns()

static void build_cxa_atexit_fns ( vec< tree > * ctors,
vec< tree > * dtors )
static
Generate new CTORs to register static destructors with __cxa_atexit and add
them to the existing list of CTORs; we then process the revised CTORs list.

We sort the DTORs into priority and then TU order, this means that they are
registered in that order with __cxa_atexit () and therefore will be run in
the reverse order.

Likewise, CTORs are sorted into priority and then TU order, which means that
they will run in that order.

This matches the behavior of using init/fini or mod_init_func/mod_term_func
sections.   

References build_cdtor(), build_cxa_dtor_registrations(), compare_cdtor_tu_order(), gcc_assert, ggc_alloc(), and targetm.

Referenced by ipa_cdtor_merge().

◆ build_cxa_dtor_registrations()

static void build_cxa_dtor_registrations ( const vec< tree > & dtors,
vec< tree > * ctors )
static
This builds one or more constructor functions that register DTORs with
__cxa_atexit ().  Within a priority level, DTORs are registered in TU
order - which means that they will run in reverse TU order from cxa_atexit.
This is the same behavior as using a .fini / .mod_term_funcs section.
As the functions are built, they are appended to the CTORs vector.   

References append_to_statement_list(), build1_loc(), build_call_expr_loc(), build_cxa_atexit_decl(), build_dso_handle_decl(), cgraph_build_static_cdtor_1(), DECL_FINI_PRIORITY, DECL_FUNCTION_SPECIFIC_OPTIMIZATION, DECL_FUNCTION_SPECIFIC_TARGET, DECL_STATIC_DESTRUCTOR, gcc_assert, ggc_alloc(), i, input_location, null_pointer_node, NULL_TREE, ptr_type_node, TREE_SIDE_EFFECTS, and UNKNOWN_LOCATION.

Referenced by build_cxa_atexit_fns().

◆ build_dso_handle_decl()

◆ cgraph_build_static_cdtor()

void cgraph_build_static_cdtor ( char which,
tree body,
int priority )
Generate and emit a static constructor or destructor.  WHICH must
be one of 'I' (for a constructor) or 'D' (for a destructor).
BODY is a STATEMENT_LIST containing GENERIC
statements.  PRIORITY is the initialization priority for this
constructor or destructor.   

References cgraph_build_static_cdtor_1(), ggc_alloc(), optimization_default_node, and target_option_default_node.

Referenced by asan_finish_file(), build_gcov_exit_decl(), build_init_ctor(), hwasan_finish_file(), ipa_lower_emutls(), and tsan_finish_file().

◆ cgraph_build_static_cdtor_1()

static tree cgraph_build_static_cdtor_1 ( char which,
tree body,
int priority,
bool final,
tree optimization,
tree target )
static

◆ clear_addressable_bit()

bool clear_addressable_bit ( varpool_node * vnode,
void * data )
Clear addressale bit of VNODE.   

References ggc_alloc(), and TREE_ADDRESSABLE.

Referenced by ipa_discover_variable_flags().

◆ compare_cdtor_tu_order()

static int compare_cdtor_tu_order ( const void * p1,
const void * p2 )
static
Comparison function for qsort.  P1 and P2 are of type "tree *" and point to
a pair of static constructors or destructors.  We first sort on the basis of
priority and then into TU order (on the strict assumption that DECL_UIDs are
ordered in the same way as the original functions).  ???: this seems quite
fragile.  

References DECL_FINI_PRIORITY, DECL_INIT_PRIORITY, DECL_STATIC_DESTRUCTOR, DECL_UID, f1, f2, gcc_checking_assert, and ggc_alloc().

Referenced by build_cxa_atexit_fns().

◆ compare_ctor()

static int compare_ctor ( const void * p1,
const void * p2 )
static
Comparison function for qsort.  P1 and P2 are actually of type
"tree *" and point to static constructors.  DECL_INIT_PRIORITY is
used to determine the sort order.   

References DECL_INIT_PRIORITY, DECL_UID, f1, f2, and ggc_alloc().

Referenced by build_cdtor_fns().

◆ compare_dtor()

static int compare_dtor ( const void * p1,
const void * p2 )
static
Comparison function for qsort.  P1 and P2 are actually of type
"tree *" and point to static destructors.  DECL_FINI_PRIORITY is
used to determine the sort order.   

References DECL_FINI_PRIORITY, DECL_UID, f1, f2, and ggc_alloc().

Referenced by build_cdtor_fns().

◆ enqueue_node()

static void enqueue_node ( symtab_node * node,
symtab_node ** first,
hash_set< symtab_node * > * reachable )
static
Add symtab NODE to queue starting at FIRST.

The queue is linked via AUX pointers and terminated by pointer to 1.
We enqueue nodes at two occasions: when we find them reachable or when we find
their bodies needed for further clonning.  In the second case we mark them
by pointer to 2 after processing so they are re-queue when they become
reachable.   

References symtab_node::aux, and ggc_alloc().

Referenced by process_references(), and walk_polymorphic_call_targets().

◆ has_addr_references_p()

static bool has_addr_references_p ( struct cgraph_node * node,
void *  )
static
Basic IPA optimizations and utilities.
   Copyright (C) 2003-2024 Free Software Foundation, Inc.

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 NODE has ADDR reference.   

References i, IPA_REF_ADDR, symtab_node::iterate_referring(), NULL, and ipa_ref::use.

Referenced by symbol_table::remove_unreachable_nodes().

◆ ipa_cdtor_merge()

static unsigned int ipa_cdtor_merge ( void )
static
Look for constructors and destructors and produce function calling them.
This is needed for targets not supporting ctors or dtors, but we perform the
transformation also at linktime to merge possibly numerous
constructors/destructors into single function to improve code locality and
reduce size.   

References build_cdtor_fns(), build_cxa_atexit_fns(), symtab_node::decl, DECL_STATIC_CONSTRUCTOR, DECL_STATIC_DESTRUCTOR, FOR_EACH_DEFINED_FUNCTION, ggc_alloc(), record_cdtor_fn(), and targetm.

◆ ipa_discover_variable_flags()

bool ipa_discover_variable_flags ( void )
Discover variables that have no longer address taken, are read-only or
write-only and update their flags.

Return true when unreachable symbol removal should be done.

FIXME: This cannot be done in between gimplify and omp_expand since
readonly flag plays role on what is shared and what is not.  Currently we do
this transformation as part of whole program visibility and re-do at
ipa-reference pass (to take into account clonning), but it would
make sense to do it before early optimizations.   

References clear_addressable_bit(), dump_file, FOR_EACH_VARIABLE, ggc_alloc(), NULL, process_references(), set_readonly_bit(), set_writeonly_bit(), TREE_ADDRESSABLE, and TREE_READONLY.

Referenced by propagate().

◆ ipa_single_use()

◆ is_indirect_call_target_p()

static bool is_indirect_call_target_p ( struct cgraph_node * node,
void *  )
static
Return true when NODE can be target of an indirect call.   

References cgraph_node::indirect_call_target.

Referenced by symbol_table::remove_unreachable_nodes().

◆ make_pass_ipa_cdtor_merge()

ipa_opt_pass_d * make_pass_ipa_cdtor_merge ( gcc::context * ctxt)

References ggc_alloc().

◆ make_pass_ipa_single_use()

ipa_opt_pass_d * make_pass_ipa_single_use ( gcc::context * ctxt)

References ggc_alloc().

◆ meet()

cgraph_node * meet ( cgraph_node * function,
varpool_node * var,
hash_map< varpool_node *, cgraph_node * > & single_user_map )
Meet operation for single user dataflow.
Here we want to associate variables with sigle function that may access it.

FUNCTION is current single user of a variable, VAR is variable that uses it.
Latttice is stored in SINGLE_USER_MAP.

We represent: 
 - TOP by no entry in SIGNLE_USER_MAP
 - BOTTOM by BOTTOM in AUX pointer (to save lookups)
 - known single user by cgraph pointer in SINGLE_USER_MAP.   

References symtab_node::aux, BOTTOM, and ggc_alloc().

Referenced by propagate_single_user().

◆ possible_inline_candidate_p()

static bool possible_inline_candidate_p ( symtab_node * node)
static
Return true if NODE may get inlined later.
This is used to keep DECL_EXTERNAL function bodies around long enough
so inliner can proces them.   

References symtab_node::decl, DECL_ATTRIBUTES, DECL_UNINLINABLE, ggc_alloc(), IPA_SSA, IPA_SSA_AFTER_INLINING, lookup_attribute(), opt_for_fn, symbol_table::state, and symtab.

Referenced by process_references(), symbol_table::remove_unreachable_nodes(), and walk_polymorphic_call_targets().

◆ process_references() [1/2]

◆ process_references() [2/2]

void process_references ( varpool_node * vnode,
bool * written,
bool * address_taken,
bool * read,
bool * explicit_refs )
Process references to VNODE and set flags WRITTEN, ADDRESS_TAKEN, READ
as needed, also clear EXPLICIT_REFS if the references to given variable
do not need to be explicit.   

References ggc_alloc(), i, IPA_REF_ADDR, IPA_REF_ALIAS, IPA_REF_LOAD, IPA_REF_STORE, process_references(), ipa_ref::referring, TREE_THIS_VOLATILE, and ipa_ref::use.

◆ propagate_single_user()

cgraph_node * propagate_single_user ( varpool_node * vnode,
cgraph_node * function,
hash_map< varpool_node *, cgraph_node * > & single_user_map )
Propagation step of single-use dataflow.

Check all uses of VNODE and see if they are used by single function FUNCTION.
SINGLE_USER_MAP represents the dataflow lattice.   

References BOTTOM, gcc_assert, ggc_alloc(), i, meet(), and ipa_ref::referring.

Referenced by ipa_single_use().

◆ record_cdtor_fn()

static void record_cdtor_fn ( struct cgraph_node * node,
vec< tree > * ctors,
vec< tree > * dtors )
static
When target does not have ctors and dtors, we call all constructor
and destructor by special initialization/destruction function
recognized by collect2.

When we are going to build this function, collect all constructors and
destructors and turn them into normal functions.   

References symtab_node::decl, DECL_DISREGARD_INLINE_LIMITS, DECL_STATIC_CONSTRUCTOR, DECL_STATIC_DESTRUCTOR, cgraph_node::get(), and ggc_alloc().

Referenced by ipa_cdtor_merge().

◆ set_readonly_bit()

bool set_readonly_bit ( varpool_node * vnode,
void * data )
Set TREE_READONLY bit.   

References ggc_alloc(), and TREE_READONLY.

Referenced by ipa_discover_variable_flags().

◆ set_writeonly_bit()

bool set_writeonly_bit ( varpool_node * vnode,
void * data )
Set writeonly bit and clear the initalizer, since it will not be needed.   

References DECL_INITIAL, ggc_alloc(), and NULL.

Referenced by ipa_discover_variable_flags().

◆ update_inlined_to_pointer()

static void update_inlined_to_pointer ( struct cgraph_node * node,
struct cgraph_node * inlined_to )
static
Look for all functions inlined to NODE and update their inlined_to pointers
to INLINED_TO.   

References cgraph_edge::callee, cgraph_node::callees, cgraph_node::inlined_to, cgraph_edge::next_callee, and update_inlined_to_pointer().

Referenced by symbol_table::remove_unreachable_nodes(), and update_inlined_to_pointer().

◆ walk_polymorphic_call_targets()

static void walk_polymorphic_call_targets ( hash_set< void * > * reachable_call_targets,
struct cgraph_edge * edge,
symtab_node ** first,
hash_set< symtab_node * > * reachable )
static