GCC Middle and Back End API Reference
tree-ssa-ccp.c File Reference
#include "config.h"
#include "system.h"
#include "coretypes.h"
#include "tm.h"
#include "tree.h"
#include "flags.h"
#include "tm_p.h"
#include "basic-block.h"
#include "function.h"
#include "gimple-pretty-print.h"
#include "gimple.h"
#include "gimple-ssa.h"
#include "tree-cfg.h"
#include "tree-phinodes.h"
#include "ssa-iterators.h"
#include "tree-ssanames.h"
#include "tree-pass.h"
#include "tree-ssa-propagate.h"
#include "value-prof.h"
#include "langhooks.h"
#include "target.h"
#include "diagnostic-core.h"
#include "dbgcnt.h"
#include "params.h"
#include "hash-table.h"
Include dependency graph for tree-ssa-ccp.c:

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

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

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

??? Delay building trees here.

References ccp_fold(), CONSTANT, double_int_zero, 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, NULL_TREE, 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 
)
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.

 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.   
     Fallthru.   
       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(), double_int::ext(), and TYPE_PRECISION.

static prop_value_t bit_value_unop ( )
static

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

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

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.

static bool ccp_finalize ( )
static

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

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
static bool ccp_fold_stmt ( )
static

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

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 ( )
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)
     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
     alignment.   
     Any other combination is VARYING.   
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.

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

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

static unsigned int do_ssa_ccp ( )
static

Main entry point for SSA Conditional Constant Propagation.

References gimple_location(), and NULL_TREE.

Referenced by visit_cond_stmt().

static void dump_lattice_value ( )
static

Dump constant propagation value VAL to file OUTF prefixed by PREFIX.

Referenced by set_lattice_value().

static prop_value_t evaluate_stmt ( )
static

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

static unsigned int execute_fold_all_builtins ( )
static

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

 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 gcc_assert, insert_clobbers_for_var(), TREE_OPERAND, and update_call_from_tree().

static bool gate_ccp ( )
static

References targetm.

static tree get_constant_value ( )
inlinestatic

Return the constant tree value associated with VAR.

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.

     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
         UNDEFINED.   
     A variable defined by a call or a PHI node is considered
     UNDEFINED.   
     Otherwise, VAR will never take on a constant value.   

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

static prop_value_t* get_value ( )
inlinestatic

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  ,
bool   
)
static
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 FOR_EACH_SSA_TREE_OPERAND, gcc_assert, get_value(), gimple_has_volatile_ops(), prop_value_d::lattice_val, SSA_OP_USE, UNDEFINED, 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.

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.

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.

Referenced by fold_builtin_alloca_with_align().

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.

 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
 undefined.   
       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 &ndash; load from read-only
 memory may have only VARYING virtual operands, but still be
 constant.   

Referenced by bit_value_binop().

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.

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

No effect, so the statement will be deleted.

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.

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

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(), gcc_assert, prop_value_d::lattice_val, TDF_DETAILS, and UNINITIALIZED.

static void set_value_varying ( )
inlinestatic
static bool surely_varying_stmt_p ( )
static

Returns true if STMT cannot be constant.

 If the statement has operands that we cannot handle, it cannot be
 constant.   
 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 FOR_EACH_SSA_TREE_OPERAND, gsi_end_p(), gsi_next(), gsi_start_bb(), gsi_stmt(), prop_set_simulate_again(), set_value_varying(), SSA_OP_ALL_DEFS, and stmt_ends_bb_p().

static bool valid_lattice_transition ( )
static

Return whether the lattice transition is valid.

 Lattice transitions must always be monotonically increasing in
 value.   
 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 ( )
static

Return a double_int that can be used for bitwise simplifications from VAL.

static tree valueize_op ( )
static

Return the constant value for OP or OP otherwise.

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.

   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(), ssa_propagate(), TODO_cleanup_cfg, and TODO_update_ssa.

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.

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

unsigned n_const_val
static