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

Functions

static bool forward_propagate_addr_expr (tree, tree, bool)
static tree rhs_to_tree (tree type, gimple stmt)
static gimple get_prop_dest_stmt ()
static gimple get_prop_source_stmt ()
static bool can_propagate_from ()
static bool remove_prop_source_from_use ()
static tree rhs_to_tree ()
static tree combine_cond_expr_cond (gimple stmt, enum tree_code code, tree type, tree op0, tree op1, bool invariant_only)
static tree forward_propagate_into_comparison_1 (gimple stmt, enum tree_code code, tree type, tree op0, tree op1)
static int forward_propagate_into_comparison ()
static int forward_propagate_into_gimple_cond ()
static bool forward_propagate_into_cond ()
static bool combine_cond_exprs ()
static void tidy_after_forward_propagate_addr ()
static bool forward_propagate_addr_expr_1 (tree name, tree def_rhs, gimple_stmt_iterator *use_stmt_gsi, bool single_use_p)
static bool forward_propagate_addr_expr ()
static bool forward_propagate_comparison ()
static bool simplify_conversion_from_bitmask ()
static bool simplify_not_neg_expr ()
static void simplify_gimple_switch_label_vec ()
static bool simplify_gimple_switch ()
static tree constant_pointer_difference ()
static bool simplify_builtin_call ()
static bool truth_valued_ssa_name ()
static tree lookup_logical_inverted_value ()
static tree simplify_bitwise_binary_1 (enum tree_code code, tree type, tree arg1, tree arg2)
static void defcodefor_name ()
static bool hoist_conversion_for_bitop_p ()
static bool simplify_bitwise_binary_boolean (gimple_stmt_iterator *gsi, enum tree_code code, tree op0, tree op1)
static bool simplify_bitwise_binary ()
static bool simplify_rotate ()
static bool associate_plusminus ()
static bool associate_pointerplus ()
static int combine_conversions ()
static bool simplify_bitfield_ref ()
static int is_combined_permutation_identity ()
static int simplify_permutation ()
static bool simplify_vector_constructor ()
static unsigned int ssa_forward_propagate_and_combine ()
static bool gate_forwprop ()
gimple_opt_passmake_pass_forwprop ()

Variables

static bool cfg_changed

Function Documentation

static bool associate_plusminus ( )
static
   Perform re-associations of the plus or minus statement STMT that are
   always permitted.  Returns true if the CFG was changed.  
     We can't reassociate at all for saturating types.  
     First contract negates.  
         A +- (-B) -> A -+ B.  
         (-A) + B -> B - A.  
     We can't reassociate floating-point or fixed-point plus or minus
     because of saturation to +-Inf.  
     Second match patterns that allow contracting a plus-minus pair
     irrespective of overflow issues.

        (A +- B) - A       ->  +- B
        (A +- B) -+ B      ->  A
        (CST +- A) +- CST  ->  CST +- A
        (A +- CST) +- CST  ->  A +- CST
        ~A + A             ->  -1
        ~A + 1             ->  -A 
        A - (A +- B)       ->  -+ B
        A +- (B +- A)      ->  +- B
        CST +- (CST +- A)  ->  CST +- A
        CST +- (A +- CST)  ->  CST +- A
        A + ~A             ->  -1

     via commutating the addition and contracting operations to zero
     by reassociation.  
                     (A +- B) - A -> +- B.  
                     (A +- B) -+ B -> A.  
                     (CST +- A) +- CST -> CST +- A.  
                     (A +- CST) +- CST -> A +- CST.  
                     ~A + A -> -1.  
                     ~A + 1 -> -A.  
                     A - (A +- B) -> -+ B.  
                     A +- (B +- A) -> +- B.  
                     CST +- (CST +- A) -> CST +- A.  
                     CST +- (A +- CST) -> CST +- A.  
                     A + ~A -> -1.  
static bool associate_pointerplus ( )
static
   Associate operands of a POINTER_PLUS_EXPR assignmen at *GSI.  Returns
   true if anything changed, false otherwise.  
     Pattern match
       tem = (sizetype) ptr;
       tem = tem & algn;
       tem = -tem;
       ... = ptr p+ tem;
     and produce the simpler and easier to analyze with respect to alignment
       ... = ptr & ~algn;  

References gimple_assign_set_rhs1(), remove_prop_source_from_use(), and update_stmt().

