re PR tree-optimization/37795 (if-combine doesn't optimize != after >= test)

2009-03-28  Richard Guenther  <rguenther@suse.de>

	PR tree-optimization/37795
	* tree.h (combine_comparisons): Declare.
	* fold-const.c (combine_comparisons): Export.
	* tree-ssa-ifcombine.c (ifcombine_ifandif): Optimize two successive
	comparisons.
	(ifcombine_iforif): Use combine_comparisons.

	* gcc.dg/tree-ssa/ssa-ifcombine-7.c: New testcase.

From-SVN: r145170
This commit is contained in:
Richard Guenther 2009-03-28 10:01:56 +00:00 committed by Richard Biener
parent a8ee227c04
commit a254e44de7
6 changed files with 72 additions and 35 deletions

View File

@ -1,3 +1,12 @@
2009-03-28 Richard Guenther <rguenther@suse.de>
PR tree-optimization/37795
* tree.h (combine_comparisons): Declare.
* fold-const.c (combine_comparisons): Export.
* tree-ssa-ifcombine.c (ifcombine_ifandif): Optimize two successive
comparisons.
(ifcombine_iforif): Use combine_comparisons.
2009-03-28 Jan Hubicka <jh@suse.cz>
* tree-eh.c (inlinable_call_p): New function.

View File

@ -103,8 +103,6 @@ static tree associate_trees (tree, tree, enum tree_code, tree);
static tree const_binop (enum tree_code, tree, tree, int);
static enum comparison_code comparison_to_compcode (enum tree_code);
static enum tree_code compcode_to_comparison (enum comparison_code);
static tree combine_comparisons (enum tree_code, enum tree_code,
enum tree_code, tree, tree, tree);
static int operand_equal_for_comparison_p (tree, tree, tree);
static int twoval_comparison_p (tree, tree *, tree *, int *);
static tree eval_subst (tree, tree, tree, tree, tree);

View File

@ -1,3 +1,8 @@
2009-03-28 Richard Guenther <rguenther@suse.de>
PR tree-optimization/37795
* gcc.dg/tree-ssa/ssa-ifcombine-7.c: New testcase.
2009-03-28 Joseph Myers <joseph@codesourcery.com>
* g++.old-deja/g++.ext/attrib5.C, g++.old-deja/g++.jason/thunk3.C,

View File

@ -0,0 +1,15 @@
/* { dg-do compile } */
/* { dg-options "-O -fdump-tree-optimized" } */
int test1 (int i, int j)
{
if (i >= j)
if (i != j)
return 0;
return -1;
}
/* The above should be optimized to a i > j test by ifcombine. */
/* { dg-final { scan-tree-dump " > " "optimized" } } */
/* { dg-final { cleanup-tree-dump "optimized" } } */

View File

@ -380,6 +380,43 @@ 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 (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;
}
@ -502,42 +539,13 @@ 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 (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;

View File

@ -4853,6 +4853,8 @@ extern bool tree_call_nonnegative_warnv_p (tree, tree, tree, tree, bool *);
extern bool tree_expr_nonzero_warnv_p (tree, bool *);
extern bool fold_real_zero_addition_p (const_tree, const_tree, int);
extern tree combine_comparisons (enum tree_code, enum tree_code,
enum tree_code, tree, tree, tree);
/* Return nonzero if CODE is a tree code that represents a truth value. */
static inline bool