Index: gcc/gcc/tree-ssa-ifcombine.c |
diff --git a/gcc/gcc/tree-ssa-ifcombine.c b/gcc/gcc/tree-ssa-ifcombine.c |
index 55b042e5ccc755c9c173d3e3714b454b34349b96..af9b15421bed2cbc66d59a259dfb6bcd77a6900c 100644 |
--- a/gcc/gcc/tree-ssa-ifcombine.c |
+++ b/gcc/gcc/tree-ssa-ifcombine.c |
@@ -108,7 +108,7 @@ bb_no_side_effects_p (basic_block bb) |
gimple stmt = gsi_stmt (gsi); |
if (gimple_has_volatile_ops (stmt) |
- || !ZERO_SSA_OPERANDS (stmt, SSA_OP_ALL_VIRTUALS)) |
+ || gimple_vuse (stmt)) |
return false; |
} |
@@ -340,6 +340,9 @@ ifcombine_ifandif (basic_block inner_cond_bb, basic_block outer_cond_bb) |
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); |
@@ -361,6 +364,44 @@ ifcombine_ifandif (basic_block inner_cond_bb, basic_block outer_cond_bb) |
return true; |
} |
+ /* 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)) |
+ { |
+ enum tree_code code1 = gimple_cond_code (inner_cond); |
+ enum tree_code code2 = gimple_cond_code (outer_cond); |
+ tree t; |
+ |
+ if (!(t = combine_comparisons (UNKNOWN_LOCATION, |
+ TRUTH_ANDIF_EXPR, code1, code2, |
+ boolean_type_node, |
+ gimple_cond_lhs (outer_cond), |
+ gimple_cond_rhs (outer_cond)))) |
+ return false; |
+ t = canonicalize_cond_expr_cond (t); |
+ if (!t) |
+ return false; |
+ gimple_cond_set_condition_from_tree (inner_cond, t); |
+ update_stmt (inner_cond); |
+ |
+ /* Leave CFG optimization to cfg_cleanup. */ |
+ gimple_cond_set_condition_from_tree (outer_cond, boolean_true_node); |
+ update_stmt (outer_cond); |
+ |
+ if (dump_file) |
+ { |
+ fprintf (dump_file, "optimizing two comparisons to "); |
+ print_generic_expr (dump_file, t, 0); |
+ fprintf (dump_file, "\n"); |
+ } |
+ |
+ return true; |
+ } |
+ |
return false; |
} |
@@ -450,6 +491,9 @@ ifcombine_iforif (basic_block inner_cond_bb, basic_block outer_cond_bb) |
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); |
@@ -483,42 +527,14 @@ ifcombine_iforif (basic_block inner_cond_bb, basic_block outer_cond_bb) |
{ |
enum tree_code code1 = gimple_cond_code (inner_cond); |
enum tree_code code2 = gimple_cond_code (outer_cond); |
- enum tree_code code; |
tree t; |
-#define CHK(a,b) ((code1 == a ## _EXPR && code2 == b ## _EXPR) \ |
- || (code2 == a ## _EXPR && code1 == b ## _EXPR)) |
- /* Merge the two condition codes if possible. */ |
- if (code1 == code2) |
- code = code1; |
- else if (CHK (EQ, LT)) |
- code = LE_EXPR; |
- else if (CHK (EQ, GT)) |
- code = GE_EXPR; |
- else if (CHK (LT, LE)) |
- code = LE_EXPR; |
- else if (CHK (GT, GE)) |
- code = GE_EXPR; |
- else if (INTEGRAL_TYPE_P (TREE_TYPE (gimple_cond_lhs (inner_cond))) |
- || flag_unsafe_math_optimizations) |
- { |
- if (CHK (LT, GT)) |
- code = NE_EXPR; |
- else if (CHK (LT, NE)) |
- code = NE_EXPR; |
- else if (CHK (GT, NE)) |
- code = NE_EXPR; |
- else |
- return false; |
- } |
- /* We could check for combinations leading to trivial true/false. */ |
- else |
+ if (!(t = combine_comparisons (UNKNOWN_LOCATION, |
+ TRUTH_ORIF_EXPR, code1, code2, |
+ boolean_type_node, |
+ gimple_cond_lhs (outer_cond), |
+ gimple_cond_rhs (outer_cond)))) |
return false; |
-#undef CHK |
- |
- /* Do it. */ |
- t = fold_build2 (code, boolean_type_node, gimple_cond_lhs (outer_cond), |
- gimple_cond_rhs (outer_cond)); |
t = canonicalize_cond_expr_cond (t); |
if (!t) |
return false; |
@@ -641,7 +657,7 @@ gate_ifcombine (void) |
return 1; |
} |
-struct gimple_opt_pass pass_tree_ifcombine = |
+struct gimple_opt_pass pass_tree_ifcombine = |
{ |
{ |
GIMPLE_PASS, |