static bool can_propagate_from ( )
static
   Checks if the destination ssa name in DEF_STMT can be used as
   propagation source.  Returns true if so, otherwise false.  
     If the rhs has side-effects we cannot propagate from it.  
     If the rhs is a load we cannot propagate from it.  
     Constants can be always propagated.  
     We cannot propagate ssa names that occur in abnormal phi nodes.  
     If the definition is a conversion of a pointer to a function type,
     then we can not apply optimizations as some targets require
     function pointers to be canonicalized and in this case this
     optimization could eliminate a necessary canonicalization.  

References gimple_assign_rhs1().

Referenced by forward_propagate_into_comparison_1().

static tree combine_cond_expr_cond ( gimple  stmt,
enum tree_code  code,
tree  type,
tree  op0,
tree  op1,
bool  invariant_only 
)
static
   Combine OP0 CODE OP1 in the context of a COND_EXPR.  Returns
   the folded result in a form suitable for COND_EXPR_COND or
   NULL_TREE, if there is no suitable simplified form.  If
   INVARIANT_ONLY is true only gimple_min_invariant results are
   considered simplified.  
     Require that we got a boolean type out if we put one in.  
     Canonicalize the combined condition for use in a COND_EXPR.  
     Bail out if we required an invariant but didn't get one.  

Referenced by forward_propagate_into_comparison_1().

static bool combine_cond_exprs ( )
static
   Propagate from the ssa name definition statements of COND_EXPR
   values in the rhs of statement STMT into the conditional arms
   if that simplifies it.
   Returns true if the stmt was changed.  

References gimple_assign_set_rhs_from_tree(), and gsi_stmt().

static int combine_conversions ( )
static
   Combine two conversions in a row for the second conversion at *GSI.
   Returns 1 if there were any changes made, 2 if cfg-cleanup needs to
   run.  Else it returns 0.  
         Don't propagate ssa names that occur in abnormal phis.  
         In addition to the cases of two conversions in a row
         handled below, if we are converting something to its own
         type via an object of identical or wider precision, neither
         conversion is needed.  
         Likewise, if the intermediate and initial types are either both
         float or both integer, we don't need the middle conversion if the
         former is wider than the latter and doesn't change the signedness
         (for integers).  Avoid this if the final type is a pointer since
         then we sometimes need the middle conversion.  Likewise if the
         final type has a precision not equal to the size of its mode.  
         If we have a sign-extension of a zero-extended value, we can
         replace that by a single zero-extension.  Likewise if the
         final conversion does not change precision we can drop the
         intermediate conversion.  
         Two conversions in a row are not needed unless:
         - some conversion is floating-point (overstrict for now), or
         - some conversion is a vector (overstrict for now), or
         - the intermediate type is narrower than both initial and
         final, or
         - the intermediate type and innermost type differ in signedness,
         and the outermost type is wider than the intermediate, or
         - the initial type is a pointer type and the precisions of the
         intermediate and final types differ, or
         - the final type is a pointer type and the precisions of the
         initial and intermediate types differ.  
         A truncation to an unsigned type should be canonicalized as
         bitwise and of a mask.  
         If we are converting an integer to a floating-point that can
         represent it exactly and back to an integer, we can skip the
         floating-point conversion.  

References gimple_assign_set_rhs1(), gimple_assign_set_rhs_code(), remove_prop_source_from_use(), and update_stmt().

static tree constant_pointer_difference ( )
static
   For pointers p2 and p1 return p2 - p1 if the
   difference is known and constant, otherwise return NULL.  
         For each of p1 and p2 we need to iterate at least
         twice, to handle ADDR_EXPR directly in p1/p2,
         SSA_NAME with ADDR_EXPR or POINTER_PLUS_EXPR etc.
         on definition's stmt RHS.  Iterate a few extra times.  

References BUILT_IN_NORMAL, compare_tree_int(), gimple_assign_lhs(), gimple_assign_rhs1(), gimple_assign_single_p(), gimple_call_arg(), gimple_call_fndecl(), gimple_call_lhs(), gimple_call_num_args(), gimple_vuse(), gsi_stmt(), host_integerp(), HOST_WIDE_INT, is_gimple_call(), string_constant(), and tree_low_cst().

static void defcodefor_name ( )
inlinestatic
   Given a ssa_name in NAME see if it was defined by an assignment and
   set CODE to be the code and ARG1 to the first operand on the rhs and ARG2
   to the second operand on the rhs. 
     Ignore arg3 currently. 

Referenced by simplify_rotate().

static bool forward_propagate_addr_expr ( tree  ,
tree  ,
bool   
)
static
@verbatim 

