/* Combining of if-expressions on trees.
- Copyright (C) 2007, 2008 Free Software Foundation, Inc.
+ Copyright (C) 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
Contributed by Richard Guenther <rguenther@suse.de>
This file is part of GCC.
#include "tree.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"
{
gimple stmt = gsi_stmt (gsi);
- if (gimple_has_volatile_ops (stmt)
+ if (gimple_has_side_effects (stmt)
|| gimple_vuse (stmt))
return false;
}
{
gimple def_stmt = SSA_NAME_DEF_STMT (candidate);
if (is_gimple_assign (def_stmt)
- && gimple_assign_cast_p (def_stmt))
+ && CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (def_stmt)))
{
if (TYPE_PRECISION (TREE_TYPE (candidate))
<= TYPE_PRECISION (TREE_TYPE (gimple_assign_rhs1 (def_stmt))))
return candidate;
}
-/* Helpers for recognize_single_bit_test defined mainly for source code
- formating. */
-
-static int
-operand_precision (tree t)
-{
- return TYPE_PRECISION (TREE_TYPE (t));
-}
-
-static bool
-integral_operand_p (tree t)
-{
- return INTEGRAL_TYPE_P (TREE_TYPE (t));
-}
-
/* Recognize a single bit test pattern in GIMPLE_COND and its defining
statements. Store the name being tested in *NAME and the bit
in *BIT. The GIMPLE_COND computes *NAME & (1 << *BIT).
stmt = SSA_NAME_DEF_STMT (orig_name);
while (is_gimple_assign (stmt)
- && (gimple_assign_ssa_name_copy_p (stmt)
- || (gimple_assign_cast_p (stmt)
- && integral_operand_p (gimple_assign_lhs (stmt))
- && integral_operand_p (gimple_assign_rhs1 (stmt))
- && (operand_precision (gimple_assign_lhs (stmt))
- <= operand_precision (gimple_assign_rhs1 (stmt))))))
- {
- stmt = SSA_NAME_DEF_STMT (gimple_assign_rhs1 (stmt));
- }
+ && ((CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (stmt))
+ && (TYPE_PRECISION (TREE_TYPE (gimple_assign_lhs (stmt)))
+ <= TYPE_PRECISION (TREE_TYPE (gimple_assign_rhs1 (stmt)))))
+ || gimple_assign_ssa_name_copy_p (stmt)))
+ stmt = SSA_NAME_DEF_STMT (gimple_assign_rhs1 (stmt));
/* If we found such, decompose it. */
if (is_gimple_assign (stmt)
t2 = force_gimple_operand_gsi (&gsi, t2, true, NULL_TREE,
true, GSI_SAME_STMT);
t = fold_build2 (EQ_EXPR, boolean_type_node, t2, t);
+ t = canonicalize_cond_expr_cond (t);
+ if (!t)
+ return false;
gimple_cond_set_condition_from_tree (inner_cond, t);
update_stmt (inner_cond);
/* See if we have two comparisons that we can merge into one. */
else if (TREE_CODE_CLASS (gimple_cond_code (inner_cond)) == tcc_comparison
- && TREE_CODE_CLASS (gimple_cond_code (outer_cond)) == tcc_comparison
- && operand_equal_p (gimple_cond_lhs (inner_cond),
- gimple_cond_lhs (outer_cond), 0)
- && operand_equal_p (gimple_cond_rhs (inner_cond),
- gimple_cond_rhs (outer_cond), 0))
+ && TREE_CODE_CLASS (gimple_cond_code (outer_cond)) == tcc_comparison)
{
- enum tree_code code1 = gimple_cond_code (inner_cond);
- enum tree_code code2 = gimple_cond_code (outer_cond);
tree t;
- if (!(t = combine_comparisons (TRUTH_ANDIF_EXPR, code1, code2,
- boolean_type_node,
- gimple_cond_lhs (outer_cond),
- gimple_cond_rhs (outer_cond))))
+ if (!(t = maybe_fold_and_comparisons (gimple_cond_code (inner_cond),
+ gimple_cond_lhs (inner_cond),
+ gimple_cond_rhs (inner_cond),
+ gimple_cond_code (outer_cond),
+ gimple_cond_lhs (outer_cond),
+ gimple_cond_rhs (outer_cond))))
return false;
t = canonicalize_cond_expr_cond (t);
if (!t)
true, GSI_SAME_STMT);
t = fold_build2 (NE_EXPR, boolean_type_node, t,
build_int_cst (TREE_TYPE (t), 0));
+ t = canonicalize_cond_expr_cond (t);
+ if (!t)
+ return false;
gimple_cond_set_condition_from_tree (inner_cond, t);
update_stmt (inner_cond);
/* See if we have two comparisons that we can merge into one.
This happens for C++ operator overloading where for example
GE_EXPR is implemented as GT_EXPR || EQ_EXPR. */
- else if (TREE_CODE_CLASS (gimple_cond_code (inner_cond)) == tcc_comparison
- && TREE_CODE_CLASS (gimple_cond_code (outer_cond)) == tcc_comparison
- && operand_equal_p (gimple_cond_lhs (inner_cond),
- gimple_cond_lhs (outer_cond), 0)
- && operand_equal_p (gimple_cond_rhs (inner_cond),
- gimple_cond_rhs (outer_cond), 0))
+ else if (TREE_CODE_CLASS (gimple_cond_code (inner_cond)) == tcc_comparison
+ && TREE_CODE_CLASS (gimple_cond_code (outer_cond)) == tcc_comparison)
{
- enum tree_code code1 = gimple_cond_code (inner_cond);
- enum tree_code code2 = gimple_cond_code (outer_cond);
tree t;
- if (!(t = combine_comparisons (TRUTH_ORIF_EXPR, code1, code2,
- boolean_type_node,
- gimple_cond_lhs (outer_cond),
- gimple_cond_rhs (outer_cond))))
+ if (!(t = maybe_fold_or_comparisons (gimple_cond_code (inner_cond),
+ gimple_cond_lhs (inner_cond),
+ gimple_cond_rhs (inner_cond),
+ gimple_cond_code (outer_cond),
+ gimple_cond_lhs (outer_cond),
+ gimple_cond_rhs (outer_cond))))
return false;
t = canonicalize_cond_expr_cond (t);
if (!t)
int i;
bbs = blocks_in_phiopt_order ();
+ calculate_dominance_info (CDI_DOMINATORS);
for (i = 0; i < n_basic_blocks - NUM_FIXED_BLOCKS; ++i)
{
return 1;
}
-struct gimple_opt_pass pass_tree_ifcombine =
+struct gimple_opt_pass pass_tree_ifcombine =
{
{
GIMPLE_PASS,
0, /* properties_provided */
0, /* properties_destroyed */
0, /* todo_flags_start */
- TODO_dump_func
- | TODO_ggc_collect
+ TODO_ggc_collect
| TODO_update_ssa
| TODO_verify_ssa /* todo_flags_finish */
}