GCC Middle and Back End API Reference
tree-ssa-ccp.c File Reference

Data Structures

struct  prop_value_d

Typedefs

typedef struct prop_value_d prop_value_t
typedef hash_table
< pointer_hash
< gimple_statement_base > > 
gimple_htab

Enumerations

enum  ccp_lattice_t { UNINITIALIZED, UNDEFINED, CONSTANT, VARYING }

Functions

static void canonicalize_float_value (prop_value_t *)
static bool ccp_fold_stmt (gimple_stmt_iterator *)
static void dump_lattice_value ()
void debug_lattice_value (prop_value_t val)
DEBUG_FUNCTION void debug_lattice_value ()
static prop_value_t get_default_value ()
static prop_value_tget_value ()
static tree get_constant_value ()
static void set_value_varying ()
static void canonicalize_float_value ()
static bool valid_lattice_transition ()
static bool set_lattice_value ()
static prop_value_t get_value_for_expr (tree, bool)
static prop_value_t bit_value_binop (enum tree_code, tree, tree, tree)
static void bit_value_binop_1 (enum tree_code, tree, double_int *, double_int *, tree, double_int, double_int, tree, double_int, double_int)
static double_int value_to_double_int ()
static prop_value_t get_value_from_alignment ()
static prop_value_t get_value_for_expr ()
static ccp_lattice_t likely_value ()
static bool surely_varying_stmt_p ()
static void ccp_initialize ()
static void do_dbg_cnt ()
static bool ccp_finalize ()
static void ccp_lattice_meet ()
static enum ssa_prop_result ccp_visit_phi_node ()
static tree valueize_op ()
static tree ccp_fold ()
static void bit_value_unop_1 (enum tree_code code, tree type, double_int *val, double_int *mask, tree rtype, double_int rval, double_int rmask)
static prop_value_t bit_value_unop ()
static prop_value_t bit_value_binop ()
static prop_value_t bit_value_assume_aligned ()
static prop_value_t evaluate_stmt ()
static void insert_clobber_before_stack_restore (tree saved_val, tree var, gimple_htab *visited)
static void gsi_prev_dom_bb_nondebug ()
static void insert_clobbers_for_var ()
static tree fold_builtin_alloca_with_align ()
static bool ccp_fold_stmt ()
static enum ssa_prop_result visit_assignment ()
static enum ssa_prop_result visit_cond_stmt ()
static enum ssa_prop_result ccp_visit_stmt ()
static unsigned int do_ssa_ccp ()
static bool gate_ccp ()
gimple_opt_passmake_pass_ccp ()
static tree optimize_stack_restore ()
static tree optimize_stdarg_builtin ()
static bool optimize_unreachable ()
static unsigned int execute_fold_all_builtins ()
gimple_opt_passmake_pass_fold_builtins ()

Variables

static prop_value_tconst_val
static unsigned n_const_val

Typedef Documentation

typedef struct prop_value_d prop_value_t

Enumeration Type Documentation

@verbatim Conditional constant propagation pass for the GNU compiler.

Copyright (C) 2000-2013 Free Software Foundation, Inc. Adapted from original RTL SSA-CCP by Daniel Berlin dberl.nosp@m.in@d.nosp@m.berli.nosp@m.n.or.nosp@m.g Adapted to GIMPLE trees by Diego Novillo dnovi.nosp@m.llo@.nosp@m.redha.nosp@m.t.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/.

