GCC Middle and Back End API Reference
ipa-cp.cc File Reference
#include "config.h"
#include "system.h"
#include "coretypes.h"
#include "backend.h"
#include "tree.h"
#include "gimple-expr.h"
#include "gimple.h"
#include "predict.h"
#include "sreal.h"
#include "alloc-pool.h"
#include "tree-pass.h"
#include "cgraph.h"
#include "diagnostic.h"
#include "fold-const.h"
#include "gimple-iterator.h"
#include "gimple-fold.h"
#include "symbol-summary.h"
#include "tree-vrp.h"
#include "ipa-cp.h"
#include "ipa-prop.h"
#include "tree-pretty-print.h"
#include "tree-inline.h"
#include "ipa-fnsummary.h"
#include "ipa-utils.h"
#include "tree-ssa-ccp.h"
#include "stringpool.h"
#include "attribs.h"
#include "dbgcnt.h"
#include "symtab-clones.h"
#include "gimple-range.h"
Include dependency graph for ipa-cp.cc:

Data Structures

struct  caller_statistics
 
class  value_topo_info< valtype >
 
class  ipa_topo_info
 
class  edge_clone_summary
 
class  edge_clone_summary_t
 
struct  gather_other_count_struct
 
struct  desc_incoming_count_struct
 
struct  symbol_and_index_together
 

Macros

#define INCLUDE_ALGORITHM
 

Functions

static class ipcp_param_latticesipa_get_parm_lattices (class ipa_node_params *info, int i)
 
static ipcp_lattice< tree > * ipa_get_scalar_lat (class ipa_node_params *info, int i)
 
static ipcp_lattice< ipa_polymorphic_call_context > * ipa_get_poly_ctx_lat (class ipa_node_params *info, int i)
 
bool values_equal_for_ipcp_p (tree x, tree y)
 
static void print_ipcp_constant_value (FILE *f, ipa_polymorphic_call_context v)
 
static void print_all_lattices (FILE *f, bool dump_sources, bool dump_benefits)
 
static void determine_versionability (struct cgraph_node *node, class ipa_node_params *info)
 
static bool ipcp_versionable_function_p (struct cgraph_node *node)
 
static void init_caller_stats (caller_statistics *stats, cgraph_node *itself=NULL)
 
static bool gather_caller_stats (struct cgraph_node *node, void *data)
 
static bool ipcp_cloning_candidate_p (struct cgraph_node *node)
 
static bool ignore_edge_p (cgraph_edge *e)
 
static void build_toporder_info (class ipa_topo_info *topo)
 
static void free_toporder_info (class ipa_topo_info *topo)
 
static void push_node_to_stack (class ipa_topo_info *topo, struct cgraph_node *node)
 
static struct cgraph_nodepop_node_from_stack (class ipa_topo_info *topo)
 
static bool set_agg_lats_to_bottom (class ipcp_param_lattices *plats)
 
static bool set_agg_lats_contain_variable (class ipcp_param_lattices *plats)
 
static bool push_agg_values_from_plats (ipcp_param_lattices *plats, int dest_index, unsigned unit_delta, vec< ipa_argagg_value > *res)
 
static unsigned intersect_argaggs_with (vec< ipa_argagg_value > &elts, const vec< ipa_argagg_value > &other)
 
static bool set_all_contains_variable (class ipcp_param_lattices *plats)
 
static bool count_callers (cgraph_node *node, void *data)
 
static bool set_single_call_flag (cgraph_node *node, void *)
 
static void initialize_node_lattices (struct cgraph_node *node)
 
static bool ipacp_value_safe_for_type (tree param_type, tree value)
 
static tree ipa_get_jf_arith_result (enum tree_code opcode, tree input, tree operand, tree res_type)
 
static tree ipa_get_jf_pass_through_result (struct ipa_jump_func *jfunc, tree input, tree res_type)
 
static tree ipa_get_jf_ancestor_result (struct ipa_jump_func *jfunc, tree input)
 
tree ipa_value_from_jfunc (class ipa_node_params *info, struct ipa_jump_func *jfunc, tree parm_type)
 
ipa_polymorphic_call_context ipa_context_from_jfunc (ipa_node_params *info, cgraph_edge *cs, int csidx, ipa_jump_func *jfunc)
 
static bool ipa_vr_operation_and_type_effects (vrange &dst_vr, const vrange &src_vr, enum tree_code operation, tree dst_type, tree src_type)
 
static bool ipa_vr_operation_and_type_effects (vrange &dst_vr, const ipa_vr &src_vr, enum tree_code operation, tree dst_type, tree src_type)
 
void ipa_value_range_from_jfunc (vrange &vr, ipa_node_params *info, cgraph_edge *cs, ipa_jump_func *jfunc, tree parm_type)
 
tree ipa_agg_value_from_jfunc (ipa_node_params *info, cgraph_node *node, const ipa_agg_jf_item *item)
 
void ipa_push_agg_values_from_jfunc (ipa_node_params *info, cgraph_node *node, ipa_agg_jump_function *agg_jfunc, unsigned dst_index, vec< ipa_argagg_value > *res)
 
DEBUG_FUNCTION void ipcp_verify_propagated_values (void)
 
static bool values_equal_for_ipcp_p (ipa_polymorphic_call_context x, ipa_polymorphic_call_context y)
 
static ipcp_value< tree > * allocate_and_init_ipcp_value (tree cst, unsigned same_lat_gen_level)
 
static ipcp_value< ipa_polymorphic_call_context > * allocate_and_init_ipcp_value (ipa_polymorphic_call_context ctx, unsigned same_lat_gen_level)
 
static tree get_val_across_arith_op (enum tree_code opcode, tree opnd1_type, tree opnd2, ipcp_value< tree > *src_val, tree res_type)
 
static bool propagate_vals_across_arith_jfunc (cgraph_edge *cs, enum tree_code opcode, tree opnd1_type, tree opnd2, ipcp_lattice< tree > *src_lat, ipcp_lattice< tree > *dest_lat, HOST_WIDE_INT src_offset, int src_idx, tree res_type)
 
static bool propagate_vals_across_pass_through (cgraph_edge *cs, ipa_jump_func *jfunc, ipcp_lattice< tree > *src_lat, ipcp_lattice< tree > *dest_lat, int src_idx, tree parm_type)
 
static bool propagate_vals_across_ancestor (struct cgraph_edge *cs, struct ipa_jump_func *jfunc, ipcp_lattice< tree > *src_lat, ipcp_lattice< tree > *dest_lat, int src_idx, tree param_type)
 
static bool propagate_scalar_across_jump_function (struct cgraph_edge *cs, struct ipa_jump_func *jfunc, ipcp_lattice< tree > *dest_lat, tree param_type)
 
static bool propagate_context_across_jump_function (cgraph_edge *cs, ipa_jump_func *jfunc, int idx, ipcp_lattice< ipa_polymorphic_call_context > *dest_lat)
 
bool propagate_bits_across_jump_function (cgraph_edge *cs, int idx, ipa_jump_func *jfunc, ipcp_bits_lattice *dest_lattice)
 
static bool propagate_vr_across_jump_function (cgraph_edge *cs, ipa_jump_func *jfunc, class ipcp_param_lattices *dest_plats, tree param_type)
 
static bool set_check_aggs_by_ref (class ipcp_param_lattices *dest_plats, bool new_aggs_by_ref)
 
static bool merge_agg_lats_step (class ipcp_param_lattices *dest_plats, HOST_WIDE_INT offset, HOST_WIDE_INT val_size, struct ipcp_agg_lattice ***aglat, bool pre_existing, bool *change, int max_agg_items)
 
static bool set_chain_of_aglats_contains_variable (struct ipcp_agg_lattice *aglat)
 
static bool merge_aggregate_lattices (struct cgraph_edge *cs, class ipcp_param_lattices *dest_plats, class ipcp_param_lattices *src_plats, int src_idx, HOST_WIDE_INT offset_delta)
 
static bool agg_pass_through_permissible_p (class ipcp_param_lattices *src_plats, struct ipa_jump_func *jfunc)
 
static bool propagate_aggregate_lattice (struct cgraph_edge *cs, struct ipa_agg_jf_item *item, struct ipcp_agg_lattice *aglat)
 
static bool propagate_aggs_across_jump_function (struct cgraph_edge *cs, struct ipa_jump_func *jfunc, class ipcp_param_lattices *dest_plats)
 
static bool call_passes_through_thunk (cgraph_edge *cs)
 
static bool propagate_constants_across_call (struct cgraph_edge *cs)
 
static tree ipa_get_indirect_edge_target_1 (struct cgraph_edge *ie, const vec< tree > &known_csts, const vec< ipa_polymorphic_call_context > &known_contexts, const ipa_argagg_value_list &avs, bool *speculative)
 
tree ipa_get_indirect_edge_target (struct cgraph_edge *ie, ipa_call_arg_values *avals, bool *speculative)
 
static int devirtualization_time_bonus (struct cgraph_node *node, ipa_auto_call_arg_values *avals)
 
static int hint_time_bonus (cgraph_node *node, const ipa_call_estimates &estimates)
 
static sreal incorporate_penalties (cgraph_node *node, ipa_node_params *info, sreal evaluation)
 
static bool good_cloning_opportunity_p (struct cgraph_node *node, sreal time_benefit, sreal freq_sum, profile_count count_sum, int size_cost)
 
