GCC Middle and Back End API Reference
ipa-pure-const.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 "tree-pass.h"
#include "tree-streamer.h"
#include "cgraph.h"
#include "diagnostic.h"
#include "calls.h"
#include "cfganal.h"
#include "tree-eh.h"
#include "gimple-iterator.h"
#include "gimple-walk.h"
#include "tree-cfg.h"
#include "tree-ssa-loop-niter.h"
#include "langhooks.h"
#include "ipa-utils.h"
#include "gimple-pretty-print.h"
#include "cfgloop.h"
#include "tree-scalar-evolution.h"
#include "intl.h"
#include "opts.h"
#include "ssa.h"
#include "alloc-pool.h"
#include "symbol-summary.h"
#include "sreal.h"
#include "ipa-cp.h"
#include "ipa-prop.h"
#include "ipa-fnsummary.h"
#include "symtab-thunks.h"
#include "dbgcnt.h"
Include dependency graph for ipa-pure-const.cc:

Data Structures

class  funct_state_d
 
class  funct_state_summary_t
 

Macros

#define DUMP_AND_RETURN(reason)
 

Typedefs

typedef class funct_state_dfunct_state
 

Enumerations

enum  pure_const_state_e { IPA_CONST , IPA_PURE , IPA_NEITHER }
 
enum  malloc_state_e { STATE_MALLOC_TOP , STATE_MALLOC , STATE_MALLOC_BOTTOM }
 

Functions

static bool gate_pure_const (void)
 
static bool function_always_visible_to_compiler_p (tree decl)
 
static hash_set< tree > * suggest_attribute (int option, tree decl, bool known_finite, hash_set< tree > *warned_about, const char *attrib_name)
 
static void warn_function_pure (tree decl, bool known_finite)
 
static void warn_function_const (tree decl, bool known_finite)
 
static void warn_function_malloc (tree decl)
 
static void warn_function_noreturn (tree decl)
 
void warn_function_cold (tree decl)
 
void warn_function_returns_nonnull (tree decl)
 
static void check_decl (funct_state local, tree t, bool checking_write, bool ipa)
 
static void check_op (funct_state local, tree t, bool checking_write)
 
static void state_from_flags (enum pure_const_state_e *state, bool *looping, int flags, bool cannot_lead_to_return)
 
static void better_state (enum pure_const_state_e *state, bool *looping, enum pure_const_state_e state2, bool looping2)
 
static void worse_state (enum pure_const_state_e *state, bool *looping, enum pure_const_state_e state2, bool looping2, struct symtab_node *from, struct symtab_node *to)
 
bool builtin_safe_for_const_function_p (bool *looping, tree callee)
 
static void check_call (funct_state local, gcall *call, bool ipa)
 
static bool check_load (gimple *, tree op, tree, void *data)
 
static bool check_store (gimple *, tree op, tree, void *data)
 
static bool check_ipa_load (gimple *, tree op, tree, void *data)
 
static bool check_ipa_store (gimple *, tree op, tree, void *data)
 
static void check_stmt (gimple_stmt_iterator *gsip, funct_state local, bool ipa)
 
static bool check_retval_uses (tree retval, gimple *stmt)
 
static bool malloc_candidate_p_1 (function *fun, tree retval, gimple *ret_stmt, bool ipa, bitmap visited)
 
static bool malloc_candidate_p (function *fun, bool ipa)
 
bool finite_function_p ()
 
static funct_state analyze_function (struct cgraph_node *fn, bool ipa)
 
static void pure_const_generate_summary (void)
 
static void pure_const_write_summary (void)
 
static void pure_const_read_summary (void)
 
static bool ignore_edge_for_nothrow (struct cgraph_edge *e)
 
static bool self_recursive_p (struct cgraph_node *node)
 
static bool cdtor_p (cgraph_node *n, void *)
 
static bool ignore_edge_for_pure_const (struct cgraph_edge *e)
 
static bool skip_function_for_local_pure_const (struct cgraph_node *node)
 
bool ipa_make_function_const (struct cgraph_node *node, bool looping, bool local)
 
bool ipa_make_function_pure (struct cgraph_node *node, bool looping, bool local)
 
static bool propagate_pure_const (void)
 
static void propagate_nothrow (void)
 