Conditional constant propagation (CCP) is based on the SSA
   propagation engine (tree-ssa-propagate.c).  Constant assignments of
   the form VAR = CST are propagated from the assignments into uses of
   VAR, which in turn may generate new constants.  The simulation uses
   a four level lattice to keep track of constant values associated
   with SSA names.  Given an SSA name V_i, it may take one of the
   following values:

        UNINITIALIZED   ->  the initial state of the value.  This value
                            is replaced with a correct initial value
                            the first time the value is used, so the
                            rest of the pass does not need to care about
                            it.  Using this value simplifies initialization
                            of the pass, and prevents us from needlessly
                            scanning statements that are never reached.

        UNDEFINED       ->  V_i is a local variable whose definition
                            has not been processed yet.  Therefore we
                            don't yet know if its value is a constant
                            or not.

        CONSTANT        ->  V_i has been found to hold a constant
                            value C.

        VARYING         ->  V_i cannot take a constant value, or if it
                            does, it is not possible to determine it
                            at compile time.

   The core of SSA-CCP is in ccp_visit_stmt and ccp_visit_phi_node:

   1- In ccp_visit_stmt, we are interested in assignments whose RHS
      evaluates into a constant and conditional jumps whose predicate
      evaluates into a boolean true or false.  When an assignment of
      the form V_i = CONST is found, V_i's lattice value is set to
      CONSTANT and CONST is associated with it.  This causes the
      propagation engine to add all the SSA edges coming out the
      assignment into the worklists, so that statements that use V_i
      can be visited.

      If the statement is a conditional with a constant predicate, we
      mark the outgoing edges as executable or not executable
      depending on the predicate's value.  This is then used when
      visiting PHI nodes to know when a PHI argument can be ignored.


   2- In ccp_visit_phi_node, if all the PHI arguments evaluate to the
      same constant C, then the LHS of the PHI is set to C.  This
      evaluation is known as the "meet operation".  Since one of the
      goals of this evaluation is to optimistically return constant
      values as often as possible, it uses two main short cuts:

      - If an argument is flowing in through a non-executable edge, it
        is ignored.  This is useful in cases like this:

                        if (PRED)
                          a_9 = 3;
                        else
                          a_10 = 100;
                        a_11 = PHI (a_9, a_10)

        If PRED is known to always evaluate to false, then we can
        assume that a_11 will always take its value from a_10, meaning
        that instead of consider it VARYING (a_9 and a_10 have
        different values), we can consider it CONSTANT 100.

      - If an argument has an UNDEFINED value, then it does not affect
        the outcome of the meet operation.  If a variable V_i has an
        UNDEFINED value, it means that either its defining statement
        hasn't been visited yet or V_i has no defining statement, in
        which case the original symbol 'V' is being used
        uninitialized.  Since 'V' is a local variable, the compiler
        may assume any initial value for it.


   After propagation, every variable V_i that ends up with a lattice
   value of CONSTANT will have the associated constant value in the
   array CONST_VAL[i].VALUE.  That is fed into substitute_and_fold for
   final substitution and folding.

   References:

     Constant propagation with conditional branches,
     Wegman and Zadeck, ACM TOPLAS 13(2):181-210.

     Building an Optimizing Compiler,
     Robert Morgan, Butterworth-Heinemann, 1998, Section 8.9.

     Advanced Compiler Design and Implementation,
     Steven Muchnick, Morgan Kaufmann, 1997, Section 12.6   
Possible lattice values.   
Enumerator:
UNINITIALIZED 
UNDEFINED 
CONSTANT 
VARYING 

Function Documentation

static prop_value_t bit_value_binop ( enum  tree_code,
tree  ,
tree  ,
tree   
)
static

Referenced by evaluate_stmt().

static prop_value_t bit_value_binop ( )
static
Return the propagation value when applying the operation CODE to
   the values RHS1 and RHS2 yielding type TYPE.   

References bit_value_binop_1(), CONSTANT, double_int_to_tree(), get_value_for_expr(), double_int::is_minus_one(), prop_value_d::lattice_val, prop_value_d::mask, UNDEFINED, prop_value_d::value, value_to_double_int(), and VARYING.

static void bit_value_binop_1 ( enum tree_code  code,
tree  type,
double_int val,
double_int mask,
tree  r1type,
double_int  r1val,
double_int  r1mask,
tree  r2type,
double_int  r2val,
double_int  r2mask 
)
static
Apply the operation CODE in type TYPE to the value, mask pairs
   R1VAL, R1MASK and R2VAL, R2MASK representing a values of type R1TYPE
   and R2TYPE and set the value, mask pair *VAL and *MASK to the result.   

References double_int::and_not(), bit_value_unop_1(), double_int::cmp(), double_int::ext(), HOST_WIDE_INT, double_int::is_negative(), double_int::is_zero(), double_int::llshift(), double_int::lrotate(), prop_value_d::mask, double_int::rshift(), shift, and swap_tree_comparison().

Referenced by bit_value_assume_aligned(), bit_value_binop(), and bit_value_unop_1().

static prop_value_t bit_value_unop ( )
static
Return the propagation value when applying the operation CODE to
   the value RHS yielding type TYPE.   

References bit_value_unop_1(), CONSTANT, double_int_to_tree(), get_value_for_expr(), double_int::is_minus_one(), prop_value_d::lattice_val, prop_value_d::mask, UNDEFINED, prop_value_d::value, value_to_double_int(), and VARYING.

Referenced by evaluate_stmt().

static void bit_value_unop_1 ( enum tree_code  code,
tree  type,
double_int val,
double_int mask,
tree  rtype,
double_int  rval,
double_int  rmask 
)
static
Apply the operation CODE in type TYPE to the value, mask pair
   RVAL and RMASK representing a value of type RTYPE and set
   the value, mask pair *VAL and *MASK to the result.   

References bit_value_binop_1(), and double_int::ext().

Referenced by bit_value_binop_1(), and bit_value_unop().

static void canonicalize_float_value ( prop_value_t )
static
static void canonicalize_float_value ( )
static
For float types, modify the value of VAL to make ccp work correctly
   for non-standard values (-0, NaN):

   If HONOR_SIGNED_ZEROS is false, and VAL = -0, we canonicalize it to 0.
   If HONOR_NANS is false, and VAL is NaN, we canonicalize it to UNDEFINED.
     This is to fix the following problem (see PR 29921): Suppose we have

     x = 0.0 * y

     and we set value of y to NaN.  This causes value of x to be set to NaN.
     When we later determine that y is in fact VARYING, fold uses the fact
     that HONOR_NANS is false, and we try to change the value of x to 0,
     causing an ICE.  With HONOR_NANS being false, the real appearance of
     NaN would cause undefined behavior, though, so claiming that y (and x)
     are UNDEFINED initially is correct.   

References build_real(), CONSTANT, dconst0, prop_value_d::lattice_val, type(), UNDEFINED, and prop_value_d::value.

static bool ccp_finalize ( )
static
Do final substitution of propagated values, cleanup the flowgraph and
   free allocated storage.

   Return TRUE when something was optimized.   

References ccp_fold_stmt(), CONSTANT, do_dbg_cnt(), free(), get_constant_value(), get_ptr_info(), get_value(), prop_value_d::lattice_val, double_int::low, prop_value_d::mask, set_ptr_info_alignment(), substitute_and_fold(), and prop_value_d::value.

Referenced by do_ssa_ccp().

static tree ccp_fold ( )
static
CCP specific front-end to the non-destructive constant folding
   routines.

   Attempt to simplify the RHS of STMT knowing that one or more
   operands are constants.

   If simplification is possible, return the simplified RHS,
   otherwise return the original RHS or NULL_TREE.   

References fold_binary_loc(), gimple_cond_code(), gimple_cond_lhs(), gimple_cond_rhs(), gimple_fold_stmt_to_constant_1(), gimple_location(), gimple_switch_index(), and valueize_op().

Referenced by evaluate_stmt().

static bool ccp_fold_stmt ( gimple_stmt_iterator )
static

Referenced by ccp_finalize().

static void ccp_lattice_meet ( )
static
Compute the meet operator between *VAL1 and *VAL2.  Store the result
   in VAL1.

                any  M UNDEFINED   = any
                any  M VARYING     = VARYING
                Ci   M Cj          = Ci         if (i == j)
                Ci   M Cj          = VARYING    if (i != j)

References CONSTANT, get_value_for_expr(), double_int::is_minus_one(), prop_value_d::lattice_val, prop_value_d::mask, simple_cst_equal(), tree_to_double_int(), UNDEFINED, prop_value_d::value, and VARYING.

Referenced by ccp_visit_phi_node().

static enum ssa_prop_result ccp_visit_phi_node ( )
static
Loop through the PHI_NODE's parameters for BLOCK and compare their
   lattice values to determine PHI_NODE's lattice value.  The value of a
   PHI node is determined calling ccp_lattice_meet with all the arguments
   of the PHI node that are incoming via executable edges.   