static bool gather_context_independent_values (class ipa_node_params *info, ipa_auto_call_arg_values *avals, bool calculate_aggs, int *removable_params_cost)
 
static void perform_estimation_of_a_value (cgraph_node *node, ipa_auto_call_arg_values *avals, int removable_params_cost, int est_move_cost, ipcp_value_base *val)
 
static long get_max_overall_size (cgraph_node *node)
 
static bool clone_for_param_removal_p (cgraph_node *node)
 
static void estimate_local_effects (struct cgraph_node *node)
 
static void add_all_node_vals_to_toposort (cgraph_node *node, ipa_topo_info *topo)
 
static void propagate_constants_topo (class ipa_topo_info *topo)
 
static int compare_edge_profile_counts (const void *a, const void *b)
 
static void ipcp_propagate_stage (class ipa_topo_info *topo)
 
static void ipcp_discover_new_direct_edges (struct cgraph_node *node, vec< tree > known_csts, vec< ipa_polymorphic_call_context > known_contexts, vec< ipa_argagg_value, va_gc > *aggvals)
 
static bool calls_same_node_or_its_all_contexts_clone_p (cgraph_edge *cs, cgraph_node *dest, bool allow_recursion_to_clone)
 
static bool cgraph_edge_brings_value_p (cgraph_edge *cs, ipcp_value_source< tree > *src, cgraph_node *dest, ipcp_value< tree > *dest_val)
 
static bool cgraph_edge_brings_value_p (cgraph_edge *cs, ipcp_value_source< ipa_polymorphic_call_context > *src, cgraph_node *dest, ipcp_value< ipa_polymorphic_call_context > *)
 
static struct cgraph_edgeget_next_cgraph_edge_clone (struct cgraph_edge *cs)
 
template<typename valtype >
static bool get_info_about_necessary_edges (ipcp_value< valtype > *val, cgraph_node *dest, sreal *freq_sum, int *caller_count, profile_count *rec_count_sum, profile_count *nonrec_count_sum)
 
static bool adjust_callers_for_value_intersection (vec< cgraph_edge * > &callers, cgraph_node *node)
 
template<typename valtype >
static vec< cgraph_edge * > gather_edges_for_value (ipcp_value< valtype > *val, cgraph_node *dest, int caller_count)
 
static struct ipa_replace_mapget_replacement_map (class ipa_node_params *info, tree value, int parm_num, bool force_load_ref)
 
static void dump_profile_updates (cgraph_node *node, bool spec)
 
profile_count lenient_count_portion_handling (profile_count remainder, cgraph_node *orig_node)
 
static bool gather_count_of_non_rec_edges (cgraph_node *node, void *data)
 
static void analyze_clone_icoming_counts (cgraph_node *node, desc_incoming_count_struct *desc)
 
static void adjust_clone_incoming_counts (cgraph_node *node, desc_incoming_count_struct *desc)
 
static void update_counts_for_self_gen_clones (cgraph_node *orig_node, const vec< cgraph_node * > &self_gen_clones)
 
static void update_profiling_info (struct cgraph_node *orig_node, struct cgraph_node *new_node)
 
static void update_specialized_profile (struct cgraph_node *new_node, struct cgraph_node *orig_node, profile_count redirected_sum)
 
static void adjust_references_in_caller (cgraph_edge *cs, symtab_node *symbol, int index)
 
static bool adjust_refs_in_act_callers (struct cgraph_node *node, void *data)
 
static bool want_remove_some_param_p (cgraph_node *node, vec< tree > known_csts)
 
static struct cgraph_nodecreate_specialized_node (struct cgraph_node *node, vec< tree > known_csts, vec< ipa_polymorphic_call_context > known_contexts, vec< ipa_argagg_value, va_gc > *aggvals, vec< cgraph_edge * > &callers)
 
static bool self_recursive_pass_through_p (cgraph_edge *cs, ipa_jump_func *jfunc, int i, bool simple=true)
 
static bool self_recursive_agg_pass_through_p (const cgraph_edge *cs, const ipa_agg_jf_item *jfunc, int i, bool simple=true)
 
static void find_more_scalar_values_for_callers_subset (struct cgraph_node *node, vec< tree > &known_csts, const vec< cgraph_edge * > &callers)
 
static void find_more_contexts_for_caller_subset (cgraph_node *node, vec< ipa_polymorphic_call_context > *known_contexts, const vec< cgraph_edge * > &callers)
 
static void push_agg_values_for_index_from_edge (struct cgraph_edge *cs, int index, vec< ipa_argagg_value > *res, const ipa_argagg_value_list *interim)
 
static void push_agg_values_from_edge (struct cgraph_edge *cs, ipa_node_params *dest_info, vec< ipa_argagg_value > *res, const ipa_argagg_value_list *interim, bool optimize_self_recursion)
 
static struct vec< ipa_argagg_value, va_gc > * find_aggregate_values_for_callers_subset (struct cgraph_node *node, const vec< cgraph_edge * > &callers)
 
static bool cgraph_edge_brings_all_scalars_for_node (struct cgraph_edge *cs, struct cgraph_node *node)
 
static bool cgraph_edge_brings_all_agg_vals_for_node (struct cgraph_edge *cs, struct cgraph_node *node)
 
template<typename valtype >
static void perhaps_add_new_callers (cgraph_node *node, ipcp_value< valtype > *val)
 
static bool known_contexts_useful_p (vec< ipa_polymorphic_call_context > known_contexts)
 
static vec< ipa_polymorphic_call_contextcopy_useful_known_contexts (const vec< ipa_polymorphic_call_context > &known_contexts)
 
static void copy_known_vectors_add_val (ipa_auto_call_arg_values *avals, vec< tree > *known_csts, vec< ipa_polymorphic_call_context > *known_contexts, ipcp_value< tree > *val, int index)
 
static void copy_known_vectors_add_val (ipa_auto_call_arg_values *avals, vec< tree > *known_csts, vec< ipa_polymorphic_call_context > *known_contexts, ipcp_value< ipa_polymorphic_call_context > *val, int index)
 
DEBUG_FUNCTION bool ipcp_val_agg_replacement_ok_p (vec< ipa_argagg_value, va_gc > *aggvals, int index, HOST_WIDE_INT offset, tree value)
 
DEBUG_FUNCTION bool ipcp_val_agg_replacement_ok_p (vec< ipa_argagg_value, va_gc > *, int, HOST_WIDE_INT offset, ipa_polymorphic_call_context)
 
template<typename valtype >
static bool decide_about_value (struct cgraph_node *node, int index, HOST_WIDE_INT offset, ipcp_value< valtype > *val, ipa_auto_call_arg_values *avals, vec< cgraph_node * > *self_gen_clones)
 
static bool ipa_range_contains_p (const vrange &r, tree val)
 
static bool decide_whether_version_node (struct cgraph_node *node)
 
static void spread_undeadness (struct cgraph_node *node)
 
static bool has_undead_caller_from_outside_scc_p (struct cgraph_node *node, void *data)
 
static void identify_dead_nodes (struct cgraph_node *node)
 
static void ipcp_decision_stage (class ipa_topo_info *topo)
 
static void ipcp_store_vr_results (void)
 
static unsigned int ipcp_driver (void)
 
static void ipcp_generate_summary (void)
 
ipa_opt_pass_dmake_pass_ipa_cp (gcc::context *ctxt)
 
void ipa_cp_cc_finalize (void)
 
static int compare_uids (const void *a, const void *b)
 

Variables

object_allocator< ipcp_value< tree > > ipcp_cst_values_pool ("IPA-CP constant values")
 
object_allocator< ipcp_value< ipa_polymorphic_call_context > > ipcp_poly_ctx_values_pool ("IPA-CP polymorphic contexts")
 
object_allocator< ipcp_value_source< tree > > ipcp_sources_pool ("IPA-CP value sources")
 
object_allocator< ipcp_agg_latticeipcp_agg_lattice_pool ("IPA_CP aggregate lattices")
 
static profile_count base_count
 
static long overall_size
 
static long orig_overall_size
 
static hash_map< const char *, unsigned > * clone_num_suffixes
 
static call_summary< edge_clone_summary * > * edge_clone_summaries = NULL
 

Macro Definition Documentation

◆ INCLUDE_ALGORITHM

#define INCLUDE_ALGORITHM
Interprocedural constant propagation
   Copyright (C) 2005-2024 Free Software Foundation, Inc.

   Contributed by Razya Ladelsky <RAZYA@il.ibm.com> and Martin Jambor
   <mjambor@suse.cz>

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/>.   
Interprocedural constant propagation (IPA-CP).

The goal of this transformation is to

1) discover functions which are always invoked with some arguments with the
   same known constant values and modify the functions so that the
   subsequent optimizations can take advantage of the knowledge, and

2) partial specialization - create specialized versions of functions
   transformed in this way if some parameters are known constants only in
   certain contexts but the estimated tradeoff between speedup and cost size
   is deemed good.

The algorithm also propagates types and attempts to perform type based
devirtualization.  Types are propagated much like constants.

The algorithm basically consists of three stages.  In the first, functions
are analyzed one at a time and jump functions are constructed for all known
call-sites.  In the second phase, the pass propagates information from the
jump functions across the call to reveal what values are available at what
call sites, performs estimations of effects of known values on functions and
their callees, and finally decides what specialized extra versions should be
created.  In the third, the special versions materialize and appropriate
calls are redirected.