static DEBUG_FUNCTION void dump_malloc_lattice (FILE *dump_file, const char *s)
 
static void propagate_malloc (void)
 
ipa_opt_pass_dmake_pass_ipa_pure_const (gcc::context *ctxt)
 
gimple_opt_passmake_pass_local_pure_const (gcc::context *ctxt)
 
gimple_opt_passmake_pass_warn_function_noreturn (gcc::context *ctxt)
 
gimple_opt_passmake_pass_nothrow (gcc::context *ctxt)
 

Variables

static const charpure_const_names [3] = {"const", "pure", "neither"}
 
static const charmalloc_state_names [] = {"malloc_top", "malloc", "malloc_bottom"}
 
static funct_state_summary_tfunct_state_summaries = NULL
 

Macro Definition Documentation

◆ DUMP_AND_RETURN

#define DUMP_AND_RETURN ( reason)
Value:
{ \
fprintf (dump_file, "\n%s is not a malloc candidate, reason: %s\n", \
(node->dump_name ()), (reason)); \
return false; \
}
dump_flags_t dump_flags
Definition dumpfile.cc:64
FILE * dump_file
Definition dumpfile.cc:62
@ TDF_DETAILS
Definition dumpfile.h:92
T * ggc_alloc(ALONE_CXX_MEM_STAT_INFO)
Definition ggc.h:184
malloc_candidate_p() checks if FUN can possibly be annotated with malloc
attribute. Currently this function does a very conservative analysis.
FUN is considered to be a candidate if
1) It returns a value of pointer type.
2) SSA_NAME_DEF_STMT (return_value) is either a function call or
   a phi, and element of phi is either NULL or
   SSA_NAME_DEF_STMT(element) is function call.
3) The return-value has immediate uses only within comparisons (gcond or gassign)
   and return_stmt (and likewise a phi arg has immediate use only within comparison
   or the phi stmt).   

Referenced by malloc_candidate_p(), and malloc_candidate_p_1().

Typedef Documentation

◆ funct_state

Enumeration Type Documentation

◆ malloc_state_e

Enumerator
STATE_MALLOC_TOP 
STATE_MALLOC 
STATE_MALLOC_BOTTOM 

◆ pure_const_state_e

Callgraph based analysis of static variables.
   Copyright (C) 2004-2024 Free Software Foundation, Inc.
   Contributed by Kenneth Zadeck <zadeck@naturalbridge.com>

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/>.   
This file marks functions as being either const (TREE_READONLY) or
pure (DECL_PURE_P).  It can also set a variant of these that
are allowed to loop indefinitely (DECL_LOOPING_CONST_PURE_P).

This must be run after inlining decisions have been made since
otherwise, the local sets will not contain information that is
consistent with post inlined state.  The global sets are not prone
to this problem since they are by definition transitive.   
The code in this module is called by the ipa pass manager. It
should be one of the later passes since it's information is used by
the rest of the compilation.  
Lattice values for const and pure functions.  Everything starts out
being const, then may drop to pure and then neither depending on
what is found.   
Enumerator
IPA_CONST 
IPA_PURE 
IPA_NEITHER 

Function Documentation

◆ analyze_function()

◆ better_state()

static void better_state ( enum pure_const_state_e * state,
bool * looping,
enum pure_const_state_e state2,
bool looping2 )
inlinestatic
Merge STATE and STATE2 and LOOPING and LOOPING2 and store
into STATE and LOOPING better of the two variants.
Be sure to merge looping correctly.  IPA_NEITHER functions
have looping 0 even if they don't have to return.   

References ggc_alloc(), IPA_NEITHER, and MIN.

Referenced by analyze_function(), and propagate_pure_const().

◆ builtin_safe_for_const_function_p()

bool builtin_safe_for_const_function_p ( bool * looping,
tree callee )
Recognize special cases of builtins that are by themselves not const
but function using them is.   

References BUILT_IN_NORMAL, CASE_BUILT_IN_ALLOCA, DECL_BUILT_IN_CLASS, DECL_FUNCTION_CODE(), and ggc_alloc().

Referenced by check_call(), and propagate_pure_const().

◆ cdtor_p()

static bool cdtor_p ( cgraph_node * n,
void *  )
static
Return true if N is cdtor that is not const or pure.  In this case we may
need to remove unreachable function if it is marked const/pure.   

