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

Functions

static bool forward_propagate_addr_expr (tree name, tree rhs)
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_pointerplus ( )
static
Associate operands of a POINTER_PLUS_EXPR assignmen at *GSI.  Returns
   true if anything changed, false otherwise.   

References double_int_to_tree(), fold_stmt_inplace(), gimple_assign_rhs1(), gimple_assign_rhs2(), gimple_assign_rhs_code(), gimple_assign_set_rhs_with_ops(), gsi_stmt(), is_gimple_assign(), tree_to_double_int(), and update_stmt().

Referenced by ssa_forward_propagate_and_combine().

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.   

References canonicalize_cond_expr_cond(), fold_binary_loc(), fold_defer_overflow_warnings(), fold_undefer_overflow_warnings(), gimple_location(), gimple_no_warning_p(), is_gimple_min_invariant(), and tcc_comparison.

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 changed, gimple_assign_rhs1(), gimple_assign_rhs2(), gimple_assign_rhs3(), gimple_assign_rhs_code(), gimple_assign_set_rhs2(), gimple_assign_set_rhs3(), gimple_assign_set_rhs_from_tree(), gsi_stmt(), is_gimple_assign(), operand_equal_p(), unshare_expr(), and update_stmt().

Referenced by ssa_forward_propagate_and_combine().

static int combine_conversions ( )
static
static tree constant_pointer_difference ( )
static
For pointers p2 and p1 return p2 - p1 if the
   difference is known and constant, otherwise return NULL.   

References double_int_to_tree(), get_addr_base_and_unit_offset(), gimple_assign_lhs(), gimple_assign_rhs1(), gimple_assign_rhs2(), gimple_assign_rhs_code(), HOST_WIDE_INT, is_gimple_assign(), mem_ref_offset(), and offset.

Referenced by simplify_builtin_call().

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.  

References can_propagate_from(), extract_ops_from_tree_1(), get_gimple_rhs_class(), gimple_assign_rhs1(), gimple_assign_rhs2(), gimple_assign_rhs_code(), GIMPLE_BINARY_RHS, GIMPLE_SINGLE_RHS, GIMPLE_TERNARY_RHS, GIMPLE_UNARY_RHS, and is_gimple_assign().

Referenced by simplify_bitwise_binary(), and simplify_rotate().

static bool forward_propagate_addr_expr ( tree  name,
tree  rhs 
)
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.   

Referenced by forward_propagate_addr_expr_1(), and ssa_forward_propagate_and_combine().

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.
   Returns true, if all uses have been propagated into.   

References bb_loop_depth(), forward_propagate_addr_expr_1(), gimple_assign_lhs(), gimple_assign_rhs1(), gsi_for_stmt(), gsi_remove(), gsi_stmt(), has_single_use(), has_zero_uses(), is_gimple_debug(), is_gimple_min_invariant(), release_defs(), 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).   

References double_int_to_tree(), fold_stmt_inplace(), forward_propagate_addr_expr(), double_int::from_shwi(), get_addr_base_and_unit_offset(), gimple_assign_lhs(), gimple_assign_rhs1(), gimple_assign_rhs2(), gimple_assign_rhs_code(), gimple_assign_set_lhs(), gimple_assign_set_rhs1(), gimple_assign_set_rhs_code(), gimple_assign_set_rhs_from_tree(), gimple_assign_set_rhs_with_ops(), gimple_clobber_p(), gimple_location(), gsi_stmt(), handled_component_p(), HOST_WIDE_INT, integer_zerop(), is_gimple_mem_ref_addr(), is_gimple_min_invariant(), mem_ref_offset(), tidy_after_forward_propagate_addr(), unshare_expr(), update_stmt(), and useless_type_conversion_p().

Referenced by forward_propagate_addr_expr().

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.   

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_next(), gsi_stmt(), integer_onep(), invert_tree_comparison(), is_gimple_assign(), print_gimple_expr(), remove_prop_source_from_use(), unshare_expr(), and update_stmt().

Referenced by ssa_forward_propagate_and_combine().

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.   

References cfg_changed, fold_stmt(), forward_propagate_into_comparison_1(), gimple_assign_lhs(), gimple_assign_rhs1(), gimple_assign_rhs2(), gimple_assign_rhs_code(), gimple_assign_set_rhs_from_tree(), gsi_stmt(), remove_prop_source_from_use(), update_stmt(), and useless_type_conversion_p().