The algorithm used is to a certain extent based on "Interprocedural Constant
Propagation", by David Callahan, Keith D Cooper, Ken Kennedy, Linda Torczon,
Comp86, pg 152-161 and "A Methodology for Procedure Cloning" by Keith D
Cooper, Mary W. Hall, and Ken Kennedy.


First stage - intraprocedural analysis
=======================================

This phase computes jump_function and modification flags.

A jump function for a call-site represents the values passed as an actual
arguments of a given call-site. In principle, there are three types of
values:

Pass through - the caller's formal parameter is passed as an actual
          argument, plus an operation on it can be performed.
Constant - a constant is passed as an actual argument.
Unknown - neither of the above.

All jump function types are described in detail in ipa-prop.h, together with
the data structures that represent them and methods of accessing them.

ipcp_generate_summary() is the main function of the first stage.

Second stage - interprocedural analysis
========================================

This stage is itself divided into two phases.  In the first, we propagate
known values over the call graph, in the second, we make cloning decisions.
It uses a different algorithm than the original Callahan's paper.

First, we traverse the functions topologically from callers to callees and,
for each strongly connected component (SCC), we propagate constants
according to previously computed jump functions.  We also record what known
values depend on other known values and estimate local effects.  Finally, we
propagate cumulative information about these effects from dependent values
to those on which they depend.

Second, we again traverse the call graph in the same topological order and
make clones for functions which we know are called with the same values in
all contexts and decide about extra specialized clones of functions just for
some contexts - these decisions are based on both local estimates and
cumulative estimates propagated from callees.

ipcp_propagate_stage() and ipcp_decision_stage() together constitute the
third stage.

Third phase - materialization of clones, call statement updates.
============================================

This stage is currently performed by call graph code (mainly in cgraphunit.cc
and tree-inline.cc) according to instructions inserted to the call graph by
the second stage.   

Function Documentation

◆ add_all_node_vals_to_toposort()

static void add_all_node_vals_to_toposort ( cgraph_node * node,
ipa_topo_info * topo )
static
Add all values in lattices associated with NODE to the topological sort if
they are not there yet.   

References ipcp_lattice< valtype >::bottom, count, ggc_alloc(), i, ipa_get_param_count(), ipa_get_parm_lattices(), ipa_node_params_sum, ipcp_value< valtype >::next, and ipcp_lattice< valtype >::values.

Referenced by propagate_constants_topo().

◆ adjust_callers_for_value_intersection()

static bool adjust_callers_for_value_intersection ( vec< cgraph_edge * > & callers,
cgraph_node * node )
static
Given a NODE, and a set of its CALLERS, try to adjust order of the callers
to let a non-self-recursive caller be the first element.  Thus, we can
simplify intersecting operations on values that arrive from all of these
callers, especially when there exists self-recursive call.  Return true if
this kind of adjustment is possible.   

References cgraph_edge::caller, and i.

Referenced by decide_whether_version_node(), and gather_edges_for_value().

◆ adjust_clone_incoming_counts()

static void adjust_clone_incoming_counts ( cgraph_node * node,
desc_incoming_count_struct * desc )
static
If caller edge counts of a clone created for a self-recursive arithmetic
jump function must be adjusted because it is coming from a the "seed" clone
for the first value and so has been excessively scaled back as if it was not
a recursive call, adjust it so that the incoming counts of NODE match its
count. NODE is the node or its thunk.   

References adjust_clone_incoming_counts(), cgraph_edge::caller, cgraph_node::callers, hash_set< KeyId, Lazy, Traits >::contains(), desc_incoming_count_struct::count, dump_file, ggc_alloc(), desc_incoming_count_struct::orig, desc_incoming_count_struct::processed_edges, and profile_count::zero().

Referenced by adjust_clone_incoming_counts(), and update_counts_for_self_gen_clones().

◆ adjust_references_in_caller()

◆ adjust_refs_in_act_callers()

static bool adjust_refs_in_act_callers ( struct cgraph_node * node,
void * data )
static
Worker callback of call_for_symbol_thunks_and_aliases to recursively call
adjust_references_in_caller on edges up in the call-graph, if necessary.  

References adjust_references_in_caller(), cgraph_node::callers, and ggc_alloc().

Referenced by adjust_references_in_caller().

◆ agg_pass_through_permissible_p()

static bool agg_pass_through_permissible_p ( class ipcp_param_lattices * src_plats,
struct ipa_jump_func * jfunc )
static
Determine whether there is anything to propagate FROM SRC_PLATS through a
pass-through JFUNC and if so, whether it has conform and conforms to the
rules about propagating values passed by reference.   

References ggc_alloc(), and ipa_get_jf_pass_through_agg_preserved().

Referenced by propagate_aggs_across_jump_function().

◆ allocate_and_init_ipcp_value() [1/2]

static ipcp_value< ipa_polymorphic_call_context > * allocate_and_init_ipcp_value ( ipa_polymorphic_call_context ctx,
unsigned same_lat_gen_level )
static
Allocate a new ipcp_value holding a polymorphic context, initialize its
value to SOURCE and clear all other fields.   

References ggc_alloc(), ipcp_poly_ctx_values_pool, ipcp_value< valtype >::self_recursion_generated_level, and ipcp_value< valtype >::value.

◆ allocate_and_init_ipcp_value() [2/2]

static ipcp_value< tree > * allocate_and_init_ipcp_value ( tree cst,
unsigned same_lat_gen_level )
static
Allocate a new ipcp_value holding a tree constant, initialize its value to
SOURCE and clear all other fields.   

References ggc_alloc(), ipcp_cst_values_pool, ipcp_value< valtype >::self_recursion_generated_level, and ipcp_value< valtype >::value.

Referenced by ipcp_lattice< valtype >::add_value().

◆ analyze_clone_icoming_counts()

◆ build_toporder_info()

static void build_toporder_info ( class ipa_topo_info * topo)
static
Allocate the arrays in TOPO and topologically sort the nodes into order.   

References symbol_table::cgraph_count, gcc_checking_assert, ggc_alloc(), ignore_edge_p(), ipa_reduced_postorder(), and symtab.

Referenced by ipcp_driver().

◆ call_passes_through_thunk()

static bool call_passes_through_thunk ( cgraph_edge * cs)
static
Return true if on the way cfrom CS->caller to the final (non-alias and
non-thunk) destination, the call passes through a thunk.   

References cgraph_edge::callee, and ggc_alloc().

Referenced by find_more_scalar_values_for_callers_subset(), and propagate_constants_across_call().

◆ calls_same_node_or_its_all_contexts_clone_p()

static bool calls_same_node_or_its_all_contexts_clone_p ( cgraph_edge * cs,
cgraph_node * dest,
bool allow_recursion_to_clone )
static
Return true is CS calls DEST or its clone for all contexts.  When
ALLOW_RECURSION_TO_CLONE is false, also return false for self-recursive
edges from/to an all-context clone.   

References AVAIL_INTERPOSABLE, cgraph_edge::callee, cgraph_edge::caller, cgraph_node::function_symbol(), ggc_alloc(), ipa_node_params_sum, ipa_node_params::ipcp_orig_node, and ipa_node_params::is_all_contexts_clone.

Referenced by cgraph_edge_brings_value_p(), and cgraph_edge_brings_value_p().

◆ cgraph_edge_brings_all_agg_vals_for_node()

static bool cgraph_edge_brings_all_agg_vals_for_node ( struct cgraph_edge * cs,
struct cgraph_node * node )
static
Determine whether CS also brings all aggregate values that NODE is
specialized for.   

References gcc_checking_assert, ggc_alloc(), ipa_node_params_sum, ipcp_get_transformation_summary(), push_agg_values_from_edge(), and vec_safe_is_empty().

Referenced by perhaps_add_new_callers().

◆ cgraph_edge_brings_all_scalars_for_node()

static bool cgraph_edge_brings_all_scalars_for_node ( struct cgraph_edge * cs,
struct cgraph_node * node )
static

◆ cgraph_edge_brings_value_p() [1/2]

static bool cgraph_edge_brings_value_p ( cgraph_edge * cs,
ipcp_value_source< ipa_polymorphic_call_context > * src,
cgraph_node * dest,
ipcp_value< ipa_polymorphic_call_context > *  )
static
Return true if edge CS does bring about the value described by SRC to
DST_VAL of node DEST or its clone for all contexts.   

References cgraph_edge::caller, calls_same_node_or_its_all_contexts_clone_p(), ggc_alloc(), ipcp_value_source< valtype >::index, ipa_get_parm_lattices(), ipa_node_params_sum, ipcp_value_source< valtype >::val, and values_equal_for_ipcp_p().

◆ cgraph_edge_brings_value_p() [2/2]

◆ clone_for_param_removal_p()

static bool clone_for_param_removal_p ( cgraph_node * node)
static
Return true if NODE should be cloned just for a parameter removal, possibly
dumping a reason if not.   

References cgraph_node::can_be_local_p(), cgraph_node::can_change_signature, dump_file, dump_flags, ggc_alloc(), and TDF_DETAILS.

Referenced by estimate_local_effects().

◆ compare_edge_profile_counts()

static int compare_edge_profile_counts ( const void * a,
const void * b )
static
Callback for qsort to sort counts of all edges.   

References a, b, and ggc_alloc().

Referenced by ipcp_propagate_stage().

