/* Forward propagation of expressions for single use variables.
- Copyright (C) 2004, 2005 Free Software Foundation, Inc.
+ Copyright (C) 2004, 2005, 2007 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 2, or (at your option)
+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,
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 COPYING. If not, write to
-the Free Software Foundation, 51 Franklin Street, Fifth Floor,
-Boston, MA 02110-1301, USA. */
+along with GCC; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>. */
#include "config.h"
#include "system.h"
{
tree rhs = GIMPLE_STMT_OPERAND (def_stmt, 1);
+ /* If the rhs has side-effects we cannot propagate from it. */
+ if (TREE_SIDE_EFFECTS (rhs))
+ return false;
+
+ /* If the rhs is a load we cannot propagate from it. */
+ if (REFERENCE_CLASS_P (rhs))
+ return false;
+
/* We cannot propagate ssa names that occur in abnormal phi nodes. */
switch (TREE_CODE_LENGTH (TREE_CODE (rhs)))
{
/* Require that we got a boolean type out if we put one in. */
gcc_assert (TREE_CODE (TREE_TYPE (t)) == TREE_CODE (type));
- /* For (bool)x use x != 0. */
- if (TREE_CODE (t) == NOP_EXPR
- && TREE_TYPE (t) == boolean_type_node)
- {
- tree top0 = TREE_OPERAND (t, 0);
- t = build2 (NE_EXPR, type,
- top0, build_int_cst (TREE_TYPE (top0), 0));
- }
- /* For !x use x == 0. */
- else if (TREE_CODE (t) == TRUTH_NOT_EXPR)
- {
- tree top0 = TREE_OPERAND (t, 0);
- t = build2 (EQ_EXPR, type,
- top0, build_int_cst (TREE_TYPE (top0), 0));
- }
- /* For cmp ? 1 : 0 use cmp. */
- else if (TREE_CODE (t) == COND_EXPR
- && COMPARISON_CLASS_P (TREE_OPERAND (t, 0))
- && integer_onep (TREE_OPERAND (t, 1))
- && integer_zerop (TREE_OPERAND (t, 2)))
- {
- tree top0 = TREE_OPERAND (t, 0);
- t = build2 (TREE_CODE (top0), type,
- TREE_OPERAND (top0, 0), TREE_OPERAND (top0, 1));
- }
+ /* Canonicalize the combined condition for use in a COND_EXPR. */
+ t = canonicalize_cond_expr_cond (t);
/* Bail out if we required an invariant but didn't get one. */
- if (invariant_only
- && !is_gimple_min_invariant (t))
+ if (!t
+ || (invariant_only
+ && !is_gimple_min_invariant (t)))
return NULL_TREE;
- /* A valid conditional for a COND_EXPR is either a gimple value
- or a comparison with two gimple value operands. */
- if (is_gimple_val (t)
- || (COMPARISON_CLASS_P (t)
- && is_gimple_val (TREE_OPERAND (t, 0))
- && is_gimple_val (TREE_OPERAND (t, 1))))
- return t;
-
- return NULL_TREE;
+ return t;
}
/* Propagate from the ssa name definition statements of COND_EXPR
do {
tree tmp = NULL_TREE;
tree cond = COND_EXPR_COND (cond_expr);
- tree name, def_stmt, rhs;
- bool single_use_p;
+ tree name, def_stmt, rhs0 = NULL_TREE, rhs1 = NULL_TREE;
+ bool single_use0_p = false, single_use1_p = false;
/* We can do tree combining on SSA_NAME and comparison expressions. */
if (COMPARISON_CLASS_P (cond)
/* For comparisons use the first operand, that is likely to
simplify comparisons against constants. */
name = TREE_OPERAND (cond, 0);
- def_stmt = get_prop_source_stmt (name, false, &single_use_p);
+ def_stmt = get_prop_source_stmt (name, false, &single_use0_p);
if (def_stmt != NULL_TREE
&& can_propagate_from (def_stmt))
{
tree op1 = TREE_OPERAND (cond, 1);
- rhs = GIMPLE_STMT_OPERAND (def_stmt, 1);
+ rhs0 = GIMPLE_STMT_OPERAND (def_stmt, 1);
tmp = combine_cond_expr_cond (TREE_CODE (cond), boolean_type_node,
- fold_convert (TREE_TYPE (op1), rhs),
- op1, !single_use_p);
+ fold_convert (TREE_TYPE (op1), rhs0),
+ op1, !single_use0_p);
}
/* If that wasn't successful, try the second operand. */
if (tmp == NULL_TREE
{
tree op0 = TREE_OPERAND (cond, 0);
name = TREE_OPERAND (cond, 1);
- def_stmt = get_prop_source_stmt (name, false, &single_use_p);
+ def_stmt = get_prop_source_stmt (name, false, &single_use1_p);
if (def_stmt == NULL_TREE
|| !can_propagate_from (def_stmt))
return did_something;
- rhs = GIMPLE_STMT_OPERAND (def_stmt, 1);
+ rhs1 = GIMPLE_STMT_OPERAND (def_stmt, 1);
tmp = combine_cond_expr_cond (TREE_CODE (cond), boolean_type_node,
op0,
- fold_convert (TREE_TYPE (op0), rhs),
- !single_use_p);
+ fold_convert (TREE_TYPE (op0), rhs1),
+ !single_use1_p);
}
+ /* If that wasn't successful either, try both operands. */
+ if (tmp == NULL_TREE
+ && rhs0 != NULL_TREE
+ && rhs1 != NULL_TREE)
+ tmp = combine_cond_expr_cond (TREE_CODE (cond), boolean_type_node,
+ rhs0,
+ fold_convert (TREE_TYPE (rhs0), rhs1),
+ !(single_use0_p && single_use1_p));
}
else if (TREE_CODE (cond) == SSA_NAME)
{
|| !can_propagate_from (def_stmt))
return did_something;
- rhs = GIMPLE_STMT_OPERAND (def_stmt, 1);
- tmp = combine_cond_expr_cond (NE_EXPR, boolean_type_node, rhs,
- build_int_cst (TREE_TYPE (rhs), 0),
+ rhs0 = GIMPLE_STMT_OPERAND (def_stmt, 1);
+ tmp = combine_cond_expr_cond (NE_EXPR, boolean_type_node, rhs0,
+ build_int_cst (TREE_TYPE (rhs0), 0),
false);
}
&& rhs == name)
|| ((TREE_CODE (rhs) == NOP_EXPR
|| TREE_CODE (rhs) == CONVERT_EXPR)
- && tree_ssa_useless_type_conversion_1 (TREE_TYPE (rhs),
- TREE_TYPE (def_rhs))))
+ && useless_type_conversion_p (TREE_TYPE (rhs),
+ TREE_TYPE (def_rhs))))
return forward_propagate_addr_expr (lhs, def_rhs);
/* Strip away any outer COMPONENT_REF, ARRAY_REF or ADDR_EXPR
&& TREE_CODE (TREE_OPERAND (rhs, 1)) == SSA_NAME
/* Avoid problems with IVopts creating PLUS_EXPRs with a
different type than their operands. */
- && lang_hooks.types_compatible_p (TREE_TYPE (name), TREE_TYPE (rhs)))
+ && useless_type_conversion_p (TREE_TYPE (rhs), TREE_TYPE (name)))
{
bool res;
continue;
}
- /* If the use_stmt has side-effects, don't propagate into it. */
- if (stmt_ann (use_stmt)->has_volatile_ops)
- {
- all = false;
- continue;
- }
-
push_stmt_changes (&use_stmt);
result = forward_propagate_addr_expr_1 (name, rhs, use_stmt,
did_something = forward_propagate_into_cond (stmt, stmt);
if (did_something == 2)
cfg_changed = true;
- fold_undefer_overflow_warnings (!TREE_NO_WARNING (stmt)
- && did_something, stmt,
+ fold_undefer_overflow_warnings (did_something, stmt,
WARN_STRICT_OVERFLOW_CONDITIONAL);
bsi_next (&bsi);
}