References symtab_node::decl, DECL_LOOPING_CONST_OR_PURE_P, DECL_PURE_P, DECL_STATIC_CONSTRUCTOR, DECL_STATIC_DESTRUCTOR, and TREE_READONLY.

Referenced by ipa_make_function_const(), and ipa_make_function_pure().

◆ check_call()

static void check_call ( funct_state local,
gcall * call,
bool ipa )
static
Check the parameters of a function call to CALL_EXPR to see if
there are any references in the parameters that are not allowed for
pure or const functions.  Also check to see if this is either an
indirect call, a call outside the compilation unit, or has special
attributes that may also effect the purity.  The CALL_EXPR node for
the entire call expression.   

References BUILT_IN_NORMAL, builtin_safe_for_const_function_p(), cfun, current_function_decl, DECL_ASSEMBLER_NAME, DECL_BUILT_IN_CLASS, DECL_FUNCTION_CODE(), dump_file, dump_flags, ECF_NORETURN, ECF_NOTHROW, ggc_alloc(), gimple_call_builtin_p(), gimple_call_flags(), gimple_call_fndecl(), gimple_call_internal_p(), gimple_num_ops(), gimple_op(), i, IDENTIFIER_POINTER, IPA_CONST, IPA_NEITHER, lookup_stmt_eh_lp(), nonfreeing_call_p(), NULL, recursive_call_p(), setjmp_call_p(), state_from_flags(), stmt_can_throw_external(), stmt_could_throw_p(), TDF_DETAILS, tree_could_throw_p(), and worse_state().

Referenced by check_stmt().

◆ check_decl()

static void check_decl ( funct_state local,
tree t,
bool checking_write,
bool ipa )
inlinestatic
Check to see if the use (or definition when CHECKING_WRITE is true)
variable T is legal in a function that is either pure or const.   

References DECL_EXTERNAL, DECL_PRESERVE_P, dump_file, ggc_alloc(), IPA_CONST, IPA_NEITHER, IPA_PURE, TREE_PUBLIC, TREE_READONLY, TREE_STATIC, and TREE_THIS_VOLATILE.

Referenced by check_ipa_load(), check_ipa_store(), check_load(), and check_store().

◆ check_ipa_load()

static bool check_ipa_load ( gimple * ,
tree op,
tree ,
void * data )
static
Wrapper around check_decl for loads in ipa mode.   

References check_decl(), check_op(), and DECL_P.

Referenced by check_stmt().

◆ check_ipa_store()

static bool check_ipa_store ( gimple * ,
tree op,
tree ,
void * data )
static
Wrapper around check_decl for stores in ipa mode.   

References check_decl(), check_op(), and DECL_P.

Referenced by check_stmt().

◆ check_load()

static bool check_load ( gimple * ,
tree op,
tree ,
void * data )
static
Wrapper around check_decl for loads in local more.   

References check_decl(), check_op(), and DECL_P.

Referenced by check_stmt().

◆ check_op()

static void check_op ( funct_state local,
tree t,
bool checking_write )
inlinestatic
Check to see if the use (or definition when CHECKING_WRITE is true)
variable T is legal in a function that is either pure or const.   

References dump_file, get_base_address(), ggc_alloc(), IPA_CONST, IPA_NEITHER, IPA_PURE, refs_local_or_readonly_memory_p(), and TREE_THIS_VOLATILE.

Referenced by check_ipa_load(), check_ipa_store(), check_load(), and check_store().

◆ check_retval_uses()

static bool check_retval_uses ( tree retval,
gimple * stmt )
static
Check that RETVAL is used only in STMT and in comparisons against 0.
RETVAL is return value of the function and STMT is return stmt.   

References FOR_EACH_IMM_USE_STMT, ggc_alloc(), gimple_assign_rhs2(), gimple_assign_rhs_code(), gimple_cond_rhs(), integer_zerop(), is_gimple_debug(), tcc_comparison, and TREE_CODE_CLASS.

Referenced by malloc_candidate_p_1().

◆ check_stmt()

◆ check_store()

static bool check_store ( gimple * ,
tree op,
tree ,
void * data )
static
Wrapper around check_decl for stores in local more.   

References check_decl(), check_op(), and DECL_P.

Referenced by check_stmt().

◆ dump_malloc_lattice()

static DEBUG_FUNCTION void dump_malloc_lattice ( FILE * dump_file,
const char * s )
static
Debugging function to dump state of malloc lattice.   

References dump_file, symtab_node::dump_name(), FOR_EACH_FUNCTION, funct_state_summaries, ggc_alloc(), and malloc_state_names.

Referenced by propagate_malloc().

◆ finite_function_p()

◆ function_always_visible_to_compiler_p()

static bool function_always_visible_to_compiler_p ( tree decl)
static
Try to guess if function body will always be visible to compiler
when compiling the call and whether compiler will be able
to propagate the information by itself.   

References DECL_COMDAT, DECL_DECLARED_INLINE_P, and TREE_PUBLIC.

Referenced by suggest_attribute().

◆ gate_pure_const()

static bool gate_pure_const ( void )
static

References ggc_alloc().

◆ ignore_edge_for_nothrow()

static bool ignore_edge_for_nothrow ( struct cgraph_edge * e)
static

◆ ignore_edge_for_pure_const()

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

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

Referenced by propagate_pure_const().

◆ ipa_make_function_const()

bool ipa_make_function_const ( struct cgraph_node * node,
bool looping,
bool local )
Make function const and output warning.  If LOCAL is true,
return true if anything changed.  Otherwise return true if
we may have introduced removale ctors.   

References cgraph_node::call_for_symbol_and_aliases(), cdtor_p(), dbg_cnt(), symtab_node::decl, DECL_LOOPING_CONST_OR_PURE_P, dump_file, symtab_node::dump_name(), ggc_alloc(), NULL, cgraph_node::set_const_flag(), skip_function_for_local_pure_const(), TREE_READONLY, and warn_function_const().

Referenced by propagate_pure_const().

◆ ipa_make_function_pure()

bool ipa_make_function_pure ( struct cgraph_node * node,
bool looping,
bool local )
Make function const and output warning.  If LOCAL is true,
return true if anything changed.  Otherwise return true if
we may have introduced removale ctors.   

References cgraph_node::call_for_symbol_and_aliases(), cdtor_p(), dbg_cnt(), symtab_node::decl, DECL_LOOPING_CONST_OR_PURE_P, DECL_PURE_P, dump_file, symtab_node::dump_name(), ggc_alloc(), NULL, cgraph_node::set_pure_flag(), skip_function_for_local_pure_const(), TREE_READONLY, and warn_function_pure().

Referenced by propagate_pure_const().

◆ make_pass_ipa_pure_const()

ipa_opt_pass_d * make_pass_ipa_pure_const ( gcc::context * ctxt)

References ggc_alloc().

◆ make_pass_local_pure_const()

gimple_opt_pass * make_pass_local_pure_const ( gcc::context * ctxt)

References ggc_alloc().

◆ make_pass_nothrow()

gimple_opt_pass * make_pass_nothrow ( gcc::context * ctxt)

References ggc_alloc().

◆ make_pass_warn_function_noreturn()

gimple_opt_pass * make_pass_warn_function_noreturn ( gcc::context * ctxt)

References ggc_alloc().

◆ malloc_candidate_p()

◆ malloc_candidate_p_1()

◆ propagate_malloc()

◆ propagate_nothrow()

◆ propagate_pure_const()

◆ pure_const_generate_summary()

static void pure_const_generate_summary ( void )
static
Analyze each function in the cgraph to see if it is locally PURE or
CONST.   

References a, analyze_function(), current_pass, symtab_node::decl, FOR_EACH_DEFINED_FUNCTION, free(), funct_state_summaries, ggc_alloc(), and opt_for_fn.

◆ pure_const_read_summary()

◆ pure_const_write_summary()

◆ self_recursive_p()

static bool self_recursive_p ( struct cgraph_node * node)
static
Return true if NODE is self recursive function.
Indirectly recursive functions appears as non-trivial strongly
connected components, so we need to care about self recursion
only.   

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

Referenced by propagate_pure_const().

◆ skip_function_for_local_pure_const()

static bool skip_function_for_local_pure_const ( struct cgraph_node * node)
static
Return true if function should be skipped for local pure const analysis.   