◆ compare_uids()

static int compare_uids ( const void * a,
const void * b )
static
Helper function to qsort a vector of ipa_uid_to_idx_map_elt elements
according to the uid.   

References a, b, gcc_unreachable, and ipa_uid_to_idx_map_elt::uid.

Referenced by ipcp_transformation::maybe_create_parm_idx_map().

◆ copy_known_vectors_add_val() [1/2]

static void copy_known_vectors_add_val ( ipa_auto_call_arg_values * avals,
vec< tree > * known_csts,
vec< ipa_polymorphic_call_context > * known_contexts,
ipcp_value< ipa_polymorphic_call_context > * val,
int index )
static
Copy known scalar values from AVALS into KNOWN_CSTS.  Similarly, copy
contexts to KNOWN_CONTEXTS and modify the copy according to VAL and
INDEX.   

References ggc_alloc(), and ipcp_value< valtype >::value.

◆ copy_known_vectors_add_val() [2/2]

static void copy_known_vectors_add_val ( ipa_auto_call_arg_values * avals,
vec< tree > * known_csts,
vec< ipa_polymorphic_call_context > * known_contexts,
ipcp_value< tree > * val,
int index )
static
Copy known scalar values from AVALS into KNOWN_CSTS and modify the copy
according to VAL and INDEX.  If non-empty, replace KNOWN_CONTEXTS with its
copy too.   

References copy_useful_known_contexts(), ggc_alloc(), and ipcp_value< valtype >::value.

Referenced by decide_about_value().

◆ copy_useful_known_contexts()

static vec< ipa_polymorphic_call_context > copy_useful_known_contexts ( const vec< ipa_polymorphic_call_context > & known_contexts)
static
Return a copy of KNOWN_CSTS if it is not empty, otherwise return vNULL.   

References known_contexts_useful_p(), and vNULL.

Referenced by copy_known_vectors_add_val(), decide_about_value(), and decide_whether_version_node().

◆ count_callers()

static bool count_callers ( cgraph_node * node,
void * data )
static
Worker of call_for_symbol_thunks_and_aliases, increment the integer DATA
points to by the number of callers to NODE.   

References cgraph_node::callers, and ggc_alloc().

Referenced by initialize_node_lattices().

◆ create_specialized_node()

static struct cgraph_node * create_specialized_node ( struct cgraph_node * node,
vec< tree > known_csts,
vec< ipa_polymorphic_call_context > known_contexts,
vec< ipa_argagg_value, va_gc > * aggvals,
vec< cgraph_edge * > & callers )
static

◆ decide_about_value()

template<typename valtype >
static bool decide_about_value ( struct cgraph_node * node,
int index,
HOST_WIDE_INT offset,
ipcp_value< valtype > * val,
ipa_auto_call_arg_values * avals,
vec< cgraph_node * > * self_gen_clones )
static

◆ decide_whether_version_node()

◆ determine_versionability()

◆ devirtualization_time_bonus()

◆ dump_profile_updates()

static void dump_profile_updates ( cgraph_node * node,
bool spec )
static
Dump new profiling counts of NODE.  SPEC is true when NODE is a specialzied
one, otherwise it will be referred to as the original node.   

References cgraph_node::callees, cgraph_node::count, profile_count::dump(), dump_file, symtab_node::dump_name(), and ggc_alloc().

Referenced by update_counts_for_self_gen_clones(), update_profiling_info(), and update_specialized_profile().

◆ estimate_local_effects()

◆ find_aggregate_values_for_callers_subset()

static struct vec< ipa_argagg_value, va_gc > * find_aggregate_values_for_callers_subset ( struct cgraph_node * node,
const vec< cgraph_edge * > & callers )
static
Look at edges in CALLERS and collect all known aggregate values that arrive
from all of them.  Return nullptr if there are none.   

References gcc_checking_assert, ggc_alloc(), i, intersect_argaggs_with(), ipa_node_params_sum, last, NULL, push_agg_values_from_edge(), and vec_safe_reserve_exact().

Referenced by decide_about_value(), and decide_whether_version_node().

◆ find_more_contexts_for_caller_subset()

static void find_more_contexts_for_caller_subset ( cgraph_node * node,
vec< ipa_polymorphic_call_context > * known_contexts,
const vec< cgraph_edge * > & callers )
static
Given a NODE and a subset of its CALLERS, try to populate plank slots in
KNOWN_CONTEXTS with polymorphic contexts that are also known for all of the
CALLERS.   

References cgraph_edge::caller, count, dump_file, dump_flags, FOR_EACH_VEC_ELT, ggc_alloc(), i, ipa_context_from_jfunc(), ipa_dump_param(), ipa_edge_args_sum, ipa_get_cs_argument_count(), ipa_get_ith_jump_func(), ipa_get_param_count(), ipa_get_poly_ctx_lat(), ipa_node_params_sum, print_ipcp_constant_value(), and TDF_DETAILS.

Referenced by decide_about_value(), and decide_whether_version_node().

◆ find_more_scalar_values_for_callers_subset()

◆ free_toporder_info()

static void free_toporder_info ( class ipa_topo_info * topo)
static
Free information about strongly connected components and the arrays in
TOPO.   

References free(), ggc_alloc(), and ipa_free_postorder_info().

Referenced by ipcp_driver().

◆ gather_caller_stats()

◆ gather_context_independent_values()

static bool gather_context_independent_values ( class ipa_node_params * info,
ipa_auto_call_arg_values * avals,
bool calculate_aggs,
int * removable_params_cost )
static
Grow vectors in AVALS and fill them with information about values of
parameters that are known to be independent of the context.  Only calculate
m_known_aggs if CALCULATE_AGGS is true.  INFO describes the function.  If
REMOVABLE_PARAMS_COST is non-NULL, the movement cost of all removable
parameters will be stored in it.

TODO: Also grow context independent value range vectors.   

References count, ipcp_param_lattices::ctxlat, estimate_move_cost(), gcc_checking_assert, ggc_alloc(), i, ipa_get_param_count(), ipa_get_param_move_cost(), ipa_get_parm_lattices(), ipa_is_param_used(), ipcp_lattice< valtype >::is_single_const(), push_agg_values_from_plats(), TREE_CODE, TREE_TYPE, ipcp_value< valtype >::value, and ipcp_lattice< valtype >::values.

Referenced by decide_whether_version_node(), and estimate_local_effects().

◆ gather_count_of_non_rec_edges()

static bool gather_count_of_non_rec_edges ( cgraph_node * node,
void * data )
static
Worker callback of call_for_symbol_thunks_and_aliases summing the number of
counts that come from non-self-recursive calls..   

References cgraph_node::callers, cgraph_node::clone_of, profile_count::ipa(), gather_other_count_struct::orig, and gather_other_count_struct::other_count.

Referenced by update_counts_for_self_gen_clones().

◆ gather_edges_for_value()

template<typename valtype >
static vec< cgraph_edge * > gather_edges_for_value ( ipcp_value< valtype > * val,
cgraph_node * dest,
int caller_count )
static
Return a vector of incoming edges that do bring value VAL to node DEST.  It
is assumed their number is known and equal to CALLER_COUNT.   

References adjust_callers_for_value_intersection(), cgraph_edge_brings_value_p(), ipcp_value_source< valtype >::cs, get_next_cgraph_edge_clone(), ggc_alloc(), ipcp_value_source< valtype >::next, and ipcp_value< valtype >::sources.

Referenced by decide_about_value().

◆ get_info_about_necessary_edges()

template<typename valtype >
static bool get_info_about_necessary_edges ( ipcp_value< valtype > * val,
cgraph_node * dest,
sreal * freq_sum,
int * caller_count,
profile_count * rec_count_sum,
profile_count * nonrec_count_sum )
static
Given VAL that is intended for DEST, iterate over all its sources and if any
of them is viable and hot, return true.  In that case, for those that still
hold, add their edge frequency and their number and cumulative profile
counts of self-ecursive and other edges into *FREQUENCY, *CALLER_COUNT,
REC_COUNT_SUM and NONREC_COUNT_SUM respectively.   

References cgraph_edge::caller, cgraph_node::callers, cgraph_edge_brings_value_p(), cgraph_edge::count, count, ipcp_value_source< valtype >::cs, get_next_cgraph_edge_clone(), ggc_alloc(), profile_count::initialized_p(), profile_count::ipa(), ipa_node_params_sum, cgraph_edge::maybe_hot_p(), ipcp_value_source< valtype >::next, cgraph_edge::next_caller, ipcp_value< valtype >::sources, cgraph_edge::sreal_frequency(), and profile_count::zero().

Referenced by decide_about_value().

◆ get_max_overall_size()

static long get_max_overall_size ( cgraph_node * node)
static
Get the overall limit oof growth based on parameters extracted from growth.
it does not really make sense to mix functions with different overall growth
limits but it is possible and if it happens, we do not want to select one
limit at random.   

References symtab_node::decl, ggc_alloc(), opt_for_fn, and orig_overall_size.

Referenced by decide_about_value(), and estimate_local_effects().

◆ get_next_cgraph_edge_clone()

static struct cgraph_edge * get_next_cgraph_edge_clone ( struct cgraph_edge * cs)
inlinestatic

◆ get_replacement_map()