Forward propagation of expressions for single use variables. Copyright (C) 2004-2013 Free Software Foundation, Inc.

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 pass propagates the RHS of assignment statements into use
   sites of the LHS of the assignment.  It's basically a specialized
   form of tree combination.   It is hoped all of this can disappear
   when we have a generalized tree combiner.

   One class of common cases we handle is forward propagating a single use
   variable into a COND_EXPR.

     bb0:
       x = a COND b;
       if (x) goto ... else goto ...

   Will be transformed into:

     bb0:
       if (a COND b) goto ... else goto ...

   Similarly for the tests (x == 0), (x != 0), (x == 1) and (x != 1).

   Or (assuming c1 and c2 are constants):

     bb0:
       x = a + c1;
       if (x EQ/NEQ c2) goto ... else goto ...

   Will be transformed into:

     bb0:
        if (a EQ/NEQ (c2 - c1)) goto ... else goto ...

   Similarly for x = a - c1.

   Or

     bb0:
       x = !a
       if (x) goto ... else goto ...

   Will be transformed into:

     bb0:
        if (a == 0) goto ... else goto ...

   Similarly for the tests (x == 0), (x != 0), (x == 1) and (x != 1).
   For these cases, we propagate A into all, possibly more than one,
   COND_EXPRs that use X.

   Or

     bb0:
       x = (typecast) a
       if (x) goto ... else goto ...

   Will be transformed into:

     bb0:
        if (a != 0) goto ... else goto ...

   (Assuming a is an integral type and x is a boolean or x is an
    integral and a is a boolean.)

   Similarly for the tests (x == 0), (x != 0), (x == 1) and (x != 1).
   For these cases, we propagate A into all, possibly more than one,
   COND_EXPRs that use X.

   In addition to eliminating the variable and the statement which assigns
   a value to the variable, we may be able to later thread the jump without
   adding insane complexity in the dominator optimizer.

   Also note these transformations can cascade.  We handle this by having
   a worklist of COND_EXPR statements to examine.  As we make a change to
   a statement, we put it back on the worklist to examine on the next
   iteration of the main loop.

   A second class of propagation opportunities arises for ADDR_EXPR
   nodes.

     ptr = &x->y->z;
     res = *ptr;

   Will get turned into

     res = x->y->z;

   Or
     ptr = (type1*)&type2var;
     res = *ptr

   Will get turned into (if type1 and type2 are the same size
   and neither have volatile on them):
     res = VIEW_CONVERT_EXPR<type1>(type2var)

   Or

     ptr = &x[0];
     ptr2 = ptr + <constant>;

   Will get turned into

     ptr2 = &x[constant/elementsize];

  Or

     ptr = &x[0];
     offset = index * element_size;
     offset_p = (pointer) offset;
     ptr2 = ptr + offset_p

  Will get turned into:

     ptr2 = &x[index];

  Or
    ssa = (int) decl
    res = ssa & 1

  Provided that decl has known alignment >= 2, will get turned into

    res = 0

  We also propagate casts into SWITCH_EXPR and COND_EXPR conditions to
  allow us to remove the cast and {NOT_EXPR,NEG_EXPR} into a subsequent
  {NOT_EXPR,NEG_EXPR}.

   This will (of course) be extended as other needs arise.  
static bool forward_propagate_addr_expr ( )
static
   STMT is a statement of the form SSA_NAME = ADDR_EXPR <whatever>.

   Try to forward propagate the ADDR_EXPR into all uses of the SSA_NAME.
   Often this will allow for removal of an ADDR_EXPR and INDIRECT_REF
   node or for recovery of array indexing from pointer arithmetic.

   PARENT_SINGLE_USE_P tells if, when in a recursive invocation, NAME was
   the single use in the previous invocation.  Pass true when calling
   this as toplevel.

   Returns true, if all uses have been propagated into.  
         If the use is not in a simple assignment statement, then
         there is nothing we can do.  
         If the use has moved to a different statement adjust
         the update machinery for the old statement too.  
         Remove intermediate now unused copy and conversion chains.  

References dump_file, dump_flags, get_prop_dest_stmt(), gimple_assign_lhs(), gimple_assign_rhs1(), gimple_assign_rhs2(), gimple_assign_rhs_code(), gimple_assign_set_rhs_from_tree(), gsi_for_stmt(), gsi_stmt(), integer_onep(), invert_tree_comparison(), is_gimple_assign(), print_gimple_expr(), unshare_expr(), and update_stmt().

