aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorRichard Guenther <rguenther@suse.de>2009-03-28 10:01:56 +0000
committerRichard Biener <rguenth@gcc.gnu.org>2009-03-28 10:01:56 +0000
commita254e44de7e7f417e3cdff485b27396e6bb16650 (patch)
tree41f27c9d3a60891996ed9cd47be2243a484783fc /gcc
parenta8ee227c046930794867e48c6478b0b04e3bd137 (diff)
downloadgcc-a254e44de7e7f417e3cdff485b27396e6bb16650.zip
gcc-a254e44de7e7f417e3cdff485b27396e6bb16650.tar.gz
gcc-a254e44de7e7f417e3cdff485b27396e6bb16650.tar.bz2
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
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog9
-rw-r--r--gcc/fold-const.c2
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/ssa-ifcombine-7.c15
-rw-r--r--gcc/tree-ssa-ifcombine.c74
-rw-r--r--gcc/tree.h2
6 files changed, 72 insertions, 35 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index f327b67..738e7db 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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.
diff --git a/gcc/fold-const.c b/gcc/fold-const.c
index 4ca91a2..2dbca3f 100644
--- a/gcc/fold-const.c
+++ b/gcc/fold-const.c
@@ -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);
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 0ea9d9b..41e5d70 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -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,
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-ifcombine-7.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-ifcombine-7.c
new file mode 100644
index 0000000..fd20250
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-ifcombine-7.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" } } */
diff --git a/gcc/tree-ssa-ifcombine.c b/gcc/tree-ssa-ifcombine.c
index 335fd06..0804856 100644
--- a/gcc/tree-ssa-ifcombine.c
+++ b/gcc/tree-ssa-ifcombine.c
@@ -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;
diff --git a/gcc/tree.h b/gcc/tree.h
index 51fd7ec..9ff30a3 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -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