static struct ipa_replace_map * get_replacement_map ( class ipa_node_params * info,
tree value,
int parm_num,
bool force_load_ref )
static
Construct a replacement map for a know VALUE for a formal parameter PARAM.
Return it or NULL if for some reason it cannot be created.  FORCE_LOAD_REF
should be set to true when the reference created for the constant should be
a load one and not an address one because the corresponding parameter p is
only used as *p.   

References dump_file, ipa_replace_map::force_load_ref, ggc_alloc(), ipa_dump_param(), ipa_replace_map::parm_num, and print_generic_expr().

Referenced by create_specialized_node().

◆ get_val_across_arith_op()

static tree get_val_across_arith_op ( enum tree_code opcode,
tree opnd1_type,
tree opnd2,
ipcp_value< tree > * src_val,
tree res_type )
static
A helper function that returns result of operation specified by OPCODE on
the value of SRC_VAL.  If non-NULL, OPND1_TYPE is expected type for the
value of SRC_VAL.  If the operation is binary, OPND2 is a constant value
acting as its second operand.  If non-NULL, RES_TYPE is expected type of
the result.   

References ggc_alloc(), ipa_get_jf_arith_result(), NULL_TREE, TREE_TYPE, and useless_type_conversion_p().

Referenced by propagate_vals_across_arith_jfunc().

◆ good_cloning_opportunity_p()

static bool good_cloning_opportunity_p ( struct cgraph_node * node,
sreal time_benefit,
sreal freq_sum,
profile_count count_sum,
int size_cost )
static

◆ has_undead_caller_from_outside_scc_p()

static bool has_undead_caller_from_outside_scc_p ( struct cgraph_node * node,
void * data )
static

◆ hint_time_bonus()

static int hint_time_bonus ( cgraph_node * node,
const ipa_call_estimates & estimates )
static
Return time bonus incurred because of hints stored in ESTIMATES.   

References symtab_node::decl, ggc_alloc(), INLINE_HINT_loop_iterations, INLINE_HINT_loop_stride, and opt_for_fn.

Referenced by estimate_local_effects(), and perform_estimation_of_a_value().

◆ identify_dead_nodes()

static void identify_dead_nodes ( struct cgraph_node * node)
static
Identify nodes within the same SCC as NODE which are no longer needed
because of new clones and will be removed as unreachable.   

References symtab_node::aux, cgraph_node::call_for_symbol_thunks_and_aliases(), dump_file, dump_flags, symtab_node::dump_name(), ggc_alloc(), has_undead_caller_from_outside_scc_p(), ipa_node_params_sum, cgraph_node::local, ipa_node_params::node_dead, NULL, spread_undeadness(), and TDF_DETAILS.

Referenced by ipcp_decision_stage().

◆ ignore_edge_p()

static bool ignore_edge_p ( cgraph_edge * e)
static
Skip edges from and to nodes without ipa_cp enabled.
Ignore not available symbols.   

References AVAIL_INTERPOSABLE, cgraph_edge::callee, cgraph_edge::caller, cgraph_node::function_or_virtual_thunk_symbol(), ggc_alloc(), and opt_for_fn.

Referenced by build_toporder_info().

◆ incorporate_penalties()

static sreal incorporate_penalties ( cgraph_node * node,
ipa_node_params * info,
sreal evaluation )
inlinestatic
If there is a reason to penalize the function described by INFO in the
cloning goodness evaluation, do so.   

References symtab_node::decl, ggc_alloc(), ipa_node_params::node_calling_single_call, ipa_node_params::node_is_self_scc, ipa_node_params::node_within_scc, and opt_for_fn.

Referenced by good_cloning_opportunity_p().

◆ init_caller_stats()

static void init_caller_stats ( caller_statistics * stats,
cgraph_node * itself = NULL )
inlinestatic
Initialize fields of STAT to zeroes and optionally set it up so that edges
from IGNORED_CALLER are not counted.   

References profile_count::zero().

Referenced by estimate_local_effects(), ipcp_cloning_candidate_p(), and update_profiling_info().

◆ initialize_node_lattices()

◆ intersect_argaggs_with()

static unsigned intersect_argaggs_with ( vec< ipa_argagg_value > & elts,
const vec< ipa_argagg_value > & other )
static
Turn all values in LIST that are not present in OTHER into NULL_TREEs.
Return the number of remaining valid entries.   

References ggc_alloc(), i, NULL_TREE, and values_equal_for_ipcp_p().

Referenced by find_aggregate_values_for_callers_subset().

◆ ipa_agg_value_from_jfunc()

◆ ipa_context_from_jfunc()

◆ ipa_cp_cc_finalize()

void ipa_cp_cc_finalize ( void )
Reset all state within ipa-cp.cc so that we can rerun the compiler
within the same process.  For use by toplev::finalize.   

References base_count, ipcp_free_transformation_sum(), orig_overall_size, overall_size, and profile_count::uninitialized().

Referenced by toplev::finalize().

◆ ipa_get_indirect_edge_target()

tree ipa_get_indirect_edge_target ( struct cgraph_edge * ie,
ipa_call_arg_values * avals,
bool * speculative )
If an indirect edge IE can be turned into a direct one based on data in
AVALS, return the destination.  Store into *SPECULATIVE a boolean determinig
whether the discovered target is only speculative guess.   

References ggc_alloc(), and ipa_get_indirect_edge_target_1().

Referenced by estimate_edge_devirt_benefit().

◆ ipa_get_indirect_edge_target_1()

static tree ipa_get_indirect_edge_target_1 ( struct cgraph_edge * ie,
const vec< tree > & known_csts,
const vec< ipa_polymorphic_call_context > & known_contexts,
const ipa_argagg_value_list & avs,
bool * speculative )
static

◆ ipa_get_jf_ancestor_result()

static tree ipa_get_jf_ancestor_result ( struct ipa_jump_func * jfunc,
tree input )
static
Return the result of an ancestor jump function JFUNC on the constant value
INPUT.  Return NULL_TREE if that cannot be determined.   

References build1(), build_int_cst(), fold_build2, gcc_checking_assert, ggc_alloc(), ipa_get_jf_ancestor_keep_null(), ipa_get_jf_ancestor_offset(), is_gimple_ip_invariant_address(), known_eq, NULL_TREE, ptr_type_node, TREE_CODE, TREE_TYPE, and zerop().

Referenced by ipa_value_from_jfunc(), and propagate_vals_across_ancestor().

◆ ipa_get_jf_arith_result()

static tree ipa_get_jf_arith_result ( enum tree_code opcode,
tree input,
tree operand,
tree res_type )
static
Return the result of a (possibly arithmetic) operation on the constant
value INPUT.  OPERAND is 2nd operand for binary operation.  RES_TYPE is
the type of the parameter to which the result is passed.  Return
NULL_TREE if that cannot be determined or be considered an
interprocedural invariant.   

References boolean_type_node, expr_type_first_operand_type_p(), fold_binary, fold_unary, ggc_alloc(), is_gimple_ip_invariant(), NULL_TREE, tcc_comparison, tcc_unary, TREE_CODE_CLASS, TREE_TYPE, and values_equal_for_ipcp_p().

Referenced by find_more_scalar_values_for_callers_subset(), get_val_across_arith_op(), ipa_agg_value_from_jfunc(), ipa_get_jf_pass_through_result(), and push_agg_values_for_index_from_edge().

◆ ipa_get_jf_pass_through_result()

static tree ipa_get_jf_pass_through_result ( struct ipa_jump_func * jfunc,
tree input,
tree res_type )
static
Return the result of a (possibly arithmetic) pass through jump function
JFUNC on the constant value INPUT.  RES_TYPE is the type of the parameter
to which the result is passed.  Return NULL_TREE if that cannot be
determined or be considered an interprocedural invariant.   

References ggc_alloc(), ipa_get_jf_arith_result(), ipa_get_jf_pass_through_operand(), and ipa_get_jf_pass_through_operation().

Referenced by ipa_value_from_jfunc().

◆ ipa_get_parm_lattices()

◆ ipa_get_poly_ctx_lat()

static ipcp_lattice< ipa_polymorphic_call_context > * ipa_get_poly_ctx_lat ( class ipa_node_params * info,
int i )
inlinestatic
Return the lattice corresponding to the scalar value of the Ith formal
parameter of the function described by INFO.   

References ggc_alloc(), i, and ipa_get_parm_lattices().

Referenced by find_more_contexts_for_caller_subset(), ipa_context_from_jfunc(), and propagate_context_across_jump_function().

◆ ipa_get_scalar_lat()

static ipcp_lattice< tree > * ipa_get_scalar_lat ( class ipa_node_params * info,
int i )
inlinestatic
Return the lattice corresponding to the scalar value of the Ith formal
parameter of the function described by INFO.   

References ggc_alloc(), i, and ipa_get_parm_lattices().

Referenced by adjust_references_in_caller(), find_more_scalar_values_for_callers_subset(), ipa_value_from_jfunc(), ipcp_verify_propagated_values(), and propagate_scalar_across_jump_function().

◆ ipa_push_agg_values_from_jfunc()

void ipa_push_agg_values_from_jfunc ( ipa_node_params * info,
cgraph_node * node,
ipa_agg_jump_function * agg_jfunc,
unsigned dst_index,
vec< ipa_argagg_value > * res )
Process all items in AGG_JFUNC relative to caller (or the node the original
caller is inlined to) NODE which described by INFO and push the results to
RES as describing values passed in parameter DST_INDEX.   

