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 "gcc-urlifier.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 (diagnostic_option_id 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 char * pure_const_names [3] = {"const", "pure", "neither"}
static const char * malloc_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:65
FILE * dump_file
Definition dumpfile.cc:63
@ TDF_DETAILS
Definition dumpfile.h:92
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

typedef class funct_state_d* 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-2025 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()

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 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, and DECL_FUNCTION_CODE().

Referenced by check_call(), and propagate_pure_const().

◆ cdtor_p()

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()

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, 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()

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, 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()

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()

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()

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()

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(), 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()

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 dyn_cast(), FOR_EACH_IMM_USE_STMT, 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()

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()

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, and malloc_state_names.

Referenced by propagate_malloc().

◆ finite_function_p()

◆ function_always_visible_to_compiler_p()

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()

bool gate_pure_const ( void )
static

◆ ignore_edge_for_nothrow()

bool ignore_edge_for_nothrow ( struct cgraph_edge * e)
static

◆ ignore_edge_for_pure_const()

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(), 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(), 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(), 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)

◆ make_pass_local_pure_const()

gimple_opt_pass * make_pass_local_pure_const ( gcc::context * ctxt)

◆ make_pass_nothrow()

gimple_opt_pass * make_pass_nothrow ( gcc::context * ctxt)

◆ make_pass_warn_function_noreturn()

gimple_opt_pass * make_pass_warn_function_noreturn ( gcc::context * ctxt)

◆ malloc_candidate_p()

◆ malloc_candidate_p_1()

◆ propagate_malloc()

◆ propagate_nothrow()

◆ propagate_pure_const()

◆ pure_const_generate_summary()

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, and opt_for_fn.

◆ pure_const_read_summary()

◆ pure_const_write_summary()

◆ self_recursive_p()

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()

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(), and symtab_node::has_aliases_p().

Referenced by ipa_make_function_const(), and ipa_make_function_pure().

◆ state_from_flags()

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, IPA_CONST, IPA_NEITHER, IPA_PURE, and TDF_DETAILS.

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

◆ suggest_attribute()

hash_set< tree > * suggest_attribute ( diagnostic_option_id 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 hash_set< KeyId, Lazy, Traits >::add(), hash_set< KeyId, Lazy, Traits >::contains(), DECL_SOURCE_LOCATION, function_always_visible_to_compiler_p(), G_, 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 suggest_attribute().

Referenced by compute_function_frequency().

◆ warn_function_const()

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 suggest_attribute(), TREE_TYPE, and VOID_TYPE_P.

Referenced by ipa_make_function_const().

◆ warn_function_malloc()

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

References suggest_attribute().

Referenced by propagate_malloc().

◆ warn_function_noreturn()

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

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

◆ warn_function_pure()

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 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 suggest_attribute().

Referenced by execute_ranger_vrp().

◆ worse_state()

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(), 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