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

Data Structures

struct  prop_value_d


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




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


static prop_value_tconst_val
static unsigned n_const_val

Typedef Documentation

typedef struct prop_value_d prop_value_t

Enumeration Type Documentation


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


     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.  

Function Documentation

static prop_value_t bit_value_assume_aligned ( )
   Return the propagation value when applying __builtin_assume_aligned to
   its arguments.  
         ???  Delay building trees here.  
static prop_value_t bit_value_binop ( enum  tree_code,
tree  ,
tree  ,

Referenced by evaluate_stmt().

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

References ccp_fold(), CONSTANT, dump_file, dump_flags, fold_defer_overflow_warnings(), fold_undefer_overflow_warnings(), is_gimple_min_invariant(), prop_value_d::lattice_val, likely_value(), prop_value_d::mask, UNDEFINED, prop_value_d::value, 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 
   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.  
     Assume we'll get a constant result.  Use an initial varying value,
     we fall back to varying in the end if necessary.  
         The mask is constant where there is a known not
         set bit, (m1 | m2) & ((v1 | m1) & (v2 | m2)) 
         The mask is constant where there is a known
         set bit, (m1 | m2) & ~((v1 & ~m1) | (v2 & ~m2)).  
         m1 | m2  
         ???  We can handle partially known shift counts if we know
         its sign.  That way we can tell that (x << (y | 8)) & 255
         is zero.  
             We need to know if we are doing a left or a right shift
             to properly shift in zeros for left shift and unsigned
             right shifts and the sign bit for signed right shifts.
             For signed right shifts we shift in varying in case
             the sign bit was varying.  
           Do the addition with unknown bits set to zero, to give carry-ins of
           zero wherever possible.  
           Do the addition with unknown bits set to one, to give carry-ins of
           one wherever possible.  
           Each bit in the result is known if (a) the corresponding bits in
           both inputs are known, and (b) the carry-in to that bit position
           is known.  We can check condition (b) by seeing if we got the same
           result with minimised carries as with maximised carries.  
           It shouldn't matter whether we choose lo or hi here.  
           Just track trailing zeros in both operands and transfer
           them to the other.  
               We know the result of a comparison is always one or zero.  
           If the most significant bits are not known we know nothing.  
           For comparisons the signedness is in the comparison operands.  
           If we know the most significant bits we know the values
           value ranges by means of treating varying bits as zero
           or one.  Do a cross comparison of the max/min pairs.  
               This probably should never happen as we'd have
               folded the thing during fully constant value folding.  
               We know the result of a comparison is always one or zero.  

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

static prop_value_t bit_value_unop ( )
   Return the propagation value when applying the operation CODE to
   the value RHS yielding type TYPE.  
         ???  Delay building trees here.  

References gimple_call_arg(), host_integerp(), and tree_low_cst().

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 
   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.  
           Return ~rval + 1.  
           First extend mask and value according to the original type.  
           Then extend mask and value according to the target type.  

References HOST_WIDE_INT, double_int::lrotate(), and shift.

static void canonicalize_float_value ( prop_value_t )
static void canonicalize_float_value ( )
   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.  
static bool ccp_finalize ( )
   Do final substitution of propagated values, cleanup the flowgraph and
   free allocated storage.

   Return TRUE when something was optimized.  
     Derive alignment and misalignment information from partially
     constant pointers in the lattice.  
         Trailing constant bits specify the alignment, trailing value
         bits the misalignment.  
     Perform substitutions based on the known constant values.  

Referenced by visit_assignment().

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

   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.  
           Handle comparison operators that can appear in GIMPLE form.  
           Return the constant switch index.  

Referenced by bit_value_binop().

static bool ccp_fold_stmt ( gimple_stmt_iterator )
static bool ccp_fold_stmt ( )
   Fold the stmt at *GSI with CCP specific information that propagating
   and regular folding does not catch.  
           Statement evaluation will handle type mismatches in constants
           more gracefully than the final propagation.  This allows us to
           fold more conditionals here.  
           If the call was folded into a constant make sure it goes
           away even if we cannot propagate into all uses because of
           type issues.  
               Don't optimize away calls that have side-effects.  
           Internal calls provide no argument types, so the extra laxity
           for normal calls does not apply.  
           The heuristic of fold_builtin_alloca_with_align differs before and
           after inlining, so we don't require the arg to be changed into a
           constant for folding, but just to be constant.  
           Propagate into the call arguments.  Compared to replace_uses_in
           this can use the argument slot types for type verification
           instead of the current argument type.  We also can safely
           drop qualifiers here as we are dealing with constants anyway.  
           If we have a load that turned out to be constant replace it
           as we cannot propagate into all uses in all cases.  
static void ccp_initialize ( )
   Initialize local data structures for CCP.  
     Initialize simulation flags for PHI nodes and statements.  
             If the statement is a control insn, then we do not
             want to avoid simulating the statement once.  Failure
             to do so means that those edges will never get added.  
                 If the statement will not produce a constant, mark
                 all its outputs VARYING.  
     Now process PHI nodes.  We never clear the simulate_again flag on
     phi nodes, since we do not know which edges are executable yet,
     except for phi nodes for virtual operands when we do not do store ccp.  

Referenced by visit_assignment().

static void ccp_lattice_meet ( )
   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)
         UNDEFINED M any = any   
         any M UNDEFINED = any
         Nothing to do.  VAL1 already contains the value we want.  
         any M VARYING = VARYING.  
         Ci M Cj = Ci           if (i == j)
         Ci M Cj = VARYING      if (i != j)

         For INTEGER_CSTs mask unequal bits.  If no equal bits remain,
         drop to varying.  
         Ci M Cj = Ci           if (i == j)
         Ci M Cj = VARYING      if (i != j)

         VAL1 already contains the value we want for equivalent values.  
         When not equal addresses are involved try meeting for
         Any other combination is VARYING.  