Referenced by ssa_forward_propagate_and_combine().

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.   

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

Referenced by forward_propagate_into_comparison(), forward_propagate_into_cond(), and forward_propagate_into_gimple_cond().

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.   

References build_zero_cst(), cfg_changed, dump_file, forward_propagate_into_comparison_1(), gimple_bb(), gimple_cond_code(), gimple_cond_lhs(), gimple_cond_rhs(), gimple_cond_set_code(), gimple_cond_set_condition_from_tree(), gimple_cond_set_rhs(), integer_onep(), integer_zerop(), is_gimple_min_invariant(), print_generic_expr(), print_gimple_expr(), remove_prop_source_from_use(), tcc_comparison, unshare_expr(), and update_stmt().

Referenced by ssa_forward_propagate_and_combine().

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.   

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

Referenced by forward_propagate_comparison().

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.   

References gimple_assign_rhs1(), gimple_assign_rhs_code(), has_single_use(), and is_gimple_assign().

Referenced by forward_propagate_into_comparison_1(), forward_propagate_into_cond(), simplify_bitfield_ref(), simplify_permutation(), and simplify_vector_constructor().

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.   

Referenced by simplify_bitwise_binary().

static int is_combined_permutation_identity ( )
static
Determine whether applying the 2 permutations (mask1 then mask2)
   gives back one of the input.   

Referenced by simplify_permutation().

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.   

References gimple_assign_rhs1(), gimple_assign_rhs2(), gimple_assign_rhs_code(), integer_onep(), integer_zerop(), is_gimple_assign(), and truth_valued_ssa_name().

Referenced by simplify_bitwise_binary_1().

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.   

References cfg_changed, gimple_assign_rhs1(), gimple_bb(), gimple_has_side_effects(), gimple_purge_dead_eh_edges(), gsi_for_stmt(), gsi_remove(), has_zero_uses(), is_gimple_assign(), release_defs(), and unlink_stmt_vdef().

Referenced by combine_conversions(), forward_propagate_comparison(), forward_propagate_into_comparison(), forward_propagate_into_gimple_cond(), and simplify_permutation().

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 get_gimple_rhs_class(), gimple_assign_rhs1(), gimple_assign_rhs2(), gimple_assign_rhs3(), gimple_assign_rhs_code(), GIMPLE_BINARY_RHS, gimple_location(), GIMPLE_SINGLE_RHS, GIMPLE_TERNARY_RHS, and GIMPLE_UNARY_RHS.

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

References lookup_logical_inverted_value(), and truth_valued_ssa_name().

Referenced by simplify_bitwise_binary().

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

Referenced by simplify_bitwise_binary().

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.   

References build_low_bits_mask(), gimple_assign_lhs(), gimple_assign_rhs1(), gimple_assign_rhs2(), gimple_assign_rhs_code(), gimple_assign_set_rhs1(), gsi_for_stmt(), gsi_remove(), gsi_stmt(), has_single_use(), is_gimple_assign(), operand_equal_p(), release_defs(), si, and update_stmt().

Referenced by ssa_forward_propagate_and_combine().

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.   

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

Referenced by ssa_forward_propagate_and_combine().

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.   

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

Referenced by ssa_forward_propagate_and_combine().

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.   

References defcodefor_name(), floor_log2(), g, gimple_assign_lhs(), gimple_assign_rhs1(), gimple_assign_rhs2(), gimple_assign_rhs_code(), gimple_build_assign_with_ops(), gsi_insert_before(), gsi_replace(), GSI_SAME_STMT, gsi_stmt(), has_single_use(), host_integerp(), HOST_WIDE_INT, make_ssa_name(), tree_low_cst(), and useless_type_conversion_p().

Referenced by ssa_forward_propagate_and_combine().

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.   

References cfg_changed, gimple_assign_rhs1(), gimple_purge_dead_eh_edges(), maybe_clean_or_replace_eh_stmt(), and recompute_tree_invariant_for_addr_expr().

Referenced by forward_propagate_addr_expr_1().

static bool truth_valued_ssa_name ( )
static
Checks if expression has type of one-bit precision, or is a known
   truth-valued expression.   

References gimple_assign_rhs_code(), is_gimple_assign(), and truth_value_p().

Referenced by lookup_logical_inverted_value(), and simplify_bitwise_binary_1().


Variable Documentation