References ccp_lattice_meet(), CONSTANT, phi_arg_d::def, edge_def::dest, dump_file, dump_flags, dump_lattice_value(), edge_def::flags, get_value(), get_value_for_expr(), gimple_phi_arg(), gimple_phi_arg_edge(), gimple_phi_num_args(), gimple_phi_result(), basic_block_def::index, prop_value_d::lattice_val, print_generic_expr(), print_gimple_stmt(), set_lattice_value(), edge_def::src, SSA_PROP_INTERESTING, SSA_PROP_NOT_INTERESTING, SSA_PROP_VARYING, UNDEFINED, prop_value_d::value, and VARYING.

Referenced by do_ssa_ccp().

static enum ssa_prop_result ccp_visit_stmt ( )
static
Evaluate statement STMT.  If the statement produces an output value and
   its evaluation changes the lattice value of its output, return
   SSA_PROP_INTERESTING and set *OUTPUT_P to the SSA_NAME holding the
   output value.

   If STMT is a conditional branch and we can determine its truth
   value, set *TAKEN_EDGE_P accordingly.  If STMT produces a varying
   value, return SSA_PROP_VARYING.   

References dump_file, dump_flags, gimple_call_lhs(), HOST_WIDE_INT, print_gimple_stmt(), set_lattice_value(), SSA_PROP_VARYING, VARYING, visit_assignment(), and visit_cond_stmt().

Referenced by do_ssa_ccp().

void debug_lattice_value ( prop_value_t  val)
Print lattice value VAL to stderr.   
DEBUG_FUNCTION void debug_lattice_value ( )

References dump_lattice_value().

static void do_dbg_cnt ( )
static
Debug count support. Reset the values of ssa names
   VARYING when the total number ssa names analyzed is
   beyond the debug count specified.   

References dbg_cnt(), prop_value_d::lattice_val, prop_value_d::mask, prop_value_d::value, and VARYING.

Referenced by ccp_finalize().

static unsigned int do_ssa_ccp ( )
static
static tree fold_builtin_alloca_with_align ( )
static
Detects a __builtin_alloca_with_align with constant size argument.  Declares
   fixed-size array and returns the address, if found, otherwise returns
   NULL_TREE.   

References function::after_inlining, pt_solution::anything, build_array_type_nelts(), build_nonstandard_integer_type(), cfun, create_tmp_var(), get_constant_value(), gimple_block(), gimple_call_arg(), gimple_call_lhs(), host_integerp(), HOST_WIDE_INT, ptr_info_def::pt, and pt_solution_singleton_p().

Referenced by ccp_fold_stmt().

static bool gate_ccp ( )
static
static tree get_constant_value ( )
inlinestatic
static prop_value_t get_default_value ( )
static
Compute a default value for variable VAR and store it in the
   CONST_VAL array.  The following rules are used to get default
   values:

   1- Global and static variables that are declared constant are
      considered CONSTANT.

   2- Any other value is considered UNDEFINED.  This is useful when
      considering PHI nodes.  PHI arguments that are undefined do not
      change the constant value of the PHI node, which allows for more
      constants to be propagated.

   3- Variables defined by statements other than assignments and PHI
      nodes are considered VARYING.

   4- Initial values of variables that are not GIMPLE registers are
      considered VARYING.   

References CONSTANT, get_symbol_constant_value(), gimple_assign_rhs1(), gimple_assign_single_p(), gimple_call_lhs(), gimple_nop_p(), is_gimple_assign(), is_gimple_call(), prop_value_d::lattice_val, prop_value_d::mask, UNDEFINED, UNINITIALIZED, prop_value_d::value, VARYING, and virtual_operand_p().

Referenced by get_value().

static prop_value_t* get_value ( )
inlinestatic
static prop_value_t get_value_for_expr ( )
static
Return the value for the tree operand EXPR.  If FOR_BITS_P is true
   return constant bits extracted from alignment information for
   invariant addresses.   

References canonicalize_float_value(), CONSTANT, get_value(), get_value_from_alignment(), is_gimple_min_invariant(), prop_value_d::lattice_val, prop_value_d::mask, prop_value_d::value, and VARYING.