References AVAIL_INTERPOSABLE, dump_file, function_called_by_processed_nodes_p(), cgraph_node::get_availability(), ggc_alloc(), and symtab_node::has_aliases_p().

Referenced by ipa_make_function_const(), and ipa_make_function_pure().

◆ state_from_flags()

static void state_from_flags ( enum pure_const_state_e * state,
bool * looping,
int flags,
bool cannot_lead_to_return )
static
compute state based on ECF FLAGS and store to STATE and LOOPING.   

References dump_file, dump_flags, ECF_CONST, ECF_LOOPING_CONST_OR_PURE, ECF_PURE, ggc_alloc(), IPA_CONST, IPA_NEITHER, IPA_PURE, and TDF_DETAILS.

Referenced by analyze_function(), check_call(), and propagate_pure_const().

◆ suggest_attribute()

static hash_set< tree > * suggest_attribute ( int option,
tree decl,
bool known_finite,
hash_set< tree > * warned_about,
const char * attrib_name )
static
Emit suggestion about attribute ATTRIB_NAME for DECL.  KNOWN_FINITE
is true if the function is known to be finite.  The diagnostic is
controlled by OPTION.  WARNED_ABOUT is a hash_set<tree> unique for
OPTION, this function may initialize it and it is always returned
by the function.   

References DECL_SOURCE_LOCATION, function_always_visible_to_compiler_p(), G_, ggc_alloc(), global_options, option(), option_enabled(), lang_hooks::option_lang_mask, TREE_THIS_VOLATILE, and warning_at().

Referenced by warn_function_cold(), warn_function_const(), warn_function_malloc(), warn_function_noreturn(), warn_function_pure(), and warn_function_returns_nonnull().

◆ warn_function_cold()

void warn_function_cold ( tree decl)
In ipa-pure-const.cc    

References ggc_alloc(), and suggest_attribute().

Referenced by compute_function_frequency().

◆ warn_function_const()

static void warn_function_const ( tree decl,
bool known_finite )
static
Emit suggestion about __attribute_((const)) for DECL.  KNOWN_FINITE
is true if the function is known to be finite.   

References ggc_alloc(), suggest_attribute(), TREE_TYPE, and VOID_TYPE_P.

Referenced by ipa_make_function_const().

◆ warn_function_malloc()

static void warn_function_malloc ( tree decl)
static
Emit suggestion about __attribute__((malloc)) for DECL.   

References ggc_alloc(), and suggest_attribute().

Referenced by propagate_malloc().

◆ warn_function_noreturn()

static void warn_function_noreturn ( tree decl)
static
Emit suggestion about __attribute__((noreturn)) for DECL.   

References ggc_alloc(), lang_hooks::missing_noreturn_ok_p, suggest_attribute(), and targetm.

◆ warn_function_pure()

static void warn_function_pure ( tree decl,
bool known_finite )
static
Emit suggestion about __attribute_((pure)) for DECL.  KNOWN_FINITE
is true if the function is known to be finite.   

References ggc_alloc(), suggest_attribute(), TREE_TYPE, and VOID_TYPE_P.

Referenced by ipa_make_function_pure().

◆ warn_function_returns_nonnull()

void warn_function_returns_nonnull ( tree decl)

References ggc_alloc(), and suggest_attribute().

Referenced by execute_ranger_vrp().

◆ worse_state()

static void worse_state ( enum pure_const_state_e * state,
bool * looping,
enum pure_const_state_e state2,
bool looping2,
struct symtab_node * from,
struct symtab_node * to )
inlinestatic
Merge STATE and STATE2 and LOOPING and LOOPING2 and store
into STATE and LOOPING worse of the two variants.
N is the actual node called.   

References symtab_node::binds_to_current_def_p(), symtab_node::decl, dump_file, dump_flags, symtab_node::dump_name(), ggc_alloc(), IPA_CONST, IPA_PURE, MAX, TDF_DETAILS, and TREE_READONLY.

Referenced by check_call(), and propagate_pure_const().

Variable Documentation

◆ funct_state_summaries

◆ malloc_state_names

const char* malloc_state_names[] = {"malloc_top", "malloc", "malloc_bottom"}
static

◆ pure_const_names

const char* pure_const_names[3] = {"const", "pure", "neither"}
static