static enum ssa_prop_result ccp_visit_phi_node ( )
   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.  
         Compute the meet operator over all the PHI arguments flowing
         through executable edges.  
         If the incoming edge is executable, Compute the meet operator for
         the existing value of the PHI node and the current PHI argument.  
     Make the transition to the new value.  

Referenced by visit_assignment().

static enum ssa_prop_result ccp_visit_stmt ( )
   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.  
           If the statement is an assignment that produces a single
           output value, evaluate its RHS to see if the lattice value of
           its output has changed.  
           A value-returning call also performs an assignment.  
           If STMT is a conditional branch, see if we can determine
           which branch will be taken.   
           FIXME.  It appears that we should be able to optimize
           computed GOTOs here as well.  
     Any other kind of statement is not interesting for constant
     propagation and, therefore, not worth simulating.  
     Definitions made by statements other than assignments to
     SSA_NAMEs represent unknown modifications to their outputs.
     Mark them VARYING.  

Referenced by visit_assignment().

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

References gimple_nop_p(), and UNINITIALIZED.

static void do_dbg_cnt ( )
   Debug count support. Reset the values of ssa names
   VARYING when the total number ssa names analyzed is
   beyond the debug count specified.  
static unsigned int do_ssa_ccp ( )
   Main entry point for SSA Conditional Constant Propagation.  

References gimple_location().

Referenced by visit_cond_stmt().

static void dump_lattice_value ( )
   Dump constant propagation value VAL to file OUTF prefixed by PREFIX.  

Referenced by set_lattice_value().

static prop_value_t evaluate_stmt ( )
   Evaluate statement STMT.
   Valid only for assignments, calls, conditionals, and switches. 
     If the statement is likely to have a CONSTANT result, then try
     to fold the statement to determine the constant value.  
     FIXME.  This is the only place that we call ccp_fold.
     Since likely_value never returns CONSTANT for calls, we will
     not attempt to fold them, including builtins that may profit.  
             The statement produced a constant value.  
     If the statement is likely to have a VARYING result, then do not
     bother folding the statement.  
             Other cases cannot satisfy is_gimple_min_invariant
             without folding.  
           These cannot satisfy is_gimple_min_invariant without folding.  
             The statement produced a constant value.  
     Resort to simplification for bitwise tracking.  
               These builtins return their first argument, unmodified.  
         The statement produced a nonconstant value.  If the statement
         had UNDEFINED operands, then the result of the statement
         should be UNDEFINED.  Otherwise, the statement is VARYING.  

References bit_value_binop(), gimple_assign_lhs(), and gimple_assign_rhs2().

static unsigned int execute_fold_all_builtins ( )
   A simple pass that attempts to fold all builtin functions.  This pass
   is run after we've propagated as many constants as we can.  
                 Remove all *ssaname_N ={v} {CLOBBER}; stmts,
                 after the last GIMPLE DSE they aren't needed and might
                 unnecessarily keep the SSA_NAMEs live.  
                   Resolve __builtin_constant_p.  If it hasn't been
                   folded to integer_one_node by now, it's fairly
                   certain that the value simply isn't constant.  
                   Remove __builtin_assume_aligned.  
                   These shouldn't be folded before pass_stdarg.  
             Retry the same statement if it changed into another
             builtin, there might be new opportunities now.  
     Delete unreachable blocks.  

References opt_pass::clone(), opt_pass::execute(), and gimple_opt_pass::gimple_opt_pass().

static tree fold_builtin_alloca_with_align ( )
   Detects a __builtin_alloca_with_align with constant size argument.  Declares
   fixed-size array and returns the address, if found, otherwise returns
     Get lhs.  
     Detect constant argument.  
     Heuristic: don't fold large allocas.  
     In case the alloca is located at function entry, it has the same lifetime
     as a declared array, so we allow a larger size.  
     Declare array.  
     Fold alloca to the address of the array.  

References insert_clobbers_for_var(), and update_call_from_tree().

static bool gate_ccp ( )

References targetm.

static tree get_constant_value ( )
   Return the constant tree value associated with VAR.  
static prop_value_t get_default_value ( )
   Compute a default value for variable VAR and store it in the
   CONST_VAL array.  The following rules are used to get default

   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.  
         Variables defined by an empty statement are those used
         before being initialized.  If VAR is a local variable, we
         can assume initially that it is UNDEFINED, otherwise we must
         consider it VARYING.  
             Any other variable defined by an assignment is considered
         A variable defined by a call or a PHI node is considered
         Otherwise, VAR will never take on a constant value.  

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

static prop_value_t* get_value ( )
   Get the constant value associated with variable VAR.  

Referenced by get_value_for_expr(), and get_value_from_alignment().