static bool forward_propagate_addr_expr_1 ( tree  name,
tree  def_rhs,
gimple_stmt_iterator use_stmt_gsi,
bool  single_use_p 
)
static
   NAME is a SSA_NAME representing DEF_RHS which is of the form
   ADDR_EXPR <whatever>.

   Try to forward propagate the ADDR_EXPR into the use USE_STMT.
   Often this will allow for removal of an ADDR_EXPR and INDIRECT_REF
   node or for recovery of array indexing from pointer arithmetic.

   Return true if the propagation was successful (the propagation can
   be not totally successful, yet things may have been changed).  
     Do not perform copy-propagation but recurse through copy chains.  
     The use statement could be a conversion.  Recurse to the uses of the
     lhs as copyprop does not copy through pointer to integer to pointer
     conversions and FRE does not catch all cases either.
     Treat the case of a single-use name and
     a conversion to def_rhs type separate, though.  
         If there is a point in a conversion chain where the types match
         so we can remove a conversion re-materialize the address here
         and stop.  
         Else recurse if the conversion preserves the address value.  
     If this isn't a conversion chain from this on we only can propagate
     into compatible pointer contexts.  
     Propagate through constant pointer adjustments.  
         As we come here with non-invariant addresses in def_rhs we need
         to make sure we can build a valid constant offsetted address
         for further propagation.  Simply rely on fold building that
         and check after the fact.  
         Recurse.  If we could propagate into all uses of lhs do not
         bother to replace into the current use but just pretend we did.  
     Now strip away any outer COMPONENT_REF/ARRAY_REF nodes from the LHS.
     ADDR_EXPR will not appear on the LHS.  
     Now see if the LHS node is a MEM_REF using NAME.  If so,
     propagate the ADDR_EXPR into the use of NAME and fold the result.  
         If the address is invariant we can always fold it.  
             Continue propagating into the RHS if this was not the only use.  
         If the LHS is a plain dereference and the value type is the same as
         that of the pointed-to type of the address we can put the
         dereferenced address on the LHS preserving the original alias-type.  
                  Don't forward anything into clobber stmts if it would result
                  in the lhs no longer being a MEM_REF.  
             Continue propagating into the RHS if this was not the
             only use.  
           We can have a struct assignment dereferencing our name twice.
           Note that we didn't propagate into the lhs to not falsely
           claim we did when propagating into the rhs.  
     Strip away any outer COMPONENT_REF, ARRAY_REF or ADDR_EXPR
     nodes from the RHS.  
     Now see if the RHS node is a MEM_REF using NAME.  If so,
     propagate the ADDR_EXPR into the use of NAME and fold the result.  
         If the RHS is a plain dereference and the value type is the same as
         that of the pointed-to type of the address we can put the
         dereferenced address on the RHS preserving the original alias-type.  
     If the use of the ADDR_EXPR is not a POINTER_PLUS_EXPR, there
     is nothing to do. 
     The remaining cases are all for turning pointer arithmetic into
     array indexing.  They only apply when we have the address of
     element zero in an array.  If that is not the case then there
     is nothing to do.  
     Optimize &x[C1] p+ C2 to  &x p+ C3 with C3 = C1 * element_size + C2.  