References gcc_assert, ggc_alloc(), and ipa_agg_value_from_jfunc().

Referenced by evaluate_properties_for_edge().

◆ ipa_range_contains_p()

static bool ipa_range_contains_p ( const vrange & r,
tree val )
inlinestatic
Like irange::contains_p(), but convert VAL to the range of R if
necessary.   

References wi::fits_to_tree_p(), fold_convert, r, and wi::to_wide().

Referenced by decide_whether_version_node().

◆ ipa_value_from_jfunc()

tree ipa_value_from_jfunc ( class ipa_node_params * info,
struct ipa_jump_func * jfunc,
tree parm_type )
Determine whether JFUNC evaluates to a single known constant value and if
so, return it.  Otherwise return NULL.  INFO describes the caller node or
the one it is inlined to, so that pass-through jump functions can be
evaluated.  PARM_TYPE is the type of the parameter to which the result is
passed.   

References ggc_alloc(), ipa_get_jf_ancestor_formal_id(), ipa_get_jf_ancestor_result(), ipa_get_jf_constant(), ipa_get_jf_pass_through_formal_id(), ipa_get_jf_pass_through_result(), ipa_get_param_count(), ipa_get_scalar_lat(), IPA_JF_ANCESTOR, IPA_JF_CONST, IPA_JF_PASS_THROUGH, ipa_node_params::ipcp_orig_node, ipa_node_params::known_csts, ipa_node_params::lattices, and NULL_TREE.

Referenced by cgraph_edge_brings_all_scalars_for_node(), evaluate_properties_for_edge(), find_more_scalar_values_for_callers_subset(), and try_make_edge_direct_simple_call().

◆ ipa_value_range_from_jfunc()

◆ ipa_vr_operation_and_type_effects() [1/2]

static bool ipa_vr_operation_and_type_effects ( vrange & dst_vr,
const ipa_vr & src_vr,
enum tree_code operation,
tree dst_type,
tree src_type )
static
Same as above, but the SRC_VR argument is an IPA_VR which must
first be extracted onto a vrange.   

References ggc_alloc(), and ipa_vr_operation_and_type_effects().

◆ ipa_vr_operation_and_type_effects() [2/2]

static bool ipa_vr_operation_and_type_effects ( vrange & dst_vr,
const vrange & src_vr,
enum tree_code operation,
tree dst_type,
tree src_type )
static
Emulate effects of unary OPERATION and/or conversion from SRC_TYPE to
DST_TYPE on value range in SRC_VR and store it to DST_VR.  Return true if
the result is a range that is not VARYING nor UNDEFINED.   

References range_op_handler::fold_range(), ggc_alloc(), ipa_supports_p(), and range_op_handler::operand_check_p().

Referenced by ipa_value_range_from_jfunc(), ipa_vr_operation_and_type_effects(), and propagate_vr_across_jump_function().

◆ ipacp_value_safe_for_type()

static bool ipacp_value_safe_for_type ( tree param_type,
tree value )
static
Return true if VALUE can be safely IPA-CP propagated to a parameter of type
PARAM_TYPE.   

References fold_convertible_p(), ggc_alloc(), TREE_TYPE, and useless_type_conversion_p().

Referenced by propagate_scalar_across_jump_function(), propagate_vals_across_ancestor(), and propagate_vals_across_arith_jfunc().

◆ ipcp_cloning_candidate_p()

◆ ipcp_decision_stage()

static void ipcp_decision_stage ( class ipa_topo_info * topo)
static
The decision stage.  Iterate over the topological order of call graph nodes
TOPO and make specialized clones if deemed beneficial.   

References symtab_node::aux, decide_whether_version_node(), dump_file, ggc_alloc(), cgraph_node::has_gimple_body_p(), i, identify_dead_nodes(), and ipcp_versionable_function_p().

Referenced by ipcp_driver().

◆ ipcp_discover_new_direct_edges()

◆ ipcp_driver()

◆ ipcp_generate_summary()

static void ipcp_generate_summary ( void )
static
Initialization and computation of IPCP data structures.  This is the initial
intraprocedural analysis of functions, which gathers information to be
propagated later on.   

References dump_file, FOR_EACH_FUNCTION_WITH_GIMPLE_BODY, ggc_alloc(), ipa_analyze_node(), and ipa_register_cgraph_hooks().

◆ ipcp_propagate_stage()

◆ ipcp_store_vr_results()

◆ ipcp_val_agg_replacement_ok_p() [1/2]

DEBUG_FUNCTION bool ipcp_val_agg_replacement_ok_p ( vec< ipa_argagg_value, va_gc > * ,
int ,
HOST_WIDE_INT offset,
ipa_polymorphic_call_context  )
Return true if offset is minus one because source of a polymorphic context
cannot be an aggregate value.   

References offset.

◆ ipcp_val_agg_replacement_ok_p() [2/2]

DEBUG_FUNCTION bool ipcp_val_agg_replacement_ok_p ( vec< ipa_argagg_value, va_gc > * aggvals,
int index,
HOST_WIDE_INT offset,
tree value )
Return true if OFFSET indicates this was not an aggregate value or there is
a replacement equivalent to VALUE, INDEX and OFFSET among those in the
AGGVALS list.   

References ggc_alloc(), offset, and values_equal_for_ipcp_p().

Referenced by decide_about_value().

◆ ipcp_verify_propagated_values()

DEBUG_FUNCTION void ipcp_verify_propagated_values ( void )
If checking is enabled, verify that no lattice is in the TOP state, i.e. not
bottom, not containing a variable component and without any known value at
the same time.   

References count, symtab_node::decl, symbol_table::dump(), dump_file, FOR_EACH_FUNCTION_WITH_GIMPLE_BODY, gcc_unreachable, ggc_alloc(), i, ipa_get_param_count(), ipa_get_scalar_lat(), ipa_node_params_sum, opt_for_fn, print_all_lattices(), and symtab.

Referenced by ipcp_propagate_stage().

◆ ipcp_versionable_function_p()

static bool ipcp_versionable_function_p ( struct cgraph_node * node)
static

◆ known_contexts_useful_p()

static bool known_contexts_useful_p ( vec< ipa_polymorphic_call_context > known_contexts)
static
Return true if KNOWN_CONTEXTS contain at least one useful context.   

References FOR_EACH_VEC_ELT, i, and ipa_polymorphic_call_context::useless_p().

Referenced by copy_useful_known_contexts(), and decide_whether_version_node().

◆ lenient_count_portion_handling()

profile_count lenient_count_portion_handling ( profile_count remainder,
cgraph_node * orig_node )
With partial train run we do not want to assume that original's count is
zero whenever we redurect all executed edges to clone.  Simply drop profile
to local one in this case.  In eany case, return the new value.  ORIG_NODE
is the original node and its count has not been updaed yet.   

References ggc_alloc(), and opt_for_fn.

Referenced by update_counts_for_self_gen_clones(), update_profiling_info(), and update_specialized_profile().

◆ make_pass_ipa_cp()

ipa_opt_pass_d * make_pass_ipa_cp ( gcc::context * ctxt)

References ggc_alloc().

◆ merge_agg_lats_step()

static bool merge_agg_lats_step ( class ipcp_param_lattices * dest_plats,
HOST_WIDE_INT offset,
HOST_WIDE_INT val_size,
struct ipcp_agg_lattice *** aglat,
bool pre_existing,
bool * change,
int max_agg_items )
static
Walk aggregate lattices in DEST_PLATS from ***AGLAT on, until ***aglat is an
already existing lattice for the given OFFSET and SIZE, marking all skipped
lattices as containing variable and checking for overlaps.  If there is no
already existing lattice for the OFFSET and VAL_SIZE, create one, initialize
it with offset, size and contains_variable to PRE_EXISTING, and return true,
unless there are too many already.  If there are two many, return false.  If
there are overlaps turn whole DEST_PLATS to bottom and return false.  If any
skipped lattices were newly marked as containing variable, set *CHANGE to
true.  MAX_AGG_ITEMS is the maximum number of lattices.   

References gcc_assert, gcc_checking_assert, ggc_alloc(), ipcp_agg_lattice_pool, offset, and set_agg_lats_to_bottom().

Referenced by merge_aggregate_lattices(), and propagate_aggs_across_jump_function().

◆ merge_aggregate_lattices()

static bool merge_aggregate_lattices ( struct cgraph_edge * cs,
class ipcp_param_lattices * dest_plats,
class ipcp_param_lattices * src_plats,
int src_idx,
HOST_WIDE_INT offset_delta )
static
Merge existing aggregate lattices in SRC_PLATS to DEST_PLATS, subtracting
DELTA_OFFSET.  CS is the call graph edge and SRC_IDX the index of the source
parameter used for lattice value sources.  Return true if DEST_PLATS changed
in any way.   

References cgraph_edge::callee, symtab_node::decl, cgraph_node::function_symbol(), ggc_alloc(), merge_agg_lats_step(), NULL, opt_for_fn, set_agg_lats_contain_variable(), set_chain_of_aglats_contains_variable(), and set_check_aggs_by_ref().

Referenced by propagate_aggs_across_jump_function().

◆ perform_estimation_of_a_value()

static void perform_estimation_of_a_value ( cgraph_node * node,
ipa_auto_call_arg_values * avals,
int removable_params_cost,
int est_move_cost,
ipcp_value_base * val )
static
Perform time and size measurement of NODE with the context given in AVALS,
calculate the benefit compared to the node without specialization and store
it into VAL.  Take into account REMOVABLE_PARAMS_COST of all
context-independent or unused removable parameters and EST_MOVE_COST, the
estimated movement of the considered parameter.   