static prop_value_t get_value_from_alignment ( )
static
static void gsi_prev_dom_bb_nondebug ( )
inlinestatic
Advance the iterator to the previous non-debug gimple statement in the same
   or dominating basic block.   

References gimple_stmt_iterator_d::bb, CDI_DOMINATORS, dom, get_immediate_dominator(), gsi_end_p(), gsi_last_bb(), and gsi_prev_nondebug().

Referenced by insert_clobbers_for_var().

static void insert_clobber_before_stack_restore ( tree  saved_val,
tree  var,
gimple_htab visited 
)
static
Given a BUILT_IN_STACK_SAVE value SAVED_VAL, insert a clobber of VAR before
   each matching BUILT_IN_STACK_RESTORE.  Mark visited phis in VISITED.   

References build_constructor(), hash_table< Descriptor, Allocator >::create(), hash_table< Descriptor, Allocator >::find_slot(), gimple_call_builtin_p(), gimple_phi_result(), gsi_for_stmt(), gsi_insert_before(), GSI_SAME_STMT, hash_table< Descriptor, Allocator >::is_created(), and is_gimple_debug().

Referenced by insert_clobbers_for_var().

static void insert_clobbers_for_var ( )
static
Find a BUILT_IN_STACK_SAVE dominating gsi_stmt (I), and insert
   a clobber of VAR before each matching BUILT_IN_STACK_RESTORE.

   It is possible that BUILT_IN_STACK_SAVE cannot be find in a dominator when a
   previous pass (such as DOM) duplicated it along multiple paths to a BB.  In
   that case the function gives up without inserting the clobbers.   

References hash_table< Descriptor, Allocator >::dispose(), gimple_call_builtin_p(), gimple_call_lhs(), gsi_end_p(), gsi_prev_dom_bb_nondebug(), gsi_stmt(), insert_clobber_before_stack_restore(), hash_table< Descriptor, Allocator >::is_created(), and visited.

Referenced by ccp_fold_stmt().

static ccp_lattice_t likely_value ( )
static
Return the likely CCP lattice value for STMT.

   If STMT has no operands, then return CONSTANT.

   Else if undefinedness of operands of STMT cause its value to be
   undefined, then return UNDEFINED.

   Else if any operands of STMT are constants, then return CONSTANT.

   Else return VARYING.   

References CONSTANT, get_value(), gimple_assign_rhs_code(), gimple_call_internal_fn(), gimple_call_internal_p(), gimple_has_lhs(), gimple_has_volatile_ops(), gimple_num_ops(), gimple_op(), gimple_references_memory_p(), is_gimple_call(), is_gimple_min_invariant(), prop_value_d::lattice_val, UNDEFINED, and VARYING.

Referenced by evaluate_stmt().

gimple_opt_pass* make_pass_ccp ( )
gimple_opt_pass* make_pass_fold_builtins ( )
static tree optimize_stack_restore ( )
static
Try to optimize out __builtin_stack_restore.  Optimize it out
   if there is another __builtin_stack_restore in the same basic
   block and no calls or ASM_EXPRs are in between, or if this block's
   only outgoing edge is to EXIT_BLOCK and there are no calls or
   ASM_EXPRs after this __builtin_stack_restore.   

References build_int_cst(), BUILT_IN_NORMAL, gimple_call_arg(), gimple_call_fndecl(), gimple_call_num_args(), gsi_bb(), gsi_end_p(), gsi_for_stmt(), gsi_next(), gsi_stmt(), has_single_use(), is_gimple_call(), single_succ_edge(), basic_block_def::succs, and update_call_from_tree().

Referenced by execute_fold_all_builtins().

static tree optimize_stdarg_builtin ( )
static
If va_list type is a simple pointer and nothing special is needed,
   optimize __builtin_va_start (&ap, 0) into ap = __builtin_next_arg (0),
   __builtin_va_end (&ap) out as NOP and __builtin_va_copy into a simple
   pointer assignment.   