static bool forward_propagate_comparison ( )
static
   Forward propagate the comparison defined in *DEFGSI like
   cond_1 = x CMP y to uses of the form
     a_1 = (T')cond_1
     a_1 = !cond_1
     a_1 = cond_1 != 0
   Returns true if stmt is now unused.  Advance DEFGSI to the next
   statement.  
     Don't propagate ssa names that occur in abnormal phis.  
     Do not un-cse comparisons.  But propagate through copies.  
     We can propagate the condition into a statement that
     computes the logical negation of the comparison result.  
     When we remove stmt now the iterator defgsi goes off it's current
     sequence, hence advance it now.  
     Remove defining statements.  
static int forward_propagate_into_comparison ( )
static
   Propagate from the ssa name definition statements of the assignment
   from a comparison at *GSI into the conditional if that simplifies it.
   Returns 1 if the stmt was modified and 2 if the CFG needs cleanup,
   otherwise returns 0.  
     Combine the comparison with defining statements.  
static tree forward_propagate_into_comparison_1 ( gimple  stmt,
enum tree_code  code,
tree  type,
tree  op0,
tree  op1 
)
static
   Combine the comparison OP0 CODE OP1 at LOC with the defining statements
   of its operand.  Return a new comparison tree or NULL_TREE if there
   were no simplifying combines.  
     For comparisons use the first operand, that is likely to
     simplify comparisons against constants.  
     If that wasn't successful, try the second operand.  
     If that wasn't successful either, try both operands.  

References can_propagate_from(), combine_cond_expr_cond(), get_prop_source_stmt(), and rhs_to_tree().

static bool forward_propagate_into_cond ( )
static
   Propagate from the ssa name definition statements of COND_EXPR
   in the rhs of statement STMT into the conditional if that simplifies it.
   Returns true zero if the stmt was changed.  
     We can do tree combining on SSA_NAME and comparison expressions.  

References gimple_assign_rhs1().

static int forward_propagate_into_gimple_cond ( )
static
   Propagate from the ssa name definition statements of COND_EXPR
   in GIMPLE_COND statement STMT into the conditional if that simplifies it.
   Returns zero if no statement was changed, one if there were
   changes and two if cfg_cleanup needs to run.

   This must be kept in sync with forward_propagate_into_cond.  
     We can do tree combining on SSA_NAME and comparison expressions.  
     Canonicalize _Bool == 0 and _Bool != 1 to _Bool != 0 by swapping edges.  
static bool gate_forwprop ( )
static
static gimple get_prop_dest_stmt ( )
static
   Get the next statement we can propagate NAME's value into skipping
   trivial copies.  Returns the statement that is suitable as a
   propagation destination or NULL_TREE if there is no such one.
   This only returns destinations in a single-use chain.  FINAL_NAME_P
   if non-NULL is written to the ssa name that represents the use.  
       If name has multiple uses, bail out.  
       If this is not a trivial copy, we found it.  
       Continue searching uses of the copy destination.  

References gimple_assign_lhs(), gimple_assign_rhs1(), gimple_assign_ssa_name_copy_p(), and single_imm_use().

Referenced by forward_propagate_addr_expr().

static gimple get_prop_source_stmt ( )
static
   Get the statement we can propagate from into NAME skipping
   trivial copies.  Returns the statement which defines the
   propagation source or NULL_TREE if there is no such one.
   If SINGLE_USE_ONLY is set considers only sources which have
   a single use chain up to NAME.  If SINGLE_USE_P is non-null,
   it is set to whether the chain to NAME is a single use chain
   or not.  SINGLE_USE_P is not written to if SINGLE_USE_ONLY is set.  
       If name is defined by a PHI node or is the default def, bail out.  
       If def_stmt is a simple copy, continue looking.  

Referenced by forward_propagate_into_comparison_1().

static bool hoist_conversion_for_bitop_p ( )
static
   Return true if a conversion of an operand from type FROM to type TO
   should be applied after performing the operation instead.  
     That's a good idea if the conversion widens the operand, thus
     after hoisting the conversion the operation will be narrower.  
     It's also a good idea if the conversion is to a non-integer mode.  
     Or if the precision of TO is not the same as the precision
     of its mode.  
static int is_combined_permutation_identity ( )
static
   Determine whether applying the 2 permutations (mask1 then mask2)
   gives back one of the input.  
static tree lookup_logical_inverted_value ( )
static
   Helper routine for simplify_bitwise_binary_1 function.
   Return for the SSA name NAME the expression X if it mets condition
   NAME = !X. Otherwise return NULL_TREE.
   Detected patterns for NAME = !X are:
     !X and X == 0 for X with integral type.
     X ^ 1, X != 1,or ~X for X with integral type with precision of one.  
     If name has none-intergal type, or isn't a SSA_NAME, then
     return.  
     Get for EQ_EXPR or BIT_XOR_EXPR operation the second operand.
     If CODE isn't an EQ_EXPR, BIT_XOR_EXPR, or BIT_NOT_EXPR, then return.  
         Check if we have X == 0 and X has an integral type.  
         Check if we have X != 1 and X is a truth-valued.  
         Check if we have X ^ 1 and X is truth valued.  
gimple_opt_pass* make_pass_forwprop ( )
static bool remove_prop_source_from_use ( )
static
   Remove a chain of dead statements starting at the definition of
   NAME.  The chain is linked via the first operand of the defining statements.
   If NAME was replaced in its only use then this function can be used
   to clean up dead stmts.  The function handles already released SSA
   names gracefully.
   Returns true if cleanup-cfg has to run.  

Referenced by associate_pointerplus(), and combine_conversions().

static tree rhs_to_tree ( tree  type,
gimple  stmt 
)
static
static tree rhs_to_tree ( )
static
   Return the rhs of a gimple_assign STMT in a form of a single tree,
   converted to type TYPE.

   This should disappear, but is needed so we can combine expressions and use
   the fold() interfaces. Long term, we need to develop folding and combine
   routines that deal with gimple exclusively . 

References fold_binary_loc(), fold_defer_overflow_warnings(), fold_undefer_overflow_warnings(), gimple_location(), and tcc_comparison.

static bool simplify_bitfield_ref ( )
static
   Combine an element access with a shuffle.  Returns true if there were
   any changes made, else it returns false.  
static bool simplify_bitwise_binary ( )
static
   Simplify bitwise binary operations.
   Return true if a transformation applied, otherwise return false.  
     Try to fold (type) X op CST -> (type) (X op ((type-x) CST))
     when profitable.  
     For bitwise binary operations apply operand conversions to the
     binary operation result instead of to the operands.  This allows
     to combine successive conversions and bitwise binary operations.  
      Simplify (A & B) OP0 (C & B) to (A OP0 C) & B. 
         If A OP0 C (this usually means C is the same as A) is 0
         then fold it down correctly. 
         If A OP0 C (this usually means C is the same as A) is a ssa_name
         then fold it down correctly. 
             Make sure to re-process the new stmt as it's walking upwards.  
     (a | CST1) & CST2  ->  (a & CST2) | (CST1 & CST2).  
         Make sure to re-process the new stmt as it's walking upwards.  
     Combine successive equal operations with constants.  
     Canonicalize X ^ ~0 to ~X.  
     Try simple folding for X op !X, and X op X.  
             ( X | Y) & X -> X 
             ( X & Y) | X -> X 
             (~X | Y) & X -> X & Y 
             (~X & Y) | X -> X | Y 
             (Y | ~X) & X -> X & Y 
             (Y & ~X) | X -> X | Y 
             X & ( X | Y) -> X 
             X | ( X & Y) -> X 
             (~X | Y) & X -> X & Y 
             (~X & Y) | X -> X | Y 
             (Y | ~X) & X -> X & Y 
             (Y & ~X) | X -> X | Y 
         If arg1 and arg2 are booleans (or any single bit type)
         then try to simplify:

           (~X & Y) -> X < Y
           (X & ~Y) -> Y < X
           (~X | Y) -> X <= Y
           (X | ~Y) -> Y <= X 

          But only do this if our result feeds into a comparison as
          this transformation is not always a win, particularly on
          targets with and-not instructions.  
static tree simplify_bitwise_binary_1 ( enum tree_code  code,
tree  type,
tree  arg1,
tree  arg2 
)
static
   Optimize ARG1 CODE ARG2 to a constant for bitwise binary
   operations CODE, if one operand has the logically inverted
   value of the other.  
     If CODE isn't a bitwise binary operation, return NULL_TREE.  
     First check if operands ARG1 and ARG2 are equal.  If so
     return NULL_TREE as this optimization is handled fold_stmt.  
     See if we have in arguments logical-not patterns.  
     X & !X -> 0.  
     X | !X -> 1 and X ^ !X -> 1, if X is truth-valued.  
     ??? Otherwise result is (X != 0 ? X : 1).  not handled.  

References gimple_assign_rhs1(), gimple_assign_rhs_code(), gimple_assign_set_rhs1(), gimple_assign_set_rhs2(), gimple_assign_set_rhs_code(), gsi_stmt(), is_gimple_assign(), and update_stmt().

static bool simplify_bitwise_binary_boolean ( gimple_stmt_iterator gsi,
enum tree_code  code,
tree  op0,
tree  op1 
)
static
   GSI points to a statement of the form

   result = OP0 CODE OP1

   Where OP0 and OP1 are single bit SSA_NAMEs and CODE is either
   BIT_AND_EXPR or BIT_IOR_EXPR.

   If OP0 is fed by a bitwise negation of another single bit SSA_NAME,
   then we can simplify the two statements into a single LT_EXPR or LE_EXPR
   when code is BIT_AND_EXPR and BIT_IOR_EXPR respectively.

   If a simplification is made, return TRUE, else return FALSE.  

References gimple_assign_set_rhs1(), gimple_assign_set_rhs2(), gimple_assign_set_rhs_code(), gimple_build_assign_with_ops(), gimple_location(), gimple_set_location(), gsi_insert_before(), GSI_NEW_STMT, make_ssa_name(), and update_stmt().

static bool simplify_builtin_call ( )
static
   *GSI_P is a GIMPLE_CALL to a builtin function.
   Optimize
   memcpy (p, "abcd", 4);
   memset (p + 4, ' ', 3);
   into
   memcpy (p, "abcd   ", 7);
   call if the latter can be stored by pieces during expansion.  
                 If first stmt is a call, it needs to be memcpy
                 or mempcpy, with string literal as second argument and
                 constant length.  
                 Otherwise look for length 1 memcpy optimized into
                 assignment.  
             If the difference between the second and first destination pointer
             is not constant, or is bigger than memcpy length, bail out.  
             Use maximum of difference plus memset length and memcpy length
             as the new memcpy length, if it is too big, bail out.  
             If mempcpy value is used elsewhere, bail out, as mempcpy
             with bigger length will return different result.  
             If anything reads memory in between memcpy and memset
             call, the modified memcpy call might change it.  
             Construct the new source string literal.  
             Neither builtin_strncpy_read_str nor builtin_memcpy_read_str
             handle embedded '\0's.  
             If the new memcpy wouldn't be emitted by storing the literal
             by pieces, this optimization might enlarge .rodata too much,
             as commonly used string literals couldn't be shared any
             longer.  
                 If STMT1 is a mem{,p}cpy call, adjust it and remove
                 memset call.  
                 Otherwise, if STMT1 is length 1 memcpy optimized into
                 assignment, remove STMT1 and change memset call into
                 memcpy call.  
static bool simplify_conversion_from_bitmask ( )
static
   GSI_P points to a statement which performs a narrowing integral
   conversion.

   Look for cases like:

     t = x & c;
     y = (T) t;

   Turn them into:

     t = x & c;
     y = (T) x;

   If T is narrower than X's type and C merely masks off bits outside
   of (T) and nothing else.

   Normally we'd let DCE remove the dead statement.  But no DCE runs
   after the last forwprop/combine pass, so we remove the obviously
   dead code ourselves.

   Return TRUE if a change was made, FALSE otherwise.  
     See if the input for the conversion was set via a BIT_AND_EXPR and
     the only use of the BIT_AND_EXPR result is the conversion.  
         Now verify suitability of the BIT_AND_EXPR's operands.
         The first must be an SSA_NAME that we can propagate and the
         second must be an integer constant that masks out all the
         bits outside the final result's type, but nothing else.  
             This is an optimizable case.  Replace the source operand
             in the conversion with the first source operand of the
             BIT_AND_EXPR.  
             There is no DCE after the last forwprop pass.  It's
             easy to clean up the first order effects here.  

References gimple_assign_rhs1(), gimple_assign_set_rhs_from_tree(), gsi_stmt(), and update_stmt().

static bool simplify_gimple_switch ( )
static
   STMT is a SWITCH_EXPR for which we attempt to find equivalent forms of
   the condition which we may be able to optimize better.  
     The optimization that we really care about is removing unnecessary
     casts.  That will let us do much better in propagating the inferred
     constant at the switch target.  
                 If we have an extension that preserves value, then we
                 can copy the source value into the switch.  
static void simplify_gimple_switch_label_vec ( )
static
   Helper function for simplify_gimple_switch.  Remove case labels that
   have values outside the range of the new type.  
     Collect the existing case labels in a VEC, and preprocess it as if
     we are gimplifying a GENERIC SWITCH_EXPR.  
     If any labels were removed, replace the existing case labels
     in the GIMPLE_SWITCH statement with the correct ones.
     Note that the type updates were done in-place on the case labels,
     so we only have to replace the case labels in the GIMPLE_SWITCH
     if the number of labels changed.  
         Corner case: *all* case labels have been removed as being
         out-of-range for INDEX_TYPE.  Push one label and let the
         CFG cleanups deal with this further.  
         Cleanup any edges that are now dead.  

References gimple_assign_rhs1(), gimple_assign_rhs_code(), gimple_switch_set_index(), is_gimple_assign(), and update_stmt().

static bool simplify_not_neg_expr ( )
static
   If we have lhs = ~x (STMT), look and see if earlier we had x = ~y.
   If so, we can change STMT into lhs = y which can later be copy
   propagated.  Similarly for negation.

   This could trivially be formulated as a forward propagation
   to immediate uses.  However, we already had an implementation
   from DOM which used backward propagation via the use-def links.

   It turns out that backward propagation is actually faster as
   there's less work to do for each NOT/NEG expression we find.
   Backwards propagation needs to look at the statement in a single
   backlink.  Forward propagation needs to look at potentially more
   than one forward link.

   Returns true when the statement was changed.  
     See if the RHS_DEF_STMT has the same form as our statement.  
         Verify that RHS_DEF_OPERAND is a suitable SSA_NAME.  
static int simplify_permutation ( )
static
   Combine a shuffle with its arguments.  Returns 1 if there were any
   changes made, 2 if cfg-cleanup needs to run.  Else it returns 0.  
     Two consecutive shuffles.  
     Shuffle of a constructor.  
             Already used twice in this statement.  
static bool simplify_rotate ( )
static
   Recognize rotation patterns.  Return true if a transformation
   applied, otherwise return false.

   We are looking for X with unsigned type T with bitsize B, OP being
   +, | or ^, some type T2 wider than T and
   (X << CNT1) OP (X >> CNT2)                           iff CNT1 + CNT2 == B
   ((T) ((T2) X << CNT1)) OP ((T) ((T2) X >> CNT2))     iff CNT1 + CNT2 == B
   (X << Y) OP (X >> (B - Y))
   (X << (int) Y) OP (X >> (int) (B - Y))
   ((T) ((T2) X << Y)) OP ((T) ((T2) X >> (B - Y)))
   ((T) ((T2) X << (int) Y)) OP ((T) ((T2) X >> (int) (B - Y)))
   (X << Y) | (X >> ((-Y) & (B - 1)))
   (X << (int) Y) | (X >> (int) ((-Y) & (B - 1)))
   ((T) ((T2) X << Y)) | ((T) ((T2) X >> ((-Y) & (B - 1))))
   ((T) ((T2) X << (int) Y)) | ((T) ((T2) X >> (int) ((-Y) & (B - 1))))

   and transform these into:
   X r<< CNT1
   X r<< Y

   Note, in the patterns with T2 type, the type of OP operands
   might be even a signed type, but should have precision B.  
     Only create rotates in complete modes.  Other cases are not
     expanded properly.  
     Look through narrowing conversions.  
     One operand has to be LSHIFT_EXPR and one RSHIFT_EXPR.  
     If we've looked through narrowing conversions before, look through
     widening conversions from unsigned type with the same precision
     as rtype here.  
     Both shifts have to use the same first operand.  
     CNT1 + CNT2 == B case above.  
         Look through conversion of the shift count argument.
         The C/C++ FE cast any shift count argument to integer_type_node.
         The only problem might be if the shift count type maximum value
         is equal or smaller than number of bits in rtype.  
           Check for one shift count being Y and the other B - Y,
           with optional casts.  
           The above sequence isn't safe for Y being 0,
           because then one of the shifts triggers undefined behavior.
           This alternative is safe even for rotation count of 0.
           One shift count is Y and the other (-Y) & (B - 1).  

References defcodefor_name(), and floor_log2().

static bool simplify_vector_constructor ( )
static
   Recognize a VEC_PERM_EXPR.  Returns true if there were any changes.  
static unsigned int ssa_forward_propagate_and_combine ( )
static
   Main entry point for the forward propagation and statement combine
   optimizer.  
         Apply forward propagation to all stmts in the basic-block.
         Note we update GSI within the loop as necessary.  
             If this statement sets an SSA_NAME to an address,
             try to propagate the address into the uses of the SSA_NAME.  
                 Handle pointer conversions on invariant addresses
                 as well, as this is valid gimple.  
                     ???  Better adjust the interface to that function
                     instead of building new trees here.  
                     Make sure to fold &a[0] + off_1 here.  
         Combine stmts with the stmts defining their operands.
         Note we update GSI within the loop as necessary.  
             Mark stmt as potentially needing revisiting.  
                       In this case the entire COND_EXPR is in rhs1. 
                       If we have a narrowing conversion to an integral
                       type that is fed by a BIT_AND_EXPR, we might be
                       able to remove the BIT_AND_EXPR if it merely
                       masks off bits outside the final type (and nothing
                       else.  
                 If the stmt changed then re-visit it and the statements
                 inserted before it.  
                 Stmt no longer needs to be revisited.  
static void tidy_after_forward_propagate_addr ( )
static
   We've just substituted an ADDR_EXPR into stmt.  Update all the
   relevant data structures to match.  
     We may have turned a trapping insn into a non-trapping insn.  
static bool truth_valued_ssa_name ( )
static
   Checks if expression has type of one-bit precision, or is a known
   truth-valued expression.  
     Don't check here for BOOLEAN_TYPE as the precision isn't
     necessarily one and so ~X is not equal to !X.  

Variable Documentation

bool cfg_changed
static
   Set to true if we delete dead edges during the optimization.