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:
parent
a8ee227c04
commit
a254e44de7
|
@ -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.
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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" } } */
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue