/* Forward propagation of expressions for single use variables.
- Copyright (C) 2004, 2005, 2007, 2008, 2009 Free Software Foundation, Inc.
+ Copyright (C) 2004, 2005, 2007, 2008, 2009, 2010
+ Free Software Foundation, Inc.
This file is part of GCC.
#include "system.h"
#include "coretypes.h"
#include "tm.h"
-#include "ggc.h"
#include "tree.h"
-#include "rtl.h"
#include "tm_p.h"
#include "basic-block.h"
#include "timevar.h"
#include "diagnostic.h"
+#include "tree-pretty-print.h"
#include "tree-flow.h"
#include "tree-pass.h"
#include "tree-dump.h"
do {
tree tmp = NULL_TREE;
- tree name, rhs0 = NULL_TREE, rhs1 = NULL_TREE;
+ tree name = NULL_TREE, rhs0 = NULL_TREE, rhs1 = NULL_TREE;
gimple def_stmt;
bool single_use0_p = false, single_use1_p = false;
enum tree_code code = gimple_cond_code (stmt);
/* We can do tree combining on SSA_NAME and comparison expressions. */
- if (TREE_CODE_CLASS (gimple_cond_code (stmt)) == tcc_comparison
- && TREE_CODE (gimple_cond_lhs (stmt)) == SSA_NAME)
+ if (TREE_CODE_CLASS (gimple_cond_code (stmt)) == tcc_comparison)
{
/* For comparisons use the first operand, that is likely to
simplify comparisons against constants. */
- name = gimple_cond_lhs (stmt);
- def_stmt = get_prop_source_stmt (name, false, &single_use0_p);
- if (def_stmt && can_propagate_from (def_stmt))
+ if (TREE_CODE (gimple_cond_lhs (stmt)) == SSA_NAME)
{
- tree op1 = gimple_cond_rhs (stmt);
- rhs0 = rhs_to_tree (TREE_TYPE (op1), def_stmt);
- tmp = combine_cond_expr_cond (loc, code, boolean_type_node, rhs0,
- op1, !single_use0_p);
+ name = gimple_cond_lhs (stmt);
+ def_stmt = get_prop_source_stmt (name, false, &single_use0_p);
+ if (def_stmt && can_propagate_from (def_stmt))
+ {
+ tree op1 = gimple_cond_rhs (stmt);
+ rhs0 = rhs_to_tree (TREE_TYPE (op1), def_stmt);
+ tmp = combine_cond_expr_cond (loc, code, boolean_type_node,
+ rhs0, op1, !single_use0_p);
+ }
}
/* If that wasn't successful, try the second operand. */
if (tmp == NULL_TREE
gimple use_stmt = gsi_stmt (*use_stmt_gsi);
enum tree_code rhs_code;
bool res = true;
+ bool addr_p = false;
gcc_assert (TREE_CODE (def_rhs) == ADDR_EXPR);
/* Strip away any outer COMPONENT_REF, ARRAY_REF or ADDR_EXPR
nodes from the RHS. */
rhsp = gimple_assign_rhs1_ptr (use_stmt);
- while (handled_component_p (*rhsp)
- || TREE_CODE (*rhsp) == ADDR_EXPR)
+ if (TREE_CODE (*rhsp) == ADDR_EXPR)
+ {
+ rhsp = &TREE_OPERAND (*rhsp, 0);
+ addr_p = true;
+ }
+ while (handled_component_p (*rhsp))
rhsp = &TREE_OPERAND (*rhsp, 0);
rhs = *rhsp;
return res;
}
/* If the defining rhs comes from an indirect reference, then do not
- convert into a VIEW_CONVERT_EXPR. */
+ convert into a VIEW_CONVERT_EXPR. Likewise if we'll end up taking
+ the address of a V_C_E of a constant. */
def_rhs_base = TREE_OPERAND (def_rhs, 0);
while (handled_component_p (def_rhs_base))
def_rhs_base = TREE_OPERAND (def_rhs_base, 0);
- if (!INDIRECT_REF_P (def_rhs_base))
+ if (!INDIRECT_REF_P (def_rhs_base)
+ && (!addr_p
+ || !is_gimple_min_invariant (def_rhs)))
{
/* We may have arbitrary VIEW_CONVERT_EXPRs in a nested component
reference. Place it there and fold the thing. */