aboutsummaryrefslogtreecommitdiffstats
path: root/toolchain-layer/recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99306.patch
diff options
context:
space:
mode:
Diffstat (limited to 'toolchain-layer/recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99306.patch')
-rw-r--r--toolchain-layer/recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99306.patch1401
1 files changed, 0 insertions, 1401 deletions
diff --git a/toolchain-layer/recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99306.patch b/toolchain-layer/recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99306.patch
deleted file mode 100644
index 423cd56528..0000000000
--- a/toolchain-layer/recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99306.patch
+++ /dev/null
@@ -1,1401 +0,0 @@
-2010-07-10 Sandra Loosemore <sandra@codesourcery.com>
-
- Backport from mainline:
-
- 2010-05-08 Sandra Loosemore <sandra@codesourcery.com>
-
- PR middle-end/28685
-
- gcc/
- * tree-ssa-reassoc.c (eliminate_redundant_comparison): New function.
- (optimize_ops_list): Call it.
-
- gcc/testsuite/
- * gcc.dg/pr28685-1.c: New file.
-
- 2010-06-08 Sandra Loosemore <sandra@codesourcery.com>
-
- PR tree-optimization/39874
- PR middle-end/28685
-
- gcc/
- * gimple.h (maybe_fold_and_comparisons, maybe_fold_or_comparisons):
- Declare.
- * gimple-fold.c (canonicalize_bool, same_bool_comparison_p,
- same_bool_result_p): New.
- (and_var_with_comparison, and_var_with_comparison_1,
- and_comparisons_1, and_comparisons, maybe_fold_and_comparisons): New.
- (or_var_with_comparison, or_var_with_comparison_1,
- or_comparisons_1, or_comparisons, maybe_fold_or_comparisons): New.
- * tree-ssa-reassoc.c (eliminate_redundant_comparison): Use
- maybe_fold_and_comparisons or maybe_fold_or_comparisons instead
- of combine_comparisons.
- * tree-ssa-ifcombine.c (ifcombine_ifandif, ifcombine_iforif): Likewise.
-
- gcc/testsuite/
- * gcc.dg/pr39874.c: New file.
-
- 2010-07-10 Yao Qi <yao@codesourcery.com>
-
- Merge from Sourcery G++ 4.4:
-
-=== modified file 'gcc/gimple.h'
---- old/gcc/gimple.h 2010-04-02 18:54:46 +0000
-+++ new/gcc/gimple.h 2010-07-30 13:21:51 +0000
-@@ -4743,4 +4743,9 @@
-
- extern void dump_gimple_statistics (void);
-
-+extern tree maybe_fold_and_comparisons (enum tree_code, tree, tree,
-+ enum tree_code, tree, tree);
-+extern tree maybe_fold_or_comparisons (enum tree_code, tree, tree,
-+ enum tree_code, tree, tree);
-+
- #endif /* GCC_GIMPLE_H */
-
-=== added file 'gcc/testsuite/gcc.dg/pr28685-1.c'
---- old/gcc/testsuite/gcc.dg/pr28685-1.c 1970-01-01 00:00:00 +0000
-+++ new/gcc/testsuite/gcc.dg/pr28685-1.c 2010-07-30 13:21:51 +0000
-@@ -0,0 +1,50 @@
-+/* { dg-do compile } */
-+/* { dg-options "-O2 -fdump-tree-optimized" } */
-+
-+/* Should produce <=. */
-+int test1 (int a, int b)
-+{
-+ return (a < b || a == b);
-+}
-+
-+/* Should produce <=. */
-+int test2 (int a, int b)
-+{
-+ int lt = a < b;
-+ int eq = a == b;
-+
-+ return (lt || eq);
-+}
-+
-+/* Should produce <= (just deleting redundant test). */
-+int test3 (int a, int b)
-+{
-+ int lt = a <= b;
-+ int eq = a == b;
-+
-+ return (lt || eq);
-+}
-+
-+/* Should produce <= (operands reversed to test the swap logic). */
-+int test4 (int a, int b)
-+{
-+ int lt = a < b;
-+ int eq = b == a;
-+
-+ return (lt || eq);
-+}
-+
-+/* Should produce constant 0. */
-+int test5 (int a, int b)
-+{
-+ int lt = a < b;
-+ int eq = a == b;
-+
-+ return (lt && eq);
-+}
-+
-+/* { dg-final { scan-tree-dump-times " <= " 4 "optimized" } } */
-+/* { dg-final { scan-tree-dump-times "return 0" 1 "optimized" } } */
-+/* { dg-final { scan-tree-dump-not " < " "optimized" } } */
-+/* { dg-final { scan-tree-dump-not " == " "optimized" } } */
-+/* { dg-final { cleanup-tree-dump "optimized" } } */
-
-=== added file 'gcc/testsuite/gcc.dg/pr39874.c'
---- old/gcc/testsuite/gcc.dg/pr39874.c 1970-01-01 00:00:00 +0000
-+++ new/gcc/testsuite/gcc.dg/pr39874.c 2010-07-30 13:21:51 +0000
-@@ -0,0 +1,29 @@
-+/* { dg-do compile } */
-+/* { dg-options "-O2 -fdump-tree-optimized" } */
-+
-+extern void func();
-+
-+void test1(char *signature)
-+{
-+ char ch = signature[0];
-+ if (ch == 15 || ch == 3)
-+ {
-+ if (ch == 15) func();
-+ }
-+}
-+
-+
-+void test2(char *signature)
-+{
-+ char ch = signature[0];
-+ if (ch == 15 || ch == 3)
-+ {
-+ if (ch > 14) func();
-+ }
-+}
-+
-+/* { dg-final { scan-tree-dump-times " == 15" 2 "optimized" } } */
-+/* { dg-final { scan-tree-dump-not " == 3" "optimized" } } */
-+/* { dg-final { cleanup-tree-dump "optimized" } } */
-+
-+
-
-=== modified file 'gcc/tree-ssa-ccp.c'
---- old/gcc/tree-ssa-ccp.c 2010-04-02 15:50:04 +0000
-+++ new/gcc/tree-ssa-ccp.c 2010-07-30 13:21:51 +0000
-@@ -3176,6 +3176,1056 @@
- return changed;
- }
-
-+/* Canonicalize and possibly invert the boolean EXPR; return NULL_TREE
-+ if EXPR is null or we don't know how.
-+ If non-null, the result always has boolean type. */
-+
-+static tree
-+canonicalize_bool (tree expr, bool invert)
-+{
-+ if (!expr)
-+ return NULL_TREE;
-+ else if (invert)
-+ {
-+ if (integer_nonzerop (expr))
-+ return boolean_false_node;
-+ else if (integer_zerop (expr))
-+ return boolean_true_node;
-+ else if (TREE_CODE (expr) == SSA_NAME)
-+ return fold_build2 (EQ_EXPR, boolean_type_node, expr,
-+ build_int_cst (TREE_TYPE (expr), 0));
-+ else if (TREE_CODE_CLASS (TREE_CODE (expr)) == tcc_comparison)
-+ return fold_build2 (invert_tree_comparison (TREE_CODE (expr), false),
-+ boolean_type_node,
-+ TREE_OPERAND (expr, 0),
-+ TREE_OPERAND (expr, 1));
-+ else
-+ return NULL_TREE;
-+ }
-+ else
-+ {
-+ if (TREE_CODE (TREE_TYPE (expr)) == BOOLEAN_TYPE)
-+ return expr;
-+ if (integer_nonzerop (expr))
-+ return boolean_true_node;
-+ else if (integer_zerop (expr))
-+ return boolean_false_node;
-+ else if (TREE_CODE (expr) == SSA_NAME)
-+ return fold_build2 (NE_EXPR, boolean_type_node, expr,
-+ build_int_cst (TREE_TYPE (expr), 0));
-+ else if (TREE_CODE_CLASS (TREE_CODE (expr)) == tcc_comparison)
-+ return fold_build2 (TREE_CODE (expr),
-+ boolean_type_node,
-+ TREE_OPERAND (expr, 0),
-+ TREE_OPERAND (expr, 1));
-+ else
-+ return NULL_TREE;
-+ }
-+}
-+
-+/* Check to see if a boolean expression EXPR is logically equivalent to the
-+ comparison (OP1 CODE OP2). Check for various identities involving
-+ SSA_NAMEs. */
-+
-+static bool
-+same_bool_comparison_p (const_tree expr, enum tree_code code,
-+ const_tree op1, const_tree op2)
-+{
-+ gimple s;
-+
-+ /* The obvious case. */
-+ if (TREE_CODE (expr) == code
-+ && operand_equal_p (TREE_OPERAND (expr, 0), op1, 0)
-+ && operand_equal_p (TREE_OPERAND (expr, 1), op2, 0))
-+ return true;
-+
-+ /* Check for comparing (name, name != 0) and the case where expr
-+ is an SSA_NAME with a definition matching the comparison. */
-+ if (TREE_CODE (expr) == SSA_NAME
-+ && TREE_CODE (TREE_TYPE (expr)) == BOOLEAN_TYPE)
-+ {
-+ if (operand_equal_p (expr, op1, 0))
-+ return ((code == NE_EXPR && integer_zerop (op2))
-+ || (code == EQ_EXPR && integer_nonzerop (op2)));
-+ s = SSA_NAME_DEF_STMT (expr);
-+ if (is_gimple_assign (s)
-+ && gimple_assign_rhs_code (s) == code
-+ && operand_equal_p (gimple_assign_rhs1 (s), op1, 0)
-+ && operand_equal_p (gimple_assign_rhs2 (s), op2, 0))
-+ return true;
-+ }
-+
-+ /* If op1 is of the form (name != 0) or (name == 0), and the definition
-+ of name is a comparison, recurse. */
-+ if (TREE_CODE (op1) == SSA_NAME
-+ && TREE_CODE (TREE_TYPE (op1)) == BOOLEAN_TYPE)
-+ {
-+ s = SSA_NAME_DEF_STMT (op1);
-+ if (is_gimple_assign (s)
-+ && TREE_CODE_CLASS (gimple_assign_rhs_code (s)) == tcc_comparison)
-+ {
-+ enum tree_code c = gimple_assign_rhs_code (s);
-+ if ((c == NE_EXPR && integer_zerop (op2))
-+ || (c == EQ_EXPR && integer_nonzerop (op2)))
-+ return same_bool_comparison_p (expr, c,
-+ gimple_assign_rhs1 (s),
-+ gimple_assign_rhs2 (s));
-+ if ((c == EQ_EXPR && integer_zerop (op2))
-+ || (c == NE_EXPR && integer_nonzerop (op2)))
-+ return same_bool_comparison_p (expr,
-+ invert_tree_comparison (c, false),
-+ gimple_assign_rhs1 (s),
-+ gimple_assign_rhs2 (s));
-+ }
-+ }
-+ return false;
-+}
-+
-+/* Check to see if two boolean expressions OP1 and OP2 are logically
-+ equivalent. */
-+
-+static bool
-+same_bool_result_p (const_tree op1, const_tree op2)
-+{
-+ /* Simple cases first. */
-+ if (operand_equal_p (op1, op2, 0))
-+ return true;
-+
-+ /* Check the cases where at least one of the operands is a comparison.
-+ These are a bit smarter than operand_equal_p in that they apply some
-+ identifies on SSA_NAMEs. */
-+ if (TREE_CODE_CLASS (TREE_CODE (op2)) == tcc_comparison
-+ && same_bool_comparison_p (op1, TREE_CODE (op2),
-+ TREE_OPERAND (op2, 0),
-+ TREE_OPERAND (op2, 1)))
-+ return true;
-+ if (TREE_CODE_CLASS (TREE_CODE (op1)) == tcc_comparison
-+ && same_bool_comparison_p (op2, TREE_CODE (op1),
-+ TREE_OPERAND (op1, 0),
-+ TREE_OPERAND (op1, 1)))
-+ return true;
-+
-+ /* Default case. */
-+ return false;
-+}
-+
-+/* Forward declarations for some mutually recursive functions. */
-+
-+static tree
-+and_comparisons_1 (enum tree_code code1, tree op1a, tree op1b,
-+ enum tree_code code2, tree op2a, tree op2b);
-+static tree
-+and_var_with_comparison (tree var, bool invert,
-+ enum tree_code code2, tree op2a, tree op2b);
-+static tree
-+and_var_with_comparison_1 (gimple stmt,
-+ enum tree_code code2, tree op2a, tree op2b);
-+static tree
-+or_comparisons_1 (enum tree_code code1, tree op1a, tree op1b,
-+ enum tree_code code2, tree op2a, tree op2b);
-+static tree
-+or_var_with_comparison (tree var, bool invert,
-+ enum tree_code code2, tree op2a, tree op2b);
-+static tree
-+or_var_with_comparison_1 (gimple stmt,
-+ enum tree_code code2, tree op2a, tree op2b);
-+
-+/* Helper function for and_comparisons_1: try to simplify the AND of the
-+ ssa variable VAR with the comparison specified by (OP2A CODE2 OP2B).
-+ If INVERT is true, invert the value of the VAR before doing the AND.
-+ Return NULL_EXPR if we can't simplify this to a single expression. */
-+
-+static tree
-+and_var_with_comparison (tree var, bool invert,
-+ enum tree_code code2, tree op2a, tree op2b)
-+{
-+ tree t;
-+ gimple stmt = SSA_NAME_DEF_STMT (var);
-+
-+ /* We can only deal with variables whose definitions are assignments. */
-+ if (!is_gimple_assign (stmt))
-+ return NULL_TREE;
-+
-+ /* If we have an inverted comparison, apply DeMorgan's law and rewrite
-+ !var AND (op2a code2 op2b) => !(var OR !(op2a code2 op2b))
-+ Then we only have to consider the simpler non-inverted cases. */
-+ if (invert)
-+ t = or_var_with_comparison_1 (stmt,
-+ invert_tree_comparison (code2, false),
-+ op2a, op2b);
-+ else
-+ t = and_var_with_comparison_1 (stmt, code2, op2a, op2b);
-+ return canonicalize_bool (t, invert);
-+}
-+
-+/* Try to simplify the AND of the ssa variable defined by the assignment
-+ STMT with the comparison specified by (OP2A CODE2 OP2B).
-+ Return NULL_EXPR if we can't simplify this to a single expression. */
-+
-+static tree
-+and_var_with_comparison_1 (gimple stmt,
-+ enum tree_code code2, tree op2a, tree op2b)
-+{
-+ tree var = gimple_assign_lhs (stmt);
-+ tree true_test_var = NULL_TREE;
-+ tree false_test_var = NULL_TREE;
-+ enum tree_code innercode = gimple_assign_rhs_code (stmt);
-+
-+ /* Check for identities like (var AND (var == 0)) => false. */
-+ if (TREE_CODE (op2a) == SSA_NAME
-+ && TREE_CODE (TREE_TYPE (var)) == BOOLEAN_TYPE)
-+ {
-+ if ((code2 == NE_EXPR && integer_zerop (op2b))
-+ || (code2 == EQ_EXPR && integer_nonzerop (op2b)))
-+ {
-+ true_test_var = op2a;
-+ if (var == true_test_var)
-+ return var;
-+ }
-+ else if ((code2 == EQ_EXPR && integer_zerop (op2b))
-+ || (code2 == NE_EXPR && integer_nonzerop (op2b)))
-+ {
-+ false_test_var = op2a;
-+ if (var == false_test_var)
-+ return boolean_false_node;
-+ }
-+ }
-+
-+ /* If the definition is a comparison, recurse on it. */
-+ if (TREE_CODE_CLASS (innercode) == tcc_comparison)
-+ {
-+ tree t = and_comparisons_1 (innercode,
-+ gimple_assign_rhs1 (stmt),
-+ gimple_assign_rhs2 (stmt),
-+ code2,
-+ op2a,
-+ op2b);
-+ if (t)
-+ return t;
-+ }
-+
-+ /* If the definition is an AND or OR expression, we may be able to
-+ simplify by reassociating. */
-+ if (innercode == TRUTH_AND_EXPR
-+ || innercode == TRUTH_OR_EXPR
-+ || (TREE_CODE (TREE_TYPE (var)) == BOOLEAN_TYPE
-+ && (innercode == BIT_AND_EXPR || innercode == BIT_IOR_EXPR)))
-+ {
-+ tree inner1 = gimple_assign_rhs1 (stmt);
-+ tree inner2 = gimple_assign_rhs2 (stmt);
-+ gimple s;
-+ tree t;
-+ tree partial = NULL_TREE;
-+ bool is_and = (innercode == TRUTH_AND_EXPR || innercode == BIT_AND_EXPR);
-+
-+ /* Check for boolean identities that don't require recursive examination
-+ of inner1/inner2:
-+ inner1 AND (inner1 AND inner2) => inner1 AND inner2 => var
-+ inner1 AND (inner1 OR inner2) => inner1
-+ !inner1 AND (inner1 AND inner2) => false
-+ !inner1 AND (inner1 OR inner2) => !inner1 AND inner2
-+ Likewise for similar cases involving inner2. */
-+ if (inner1 == true_test_var)
-+ return (is_and ? var : inner1);
-+ else if (inner2 == true_test_var)
-+ return (is_and ? var : inner2);
-+ else if (inner1 == false_test_var)
-+ return (is_and
-+ ? boolean_false_node
-+ : and_var_with_comparison (inner2, false, code2, op2a, op2b));
-+ else if (inner2 == false_test_var)
-+ return (is_and
-+ ? boolean_false_node
-+ : and_var_with_comparison (inner1, false, code2, op2a, op2b));
-+
-+ /* Next, redistribute/reassociate the AND across the inner tests.
-+ Compute the first partial result, (inner1 AND (op2a code op2b)) */
-+ if (TREE_CODE (inner1) == SSA_NAME
-+ && is_gimple_assign (s = SSA_NAME_DEF_STMT (inner1))
-+ && TREE_CODE_CLASS (gimple_assign_rhs_code (s)) == tcc_comparison
-+ && (t = maybe_fold_and_comparisons (gimple_assign_rhs_code (s),
-+ gimple_assign_rhs1 (s),
-+ gimple_assign_rhs2 (s),
-+ code2, op2a, op2b)))
-+ {
-+ /* Handle the AND case, where we are reassociating:
-+ (inner1 AND inner2) AND (op2a code2 op2b)
-+ => (t AND inner2)
-+ If the partial result t is a constant, we win. Otherwise
-+ continue on to try reassociating with the other inner test. */
-+ if (is_and)
-+ {
-+ if (integer_onep (t))
-+ return inner2;
-+ else if (integer_zerop (t))
-+ return boolean_false_node;
-+ }
-+
-+ /* Handle the OR case, where we are redistributing:
-+ (inner1 OR inner2) AND (op2a code2 op2b)
-+ => (t OR (inner2 AND (op2a code2 op2b))) */
-+ else
-+ {
-+ if (integer_onep (t))
-+ return boolean_true_node;
-+ else
-+ /* Save partial result for later. */
-+ partial = t;
-+ }
-+ }
-+
-+ /* Compute the second partial result, (inner2 AND (op2a code op2b)) */
-+ if (TREE_CODE (inner2) == SSA_NAME
-+ && is_gimple_assign (s = SSA_NAME_DEF_STMT (inner2))
-+ && TREE_CODE_CLASS (gimple_assign_rhs_code (s)) == tcc_comparison
-+ && (t = maybe_fold_and_comparisons (gimple_assign_rhs_code (s),
-+ gimple_assign_rhs1 (s),
-+ gimple_assign_rhs2 (s),
-+ code2, op2a, op2b)))
-+ {
-+ /* Handle the AND case, where we are reassociating:
-+ (inner1 AND inner2) AND (op2a code2 op2b)
-+ => (inner1 AND t) */
-+ if (is_and)
-+ {
-+ if (integer_onep (t))
-+ return inner1;
-+ else if (integer_zerop (t))
-+ return boolean_false_node;
-+ }
-+
-+ /* Handle the OR case. where we are redistributing:
-+ (inner1 OR inner2) AND (op2a code2 op2b)
-+ => (t OR (inner1 AND (op2a code2 op2b)))
-+ => (t OR partial) */
-+ else
-+ {
-+ if (integer_onep (t))
-+ return boolean_true_node;
-+ else if (partial)
-+ {
-+ /* We already got a simplification for the other
-+ operand to the redistributed OR expression. The
-+ interesting case is when at least one is false.
-+ Or, if both are the same, we can apply the identity
-+ (x OR x) == x. */
-+ if (integer_zerop (partial))
-+ return t;
-+ else if (integer_zerop (t))
-+ return partial;
-+ else if (same_bool_result_p (t, partial))
-+ return t;
-+ }
-+ }
-+ }
-+ }
-+ return NULL_TREE;
-+}
-+
-+/* Try to simplify the AND of two comparisons defined by
-+ (OP1A CODE1 OP1B) and (OP2A CODE2 OP2B), respectively.
-+ If this can be done without constructing an intermediate value,
-+ return the resulting tree; otherwise NULL_TREE is returned.
-+ This function is deliberately asymmetric as it recurses on SSA_DEFs
-+ in the first comparison but not the second. */
-+
-+static tree
-+and_comparisons_1 (enum tree_code code1, tree op1a, tree op1b,
-+ enum tree_code code2, tree op2a, tree op2b)
-+{
-+ /* First check for ((x CODE1 y) AND (x CODE2 y)). */
-+ if (operand_equal_p (op1a, op2a, 0)
-+ && operand_equal_p (op1b, op2b, 0))
-+ {
-+ tree t = combine_comparisons (UNKNOWN_LOCATION,
-+ TRUTH_ANDIF_EXPR, code1, code2,
-+ boolean_type_node, op1a, op1b);
-+ if (t)
-+ return t;
-+ }
-+
-+ /* Likewise the swapped case of the above. */
-+ if (operand_equal_p (op1a, op2b, 0)
-+ && operand_equal_p (op1b, op2a, 0))
-+ {
-+ tree t = combine_comparisons (UNKNOWN_LOCATION,
-+ TRUTH_ANDIF_EXPR, code1,
-+ swap_tree_comparison (code2),
-+ boolean_type_node, op1a, op1b);
-+ if (t)
-+ return t;
-+ }
-+
-+ /* If both comparisons are of the same value against constants, we might
-+ be able to merge them. */
-+ if (operand_equal_p (op1a, op2a, 0)
-+ && TREE_CODE (op1b) == INTEGER_CST
-+ && TREE_CODE (op2b) == INTEGER_CST)
-+ {
-+ int cmp = tree_int_cst_compare (op1b, op2b);
-+
-+ /* If we have (op1a == op1b), we should either be able to
-+ return that or FALSE, depending on whether the constant op1b
-+ also satisfies the other comparison against op2b. */
-+ if (code1 == EQ_EXPR)
-+ {
-+ bool done = true;
-+ bool val;
-+ switch (code2)
-+ {
-+ case EQ_EXPR: val = (cmp == 0); break;
-+ case NE_EXPR: val = (cmp != 0); break;
-+ case LT_EXPR: val = (cmp < 0); break;
-+ case GT_EXPR: val = (cmp > 0); break;
-+ case LE_EXPR: val = (cmp <= 0); break;
-+ case GE_EXPR: val = (cmp >= 0); break;
-+ default: done = false;
-+ }
-+ if (done)
-+ {
-+ if (val)
-+ return fold_build2 (code1, boolean_type_node, op1a, op1b);
-+ else
-+ return boolean_false_node;
-+ }
-+ }
-+ /* Likewise if the second comparison is an == comparison. */
-+ else if (code2 == EQ_EXPR)
-+ {
-+ bool done = true;
-+ bool val;
-+ switch (code1)
-+ {
-+ case EQ_EXPR: val = (cmp == 0); break;
-+ case NE_EXPR: val = (cmp != 0); break;
-+ case LT_EXPR: val = (cmp > 0); break;
-+ case GT_EXPR: val = (cmp < 0); break;
-+ case LE_EXPR: val = (cmp >= 0); break;
-+ case GE_EXPR: val = (cmp <= 0); break;
-+ default: done = false;
-+ }
-+ if (done)
-+ {
-+ if (val)
-+ return fold_build2 (code2, boolean_type_node, op2a, op2b);
-+ else
-+ return boolean_false_node;
-+ }
-+ }
-+
-+ /* Same business with inequality tests. */
-+ else if (code1 == NE_EXPR)
-+ {
-+ bool val;
-+ switch (code2)
-+ {
-+ case EQ_EXPR: val = (cmp != 0); break;
-+ case NE_EXPR: val = (cmp == 0); break;
-+ case LT_EXPR: val = (cmp >= 0); break;
-+ case GT_EXPR: val = (cmp <= 0); break;
-+ case LE_EXPR: val = (cmp > 0); break;
-+ case GE_EXPR: val = (cmp < 0); break;
-+ default:
-+ val = false;
-+ }
-+ if (val)
-+ return fold_build2 (code2, boolean_type_node, op2a, op2b);
-+ }
-+ else if (code2 == NE_EXPR)
-+ {
-+ bool val;
-+ switch (code1)
-+ {
-+ case EQ_EXPR: val = (cmp == 0); break;
-+ case NE_EXPR: val = (cmp != 0); break;
-+ case LT_EXPR: val = (cmp <= 0); break;
-+ case GT_EXPR: val = (cmp >= 0); break;
-+ case LE_EXPR: val = (cmp < 0); break;
-+ case GE_EXPR: val = (cmp > 0); break;
-+ default:
-+ val = false;
-+ }
-+ if (val)
-+ return fold_build2 (code1, boolean_type_node, op1a, op1b);
-+ }
-+
-+ /* Chose the more restrictive of two < or <= comparisons. */
-+ else if ((code1 == LT_EXPR || code1 == LE_EXPR)
-+ && (code2 == LT_EXPR || code2 == LE_EXPR))
-+ {
-+ if ((cmp < 0) || (cmp == 0 && code1 == LT_EXPR))
-+ return fold_build2 (code1, boolean_type_node, op1a, op1b);
-+ else
-+ return fold_build2 (code2, boolean_type_node, op2a, op2b);
-+ }
-+
-+ /* Likewise chose the more restrictive of two > or >= comparisons. */
-+ else if ((code1 == GT_EXPR || code1 == GE_EXPR)
-+ && (code2 == GT_EXPR || code2 == GE_EXPR))
-+ {
-+ if ((cmp > 0) || (cmp == 0 && code1 == GT_EXPR))
-+ return fold_build2 (code1, boolean_type_node, op1a, op1b);
-+ else
-+ return fold_build2 (code2, boolean_type_node, op2a, op2b);
-+ }
-+
-+ /* Check for singleton ranges. */
-+ else if (cmp == 0
-+ && ((code1 == LE_EXPR && code2 == GE_EXPR)
-+ || (code1 == GE_EXPR && code2 == LE_EXPR)))
-+ return fold_build2 (EQ_EXPR, boolean_type_node, op1a, op2b);
-+
-+ /* Check for disjoint ranges. */
-+ else if (cmp <= 0
-+ && (code1 == LT_EXPR || code1 == LE_EXPR)
-+ && (code2 == GT_EXPR || code2 == GE_EXPR))
-+ return boolean_false_node;
-+ else if (cmp >= 0
-+ && (code1 == GT_EXPR || code1 == GE_EXPR)
-+ && (code2 == LT_EXPR || code2 == LE_EXPR))
-+ return boolean_false_node;
-+ }
-+
-+ /* Perhaps the first comparison is (NAME != 0) or (NAME == 1) where
-+ NAME's definition is a truth value. See if there are any simplifications
-+ that can be done against the NAME's definition. */
-+ if (TREE_CODE (op1a) == SSA_NAME
-+ && (code1 == NE_EXPR || code1 == EQ_EXPR)
-+ && (integer_zerop (op1b) || integer_onep (op1b)))
-+ {
-+ bool invert = ((code1 == EQ_EXPR && integer_zerop (op1b))
-+ || (code1 == NE_EXPR && integer_onep (op1b)));
-+ gimple stmt = SSA_NAME_DEF_STMT (op1a);
-+ switch (gimple_code (stmt))
-+ {
-+ case GIMPLE_ASSIGN:
-+ /* Try to simplify by copy-propagating the definition. */
-+ return and_var_with_comparison (op1a, invert, code2, op2a, op2b);
-+
-+ case GIMPLE_PHI:
-+ /* If every argument to the PHI produces the same result when
-+ ANDed with the second comparison, we win.
-+ Do not do this unless the type is bool since we need a bool
-+ result here anyway. */
-+ if (TREE_CODE (TREE_TYPE (op1a)) == BOOLEAN_TYPE)
-+ {
-+ tree result = NULL_TREE;
-+ unsigned i;
-+ for (i = 0; i < gimple_phi_num_args (stmt); i++)
-+ {
-+ tree arg = gimple_phi_arg_def (stmt, i);
-+
-+ /* If this PHI has itself as an argument, ignore it.
-+ If all the other args produce the same result,
-+ we're still OK. */
-+ if (arg == gimple_phi_result (stmt))
-+ continue;
-+ else if (TREE_CODE (arg) == INTEGER_CST)
-+ {
-+ if (invert ? integer_nonzerop (arg) : integer_zerop (arg))
-+ {
-+ if (!result)
-+ result = boolean_false_node;
-+ else if (!integer_zerop (result))
-+ return NULL_TREE;
-+ }
-+ else if (!result)
-+ result = fold_build2 (code2, boolean_type_node,
-+ op2a, op2b);
-+ else if (!same_bool_comparison_p (result,
-+ code2, op2a, op2b))
-+ return NULL_TREE;
-+ }
-+ else if (TREE_CODE (arg) == SSA_NAME)
-+ {
-+ tree temp = and_var_with_comparison (arg, invert,
-+ code2, op2a, op2b);
-+ if (!temp)
-+ return NULL_TREE;
-+ else if (!result)
-+ result = temp;
-+ else if (!same_bool_result_p (result, temp))
-+ return NULL_TREE;
-+ }
-+ else
-+ return NULL_TREE;
-+ }
-+ return result;
-+ }
-+
-+ default:
-+ break;
-+ }
-+ }
-+ return NULL_TREE;
-+}
-+
-+/* Try to simplify the AND of two comparisons, specified by
-+ (OP1A CODE1 OP1B) and (OP2B CODE2 OP2B), respectively.
-+ If this can be simplified to a single expression (without requiring
-+ introducing more SSA variables to hold intermediate values),
-+ return the resulting tree. Otherwise return NULL_TREE.
-+ If the result expression is non-null, it has boolean type. */
-+
-+tree
-+maybe_fold_and_comparisons (enum tree_code code1, tree op1a, tree op1b,
-+ enum tree_code code2, tree op2a, tree op2b)
-+{
-+ tree t = and_comparisons_1 (code1, op1a, op1b, code2, op2a, op2b);
-+ if (t)
-+ return t;
-+ else
-+ return and_comparisons_1 (code2, op2a, op2b, code1, op1a, op1b);
-+}
-+
-+/* Helper function for or_comparisons_1: try to simplify the OR of the
-+ ssa variable VAR with the comparison specified by (OP2A CODE2 OP2B).
-+ If INVERT is true, invert the value of VAR before doing the OR.
-+ Return NULL_EXPR if we can't simplify this to a single expression. */
-+
-+static tree
-+or_var_with_comparison (tree var, bool invert,
-+ enum tree_code code2, tree op2a, tree op2b)
-+{
-+ tree t;
-+ gimple stmt = SSA_NAME_DEF_STMT (var);
-+
-+ /* We can only deal with variables whose definitions are assignments. */
-+ if (!is_gimple_assign (stmt))
-+ return NULL_TREE;
-+
-+ /* If we have an inverted comparison, apply DeMorgan's law and rewrite
-+ !var OR (op2a code2 op2b) => !(var AND !(op2a code2 op2b))
-+ Then we only have to consider the simpler non-inverted cases. */
-+ if (invert)
-+ t = and_var_with_comparison_1 (stmt,
-+ invert_tree_comparison (code2, false),
-+ op2a, op2b);
-+ else
-+ t = or_var_with_comparison_1 (stmt, code2, op2a, op2b);
-+ return canonicalize_bool (t, invert);
-+}
-+
-+/* Try to simplify the OR of the ssa variable defined by the assignment
-+ STMT with the comparison specified by (OP2A CODE2 OP2B).
-+ Return NULL_EXPR if we can't simplify this to a single expression. */
-+
-+static tree
-+or_var_with_comparison_1 (gimple stmt,
-+ enum tree_code code2, tree op2a, tree op2b)
-+{
-+ tree var = gimple_assign_lhs (stmt);
-+ tree true_test_var = NULL_TREE;
-+ tree false_test_var = NULL_TREE;
-+ enum tree_code innercode = gimple_assign_rhs_code (stmt);
-+
-+ /* Check for identities like (var OR (var != 0)) => true . */
-+ if (TREE_CODE (op2a) == SSA_NAME
-+ && TREE_CODE (TREE_TYPE (var)) == BOOLEAN_TYPE)
-+ {
-+ if ((code2 == NE_EXPR && integer_zerop (op2b))
-+ || (code2 == EQ_EXPR && integer_nonzerop (op2b)))
-+ {
-+ true_test_var = op2a;
-+ if (var == true_test_var)
-+ return var;
-+ }
-+ else if ((code2 == EQ_EXPR && integer_zerop (op2b))
-+ || (code2 == NE_EXPR && integer_nonzerop (op2b)))
-+ {
-+ false_test_var = op2a;
-+ if (var == false_test_var)
-+ return boolean_true_node;
-+ }
-+ }
-+
-+ /* If the definition is a comparison, recurse on it. */
-+ if (TREE_CODE_CLASS (innercode) == tcc_comparison)
-+ {
-+ tree t = or_comparisons_1 (innercode,
-+ gimple_assign_rhs1 (stmt),
-+ gimple_assign_rhs2 (stmt),
-+ code2,
-+ op2a,
-+ op2b);
-+ if (t)
-+ return t;
-+ }
-+
-+ /* If the definition is an AND or OR expression, we may be able to
-+ simplify by reassociating. */
-+ if (innercode == TRUTH_AND_EXPR
-+ || innercode == TRUTH_OR_EXPR
-+ || (TREE_CODE (TREE_TYPE (var)) == BOOLEAN_TYPE
-+ && (innercode == BIT_AND_EXPR || innercode == BIT_IOR_EXPR)))
-+ {
-+ tree inner1 = gimple_assign_rhs1 (stmt);
-+ tree inner2 = gimple_assign_rhs2 (stmt);
-+ gimple s;
-+ tree t;
-+ tree partial = NULL_TREE;
-+ bool is_or = (innercode == TRUTH_OR_EXPR || innercode == BIT_IOR_EXPR);
-+
-+ /* Check for boolean identities that don't require recursive examination
-+ of inner1/inner2:
-+ inner1 OR (inner1 OR inner2) => inner1 OR inner2 => var
-+ inner1 OR (inner1 AND inner2) => inner1
-+ !inner1 OR (inner1 OR inner2) => true
-+ !inner1 OR (inner1 AND inner2) => !inner1 OR inner2
-+ */
-+ if (inner1 == true_test_var)
-+ return (is_or ? var : inner1);
-+ else if (inner2 == true_test_var)
-+ return (is_or ? var : inner2);
-+ else if (inner1 == false_test_var)
-+ return (is_or
-+ ? boolean_true_node
-+ : or_var_with_comparison (inner2, false, code2, op2a, op2b));
-+ else if (inner2 == false_test_var)
-+ return (is_or
-+ ? boolean_true_node
-+ : or_var_with_comparison (inner1, false, code2, op2a, op2b));
-+
-+ /* Next, redistribute/reassociate the OR across the inner tests.
-+ Compute the first partial result, (inner1 OR (op2a code op2b)) */
-+ if (TREE_CODE (inner1) == SSA_NAME
-+ && is_gimple_assign (s = SSA_NAME_DEF_STMT (inner1))
-+ && TREE_CODE_CLASS (gimple_assign_rhs_code (s)) == tcc_comparison
-+ && (t = maybe_fold_or_comparisons (gimple_assign_rhs_code (s),
-+ gimple_assign_rhs1 (s),
-+ gimple_assign_rhs2 (s),
-+ code2, op2a, op2b)))
-+ {
-+ /* Handle the OR case, where we are reassociating:
-+ (inner1 OR inner2) OR (op2a code2 op2b)
-+ => (t OR inner2)
-+ If the partial result t is a constant, we win. Otherwise
-+ continue on to try reassociating with the other inner test. */
-+ if (innercode == TRUTH_OR_EXPR)
-+ {
-+ if (integer_onep (t))
-+ return boolean_true_node;
-+ else if (integer_zerop (t))
-+ return inner2;
-+ }
-+
-+ /* Handle the AND case, where we are redistributing:
-+ (inner1 AND inner2) OR (op2a code2 op2b)
-+ => (t AND (inner2 OR (op2a code op2b))) */
-+ else
-+ {
-+ if (integer_zerop (t))
-+ return boolean_false_node;
-+ else
-+ /* Save partial result for later. */
-+ partial = t;
-+ }
-+ }
-+
-+ /* Compute the second partial result, (inner2 OR (op2a code op2b)) */
-+ if (TREE_CODE (inner2) == SSA_NAME
-+ && is_gimple_assign (s = SSA_NAME_DEF_STMT (inner2))
-+ && TREE_CODE_CLASS (gimple_assign_rhs_code (s)) == tcc_comparison
-+ && (t = maybe_fold_or_comparisons (gimple_assign_rhs_code (s),
-+ gimple_assign_rhs1 (s),
-+ gimple_assign_rhs2 (s),
-+ code2, op2a, op2b)))
-+ {
-+ /* Handle the OR case, where we are reassociating:
-+ (inner1 OR inner2) OR (op2a code2 op2b)
-+ => (inner1 OR t) */
-+ if (innercode == TRUTH_OR_EXPR)
-+ {
-+ if (integer_zerop (t))
-+ return inner1;
-+ else if (integer_onep (t))
-+ return boolean_true_node;
-+ }
-+
-+ /* Handle the AND case, where we are redistributing:
-+ (inner1 AND inner2) OR (op2a code2 op2b)
-+ => (t AND (inner1 OR (op2a code2 op2b)))
-+ => (t AND partial) */
-+ else
-+ {
-+ if (integer_zerop (t))
-+ return boolean_false_node;
-+ else if (partial)
-+ {
-+ /* We already got a simplification for the other
-+ operand to the redistributed AND expression. The
-+ interesting case is when at least one is true.
-+ Or, if both are the same, we can apply the identity
-+ (x AND x) == true. */
-+ if (integer_onep (partial))
-+ return t;
-+ else if (integer_onep (t))
-+ return partial;
-+ else if (same_bool_result_p (t, partial))
-+ return boolean_true_node;
-+ }
-+ }
-+ }
-+ }
-+ return NULL_TREE;
-+}
-+
-+/* Try to simplify the OR of two comparisons defined by
-+ (OP1A CODE1 OP1B) and (OP2A CODE2 OP2B), respectively.
-+ If this can be done without constructing an intermediate value,
-+ return the resulting tree; otherwise NULL_TREE is returned.
-+ This function is deliberately asymmetric as it recurses on SSA_DEFs
-+ in the first comparison but not the second. */
-+
-+static tree
-+or_comparisons_1 (enum tree_code code1, tree op1a, tree op1b,
-+ enum tree_code code2, tree op2a, tree op2b)
-+{
-+ /* First check for ((x CODE1 y) OR (x CODE2 y)). */
-+ if (operand_equal_p (op1a, op2a, 0)
-+ && operand_equal_p (op1b, op2b, 0))
-+ {
-+ tree t = combine_comparisons (UNKNOWN_LOCATION,
-+ TRUTH_ORIF_EXPR, code1, code2,
-+ boolean_type_node, op1a, op1b);
-+ if (t)
-+ return t;
-+ }
-+
-+ /* Likewise the swapped case of the above. */
-+ if (operand_equal_p (op1a, op2b, 0)
-+ && operand_equal_p (op1b, op2a, 0))
-+ {
-+ tree t = combine_comparisons (UNKNOWN_LOCATION,
-+ TRUTH_ORIF_EXPR, code1,
-+ swap_tree_comparison (code2),
-+ boolean_type_node, op1a, op1b);
-+ if (t)
-+ return t;
-+ }
-+
-+ /* If both comparisons are of the same value against constants, we might
-+ be able to merge them. */
-+ if (operand_equal_p (op1a, op2a, 0)
-+ && TREE_CODE (op1b) == INTEGER_CST
-+ && TREE_CODE (op2b) == INTEGER_CST)
-+ {
-+ int cmp = tree_int_cst_compare (op1b, op2b);
-+
-+ /* If we have (op1a != op1b), we should either be able to
-+ return that or TRUE, depending on whether the constant op1b
-+ also satisfies the other comparison against op2b. */
-+ if (code1 == NE_EXPR)
-+ {
-+ bool done = true;
-+ bool val;
-+ switch (code2)
-+ {
-+ case EQ_EXPR: val = (cmp == 0); break;
-+ case NE_EXPR: val = (cmp != 0); break;
-+ case LT_EXPR: val = (cmp < 0); break;
-+ case GT_EXPR: val = (cmp > 0); break;
-+ case LE_EXPR: val = (cmp <= 0); break;
-+ case GE_EXPR: val = (cmp >= 0); break;
-+ default: done = false;
-+ }
-+ if (done)
-+ {
-+ if (val)
-+ return boolean_true_node;
-+ else
-+ return fold_build2 (code1, boolean_type_node, op1a, op1b);
-+ }
-+ }
-+ /* Likewise if the second comparison is a != comparison. */
-+ else if (code2 == NE_EXPR)
-+ {
-+ bool done = true;
-+ bool val;
-+ switch (code1)
-+ {
-+ case EQ_EXPR: val = (cmp == 0); break;
-+ case NE_EXPR: val = (cmp != 0); break;
-+ case LT_EXPR: val = (cmp > 0); break;
-+ case GT_EXPR: val = (cmp < 0); break;
-+ case LE_EXPR: val = (cmp >= 0); break;
-+ case GE_EXPR: val = (cmp <= 0); break;
-+ default: done = false;
-+ }
-+ if (done)
-+ {
-+ if (val)
-+ return boolean_true_node;
-+ else
-+ return fold_build2 (code2, boolean_type_node, op2a, op2b);
-+ }
-+ }
-+
-+ /* See if an equality test is redundant with the other comparison. */
-+ else if (code1 == EQ_EXPR)
-+ {
-+ bool val;
-+ switch (code2)
-+ {
-+ case EQ_EXPR: val = (cmp == 0); break;
-+ case NE_EXPR: val = (cmp != 0); break;
-+ case LT_EXPR: val = (cmp < 0); break;
-+ case GT_EXPR: val = (cmp > 0); break;
-+ case LE_EXPR: val = (cmp <= 0); break;
-+ case GE_EXPR: val = (cmp >= 0); break;
-+ default:
-+ val = false;
-+ }
-+ if (val)
-+ return fold_build2 (code2, boolean_type_node, op2a, op2b);
-+ }
-+ else if (code2 == EQ_EXPR)
-+ {
-+ bool val;
-+ switch (code1)
-+ {
-+ case EQ_EXPR: val = (cmp == 0); break;
-+ case NE_EXPR: val = (cmp != 0); break;
-+ case LT_EXPR: val = (cmp > 0); break;
-+ case GT_EXPR: val = (cmp < 0); break;
-+ case LE_EXPR: val = (cmp >= 0); break;
-+ case GE_EXPR: val = (cmp <= 0); break;
-+ default:
-+ val = false;
-+ }
-+ if (val)
-+ return fold_build2 (code1, boolean_type_node, op1a, op1b);
-+ }
-+
-+ /* Chose the less restrictive of two < or <= comparisons. */
-+ else if ((code1 == LT_EXPR || code1 == LE_EXPR)
-+ && (code2 == LT_EXPR || code2 == LE_EXPR))
-+ {
-+ if ((cmp < 0) || (cmp == 0 && code1 == LT_EXPR))
-+ return fold_build2 (code2, boolean_type_node, op2a, op2b);
-+ else
-+ return fold_build2 (code1, boolean_type_node, op1a, op1b);
-+ }
-+
-+ /* Likewise chose the less restrictive of two > or >= comparisons. */
-+ else if ((code1 == GT_EXPR || code1 == GE_EXPR)
-+ && (code2 == GT_EXPR || code2 == GE_EXPR))
-+ {
-+ if ((cmp > 0) || (cmp == 0 && code1 == GT_EXPR))
-+ return fold_build2 (code2, boolean_type_node, op2a, op2b);
-+ else
-+ return fold_build2 (code1, boolean_type_node, op1a, op1b);
-+ }
-+
-+ /* Check for singleton ranges. */
-+ else if (cmp == 0
-+ && ((code1 == LT_EXPR && code2 == GT_EXPR)
-+ || (code1 == GT_EXPR && code2 == LT_EXPR)))
-+ return fold_build2 (NE_EXPR, boolean_type_node, op1a, op2b);
-+
-+ /* Check for less/greater pairs that don't restrict the range at all. */
-+ else if (cmp >= 0
-+ && (code1 == LT_EXPR || code1 == LE_EXPR)
-+ && (code2 == GT_EXPR || code2 == GE_EXPR))
-+ return boolean_true_node;
-+ else if (cmp <= 0
-+ && (code1 == GT_EXPR || code1 == GE_EXPR)
-+ && (code2 == LT_EXPR || code2 == LE_EXPR))
-+ return boolean_true_node;
-+ }
-+
-+ /* Perhaps the first comparison is (NAME != 0) or (NAME == 1) where
-+ NAME's definition is a truth value. See if there are any simplifications
-+ that can be done against the NAME's definition. */
-+ if (TREE_CODE (op1a) == SSA_NAME
-+ && (code1 == NE_EXPR || code1 == EQ_EXPR)
-+ && (integer_zerop (op1b) || integer_onep (op1b)))
-+ {
-+ bool invert = ((code1 == EQ_EXPR && integer_zerop (op1b))
-+ || (code1 == NE_EXPR && integer_onep (op1b)));
-+ gimple stmt = SSA_NAME_DEF_STMT (op1a);
-+ switch (gimple_code (stmt))
-+ {
-+ case GIMPLE_ASSIGN:
-+ /* Try to simplify by copy-propagating the definition. */
-+ return or_var_with_comparison (op1a, invert, code2, op2a, op2b);
-+
-+ case GIMPLE_PHI:
-+ /* If every argument to the PHI produces the same result when
-+ ORed with the second comparison, we win.
-+ Do not do this unless the type is bool since we need a bool
-+ result here anyway. */
-+ if (TREE_CODE (TREE_TYPE (op1a)) == BOOLEAN_TYPE)
-+ {
-+ tree result = NULL_TREE;
-+ unsigned i;
-+ for (i = 0; i < gimple_phi_num_args (stmt); i++)
-+ {
-+ tree arg = gimple_phi_arg_def (stmt, i);
-+
-+ /* If this PHI has itself as an argument, ignore it.
-+ If all the other args produce the same result,
-+ we're still OK. */
-+ if (arg == gimple_phi_result (stmt))
-+ continue;
-+ else if (TREE_CODE (arg) == INTEGER_CST)
-+ {
-+ if (invert ? integer_zerop (arg) : integer_nonzerop (arg))
-+ {
-+ if (!result)
-+ result = boolean_true_node;
-+ else if (!integer_onep (result))
-+ return NULL_TREE;
-+ }
-+ else if (!result)
-+ result = fold_build2 (code2, boolean_type_node,
-+ op2a, op2b);
-+ else if (!same_bool_comparison_p (result,
-+ code2, op2a, op2b))
-+ return NULL_TREE;
-+ }
-+ else if (TREE_CODE (arg) == SSA_NAME)
-+ {
-+ tree temp = or_var_with_comparison (arg, invert,
-+ code2, op2a, op2b);
-+ if (!temp)
-+ return NULL_TREE;
-+ else if (!result)
-+ result = temp;
-+ else if (!same_bool_result_p (result, temp))
-+ return NULL_TREE;
-+ }
-+ else
-+ return NULL_TREE;
-+ }
-+ return result;
-+ }
-+
-+ default:
-+ break;
-+ }
-+ }
-+ return NULL_TREE;
-+}
-+
-+/* Try to simplify the OR of two comparisons, specified by
-+ (OP1A CODE1 OP1B) and (OP2B CODE2 OP2B), respectively.
-+ If this can be simplified to a single expression (without requiring
-+ introducing more SSA variables to hold intermediate values),
-+ return the resulting tree. Otherwise return NULL_TREE.
-+ If the result expression is non-null, it has boolean type. */
-+
-+tree
-+maybe_fold_or_comparisons (enum tree_code code1, tree op1a, tree op1b,
-+ enum tree_code code2, tree op2a, tree op2b)
-+{
-+ tree t = or_comparisons_1 (code1, op1a, op1b, code2, op2a, op2b);
-+ if (t)
-+ return t;
-+ else
-+ return or_comparisons_1 (code2, op2a, op2b, code1, op1a, op1b);
-+}
-+
- /* Try to optimize out __builtin_stack_restore. Optimize it out
- if there is another __builtin_stack_restore in the same basic
- block and no calls or ASM_EXPRs are in between, or if this block's
-
-=== modified file 'gcc/tree-ssa-ifcombine.c'
---- old/gcc/tree-ssa-ifcombine.c 2009-11-25 10:55:54 +0000
-+++ new/gcc/tree-ssa-ifcombine.c 2010-07-30 13:21:51 +0000
-@@ -366,21 +366,16 @@
-
- /* 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 (UNKNOWN_LOCATION,
-- 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)
-@@ -518,22 +513,17 @@
- /* 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 (UNKNOWN_LOCATION,
-- 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)
-
-=== modified file 'gcc/tree-ssa-reassoc.c'
---- old/gcc/tree-ssa-reassoc.c 2010-01-13 15:04:38 +0000
-+++ new/gcc/tree-ssa-reassoc.c 2010-07-30 13:21:51 +0000
-@@ -1159,6 +1159,117 @@
- return changed;
- }
-
-+/* If OPCODE is BIT_IOR_EXPR or BIT_AND_EXPR and CURR is a comparison
-+ expression, examine the other OPS to see if any of them are comparisons
-+ of the same values, which we may be able to combine or eliminate.
-+ For example, we can rewrite (a < b) | (a == b) as (a <= b). */
-+
-+static bool
-+eliminate_redundant_comparison (enum tree_code opcode,
-+ VEC (operand_entry_t, heap) **ops,
-+ unsigned int currindex,
-+ operand_entry_t curr)
-+{
-+ tree op1, op2;
-+ enum tree_code lcode, rcode;
-+ gimple def1, def2;
-+ int i;
-+ operand_entry_t oe;
-+
-+ if (opcode != BIT_IOR_EXPR && opcode != BIT_AND_EXPR)
-+ return false;
-+
-+ /* Check that CURR is a comparison. */
-+ if (TREE_CODE (curr->op) != SSA_NAME)
-+ return false;
-+ def1 = SSA_NAME_DEF_STMT (curr->op);
-+ if (!is_gimple_assign (def1))
-+ return false;
-+ lcode = gimple_assign_rhs_code (def1);
-+ if (TREE_CODE_CLASS (lcode) != tcc_comparison)
-+ return false;
-+ op1 = gimple_assign_rhs1 (def1);
-+ op2 = gimple_assign_rhs2 (def1);
-+
-+ /* Now look for a similar comparison in the remaining OPS. */
-+ for (i = currindex + 1;
-+ VEC_iterate (operand_entry_t, *ops, i, oe);
-+ i++)
-+ {
-+ tree t;
-+
-+ if (TREE_CODE (oe->op) != SSA_NAME)
-+ continue;
-+ def2 = SSA_NAME_DEF_STMT (oe->op);
-+ if (!is_gimple_assign (def2))
-+ continue;
-+ rcode = gimple_assign_rhs_code (def2);
-+ if (TREE_CODE_CLASS (rcode) != tcc_comparison)
-+ continue;
-+
-+ /* If we got here, we have a match. See if we can combine the
-+ two comparisons. */
-+ if (opcode == BIT_IOR_EXPR)
-+ t = maybe_fold_or_comparisons (lcode, op1, op2,
-+ rcode, gimple_assign_rhs1 (def2),
-+ gimple_assign_rhs2 (def2));
-+ else
-+ t = maybe_fold_and_comparisons (lcode, op1, op2,
-+ rcode, gimple_assign_rhs1 (def2),
-+ gimple_assign_rhs2 (def2));
-+ if (!t)
-+ continue;
-+
-+ /* maybe_fold_and_comparisons and maybe_fold_or_comparisons
-+ always give us a boolean_type_node value back. If the original
-+ BIT_AND_EXPR or BIT_IOR_EXPR was of a wider integer type,
-+ we need to convert. */
-+ if (!useless_type_conversion_p (TREE_TYPE (curr->op), TREE_TYPE (t)))
-+ t = fold_convert (TREE_TYPE (curr->op), t);
-+
-+ if (dump_file && (dump_flags & TDF_DETAILS))
-+ {
-+ fprintf (dump_file, "Equivalence: ");
-+ print_generic_expr (dump_file, curr->op, 0);
-+ fprintf (dump_file, " %s ", op_symbol_code (opcode));
-+ print_generic_expr (dump_file, oe->op, 0);
-+ fprintf (dump_file, " -> ");
-+ print_generic_expr (dump_file, t, 0);
-+ fprintf (dump_file, "\n");
-+ }
-+
-+ /* Now we can delete oe, as it has been subsumed by the new combined
-+ expression t. */
-+ VEC_ordered_remove (operand_entry_t, *ops, i);
-+ reassociate_stats.ops_eliminated ++;
-+
-+ /* If t is the same as curr->op, we're done. Otherwise we must
-+ replace curr->op with t. Special case is if we got a constant
-+ back, in which case we add it to the end instead of in place of
-+ the current entry. */
-+ if (TREE_CODE (t) == INTEGER_CST)
-+ {
-+ VEC_ordered_remove (operand_entry_t, *ops, currindex);
-+ add_to_ops_vec (ops, t);
-+ }
-+ else if (!operand_equal_p (t, curr->op, 0))
-+ {
-+ tree tmpvar;
-+ gimple sum;
-+ enum tree_code subcode;
-+ tree newop1;
-+ tree newop2;
-+ tmpvar = create_tmp_var (TREE_TYPE (t), NULL);
-+ add_referenced_var (tmpvar);
-+ extract_ops_from_tree (t, &subcode, &newop1, &newop2);
-+ sum = build_and_add_sum (tmpvar, newop1, newop2, subcode);
-+ curr->op = gimple_get_lhs (sum);
-+ }
-+ return true;
-+ }
-+
-+ return false;
-+}
-
- /* Perform various identities and other optimizations on the list of
- operand entries, stored in OPS. The tree code for the binary
-@@ -1220,7 +1331,8 @@
- if (eliminate_not_pairs (opcode, ops, i, oe))
- return;
- if (eliminate_duplicate_pair (opcode, ops, &done, i, oe, oelast)
-- || (!done && eliminate_plus_minus_pair (opcode, ops, i, oe)))
-+ || (!done && eliminate_plus_minus_pair (opcode, ops, i, oe))
-+ || (!done && eliminate_redundant_comparison (opcode, ops, i, oe)))
- {
- if (done)
- return;
-