static prop_value_t get_value_for_expr ( tree  ,
static prop_value_t get_value_for_expr ( )
   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 get_value(), gimple_has_volatile_ops(), prop_value_d::lattice_val, UNDEFINED, and VARYING.

static prop_value_t get_value_from_alignment ( )
   Return the value for the address expression EXPR based on alignment

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

static void gsi_prev_dom_bb_nondebug ( )
   Advance the iterator to the previous non-debug gimple statement in the same
   or dominating basic block.  
static void insert_clobber_before_stack_restore ( tree  saved_val,
tree  var,
gimple_htab visited 
   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.  
static void insert_clobbers_for_var ( )
   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.  

Referenced by fold_builtin_alloca_with_align().

static ccp_lattice_t likely_value ( )
   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.  
     This function appears to be called only for assignments, calls,
     conditionals, and switches, due to the logic in visit_stmt.  
     If the statement has volatile operands, it won't fold to a
     constant value.  
     Arrive here for more complex cases.  
     There may be constants in regular rhs operands.  For calls we
     have to ignore lhs, fndecl and static chain, otherwise only
     the lhs.  
           These 3 builtins use the first argument just as a magic
           way how to find out a decl uid.  
     If the operation combines operands like COMPLEX_EXPR make sure to
     not mark the result UNDEFINED if only one part of the result is
           Unary operators are handled with all_undefined_operands.  
             Not MIN_EXPR, MAX_EXPR.  One VARYING operand may be selected.
             Not bitwise operators, one VARYING operand may specify the
             result completely.  Not logical operators for the same reason.
             Not COMPLEX_EXPR as one VARYING operand makes the result partly
             not UNDEFINED.  Not *DIV_EXPR, comparisons and shifts because
             the undefined operand may be promoted.  
             If any part of an address is UNDEFINED, like the index
             of an ARRAY_EXPR, then treat the result as UNDEFINED.  
     If there was an UNDEFINED operand but the result may be not UNDEFINED
     fall back to CONSTANT.  During iteration UNDEFINED may still drop
     to CONSTANT.  
     We do not consider virtual operands here -- load from read-only
     memory may have only VARYING virtual operands, but still be

Referenced by bit_value_binop().

gimple_opt_pass* make_pass_ccp ( )
gimple_opt_pass* make_pass_fold_builtins ( )
static tree optimize_stack_restore ( )
   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.  
             All regular builtins are ok, just obviously not alloca.  
     Allow one successor of the exit block, or zero successors.  
     If there's exactly one use, then zap the call to __builtin_stack_save.
     If there are multiple uses, then the last one should remove the call.
     In any case, whether the call to __builtin_stack_save can be removed
     or not is irrelevant to removing the call to __builtin_stack_restore.  
     No effect, so the statement will be deleted.  
static tree optimize_stdarg_builtin ( )
   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.  
         No effect, so the statement will be deleted.  
static bool optimize_unreachable ( )
   Attemp to make the block of __builtin_unreachable I unreachable by changing
   the incoming jumps.  Return true if at least one jump was changed.  
             Verify we do not need to preserve the label.  
         Only handle the case that __builtin_unreachable is the first statement
         in the block.  We rely on DCE to remove stmts without side-effects
         before __builtin_unreachable.  
             Todo: handle other cases, f.i. switch statement.  

References dump_file, dump_flags, and print_gimple_stmt().

static bool set_lattice_value ( )
   Set the value for variable VAR to NEW_VAL.  Return true if the new
   value is different from VAR's previous value.  
     We can deal with old UNINITIALIZED values just fine here.  
     We have to be careful to not go up the bitwise lattice
     represented by the mask.
     ???  This doesn't seem to be the best place to enforce this.  
     If *OLD_VAL and NEW_VAL are the same, return false to inform the
     caller that this was a non-transition.  
         ???  We would like to delay creation of INTEGER_CSTs from
         partially constants here.  

References dump_file, dump_flags, dump_lattice_value(), prop_value_d::lattice_val, and UNINITIALIZED.

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

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

Referenced by surely_varying_stmt_p().

static bool surely_varying_stmt_p ( )
   Returns true if STMT cannot be constant.  
     If the statement has operands that we cannot handle, it cannot be
     If it is a call and does not return a value or is not a
     builtin and not an indirect call, it is varying.  
     Any other store operation is not interesting.  
     Anything other than assignments and conditional jumps are not
     interesting for CCP.  

References gsi_end_p(), gsi_next(), gsi_start_bb(), gsi_stmt(), prop_set_simulate_again(), set_value_varying(), and stmt_ends_bb_p().

static bool valid_lattice_transition ( )
   Return whether the lattice transition is valid.  
     Lattice transitions must always be monotonically increasing in
     Now both lattice values are CONSTANT.  
     Allow transitioning from PHI <&x, not executable> == &x
     to PHI <&x, &y> == common alignment.  
     Bit-lattices have to agree in the still valid bits.  
     Otherwise constant values have to agree.  
static double_int value_to_double_int ( )
   Return a double_int that can be used for bitwise simplifications
   from VAL.  
static tree valueize_op ( )
   Return the constant value for OP or OP otherwise.  
static enum ssa_prop_result visit_assignment ( )
   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.  
       For a simple copy operation, we copy the lattice values.  
       Evaluate the statement, which could be
       either a GIMPLE_ASSIGN or a GIMPLE_CALL.  
     Set the lattice value of the statement's output.  
         If STMT is an assignment to an SSA_NAME, we only have one
         value to set.  

References calculate_dominance_info(), ccp_finalize(), ccp_initialize(), ccp_visit_phi_node(), ccp_visit_stmt(), CDI_DOMINATORS, free_dominance_info(), and ssa_propagate().

static enum ssa_prop_result visit_cond_stmt ( )
   Visit the conditional statement STMT.  Return SSA_PROP_INTERESTING
   if it can determine which edge will be taken.  Otherwise, return
     Find which edge out of the conditional block will be taken and add it
     to the worklist.  If no single edge can be determined statically,
     return SSA_PROP_VARYING to feed all the outgoing edges to the
     propagation engine.  

References do_ssa_ccp().

Variable Documentation

prop_value_t* const_val
   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).  
unsigned n_const_val