References symtab_node::decl, DECL_DECLARED_INLINE_P, DECL_EXTERNAL, devirtualization_time_bonus(), estimate_ipcp_clone_size_and_time(), gcc_checking_assert, ggc_alloc(), hint_time_bonus(), ipcp_value_base::local_size_cost, and ipcp_value_base::local_time_benefit.

Referenced by estimate_local_effects().

◆ perhaps_add_new_callers()

template<typename valtype >
static void perhaps_add_new_callers ( cgraph_node * node,
ipcp_value< valtype > * val )
static
Given an original NODE and a VAL for which we have already created a
specialized clone, look whether there are incoming edges that still lead
into the old node but now also bring the requested value and also conform to
all other criteria such that they can be redirected the special node.
This function can therefore redirect the final edge in a SCC.   

References cgraph_edge::caller, cgraph_edge_brings_all_agg_vals_for_node(), cgraph_edge_brings_all_scalars_for_node(), cgraph_edge_brings_value_p(), cgraph_edge::count, ipcp_value_source< valtype >::cs, dump_file, symtab_node::dump_name(), cgraph_node::expand_all_artificial_thunks(), get_next_cgraph_edge_clone(), ggc_alloc(), profile_count::initialized_p(), profile_count::ipa(), ipcp_value_source< valtype >::next, cgraph_edge::redirect_callee_duplicating_thunks(), ipcp_value< valtype >::sources, ipcp_value< valtype >::spec_node, update_specialized_profile(), and profile_count::zero().

Referenced by decide_about_value().

◆ pop_node_from_stack()

static struct cgraph_node * pop_node_from_stack ( class ipa_topo_info * topo)
static
Pop a node from the stack in TOPO and return it or return NULL if the stack
is empty.   

References ggc_alloc(), ipa_node_params_sum, and NULL.

Referenced by propagate_constants_topo().

◆ print_all_lattices()

◆ print_ipcp_constant_value()

◆ propagate_aggregate_lattice()

◆ propagate_aggs_across_jump_function()

◆ propagate_bits_across_jump_function()

◆ propagate_constants_across_call()

◆ propagate_constants_topo()

◆ propagate_context_across_jump_function()

◆ propagate_scalar_across_jump_function()

static bool propagate_scalar_across_jump_function ( struct cgraph_edge * cs,
struct ipa_jump_func * jfunc,
ipcp_lattice< tree > * dest_lat,
tree param_type )
static
Propagate scalar values across jump function JFUNC that is associated with
edge CS and put the values into DEST_LAT.  PARM_TYPE is the type of the
parameter to which the result is passed.   

References cgraph_edge::caller, ggc_alloc(), ipa_get_jf_ancestor_formal_id(), ipa_get_jf_constant(), ipa_get_jf_pass_through_formal_id(), ipa_get_scalar_lat(), IPA_JF_ANCESTOR, IPA_JF_CONST, IPA_JF_PASS_THROUGH, ipa_node_params_sum, ipacp_value_safe_for_type(), ipcp_versionable_function_p(), NULL, propagate_vals_across_ancestor(), and propagate_vals_across_pass_through().

Referenced by propagate_constants_across_call().

◆ propagate_vals_across_ancestor()

static bool propagate_vals_across_ancestor ( struct cgraph_edge * cs,
struct ipa_jump_func * jfunc,
ipcp_lattice< tree > * src_lat,
ipcp_lattice< tree > * dest_lat,
int src_idx,
tree param_type )
static
Propagate values through an ancestor jump function JFUNC associated with
edge CS, taking values from SRC_LAT and putting them into DEST_LAT.  SRC_IDX
is the index of the source parameter.   

References ggc_alloc(), ipa_edge_within_scc(), ipa_get_jf_ancestor_result(), and ipacp_value_safe_for_type().

Referenced by propagate_scalar_across_jump_function().

◆ propagate_vals_across_arith_jfunc()

static bool propagate_vals_across_arith_jfunc ( cgraph_edge * cs,
enum tree_code opcode,
tree opnd1_type,
tree opnd2,
ipcp_lattice< tree > * src_lat,
ipcp_lattice< tree > * dest_lat,
HOST_WIDE_INT src_offset,
int src_idx,
tree res_type )
static
Propagate values through an arithmetic transformation described by a jump
function associated with edge CS, taking values from SRC_LAT and putting
them into DEST_LAT.  OPND1_TYPE is expected type for the values in SRC_LAT.
OPND2 is a constant value if transformation is a binary operation.
SRC_OFFSET specifies offset in an aggregate if SRC_LAT describes lattice of
a part of the aggregate.  SRC_IDX is the index of the source parameter.
RES_TYPE is the value type of result being propagated into.  Return true if
DEST_LAT changed.   

References cgraph_edge::caller, ipcp_value_source< valtype >::cs, symtab_node::decl, FOR_EACH_VEC_ELT, gcc_assert, gcc_checking_assert, get_val_across_arith_op(), ggc_alloc(), i, ipa_edge_within_scc(), ipacp_value_safe_for_type(), ipcp_value_source< valtype >::next, opt_for_fn, and cgraph_edge::sreal_frequency().

Referenced by propagate_aggregate_lattice(), and propagate_vals_across_pass_through().

◆ propagate_vals_across_pass_through()

static bool propagate_vals_across_pass_through ( cgraph_edge * cs,
ipa_jump_func * jfunc,
ipcp_lattice< tree > * src_lat,
ipcp_lattice< tree > * dest_lat,
int src_idx,
tree parm_type )
static
Propagate values through a pass-through jump function JFUNC associated with
edge CS, taking values from SRC_LAT and putting them into DEST_LAT.  SRC_IDX
is the index of the source parameter.  PARM_TYPE is the type of the
parameter to which the result is passed.   

References ggc_alloc(), ipa_get_jf_pass_through_operand(), ipa_get_jf_pass_through_operation(), NULL_TREE, and propagate_vals_across_arith_jfunc().

Referenced by propagate_scalar_across_jump_function().

◆ propagate_vr_across_jump_function()

◆ push_agg_values_for_index_from_edge()

static void push_agg_values_for_index_from_edge ( struct cgraph_edge * cs,
int index,
vec< ipa_argagg_value > * res,
const ipa_argagg_value_list * interim )
static
Push all aggregate values coming along edge CS for parameter number INDEX to
RES.  If INTERIM is non-NULL, it contains the current interim state of
collected aggregate values which can be used to compute values passed over
self-recursive edges.

This basically one iteration of push_agg_values_from_edge over one
parameter, which allows for simpler early returns.   

References cgraph_edge::caller, gcc_assert, ggc_alloc(), ipa_argagg_value::index, ipa_agg_value_from_jfunc(), ipa_edge_args_sum, ipa_get_ith_jump_func(), ipa_get_jf_ancestor_agg_preserved(), ipa_get_jf_ancestor_formal_id(), ipa_get_jf_ancestor_offset(), ipa_get_jf_arith_result(), ipa_get_jf_pass_through_agg_preserved(), ipa_get_jf_pass_through_formal_id(), ipa_get_jf_pass_through_operation(), ipa_get_parm_lattices(), IPA_JF_ANCESTOR, IPA_JF_PASS_THROUGH, ipa_node_params_sum, ipcp_get_transformation_summary(), ipa_argagg_value_list::push_adjusted_values(), push_agg_values_from_plats(), self_recursive_agg_pass_through_p(), self_recursive_pass_through_p(), UINT_MAX, and ipa_argagg_value::value.

Referenced by push_agg_values_from_edge().

◆ push_agg_values_from_edge()

static void push_agg_values_from_edge ( struct cgraph_edge * cs,
ipa_node_params * dest_info,
vec< ipa_argagg_value > * res,
const ipa_argagg_value_list * interim,
bool optimize_self_recursion )
static
Push all aggregate values coming along edge CS to RES.  DEST_INFO is the
description of ultimate callee of CS or the one it was cloned from (the
summary where lattices are).  If INTERIM is non-NULL, it contains the
current interim state of collected aggregate values which can be used to
compute values passed over self-recursive edges (if OPTIMIZE_SELF_RECURSION
is true) and to skip values which clearly will not be part of intersection
with INTERIM.   

References count, ggc_alloc(), ipa_argagg_value::index, ipa_edge_args_sum, ipa_get_cs_argument_count(), ipa_get_param_count(), ipa_get_parm_lattices(), ipa_is_param_used(), MIN, NULL, and push_agg_values_for_index_from_edge().

Referenced by cgraph_edge_brings_all_agg_vals_for_node(), and find_aggregate_values_for_callers_subset().

◆ push_agg_values_from_plats()

static bool push_agg_values_from_plats ( ipcp_param_lattices * plats,
int dest_index,
unsigned unit_delta,
vec< ipa_argagg_value > * res )
static
Push to RES information about single lattices describing aggregate values in
PLATS as those describing parameter DEST_INDEX and the original offset minus
UNIT_DELTA.  Return true if any item has been pushed to RES.   

References gcc_assert, and ggc_alloc().

Referenced by gather_context_independent_values(), and push_agg_values_for_index_from_edge().

◆ push_node_to_stack()

