GCC Middle and Back End API Reference
ipa-pure-const.c File Reference

Data Structures

struct  funct_state_d

Typedefs

typedef struct funct_state_dfunct_state

Enumerations

enum  pure_const_state_e { IPA_CONST, IPA_PURE, IPA_NEITHER }

Functions

static bool function_always_visible_to_compiler_p ()
static struct pointer_set_tsuggest_attribute (int option, tree decl, bool known_finite, struct pointer_set_t *warned_about, const char *attrib_name)
static void warn_function_pure ()
static void warn_function_const ()
static void warn_function_noreturn ()
static bool has_function_state ()
static funct_state get_function_state ()
static void set_function_state ()
static void check_decl (funct_state local, tree t, bool checking_write, bool ipa)
static void check_op ()
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)
static bool special_builtin_state (enum pure_const_state_e *state, bool *looping, tree callee)
static void check_call ()
static bool check_load ()
static bool check_store ()
static bool check_ipa_load ()
static bool check_ipa_store ()
static void check_stmt ()
static funct_state analyze_function ()
static void add_new_function ()
static void duplicate_node_data (struct cgraph_node *src, struct cgraph_node *dst, void *data)
static void remove_node_data ()
static void register_hooks ()
static void pure_const_generate_summary ()
static void pure_const_write_summary ()
static void pure_const_read_summary ()
static bool ignore_edge ()
static bool self_recursive_p ()
static void propagate_pure_const ()
static void propagate_nothrow ()
static unsigned int propagate ()
static bool gate_pure_const ()
ipa_opt_pass_dmake_pass_ipa_pure_const ()
static bool skip_function_for_local_pure_const ()
static unsigned int local_pure_const ()
gimple_opt_passmake_pass_local_pure_const ()
static unsigned int execute_warn_function_noreturn ()
static bool gate_warn_function_noreturn ()
gimple_opt_passmake_pass_warn_function_noreturn ()

Variables

static struct pointer_set_tvisited_nodes
const char * pure_const_names [3] = {"const", "pure", "neither"}
static struct funct_state_d varying_state = { IPA_NEITHER, IPA_NEITHER, true, true, true }
static vec< funct_statefunct_state_vec
static struct
cgraph_node_hook_list
function_insertion_hook_holder
static struct
cgraph_2node_hook_list
node_duplication_hook_holder
static struct
cgraph_node_hook_list
node_removal_hook_holder

Typedef Documentation

typedef struct funct_state_d* funct_state

Enumeration Type Documentation

   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

static void add_new_function ( )
static
   Called when new function is inserted to callgraph late.  
     There are some shared nodes, in particular the initializers on
     static declarations.  We do not need to scan them more than once
     since all we would be interested in are the addressof
     operations.  