References build_call_expr_loc(), build_fold_indirect_ref_loc(), builtin_decl_explicit(), builtin_decl_explicit_p(), fold_convert_loc(), gimple_call_arg(), gimple_call_fndecl(), gimple_call_num_args(), gimple_location(), and targetm.

Referenced by execute_fold_all_builtins().

static bool optimize_unreachable ( )
static
Attemp to make the block of __builtin_unreachable I unreachable by changing
   the incoming jumps.  Return true if at least one jump was changed.   

References edge_def::flags, gimple_cond_make_false(), gimple_cond_make_true(), gimple_label_label(), gsi_bb(), gsi_end_p(), gsi_last_bb(), gsi_next(), gsi_start_bb(), gsi_stmt(), is_gimple_debug(), basic_block_def::preds, edge_def::src, and update_stmt().

Referenced by execute_fold_all_builtins().

static bool set_lattice_value ( )
static
Set the value for variable VAR to NEW_VAL.  Return true if the new
   value is different from VAR's previous value.   

References canonicalize_float_value(), CONSTANT, dump_file, dump_flags, dump_lattice_value(), prop_value_d::lattice_val, prop_value_d::mask, tree_to_double_int(), UNINITIALIZED, valid_lattice_transition(), and prop_value_d::value.

Referenced by ccp_visit_phi_node(), ccp_visit_stmt(), and visit_assignment().

static void set_value_varying ( )
inlinestatic
Sets the value associated with VAR to VARYING.   

References prop_value_d::lattice_val, prop_value_d::mask, prop_value_d::value, and VARYING.

Referenced by ccp_initialize().

static bool surely_varying_stmt_p ( )
static
Returns true if STMT cannot be constant.   

References gimple_call_fndecl(), gimple_call_lhs(), gimple_has_volatile_ops(), gimple_vdef(), and is_gimple_call().

Referenced by ccp_initialize().

static bool valid_lattice_transition ( )
static
static double_int value_to_double_int ( )
static
Return a double_int that can be used for bitwise simplifications
   from VAL.   

References tree_to_double_int(), and prop_value_d::value.

Referenced by bit_value_assume_aligned(), bit_value_binop(), and bit_value_unop().

static tree valueize_op ( )
static
Return the constant value for OP or OP otherwise.   

References get_constant_value().

Referenced by ccp_fold().

static enum ssa_prop_result visit_assignment ( )
static
Visit the assignment statement STMT.  Set the value of its LHS to the
   value computed by the RHS and store LHS in *OUTPUT_P.  If STMT
   creates virtual definitions, set the value of each new name to that
   of the RHS (if we can derive a constant out of the RHS).
   Value-returning call statements also perform an assignment, and
   are handled here.   

References evaluate_stmt(), get_value(), gimple_assign_rhs1(), gimple_assign_rhs_code(), gimple_assign_single_p(), gimple_call_lhs(), gimple_get_lhs(), prop_value_d::lattice_val, set_lattice_value(), SSA_PROP_INTERESTING, SSA_PROP_NOT_INTERESTING, SSA_PROP_VARYING, and VARYING.

Referenced by ccp_visit_stmt().

static enum ssa_prop_result visit_cond_stmt ( )
static
Visit the conditional statement STMT.  Return SSA_PROP_INTERESTING
   if it can determine which edge will be taken.  Otherwise, return
   SSA_PROP_VARYING.   

References CONSTANT, evaluate_stmt(), find_taken_edge(), gimple_bb(), double_int::is_zero(), prop_value_d::lattice_val, prop_value_d::mask, SSA_PROP_INTERESTING, SSA_PROP_VARYING, and prop_value_d::value.

Referenced by ccp_visit_stmt().


Variable Documentation

prop_value_t* const_val
static
Array of propagated constant values.  After propagation,
   CONST_VAL[I].VALUE holds the constant value for SSA_NAME(I).  If
   the constant is held in an SSA name representing a memory store
   (i.e., a VDEF), CONST_VAL[I].MEM_REF will contain the actual
   memory reference used to store (i.e., the LHS of the assignment
   doing the store).   

Referenced by canon_condition(), and canonicalize_condition().

unsigned n_const_val
static

Referenced by ccp_initialize(), and get_value().