static void push_node_to_stack ( class ipa_topo_info * topo,
struct cgraph_node * node )
inlinestatic
Add NODE to the stack in TOPO, unless it is already there.   

References ggc_alloc(), ipa_node_params_sum, and ipa_node_params::node_enqueued.

Referenced by propagate_constants_topo().

◆ self_recursive_agg_pass_through_p()

static bool self_recursive_agg_pass_through_p ( const cgraph_edge * cs,
const ipa_agg_jf_item * jfunc,
int i,
bool simple = true )
static
Return true if JFUNC, which describes a part of an aggregate represented or
pointed to by the i-th parameter of call CS, is a pass-through function to
itself when the cgraph_node involved is not an IPA-CP clone..  When
SIMPLE is true, further check if JFUNC is a simple no-operation
pass-through.   

References AVAIL_INTERPOSABLE, cgraph_edge::callee, cgraph_edge::caller, cgraph_node::function_symbol(), ggc_alloc(), i, IPA_JF_LOAD_AGG, ipa_node_params_sum, and useless_type_conversion_p().

Referenced by push_agg_values_for_index_from_edge().

◆ self_recursive_pass_through_p()

static bool self_recursive_pass_through_p ( cgraph_edge * cs,
ipa_jump_func * jfunc,
int i,
bool simple = true )
static
Return true if JFUNC, which describes a i-th parameter of call CS, is a
pass-through function to itself when the cgraph_node involved is not an
IPA-CP clone.  When SIMPLE is true, further check if JFUNC is a simple
no-operation pass-through.   

References AVAIL_INTERPOSABLE, cgraph_edge::callee, cgraph_edge::caller, cgraph_node::function_symbol(), ggc_alloc(), i, ipa_get_jf_pass_through_formal_id(), ipa_get_jf_pass_through_operation(), IPA_JF_PASS_THROUGH, and ipa_node_params_sum.

Referenced by find_more_scalar_values_for_callers_subset(), and push_agg_values_for_index_from_edge().

◆ set_agg_lats_contain_variable()

static bool set_agg_lats_contain_variable ( class ipcp_param_lattices * plats)
inlinestatic
Mark all aggregate lattices in PLATS as containing an unknown value and
return true if they were not previously marked as such.   

References ggc_alloc().

Referenced by merge_aggregate_lattices(), propagate_aggs_across_jump_function(), and set_all_contains_variable().

◆ set_agg_lats_to_bottom()

static bool set_agg_lats_to_bottom ( class ipcp_param_lattices * plats)
inlinestatic
Set all aggregate lattices in PLATS to bottom and return true if they were
not previously set as such.   

References ggc_alloc().

Referenced by initialize_node_lattices(), merge_agg_lats_step(), propagate_aggs_across_jump_function(), and set_check_aggs_by_ref().

◆ set_all_contains_variable()

static bool set_all_contains_variable ( class ipcp_param_lattices * plats)
inlinestatic
Mark bot aggregate and scalar lattices as containing an unknown variable,
return true is any of them has not been marked as such so far.   

References ggc_alloc(), and set_agg_lats_contain_variable().

Referenced by initialize_node_lattices(), and propagate_constants_across_call().

◆ set_chain_of_aglats_contains_variable()

static bool set_chain_of_aglats_contains_variable ( struct ipcp_agg_lattice * aglat)
static
Set all AGLAT and all other aggregate lattices reachable by next pointers as
containing an unknown value.   

References ggc_alloc().

Referenced by merge_aggregate_lattices(), and propagate_aggs_across_jump_function().

◆ set_check_aggs_by_ref()

static bool set_check_aggs_by_ref ( class ipcp_param_lattices * dest_plats,
bool new_aggs_by_ref )
static
If DEST_PLATS already has aggregate items, check that aggs_by_ref matches
NEW_AGGS_BY_REF and if not, mark all aggs as bottoms and return true (in all
other cases, return false).  If there are no aggregate items, set
aggs_by_ref to NEW_AGGS_BY_REF.   

References ggc_alloc(), and set_agg_lats_to_bottom().

Referenced by merge_aggregate_lattices(), and propagate_aggs_across_jump_function().

◆ set_single_call_flag()

static bool set_single_call_flag ( cgraph_node * node,
void *  )
static
Worker of call_for_symbol_thunks_and_aliases, it is supposed to be called on
the one caller of some other node.  Set the caller's corresponding flag.   

References cgraph_edge::caller, cgraph_node::callers, ipa_node_params_sum, cgraph_node::local, cgraph_edge::next_caller, and cgraph_node::thunk.

Referenced by initialize_node_lattices().

◆ spread_undeadness()

static void spread_undeadness ( struct cgraph_node * node)
static

◆ update_counts_for_self_gen_clones()

static void update_counts_for_self_gen_clones ( cgraph_node * orig_node,
const vec< cgraph_node * > & self_gen_clones )
static
When ORIG_NODE has been cloned for values which have been generated fora
self-recursive call as a result of an arithmetic pass-through
jump-functions, adjust its count together with counts of all such clones in
SELF_GEN_CLONES which also at this point contains ORIG_NODE itself.

The function sums the counts of the original node and all its clones that
cannot be attributed to a specific clone because it comes from a
non-recursive edge.  This sum is then evenly divided between the clones and
on top of that each one gets all the counts which can be attributed directly
to it.   

References hash_set< KeyId, Lazy, Traits >::add(), adjust_clone_incoming_counts(), profile_count::adjust_for_ipa_scaling(), analyze_clone_icoming_counts(), hash_set< KeyId, Lazy, Traits >::contains(), desc_incoming_count_struct::count, dump_file, dump_profile_updates(), gather_count_of_non_rec_edges(), get_next_cgraph_edge_clone(), ggc_alloc(), i, lenient_count_portion_handling(), desc_incoming_count_struct::orig, desc_incoming_count_struct::processed_edges, desc_incoming_count_struct::unproc_orig_rec_edges, and profile_count::zero().

Referenced by decide_whether_version_node().

◆ update_profiling_info()

static void update_profiling_info ( struct cgraph_node * orig_node,
struct cgraph_node * new_node )
static
After a specialized NEW_NODE version of ORIG_NODE has been created, update
their profile information to reflect this.  This function should not be used
for clones generated for arithmetic pass-through jump functions on a
self-recursive call graph edge, that situation is handled by
update_counts_for_self_gen_clones.   

References profile_count::adjust_for_ipa_scaling(), profile_count::adjusted_zero(), cgraph_node::call_for_symbol_thunks_and_aliases(), cgraph_node::callees, cgraph_node::count, dump_file, dump_profile_updates(), gather_caller_stats(), ggc_alloc(), profile_count::guessed_local(), cgraph_node::indirect_calls, init_caller_stats(), lenient_count_portion_handling(), MAX, MIN, opt_for_fn, and profile_count::zero().

Referenced by decide_about_value().

◆ update_specialized_profile()

static void update_specialized_profile ( struct cgraph_node * new_node,
struct cgraph_node * orig_node,
profile_count redirected_sum )
static
Update the respective profile of specialized NEW_NODE and the original
ORIG_NODE after additional edges with cumulative count sum REDIRECTED_SUM
have been redirected to the specialized version.   

References profile_count::apply_scale(), cgraph_node::callees, cgraph_node::count, cgraph_edge::count, dump_file, dump_profile_updates(), ggc_alloc(), lenient_count_portion_handling(), cgraph_edge::next_callee, and profile_count::zero().

Referenced by perhaps_add_new_callers().

◆ values_equal_for_ipcp_p() [1/2]

static bool values_equal_for_ipcp_p ( ipa_polymorphic_call_context x,
ipa_polymorphic_call_context y )
static
Return true iff X and Y should be considered equal contexts by IPA-CP.   

References ipa_polymorphic_call_context::equal_to(), and y.

◆ values_equal_for_ipcp_p() [2/2]

◆ want_remove_some_param_p()

static bool want_remove_some_param_p ( cgraph_node * node,
vec< tree > known_csts )
static
Return true if we would like to remove a parameter from NODE when cloning it
with KNOWN_CSTS scalar constants.   

References count, clone_info::get(), ipa_param_adjustments::get_surviving_params(), ggc_alloc(), i, ipa_get_param_count(), ipa_is_param_used(), ipa_node_params_sum, and clone_info::param_adjustments.

Referenced by create_specialized_node().

Variable Documentation

◆ base_count

profile_count base_count
static
Base count to use in heuristics when using profile feedback.   

Referenced by good_cloning_opportunity_p(), ipa_cp_cc_finalize(), and ipcp_propagate_stage().

◆ clone_num_suffixes

hash_map<const char *, unsigned>* clone_num_suffixes
static
Node name to unique clone suffix number map.   

Referenced by create_specialized_node(), and ipcp_driver().

◆ edge_clone_summaries

◆ ipcp_agg_lattice_pool

◆ ipcp_cst_values_pool

object_allocator< ipcp_value< tree > > ipcp_cst_values_pool("IPA-CP constant values") ( "IPA-CP constant values" )
Allocation pools for values and their sources in ipa-cp.   

Referenced by allocate_and_init_ipcp_value(), ipa_free_all_structures_after_iinln(), and ipa_free_all_structures_after_ipa_cp().

◆ ipcp_poly_ctx_values_pool

◆ ipcp_sources_pool

◆ orig_overall_size

long orig_overall_size
static

◆ overall_size