static funct_state analyze_function ( )
static
   This is the main routine for finding the reference patterns for
   global variables within a function FN.  
         Thunk gets propagated through, so nothing interesting happens.  
         Const functions cannot have back edges (an
         indication of possible infinite loop side
         effect.  
             Preheaders are needed for SCEV to work.
             Simple latches and recorded exits improve chances that loop will
             proved to be finite in testcases such as in loop-15.c
             and loop-24.c  

References dump_file, dump_flags, finite_loop_p(), flow_loops_dump(), loop_optimizer_finalize(), loop_optimizer_init(), funct_state_d::looping, LOOPS_HAVE_PREHEADERS, LOOPS_HAVE_RECORDED_EXITS, LOOPS_HAVE_SIMPLE_LATCHES, mark_irreducible_loops(), loop::num, scev_finalize(), and scev_initialize().

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 IPA_CONST.

static void check_call ( )
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.  
     The const and pure flags are set by a variety of places in the
     compiler (including here).  If someone has already set the flags
     for the callee, (such as for some of the builtins) we will use
     them, otherwise we will compute our own information.

     Const and pure functions have less clobber effects than other
     functions so we process these first.  Otherwise if it is a call
     outside the compilation unit or an indirect call we punt.  This
     leaves local calls which will be processed by following the call
     graph.  
         When bad things happen to bad functions, they cannot be const
         or pure.  
     When not in IPA mode, we can still handle self recursion.  
     Either callee is unknown or we are doing local analysis.
     Look to see if there are any bits available for the callee (such as by
     declaration or because it is builtin) and process solely on the basis of
     those bits. 
     Direct functions calls are handled by IPA propagation.  

References BUILT_IN_NORMAL, dump_file, IPA_NEITHER, funct_state_d::looping, funct_state_d::pure_const_state, setjmp_call_p(), special_builtin_state(), and worse_state().

Referenced by check_stmt().

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.  
     Do not want to do anything with volatile except mark any
     function that uses one to be not const or pure.  
     Do not care about a local automatic that is not static.  
     If the variable has the "used" attribute, treat it as if it had a
     been touched by the devil.  
     In IPA mode we are not interested in checking actual loads and stores;
     they will be processed at propagation time using ipa_ref.  
     Since we have dealt with the locals and params cases above, if we
     are CHECKING_WRITE, this cannot be a pure or constant
     function.  
         Readonly reads are safe.  
             Just a regular read.  
         Compilation level statics can be read if they are readonly
         variables.  
         Just a regular read.  
static bool check_ipa_load ( )
static
   Wrapper around check_decl for loads in ipa mode.  
static bool check_ipa_store ( )
static
   Wrapper around check_decl for stores in ipa mode.  
static bool check_load ( )
static
   Wrapper around check_decl for loads in local more.  
static void check_op ( )
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.  
static void check_stmt ( )
static
   Look into pointer pointed to by GSIP and figure out what interesting side
   effects it has.  
     Look for loads and stores.  
           Target of long jump. 
             Abandon all hope, ye who enter here. 
             Abandon all hope, ye who enter here. 

References check_call(), dump_file, gimple_asm_clobbers_memory_p(), gimple_asm_volatile_p(), gimple_label_label(), IPA_NEITHER, funct_state_d::looping, and funct_state_d::pure_const_state.

static bool check_store ( )
static
   Wrapper around check_decl for stores in local more.  

References dump_file, and print_gimple_stmt().

static void duplicate_node_data ( struct cgraph_node src,
struct cgraph_node dst,
void *  data 
)
static
   Called when new clone is inserted to callgraph late.  
static unsigned int execute_warn_function_noreturn ( )
static
   Emit noreturn warnings.  
static bool function_always_visible_to_compiler_p ( )
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 option_enabled(), pointer_set_contains(), and pointer_set_create().

static bool gate_pure_const ( )
static
             Don't bother doing anything if the program has errors.  
static bool gate_warn_function_noreturn ( )
static
static funct_state get_function_state ( )
inlinestatic
   Return the function state from NODE.  
       We might want to put correct previously_known state into varying.  
static bool has_function_state ( )
inlinestatic
   Return true if we have a function state for NODE.  
static bool ignore_edge ( )
static

Referenced by searchc().

static unsigned int local_pure_const ( )
static
   Simple local pass for pure const discovery reusing the analysis from
   ipa_pure_const.   This pass is effective when executed together with
   other optimization passes in early optimization pass queue.  
     Do NORETURN discovery.  
         Update declaration and reduce profile to executed once.  
ipa_opt_pass_d* make_pass_ipa_pure_const ( )
gimple_opt_pass* make_pass_local_pure_const ( )
gimple_opt_pass* make_pass_warn_function_noreturn ( )
static unsigned int propagate ( )
static
   Produce the global information by preforming a transitive closure
   on the local information that was produced by generate_summary.  
     Nothrow makes more function to not lead to return and improve
     later analysis.  
     Cleanup. 
static void propagate_nothrow ( )
static
   Produce transitive closure over the callgraph and compute nothrow
   attributes.  
     Propagate the local information through the call graph to produce
     the global information.  All the nodes within a cycle will have
     the same info so we collapse cycles first.  Then we can do the
     propagation in one pass from the leaves to the roots.  
         Find the worst state for any node in the cycle.  
         Copy back the region's pure_const_state which is shared by
         all nodes in the region.  
static void propagate_pure_const ( )
static
   Produce transitive closure over the callgraph and compute pure/const
   attributes.  
     Propagate the local information through the call graph to produce
     the global information.  All the nodes within a cycle will have
     the same info so we collapse cycles first.  Then we can do the
     propagation in one pass from the leaves to the roots.  
         Find the worst state for any node in the cycle.  
             First merge in function body properties.  
             For overwritable nodes we can not assume anything.  
             We consider recursive cycles as possibly infinite.
             This might be relaxed since infinite recursion leads to stack
             overflow.  
             Now walk the edges and merge in callee properties.  
                 Merge the results with what we already know.  
             Now process the indirect call.  
                 Merge the results with what we already know.  
             And finally all loads and stores.  
                     readonly reads are safe.  
         Copy back the region's pure_const_state which is shared by
         all nodes in the region.  
             All nodes within a cycle share the same info.  
static void pure_const_generate_summary ( )
static
   Analyze each function in the cgraph to see if it is locally PURE or
   CONST.  
     There are some shared nodes, in particular the initializers on
     static declarations.  We do not need to scan them more than once
     since all we would be interested in are the addressof
     operations.  
     Process all of the functions.

     We process AVAIL_OVERWRITABLE functions.  We can not use the results
     by default, but the info can be used at LTO with -fwhole-program or
     when function got cloned and the clone is AVAILABLE.  
static void pure_const_read_summary ( )
static
   Deserialize the ipa info for lto.  
                 Note that the flags must be read in the opposite
                 order in which they were written (the bitflags were
                 pushed into FLAGS).  
static void pure_const_write_summary ( )
static
   Serialize the ipa info for lto.  
     Process all of the functions.  
             Note that flags will need to be read in the opposite
             order as we are pushing the bitflags into FLAGS.  
static void register_hooks ( )
static
static void remove_node_data ( )
static
   Called when new clone is inserted to callgraph late.  

References count, lto_create_simple_output_block(), and LTO_section_ipa_pure_const.

static bool self_recursive_p ( )
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 dump_file, dump_flags, funct_state_d::looping_previously_known, pure_const_names, funct_state_d::state_previously_known, and worse_state().

static void set_function_state ( )
inlinestatic
   Set the function state S for NODE.  
static bool skip_function_for_local_pure_const ( )
static
   Return true if function should be skipped for local pure const analysis.  
     Because we do not schedule pass_fixup_cfg over whole program after early optimizations
     we must not promote functions that are called by already processed functions.  

References cgraph_set_pure_flag(), and funct_state_d::looping.

static bool special_builtin_state ( enum pure_const_state_e state,
bool *  looping,
tree  callee 
)
static
   Recognize special cases of builtins that are by themselves not pure or const
   but function using them is.  

References funct_state_d::can_throw, function::can_throw_non_call_exceptions, cfun, dump_file, gimple_call_flags(), gimple_call_fndecl(), gimple_num_ops(), gimple_op(), funct_state_d::looping, stmt_can_throw_external(), stmt_could_throw_p(), and tree_could_throw_p().

Referenced by check_call().

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.  
static struct pointer_set_t* suggest_attribute ( int  option,
tree  decl,
bool  known_finite,
struct pointer_set_t warned_about,
const char *  attrib_name 
)
staticread
   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 pointer_set unique for
   OPTION, this function may initialize it and it is always returned
   by the function.  
static void warn_function_const ( )
static
   Emit suggestion about __attribute_((const)) for DECL.  KNOWN_FINITE
   is true if the function is known to be finite.  
static void warn_function_noreturn ( )
static
static void warn_function_pure ( )
static
   Emit suggestion about __attribute_((pure)) for DECL.  KNOWN_FINITE
   is true if the function is known to be finite.  
static void worse_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 worse of the two variants.  

Referenced by check_call(), and self_recursive_p().


Variable Documentation

vec<funct_state> funct_state_vec
static
   The storage of the funct_state is abstracted because there is the
   possibility that it may be desirable to move this to the cgraph
   local info.  
   Array, indexed by cgraph node uid, of function states.  
struct cgraph_node_hook_list* function_insertion_hook_holder
static
   Holders of ipa cgraph hooks: 
struct cgraph_2node_hook_list* node_duplication_hook_holder
static
struct cgraph_node_hook_list* node_removal_hook_holder
static
const char* pure_const_names[3] = {"const", "pure", "neither"}

Referenced by self_recursive_p().

struct funct_state_d varying_state = { IPA_NEITHER, IPA_NEITHER, true, true, true }
static
   State used when we know nothing about function.  
struct pointer_set_t* visited_nodes
static
@verbatim 

Callgraph based analysis of static variables. Copyright (C) 2004-2013 Free Software Foundation, Inc. Contributed by Kenneth Zadeck zadec.nosp@m.k@na.nosp@m.tural.nosp@m.brid.nosp@m.ge.co.nosp@m.m

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.