summaryrefslogtreecommitdiffstats
path: root/meta-oe/recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99306.patch
diff options
context:
space:
mode:
authorKoen Kooi <koen@dominion.thruhere.net>2011-03-17 21:41:22 +0100
committerKoen Kooi <koen@dominion.thruhere.net>2011-03-17 21:41:22 +0100
commitc58cc7d3796dcee6e93885c835ed04cb566abeb2 (patch)
tree3eea4d4ef6a4ef79e0f4e025d7012c1a5cc38835 /meta-oe/recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99306.patch
parenteec6ab97f712e06eb52c9f7c99e19ffab3ce9d74 (diff)
downloadmeta-openembedded-c58cc7d3796dcee6e93885c835ed04cb566abeb2.tar.gz
move layer into meta-oe in preparation for future splits
As per TSC decision Signed-off-by: Koen Kooi <koen@dominion.thruhere.net>
Diffstat (limited to 'meta-oe/recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99306.patch')
-rw-r--r--meta-oe/recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99306.patch1401
1 files changed, 1401 insertions, 0 deletions
diff --git a/meta-oe/recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99306.patch b/meta-oe/recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99306.patch
new file mode 100644
index 000000000..423cd5652
--- /dev/null
+++ b/meta-oe/recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99306.patch
@@ -0,0 +1,1401 @@
12010-07-10 Sandra Loosemore <sandra@codesourcery.com>
2
3 Backport from mainline:
4
5 2010-05-08 Sandra Loosemore <sandra@codesourcery.com>
6
7 PR middle-end/28685
8
9 gcc/
10 * tree-ssa-reassoc.c (eliminate_redundant_comparison): New function.
11 (optimize_ops_list): Call it.
12
13 gcc/testsuite/
14 * gcc.dg/pr28685-1.c: New file.
15
16 2010-06-08 Sandra Loosemore <sandra@codesourcery.com>
17
18 PR tree-optimization/39874
19 PR middle-end/28685
20
21 gcc/
22 * gimple.h (maybe_fold_and_comparisons, maybe_fold_or_comparisons):
23 Declare.
24 * gimple-fold.c (canonicalize_bool, same_bool_comparison_p,
25 same_bool_result_p): New.
26 (and_var_with_comparison, and_var_with_comparison_1,
27 and_comparisons_1, and_comparisons, maybe_fold_and_comparisons): New.
28 (or_var_with_comparison, or_var_with_comparison_1,
29 or_comparisons_1, or_comparisons, maybe_fold_or_comparisons): New.
30 * tree-ssa-reassoc.c (eliminate_redundant_comparison): Use
31 maybe_fold_and_comparisons or maybe_fold_or_comparisons instead
32 of combine_comparisons.
33 * tree-ssa-ifcombine.c (ifcombine_ifandif, ifcombine_iforif): Likewise.
34
35 gcc/testsuite/
36 * gcc.dg/pr39874.c: New file.
37
38 2010-07-10 Yao Qi <yao@codesourcery.com>
39
40 Merge from Sourcery G++ 4.4:
41
42=== modified file 'gcc/gimple.h'
43--- old/gcc/gimple.h 2010-04-02 18:54:46 +0000
44+++ new/gcc/gimple.h 2010-07-30 13:21:51 +0000
45@@ -4743,4 +4743,9 @@
46
47 extern void dump_gimple_statistics (void);
48
49+extern tree maybe_fold_and_comparisons (enum tree_code, tree, tree,
50+ enum tree_code, tree, tree);
51+extern tree maybe_fold_or_comparisons (enum tree_code, tree, tree,
52+ enum tree_code, tree, tree);
53+
54 #endif /* GCC_GIMPLE_H */
55
56=== added file 'gcc/testsuite/gcc.dg/pr28685-1.c'
57--- old/gcc/testsuite/gcc.dg/pr28685-1.c 1970-01-01 00:00:00 +0000
58+++ new/gcc/testsuite/gcc.dg/pr28685-1.c 2010-07-30 13:21:51 +0000
59@@ -0,0 +1,50 @@
60+/* { dg-do compile } */
61+/* { dg-options "-O2 -fdump-tree-optimized" } */
62+
63+/* Should produce <=. */
64+int test1 (int a, int b)
65+{
66+ return (a < b || a == b);
67+}
68+
69+/* Should produce <=. */
70+int test2 (int a, int b)
71+{
72+ int lt = a < b;
73+ int eq = a == b;
74+
75+ return (lt || eq);
76+}
77+
78+/* Should produce <= (just deleting redundant test). */
79+int test3 (int a, int b)
80+{
81+ int lt = a <= b;
82+ int eq = a == b;
83+
84+ return (lt || eq);
85+}
86+
87+/* Should produce <= (operands reversed to test the swap logic). */
88+int test4 (int a, int b)
89+{
90+ int lt = a < b;
91+ int eq = b == a;
92+
93+ return (lt || eq);
94+}
95+
96+/* Should produce constant 0. */
97+int test5 (int a, int b)
98+{
99+ int lt = a < b;
100+ int eq = a == b;
101+
102+ return (lt && eq);
103+}
104+
105+/* { dg-final { scan-tree-dump-times " <= " 4 "optimized" } } */
106+/* { dg-final { scan-tree-dump-times "return 0" 1 "optimized" } } */
107+/* { dg-final { scan-tree-dump-not " < " "optimized" } } */
108+/* { dg-final { scan-tree-dump-not " == " "optimized" } } */
109+/* { dg-final { cleanup-tree-dump "optimized" } } */
110
111=== added file 'gcc/testsuite/gcc.dg/pr39874.c'
112--- old/gcc/testsuite/gcc.dg/pr39874.c 1970-01-01 00:00:00 +0000
113+++ new/gcc/testsuite/gcc.dg/pr39874.c 2010-07-30 13:21:51 +0000
114@@ -0,0 +1,29 @@
115+/* { dg-do compile } */
116+/* { dg-options "-O2 -fdump-tree-optimized" } */
117+
118+extern void func();
119+
120+void test1(char *signature)
121+{
122+ char ch = signature[0];
123+ if (ch == 15 || ch == 3)
124+ {
125+ if (ch == 15) func();
126+ }
127+}
128+
129+
130+void test2(char *signature)
131+{
132+ char ch = signature[0];
133+ if (ch == 15 || ch == 3)
134+ {
135+ if (ch > 14) func();
136+ }
137+}
138+
139+/* { dg-final { scan-tree-dump-times " == 15" 2 "optimized" } } */
140+/* { dg-final { scan-tree-dump-not " == 3" "optimized" } } */
141+/* { dg-final { cleanup-tree-dump "optimized" } } */
142+
143+
144
145=== modified file 'gcc/tree-ssa-ccp.c'
146--- old/gcc/tree-ssa-ccp.c 2010-04-02 15:50:04 +0000
147+++ new/gcc/tree-ssa-ccp.c 2010-07-30 13:21:51 +0000
148@@ -3176,6 +3176,1056 @@
149 return changed;
150 }
151
152+/* Canonicalize and possibly invert the boolean EXPR; return NULL_TREE
153+ if EXPR is null or we don't know how.
154+ If non-null, the result always has boolean type. */
155+
156+static tree
157+canonicalize_bool (tree expr, bool invert)
158+{
159+ if (!expr)
160+ return NULL_TREE;
161+ else if (invert)
162+ {
163+ if (integer_nonzerop (expr))
164+ return boolean_false_node;
165+ else if (integer_zerop (expr))
166+ return boolean_true_node;
167+ else if (TREE_CODE (expr) == SSA_NAME)
168+ return fold_build2 (EQ_EXPR, boolean_type_node, expr,
169+ build_int_cst (TREE_TYPE (expr), 0));
170+ else if (TREE_CODE_CLASS (TREE_CODE (expr)) == tcc_comparison)
171+ return fold_build2 (invert_tree_comparison (TREE_CODE (expr), false),
172+ boolean_type_node,
173+ TREE_OPERAND (expr, 0),
174+ TREE_OPERAND (expr, 1));
175+ else
176+ return NULL_TREE;
177+ }
178+ else
179+ {
180+ if (TREE_CODE (TREE_TYPE (expr)) == BOOLEAN_TYPE)
181+ return expr;
182+ if (integer_nonzerop (expr))
183+ return boolean_true_node;
184+ else if (integer_zerop (expr))
185+ return boolean_false_node;
186+ else if (TREE_CODE (expr) == SSA_NAME)
187+ return fold_build2 (NE_EXPR, boolean_type_node, expr,
188+ build_int_cst (TREE_TYPE (expr), 0));
189+ else if (TREE_CODE_CLASS (TREE_CODE (expr)) == tcc_comparison)
190+ return fold_build2 (TREE_CODE (expr),
191+ boolean_type_node,
192+ TREE_OPERAND (expr, 0),
193+ TREE_OPERAND (expr, 1));
194+ else
195+ return NULL_TREE;
196+ }
197+}
198+
199+/* Check to see if a boolean expression EXPR is logically equivalent to the
200+ comparison (OP1 CODE OP2). Check for various identities involving
201+ SSA_NAMEs. */
202+
203+static bool
204+same_bool_comparison_p (const_tree expr, enum tree_code code,
205+ const_tree op1, const_tree op2)
206+{
207+ gimple s;
208+
209+ /* The obvious case. */
210+ if (TREE_CODE (expr) == code
211+ && operand_equal_p (TREE_OPERAND (expr, 0), op1, 0)
212+ && operand_equal_p (TREE_OPERAND (expr, 1), op2, 0))
213+ return true;
214+
215+ /* Check for comparing (name, name != 0) and the case where expr
216+ is an SSA_NAME with a definition matching the comparison. */
217+ if (TREE_CODE (expr) == SSA_NAME
218+ && TREE_CODE (TREE_TYPE (expr)) == BOOLEAN_TYPE)
219+ {
220+ if (operand_equal_p (expr, op1, 0))
221+ return ((code == NE_EXPR && integer_zerop (op2))
222+ || (code == EQ_EXPR && integer_nonzerop (op2)));
223+ s = SSA_NAME_DEF_STMT (expr);
224+ if (is_gimple_assign (s)
225+ && gimple_assign_rhs_code (s) == code
226+ && operand_equal_p (gimple_assign_rhs1 (s), op1, 0)
227+ && operand_equal_p (gimple_assign_rhs2 (s), op2, 0))
228+ return true;
229+ }
230+
231+ /* If op1 is of the form (name != 0) or (name == 0), and the definition
232+ of name is a comparison, recurse. */
233+ if (TREE_CODE (op1) == SSA_NAME
234+ && TREE_CODE (TREE_TYPE (op1)) == BOOLEAN_TYPE)
235+ {
236+ s = SSA_NAME_DEF_STMT (op1);
237+ if (is_gimple_assign (s)
238+ && TREE_CODE_CLASS (gimple_assign_rhs_code (s)) == tcc_comparison)
239+ {
240+ enum tree_code c = gimple_assign_rhs_code (s);
241+ if ((c == NE_EXPR && integer_zerop (op2))
242+ || (c == EQ_EXPR && integer_nonzerop (op2)))
243+ return same_bool_comparison_p (expr, c,
244+ gimple_assign_rhs1 (s),
245+ gimple_assign_rhs2 (s));
246+ if ((c == EQ_EXPR && integer_zerop (op2))
247+ || (c == NE_EXPR && integer_nonzerop (op2)))
248+ return same_bool_comparison_p (expr,
249+ invert_tree_comparison (c, false),
250+ gimple_assign_rhs1 (s),
251+ gimple_assign_rhs2 (s));
252+ }
253+ }
254+ return false;
255+}
256+
257+/* Check to see if two boolean expressions OP1 and OP2 are logically
258+ equivalent. */
259+
260+static bool
261+same_bool_result_p (const_tree op1, const_tree op2)
262+{
263+ /* Simple cases first. */
264+ if (operand_equal_p (op1, op2, 0))
265+ return true;
266+
267+ /* Check the cases where at least one of the operands is a comparison.
268+ These are a bit smarter than operand_equal_p in that they apply some
269+ identifies on SSA_NAMEs. */
270+ if (TREE_CODE_CLASS (TREE_CODE (op2)) == tcc_comparison
271+ && same_bool_comparison_p (op1, TREE_CODE (op2),
272+ TREE_OPERAND (op2, 0),
273+ TREE_OPERAND (op2, 1)))
274+ return true;
275+ if (TREE_CODE_CLASS (TREE_CODE (op1)) == tcc_comparison
276+ && same_bool_comparison_p (op2, TREE_CODE (op1),
277+ TREE_OPERAND (op1, 0),
278+ TREE_OPERAND (op1, 1)))
279+ return true;
280+
281+ /* Default case. */
282+ return false;
283+}
284+
285+/* Forward declarations for some mutually recursive functions. */
286+
287+static tree
288+and_comparisons_1 (enum tree_code code1, tree op1a, tree op1b,
289+ enum tree_code code2, tree op2a, tree op2b);
290+static tree
291+and_var_with_comparison (tree var, bool invert,
292+ enum tree_code code2, tree op2a, tree op2b);
293+static tree
294+and_var_with_comparison_1 (gimple stmt,
295+ enum tree_code code2, tree op2a, tree op2b);
296+static tree
297+or_comparisons_1 (enum tree_code code1, tree op1a, tree op1b,
298+ enum tree_code code2, tree op2a, tree op2b);
299+static tree
300+or_var_with_comparison (tree var, bool invert,
301+ enum tree_code code2, tree op2a, tree op2b);
302+static tree
303+or_var_with_comparison_1 (gimple stmt,
304+ enum tree_code code2, tree op2a, tree op2b);
305+
306+/* Helper function for and_comparisons_1: try to simplify the AND of the
307+ ssa variable VAR with the comparison specified by (OP2A CODE2 OP2B).
308+ If INVERT is true, invert the value of the VAR before doing the AND.
309+ Return NULL_EXPR if we can't simplify this to a single expression. */
310+
311+static tree
312+and_var_with_comparison (tree var, bool invert,
313+ enum tree_code code2, tree op2a, tree op2b)
314+{
315+ tree t;
316+ gimple stmt = SSA_NAME_DEF_STMT (var);
317+
318+ /* We can only deal with variables whose definitions are assignments. */
319+ if (!is_gimple_assign (stmt))
320+ return NULL_TREE;
321+
322+ /* If we have an inverted comparison, apply DeMorgan's law and rewrite
323+ !var AND (op2a code2 op2b) => !(var OR !(op2a code2 op2b))
324+ Then we only have to consider the simpler non-inverted cases. */
325+ if (invert)
326+ t = or_var_with_comparison_1 (stmt,
327+ invert_tree_comparison (code2, false),
328+ op2a, op2b);
329+ else
330+ t = and_var_with_comparison_1 (stmt, code2, op2a, op2b);
331+ return canonicalize_bool (t, invert);
332+}
333+
334+/* Try to simplify the AND of the ssa variable defined by the assignment
335+ STMT with the comparison specified by (OP2A CODE2 OP2B).
336+ Return NULL_EXPR if we can't simplify this to a single expression. */
337+
338+static tree
339+and_var_with_comparison_1 (gimple stmt,
340+ enum tree_code code2, tree op2a, tree op2b)
341+{
342+ tree var = gimple_assign_lhs (stmt);
343+ tree true_test_var = NULL_TREE;
344+ tree false_test_var = NULL_TREE;
345+ enum tree_code innercode = gimple_assign_rhs_code (stmt);
346+
347+ /* Check for identities like (var AND (var == 0)) => false. */
348+ if (TREE_CODE (op2a) == SSA_NAME
349+ && TREE_CODE (TREE_TYPE (var)) == BOOLEAN_TYPE)
350+ {
351+ if ((code2 == NE_EXPR && integer_zerop (op2b))
352+ || (code2 == EQ_EXPR && integer_nonzerop (op2b)))
353+ {
354+ true_test_var = op2a;
355+ if (var == true_test_var)
356+ return var;
357+ }
358+ else if ((code2 == EQ_EXPR && integer_zerop (op2b))
359+ || (code2 == NE_EXPR && integer_nonzerop (op2b)))
360+ {
361+ false_test_var = op2a;
362+ if (var == false_test_var)
363+ return boolean_false_node;
364+ }
365+ }
366+
367+ /* If the definition is a comparison, recurse on it. */
368+ if (TREE_CODE_CLASS (innercode) == tcc_comparison)
369+ {
370+ tree t = and_comparisons_1 (innercode,
371+ gimple_assign_rhs1 (stmt),
372+ gimple_assign_rhs2 (stmt),
373+ code2,
374+ op2a,
375+ op2b);
376+ if (t)
377+ return t;
378+ }
379+
380+ /* If the definition is an AND or OR expression, we may be able to
381+ simplify by reassociating. */
382+ if (innercode == TRUTH_AND_EXPR
383+ || innercode == TRUTH_OR_EXPR
384+ || (TREE_CODE (TREE_TYPE (var)) == BOOLEAN_TYPE
385+ && (innercode == BIT_AND_EXPR || innercode == BIT_IOR_EXPR)))
386+ {
387+ tree inner1 = gimple_assign_rhs1 (stmt);
388+ tree inner2 = gimple_assign_rhs2 (stmt);
389+ gimple s;
390+ tree t;
391+ tree partial = NULL_TREE;
392+ bool is_and = (innercode == TRUTH_AND_EXPR || innercode == BIT_AND_EXPR);
393+
394+ /* Check for boolean identities that don't require recursive examination
395+ of inner1/inner2:
396+ inner1 AND (inner1 AND inner2) => inner1 AND inner2 => var
397+ inner1 AND (inner1 OR inner2) => inner1
398+ !inner1 AND (inner1 AND inner2) => false
399+ !inner1 AND (inner1 OR inner2) => !inner1 AND inner2
400+ Likewise for similar cases involving inner2. */
401+ if (inner1 == true_test_var)
402+ return (is_and ? var : inner1);
403+ else if (inner2 == true_test_var)
404+ return (is_and ? var : inner2);
405+ else if (inner1 == false_test_var)
406+ return (is_and
407+ ? boolean_false_node
408+ : and_var_with_comparison (inner2, false, code2, op2a, op2b));
409+ else if (inner2 == false_test_var)
410+ return (is_and
411+ ? boolean_false_node
412+ : and_var_with_comparison (inner1, false, code2, op2a, op2b));
413+
414+ /* Next, redistribute/reassociate the AND across the inner tests.
415+ Compute the first partial result, (inner1 AND (op2a code op2b)) */
416+ if (TREE_CODE (inner1) == SSA_NAME
417+ && is_gimple_assign (s = SSA_NAME_DEF_STMT (inner1))
418+ && TREE_CODE_CLASS (gimple_assign_rhs_code (s)) == tcc_comparison
419+ && (t = maybe_fold_and_comparisons (gimple_assign_rhs_code (s),
420+ gimple_assign_rhs1 (s),
421+ gimple_assign_rhs2 (s),
422+ code2, op2a, op2b)))
423+ {
424+ /* Handle the AND case, where we are reassociating:
425+ (inner1 AND inner2) AND (op2a code2 op2b)
426+ => (t AND inner2)
427+ If the partial result t is a constant, we win. Otherwise
428+ continue on to try reassociating with the other inner test. */
429+ if (is_and)
430+ {
431+ if (integer_onep (t))
432+ return inner2;
433+ else if (integer_zerop (t))
434+ return boolean_false_node;
435+ }
436+
437+ /* Handle the OR case, where we are redistributing:
438+ (inner1 OR inner2) AND (op2a code2 op2b)
439+ => (t OR (inner2 AND (op2a code2 op2b))) */
440+ else
441+ {
442+ if (integer_onep (t))
443+ return boolean_true_node;
444+ else
445+ /* Save partial result for later. */
446+ partial = t;
447+ }
448+ }
449+
450+ /* Compute the second partial result, (inner2 AND (op2a code op2b)) */
451+ if (TREE_CODE (inner2) == SSA_NAME
452+ && is_gimple_assign (s = SSA_NAME_DEF_STMT (inner2))
453+ && TREE_CODE_CLASS (gimple_assign_rhs_code (s)) == tcc_comparison
454+ && (t = maybe_fold_and_comparisons (gimple_assign_rhs_code (s),
455+ gimple_assign_rhs1 (s),
456+ gimple_assign_rhs2 (s),
457+ code2, op2a, op2b)))
458+ {
459+ /* Handle the AND case, where we are reassociating:
460+ (inner1 AND inner2) AND (op2a code2 op2b)
461+ => (inner1 AND t) */
462+ if (is_and)
463+ {
464+ if (integer_onep (t))
465+ return inner1;
466+ else if (integer_zerop (t))
467+ return boolean_false_node;
468+ }
469+
470+ /* Handle the OR case. where we are redistributing:
471+ (inner1 OR inner2) AND (op2a code2 op2b)
472+ => (t OR (inner1 AND (op2a code2 op2b)))
473+ => (t OR partial) */
474+ else
475+ {
476+ if (integer_onep (t))
477+ return boolean_true_node;
478+ else if (partial)
479+ {
480+ /* We already got a simplification for the other
481+ operand to the redistributed OR expression. The
482+ interesting case is when at least one is false.
483+ Or, if both are the same, we can apply the identity
484+ (x OR x) == x. */
485+ if (integer_zerop (partial))
486+ return t;
487+ else if (integer_zerop (t))
488+ return partial;
489+ else if (same_bool_result_p (t, partial))
490+ return t;
491+ }
492+ }
493+ }
494+ }
495+ return NULL_TREE;
496+}
497+
498+/* Try to simplify the AND of two comparisons defined by
499+ (OP1A CODE1 OP1B) and (OP2A CODE2 OP2B), respectively.
500+ If this can be done without constructing an intermediate value,
501+ return the resulting tree; otherwise NULL_TREE is returned.
502+ This function is deliberately asymmetric as it recurses on SSA_DEFs
503+ in the first comparison but not the second. */
504+
505+static tree
506+and_comparisons_1 (enum tree_code code1, tree op1a, tree op1b,
507+ enum tree_code code2, tree op2a, tree op2b)
508+{
509+ /* First check for ((x CODE1 y) AND (x CODE2 y)). */
510+ if (operand_equal_p (op1a, op2a, 0)
511+ && operand_equal_p (op1b, op2b, 0))
512+ {
513+ tree t = combine_comparisons (UNKNOWN_LOCATION,
514+ TRUTH_ANDIF_EXPR, code1, code2,
515+ boolean_type_node, op1a, op1b);
516+ if (t)
517+ return t;
518+ }
519+
520+ /* Likewise the swapped case of the above. */
521+ if (operand_equal_p (op1a, op2b, 0)
522+ && operand_equal_p (op1b, op2a, 0))
523+ {
524+ tree t = combine_comparisons (UNKNOWN_LOCATION,
525+ TRUTH_ANDIF_EXPR, code1,
526+ swap_tree_comparison (code2),
527+ boolean_type_node, op1a, op1b);
528+ if (t)
529+ return t;
530+ }
531+
532+ /* If both comparisons are of the same value against constants, we might
533+ be able to merge them. */
534+ if (operand_equal_p (op1a, op2a, 0)
535+ && TREE_CODE (op1b) == INTEGER_CST
536+ && TREE_CODE (op2b) == INTEGER_CST)
537+ {
538+ int cmp = tree_int_cst_compare (op1b, op2b);
539+
540+ /* If we have (op1a == op1b), we should either be able to
541+ return that or FALSE, depending on whether the constant op1b
542+ also satisfies the other comparison against op2b. */
543+ if (code1 == EQ_EXPR)
544+ {
545+ bool done = true;
546+ bool val;
547+ switch (code2)
548+ {
549+ case EQ_EXPR: val = (cmp == 0); break;
550+ case NE_EXPR: val = (cmp != 0); break;
551+ case LT_EXPR: val = (cmp < 0); break;
552+ case GT_EXPR: val = (cmp > 0); break;
553+ case LE_EXPR: val = (cmp <= 0); break;
554+ case GE_EXPR: val = (cmp >= 0); break;
555+ default: done = false;
556+ }
557+ if (done)
558+ {
559+ if (val)
560+ return fold_build2 (code1, boolean_type_node, op1a, op1b);
561+ else
562+ return boolean_false_node;
563+ }
564+ }
565+ /* Likewise if the second comparison is an == comparison. */
566+ else if (code2 == EQ_EXPR)
567+ {
568+ bool done = true;
569+ bool val;
570+ switch (code1)
571+ {
572+ case EQ_EXPR: val = (cmp == 0); break;
573+ case NE_EXPR: val = (cmp != 0); break;
574+ case LT_EXPR: val = (cmp > 0); break;
575+ case GT_EXPR: val = (cmp < 0); break;
576+ case LE_EXPR: val = (cmp >= 0); break;
577+ case GE_EXPR: val = (cmp <= 0); break;
578+ default: done = false;
579+ }
580+ if (done)
581+ {
582+ if (val)
583+ return fold_build2 (code2, boolean_type_node, op2a, op2b);
584+ else
585+ return boolean_false_node;
586+ }
587+ }
588+
589+ /* Same business with inequality tests. */
590+ else if (code1 == NE_EXPR)
591+ {
592+ bool val;
593+ switch (code2)
594+ {
595+ case EQ_EXPR: val = (cmp != 0); break;
596+ case NE_EXPR: val = (cmp == 0); break;
597+ case LT_EXPR: val = (cmp >= 0); break;
598+ case GT_EXPR: val = (cmp <= 0); break;
599+ case LE_EXPR: val = (cmp > 0); break;
600+ case GE_EXPR: val = (cmp < 0); break;
601+ default:
602+ val = false;
603+ }
604+ if (val)
605+ return fold_build2 (code2, boolean_type_node, op2a, op2b);
606+ }
607+ else if (code2 == NE_EXPR)
608+ {
609+ bool val;
610+ switch (code1)
611+ {
612+ case EQ_EXPR: val = (cmp == 0); break;
613+ case NE_EXPR: val = (cmp != 0); break;
614+ case LT_EXPR: val = (cmp <= 0); break;
615+ case GT_EXPR: val = (cmp >= 0); break;
616+ case LE_EXPR: val = (cmp < 0); break;
617+ case GE_EXPR: val = (cmp > 0); break;
618+ default:
619+ val = false;
620+ }
621+ if (val)
622+ return fold_build2 (code1, boolean_type_node, op1a, op1b);
623+ }
624+
625+ /* Chose the more restrictive of two < or <= comparisons. */
626+ else if ((code1 == LT_EXPR || code1 == LE_EXPR)
627+ && (code2 == LT_EXPR || code2 == LE_EXPR))
628+ {
629+ if ((cmp < 0) || (cmp == 0 && code1 == LT_EXPR))
630+ return fold_build2 (code1, boolean_type_node, op1a, op1b);
631+ else
632+ return fold_build2 (code2, boolean_type_node, op2a, op2b);
633+ }
634+
635+ /* Likewise chose the more restrictive of two > or >= comparisons. */
636+ else if ((code1 == GT_EXPR || code1 == GE_EXPR)
637+ && (code2 == GT_EXPR || code2 == GE_EXPR))
638+ {
639+ if ((cmp > 0) || (cmp == 0 && code1 == GT_EXPR))
640+ return fold_build2 (code1, boolean_type_node, op1a, op1b);
641+ else
642+ return fold_build2 (code2, boolean_type_node, op2a, op2b);
643+ }
644+
645+ /* Check for singleton ranges. */
646+ else if (cmp == 0
647+ && ((code1 == LE_EXPR && code2 == GE_EXPR)
648+ || (code1 == GE_EXPR && code2 == LE_EXPR)))
649+ return fold_build2 (EQ_EXPR, boolean_type_node, op1a, op2b);
650+
651+ /* Check for disjoint ranges. */
652+ else if (cmp <= 0
653+ && (code1 == LT_EXPR || code1 == LE_EXPR)
654+ && (code2 == GT_EXPR || code2 == GE_EXPR))
655+ return boolean_false_node;
656+ else if (cmp >= 0
657+ && (code1 == GT_EXPR || code1 == GE_EXPR)
658+ && (code2 == LT_EXPR || code2 == LE_EXPR))
659+ return boolean_false_node;
660+ }
661+
662+ /* Perhaps the first comparison is (NAME != 0) or (NAME == 1) where
663+ NAME's definition is a truth value. See if there are any simplifications
664+ that can be done against the NAME's definition. */
665+ if (TREE_CODE (op1a) == SSA_NAME
666+ && (code1 == NE_EXPR || code1 == EQ_EXPR)
667+ && (integer_zerop (op1b) || integer_onep (op1b)))
668+ {
669+ bool invert = ((code1 == EQ_EXPR && integer_zerop (op1b))
670+ || (code1 == NE_EXPR && integer_onep (op1b)));
671+ gimple stmt = SSA_NAME_DEF_STMT (op1a);
672+ switch (gimple_code (stmt))
673+ {
674+ case GIMPLE_ASSIGN:
675+ /* Try to simplify by copy-propagating the definition. */
676+ return and_var_with_comparison (op1a, invert, code2, op2a, op2b);
677+
678+ case GIMPLE_PHI:
679+ /* If every argument to the PHI produces the same result when
680+ ANDed with the second comparison, we win.
681+ Do not do this unless the type is bool since we need a bool
682+ result here anyway. */
683+ if (TREE_CODE (TREE_TYPE (op1a)) == BOOLEAN_TYPE)
684+ {
685+ tree result = NULL_TREE;
686+ unsigned i;
687+ for (i = 0; i < gimple_phi_num_args (stmt); i++)
688+ {
689+ tree arg = gimple_phi_arg_def (stmt, i);
690+
691+ /* If this PHI has itself as an argument, ignore it.
692+ If all the other args produce the same result,
693+ we're still OK. */
694+ if (arg == gimple_phi_result (stmt))
695+ continue;
696+ else if (TREE_CODE (arg) == INTEGER_CST)
697+ {
698+ if (invert ? integer_nonzerop (arg) : integer_zerop (arg))
699+ {
700+ if (!result)
701+ result = boolean_false_node;
702+ else if (!integer_zerop (result))
703+ return NULL_TREE;
704+ }
705+ else if (!result)
706+ result = fold_build2 (code2, boolean_type_node,
707+ op2a, op2b);
708+ else if (!same_bool_comparison_p (result,
709+ code2, op2a, op2b))
710+ return NULL_TREE;
711+ }
712+ else if (TREE_CODE (arg) == SSA_NAME)
713+ {
714+ tree temp = and_var_with_comparison (arg, invert,
715+ code2, op2a, op2b);
716+ if (!temp)
717+ return NULL_TREE;
718+ else if (!result)
719+ result = temp;
720+ else if (!same_bool_result_p (result, temp))
721+ return NULL_TREE;
722+ }
723+ else
724+ return NULL_TREE;
725+ }
726+ return result;
727+ }
728+
729+ default:
730+ break;
731+ }
732+ }
733+ return NULL_TREE;
734+}
735+
736+/* Try to simplify the AND of two comparisons, specified by
737+ (OP1A CODE1 OP1B) and (OP2B CODE2 OP2B), respectively.
738+ If this can be simplified to a single expression (without requiring
739+ introducing more SSA variables to hold intermediate values),
740+ return the resulting tree. Otherwise return NULL_TREE.
741+ If the result expression is non-null, it has boolean type. */
742+
743+tree
744+maybe_fold_and_comparisons (enum tree_code code1, tree op1a, tree op1b,
745+ enum tree_code code2, tree op2a, tree op2b)
746+{
747+ tree t = and_comparisons_1 (code1, op1a, op1b, code2, op2a, op2b);
748+ if (t)
749+ return t;
750+ else
751+ return and_comparisons_1 (code2, op2a, op2b, code1, op1a, op1b);
752+}
753+
754+/* Helper function for or_comparisons_1: try to simplify the OR of the
755+ ssa variable VAR with the comparison specified by (OP2A CODE2 OP2B).
756+ If INVERT is true, invert the value of VAR before doing the OR.
757+ Return NULL_EXPR if we can't simplify this to a single expression. */
758+
759+static tree
760+or_var_with_comparison (tree var, bool invert,
761+ enum tree_code code2, tree op2a, tree op2b)
762+{
763+ tree t;
764+ gimple stmt = SSA_NAME_DEF_STMT (var);
765+
766+ /* We can only deal with variables whose definitions are assignments. */
767+ if (!is_gimple_assign (stmt))
768+ return NULL_TREE;
769+
770+ /* If we have an inverted comparison, apply DeMorgan's law and rewrite
771+ !var OR (op2a code2 op2b) => !(var AND !(op2a code2 op2b))
772+ Then we only have to consider the simpler non-inverted cases. */
773+ if (invert)
774+ t = and_var_with_comparison_1 (stmt,
775+ invert_tree_comparison (code2, false),
776+ op2a, op2b);
777+ else
778+ t = or_var_with_comparison_1 (stmt, code2, op2a, op2b);
779+ return canonicalize_bool (t, invert);
780+}
781+
782+/* Try to simplify the OR of the ssa variable defined by the assignment
783+ STMT with the comparison specified by (OP2A CODE2 OP2B).
784+ Return NULL_EXPR if we can't simplify this to a single expression. */
785+
786+static tree
787+or_var_with_comparison_1 (gimple stmt,
788+ enum tree_code code2, tree op2a, tree op2b)
789+{
790+ tree var = gimple_assign_lhs (stmt);
791+ tree true_test_var = NULL_TREE;
792+ tree false_test_var = NULL_TREE;
793+ enum tree_code innercode = gimple_assign_rhs_code (stmt);
794+
795+ /* Check for identities like (var OR (var != 0)) => true . */
796+ if (TREE_CODE (op2a) == SSA_NAME
797+ && TREE_CODE (TREE_TYPE (var)) == BOOLEAN_TYPE)
798+ {
799+ if ((code2 == NE_EXPR && integer_zerop (op2b))
800+ || (code2 == EQ_EXPR && integer_nonzerop (op2b)))
801+ {
802+ true_test_var = op2a;
803+ if (var == true_test_var)
804+ return var;
805+ }
806+ else if ((code2 == EQ_EXPR && integer_zerop (op2b))
807+ || (code2 == NE_EXPR && integer_nonzerop (op2b)))
808+ {
809+ false_test_var = op2a;
810+ if (var == false_test_var)
811+ return boolean_true_node;
812+ }
813+ }
814+
815+ /* If the definition is a comparison, recurse on it. */
816+ if (TREE_CODE_CLASS (innercode) == tcc_comparison)
817+ {
818+ tree t = or_comparisons_1 (innercode,
819+ gimple_assign_rhs1 (stmt),
820+ gimple_assign_rhs2 (stmt),
821+ code2,
822+ op2a,
823+ op2b);
824+ if (t)
825+ return t;
826+ }
827+
828+ /* If the definition is an AND or OR expression, we may be able to
829+ simplify by reassociating. */
830+ if (innercode == TRUTH_AND_EXPR
831+ || innercode == TRUTH_OR_EXPR
832+ || (TREE_CODE (TREE_TYPE (var)) == BOOLEAN_TYPE
833+ && (innercode == BIT_AND_EXPR || innercode == BIT_IOR_EXPR)))
834+ {
835+ tree inner1 = gimple_assign_rhs1 (stmt);
836+ tree inner2 = gimple_assign_rhs2 (stmt);
837+ gimple s;
838+ tree t;
839+ tree partial = NULL_TREE;
840+ bool is_or = (innercode == TRUTH_OR_EXPR || innercode == BIT_IOR_EXPR);
841+
842+ /* Check for boolean identities that don't require recursive examination
843+ of inner1/inner2:
844+ inner1 OR (inner1 OR inner2) => inner1 OR inner2 => var
845+ inner1 OR (inner1 AND inner2) => inner1
846+ !inner1 OR (inner1 OR inner2) => true
847+ !inner1 OR (inner1 AND inner2) => !inner1 OR inner2
848+ */
849+ if (inner1 == true_test_var)
850+ return (is_or ? var : inner1);
851+ else if (inner2 == true_test_var)
852+ return (is_or ? var : inner2);
853+ else if (inner1 == false_test_var)
854+ return (is_or
855+ ? boolean_true_node
856+ : or_var_with_comparison (inner2, false, code2, op2a, op2b));
857+ else if (inner2 == false_test_var)
858+ return (is_or
859+ ? boolean_true_node
860+ : or_var_with_comparison (inner1, false, code2, op2a, op2b));
861+
862+ /* Next, redistribute/reassociate the OR across the inner tests.
863+ Compute the first partial result, (inner1 OR (op2a code op2b)) */
864+ if (TREE_CODE (inner1) == SSA_NAME
865+ && is_gimple_assign (s = SSA_NAME_DEF_STMT (inner1))
866+ && TREE_CODE_CLASS (gimple_assign_rhs_code (s)) == tcc_comparison
867+ && (t = maybe_fold_or_comparisons (gimple_assign_rhs_code (s),
868+ gimple_assign_rhs1 (s),
869+ gimple_assign_rhs2 (s),
870+ code2, op2a, op2b)))
871+ {
872+ /* Handle the OR case, where we are reassociating:
873+ (inner1 OR inner2) OR (op2a code2 op2b)
874+ => (t OR inner2)
875+ If the partial result t is a constant, we win. Otherwise
876+ continue on to try reassociating with the other inner test. */
877+ if (innercode == TRUTH_OR_EXPR)
878+ {
879+ if (integer_onep (t))
880+ return boolean_true_node;
881+ else if (integer_zerop (t))
882+ return inner2;
883+ }
884+
885+ /* Handle the AND case, where we are redistributing:
886+ (inner1 AND inner2) OR (op2a code2 op2b)
887+ => (t AND (inner2 OR (op2a code op2b))) */
888+ else
889+ {
890+ if (integer_zerop (t))
891+ return boolean_false_node;
892+ else
893+ /* Save partial result for later. */
894+ partial = t;
895+ }
896+ }
897+
898+ /* Compute the second partial result, (inner2 OR (op2a code op2b)) */
899+ if (TREE_CODE (inner2) == SSA_NAME
900+ && is_gimple_assign (s = SSA_NAME_DEF_STMT (inner2))
901+ && TREE_CODE_CLASS (gimple_assign_rhs_code (s)) == tcc_comparison
902+ && (t = maybe_fold_or_comparisons (gimple_assign_rhs_code (s),
903+ gimple_assign_rhs1 (s),
904+ gimple_assign_rhs2 (s),
905+ code2, op2a, op2b)))
906+ {
907+ /* Handle the OR case, where we are reassociating:
908+ (inner1 OR inner2) OR (op2a code2 op2b)
909+ => (inner1 OR t) */
910+ if (innercode == TRUTH_OR_EXPR)
911+ {
912+ if (integer_zerop (t))
913+ return inner1;
914+ else if (integer_onep (t))
915+ return boolean_true_node;
916+ }
917+
918+ /* Handle the AND case, where we are redistributing:
919+ (inner1 AND inner2) OR (op2a code2 op2b)
920+ => (t AND (inner1 OR (op2a code2 op2b)))
921+ => (t AND partial) */
922+ else
923+ {
924+ if (integer_zerop (t))
925+ return boolean_false_node;
926+ else if (partial)
927+ {
928+ /* We already got a simplification for the other
929+ operand to the redistributed AND expression. The
930+ interesting case is when at least one is true.
931+ Or, if both are the same, we can apply the identity
932+ (x AND x) == true. */
933+ if (integer_onep (partial))
934+ return t;
935+ else if (integer_onep (t))
936+ return partial;
937+ else if (same_bool_result_p (t, partial))
938+ return boolean_true_node;
939+ }
940+ }
941+ }
942+ }
943+ return NULL_TREE;
944+}
945+
946+/* Try to simplify the OR of two comparisons defined by
947+ (OP1A CODE1 OP1B) and (OP2A CODE2 OP2B), respectively.
948+ If this can be done without constructing an intermediate value,
949+ return the resulting tree; otherwise NULL_TREE is returned.
950+ This function is deliberately asymmetric as it recurses on SSA_DEFs
951+ in the first comparison but not the second. */
952+
953+static tree
954+or_comparisons_1 (enum tree_code code1, tree op1a, tree op1b,
955+ enum tree_code code2, tree op2a, tree op2b)
956+{
957+ /* First check for ((x CODE1 y) OR (x CODE2 y)). */
958+ if (operand_equal_p (op1a, op2a, 0)
959+ && operand_equal_p (op1b, op2b, 0))
960+ {
961+ tree t = combine_comparisons (UNKNOWN_LOCATION,
962+ TRUTH_ORIF_EXPR, code1, code2,
963+ boolean_type_node, op1a, op1b);
964+ if (t)
965+ return t;
966+ }
967+
968+ /* Likewise the swapped case of the above. */
969+ if (operand_equal_p (op1a, op2b, 0)
970+ && operand_equal_p (op1b, op2a, 0))
971+ {
972+ tree t = combine_comparisons (UNKNOWN_LOCATION,
973+ TRUTH_ORIF_EXPR, code1,
974+ swap_tree_comparison (code2),
975+ boolean_type_node, op1a, op1b);
976+ if (t)
977+ return t;
978+ }
979+
980+ /* If both comparisons are of the same value against constants, we might
981+ be able to merge them. */
982+ if (operand_equal_p (op1a, op2a, 0)
983+ && TREE_CODE (op1b) == INTEGER_CST
984+ && TREE_CODE (op2b) == INTEGER_CST)
985+ {
986+ int cmp = tree_int_cst_compare (op1b, op2b);
987+
988+ /* If we have (op1a != op1b), we should either be able to
989+ return that or TRUE, depending on whether the constant op1b
990+ also satisfies the other comparison against op2b. */
991+ if (code1 == NE_EXPR)
992+ {
993+ bool done = true;
994+ bool val;
995+ switch (code2)
996+ {
997+ case EQ_EXPR: val = (cmp == 0); break;
998+ case NE_EXPR: val = (cmp != 0); break;
999+ case LT_EXPR: val = (cmp < 0); break;
1000+ case GT_EXPR: val = (cmp > 0); break;
1001+ case LE_EXPR: val = (cmp <= 0); break;
1002+ case GE_EXPR: val = (cmp >= 0); break;
1003+ default: done = false;
1004+ }
1005+ if (done)
1006+ {
1007+ if (val)
1008+ return boolean_true_node;
1009+ else
1010+ return fold_build2 (code1, boolean_type_node, op1a, op1b);
1011+ }
1012+ }
1013+ /* Likewise if the second comparison is a != comparison. */
1014+ else if (code2 == NE_EXPR)
1015+ {
1016+ bool done = true;
1017+ bool val;
1018+ switch (code1)
1019+ {
1020+ case EQ_EXPR: val = (cmp == 0); break;
1021+ case NE_EXPR: val = (cmp != 0); break;
1022+ case LT_EXPR: val = (cmp > 0); break;
1023+ case GT_EXPR: val = (cmp < 0); break;
1024+ case LE_EXPR: val = (cmp >= 0); break;
1025+ case GE_EXPR: val = (cmp <= 0); break;
1026+ default: done = false;
1027+ }
1028+ if (done)
1029+ {
1030+ if (val)
1031+ return boolean_true_node;
1032+ else
1033+ return fold_build2 (code2, boolean_type_node, op2a, op2b);
1034+ }
1035+ }
1036+
1037+ /* See if an equality test is redundant with the other comparison. */
1038+ else if (code1 == EQ_EXPR)
1039+ {
1040+ bool val;
1041+ switch (code2)
1042+ {
1043+ case EQ_EXPR: val = (cmp == 0); break;
1044+ case NE_EXPR: val = (cmp != 0); break;
1045+ case LT_EXPR: val = (cmp < 0); break;
1046+ case GT_EXPR: val = (cmp > 0); break;
1047+ case LE_EXPR: val = (cmp <= 0); break;
1048+ case GE_EXPR: val = (cmp >= 0); break;
1049+ default:
1050+ val = false;
1051+ }
1052+ if (val)
1053+ return fold_build2 (code2, boolean_type_node, op2a, op2b);
1054+ }
1055+ else if (code2 == EQ_EXPR)
1056+ {
1057+ bool val;
1058+ switch (code1)
1059+ {
1060+ case EQ_EXPR: val = (cmp == 0); break;
1061+ case NE_EXPR: val = (cmp != 0); break;
1062+ case LT_EXPR: val = (cmp > 0); break;
1063+ case GT_EXPR: val = (cmp < 0); break;
1064+ case LE_EXPR: val = (cmp >= 0); break;
1065+ case GE_EXPR: val = (cmp <= 0); break;
1066+ default:
1067+ val = false;
1068+ }
1069+ if (val)
1070+ return fold_build2 (code1, boolean_type_node, op1a, op1b);
1071+ }
1072+
1073+ /* Chose the less restrictive of two < or <= comparisons. */
1074+ else if ((code1 == LT_EXPR || code1 == LE_EXPR)
1075+ && (code2 == LT_EXPR || code2 == LE_EXPR))
1076+ {
1077+ if ((cmp < 0) || (cmp == 0 && code1 == LT_EXPR))
1078+ return fold_build2 (code2, boolean_type_node, op2a, op2b);
1079+ else
1080+ return fold_build2 (code1, boolean_type_node, op1a, op1b);
1081+ }
1082+
1083+ /* Likewise chose the less restrictive of two > or >= comparisons. */
1084+ else if ((code1 == GT_EXPR || code1 == GE_EXPR)
1085+ && (code2 == GT_EXPR || code2 == GE_EXPR))
1086+ {
1087+ if ((cmp > 0) || (cmp == 0 && code1 == GT_EXPR))
1088+ return fold_build2 (code2, boolean_type_node, op2a, op2b);
1089+ else
1090+ return fold_build2 (code1, boolean_type_node, op1a, op1b);
1091+ }
1092+
1093+ /* Check for singleton ranges. */
1094+ else if (cmp == 0
1095+ && ((code1 == LT_EXPR && code2 == GT_EXPR)
1096+ || (code1 == GT_EXPR && code2 == LT_EXPR)))
1097+ return fold_build2 (NE_EXPR, boolean_type_node, op1a, op2b);
1098+
1099+ /* Check for less/greater pairs that don't restrict the range at all. */
1100+ else if (cmp >= 0
1101+ && (code1 == LT_EXPR || code1 == LE_EXPR)
1102+ && (code2 == GT_EXPR || code2 == GE_EXPR))
1103+ return boolean_true_node;
1104+ else if (cmp <= 0
1105+ && (code1 == GT_EXPR || code1 == GE_EXPR)
1106+ && (code2 == LT_EXPR || code2 == LE_EXPR))
1107+ return boolean_true_node;
1108+ }
1109+
1110+ /* Perhaps the first comparison is (NAME != 0) or (NAME == 1) where
1111+ NAME's definition is a truth value. See if there are any simplifications
1112+ that can be done against the NAME's definition. */
1113+ if (TREE_CODE (op1a) == SSA_NAME
1114+ && (code1 == NE_EXPR || code1 == EQ_EXPR)
1115+ && (integer_zerop (op1b) || integer_onep (op1b)))
1116+ {
1117+ bool invert = ((code1 == EQ_EXPR && integer_zerop (op1b))
1118+ || (code1 == NE_EXPR && integer_onep (op1b)));
1119+ gimple stmt = SSA_NAME_DEF_STMT (op1a);
1120+ switch (gimple_code (stmt))
1121+ {
1122+ case GIMPLE_ASSIGN:
1123+ /* Try to simplify by copy-propagating the definition. */
1124+ return or_var_with_comparison (op1a, invert, code2, op2a, op2b);
1125+
1126+ case GIMPLE_PHI:
1127+ /* If every argument to the PHI produces the same result when
1128+ ORed with the second comparison, we win.
1129+ Do not do this unless the type is bool since we need a bool
1130+ result here anyway. */
1131+ if (TREE_CODE (TREE_TYPE (op1a)) == BOOLEAN_TYPE)
1132+ {
1133+ tree result = NULL_TREE;
1134+ unsigned i;
1135+ for (i = 0; i < gimple_phi_num_args (stmt); i++)
1136+ {
1137+ tree arg = gimple_phi_arg_def (stmt, i);
1138+
1139+ /* If this PHI has itself as an argument, ignore it.
1140+ If all the other args produce the same result,
1141+ we're still OK. */
1142+ if (arg == gimple_phi_result (stmt))
1143+ continue;
1144+ else if (TREE_CODE (arg) == INTEGER_CST)
1145+ {
1146+ if (invert ? integer_zerop (arg) : integer_nonzerop (arg))
1147+ {
1148+ if (!result)
1149+ result = boolean_true_node;
1150+ else if (!integer_onep (result))
1151+ return NULL_TREE;
1152+ }
1153+ else if (!result)
1154+ result = fold_build2 (code2, boolean_type_node,
1155+ op2a, op2b);
1156+ else if (!same_bool_comparison_p (result,
1157+ code2, op2a, op2b))
1158+ return NULL_TREE;
1159+ }
1160+ else if (TREE_CODE (arg) == SSA_NAME)
1161+ {
1162+ tree temp = or_var_with_comparison (arg, invert,
1163+ code2, op2a, op2b);
1164+ if (!temp)
1165+ return NULL_TREE;
1166+ else if (!result)
1167+ result = temp;
1168+ else if (!same_bool_result_p (result, temp))
1169+ return NULL_TREE;
1170+ }
1171+ else
1172+ return NULL_TREE;
1173+ }
1174+ return result;
1175+ }
1176+
1177+ default:
1178+ break;
1179+ }
1180+ }
1181+ return NULL_TREE;
1182+}
1183+
1184+/* Try to simplify the OR of two comparisons, specified by
1185+ (OP1A CODE1 OP1B) and (OP2B CODE2 OP2B), respectively.
1186+ If this can be simplified to a single expression (without requiring
1187+ introducing more SSA variables to hold intermediate values),
1188+ return the resulting tree. Otherwise return NULL_TREE.
1189+ If the result expression is non-null, it has boolean type. */
1190+
1191+tree
1192+maybe_fold_or_comparisons (enum tree_code code1, tree op1a, tree op1b,
1193+ enum tree_code code2, tree op2a, tree op2b)
1194+{
1195+ tree t = or_comparisons_1 (code1, op1a, op1b, code2, op2a, op2b);
1196+ if (t)
1197+ return t;
1198+ else
1199+ return or_comparisons_1 (code2, op2a, op2b, code1, op1a, op1b);
1200+}
1201+
1202 /* Try to optimize out __builtin_stack_restore. Optimize it out
1203 if there is another __builtin_stack_restore in the same basic
1204 block and no calls or ASM_EXPRs are in between, or if this block's
1205
1206=== modified file 'gcc/tree-ssa-ifcombine.c'
1207--- old/gcc/tree-ssa-ifcombine.c 2009-11-25 10:55:54 +0000
1208+++ new/gcc/tree-ssa-ifcombine.c 2010-07-30 13:21:51 +0000
1209@@ -366,21 +366,16 @@
1210
1211 /* See if we have two comparisons that we can merge into one. */
1212 else if (TREE_CODE_CLASS (gimple_cond_code (inner_cond)) == tcc_comparison
1213- && TREE_CODE_CLASS (gimple_cond_code (outer_cond)) == tcc_comparison
1214- && operand_equal_p (gimple_cond_lhs (inner_cond),
1215- gimple_cond_lhs (outer_cond), 0)
1216- && operand_equal_p (gimple_cond_rhs (inner_cond),
1217- gimple_cond_rhs (outer_cond), 0))
1218+ && TREE_CODE_CLASS (gimple_cond_code (outer_cond)) == tcc_comparison)
1219 {
1220- enum tree_code code1 = gimple_cond_code (inner_cond);
1221- enum tree_code code2 = gimple_cond_code (outer_cond);
1222 tree t;
1223
1224- if (!(t = combine_comparisons (UNKNOWN_LOCATION,
1225- TRUTH_ANDIF_EXPR, code1, code2,
1226- boolean_type_node,
1227- gimple_cond_lhs (outer_cond),
1228- gimple_cond_rhs (outer_cond))))
1229+ if (!(t = maybe_fold_and_comparisons (gimple_cond_code (inner_cond),
1230+ gimple_cond_lhs (inner_cond),
1231+ gimple_cond_rhs (inner_cond),
1232+ gimple_cond_code (outer_cond),
1233+ gimple_cond_lhs (outer_cond),
1234+ gimple_cond_rhs (outer_cond))))
1235 return false;
1236 t = canonicalize_cond_expr_cond (t);
1237 if (!t)
1238@@ -518,22 +513,17 @@
1239 /* See if we have two comparisons that we can merge into one.
1240 This happens for C++ operator overloading where for example
1241 GE_EXPR is implemented as GT_EXPR || EQ_EXPR. */
1242- else if (TREE_CODE_CLASS (gimple_cond_code (inner_cond)) == tcc_comparison
1243- && TREE_CODE_CLASS (gimple_cond_code (outer_cond)) == tcc_comparison
1244- && operand_equal_p (gimple_cond_lhs (inner_cond),
1245- gimple_cond_lhs (outer_cond), 0)
1246- && operand_equal_p (gimple_cond_rhs (inner_cond),
1247- gimple_cond_rhs (outer_cond), 0))
1248+ else if (TREE_CODE_CLASS (gimple_cond_code (inner_cond)) == tcc_comparison
1249+ && TREE_CODE_CLASS (gimple_cond_code (outer_cond)) == tcc_comparison)
1250 {
1251- enum tree_code code1 = gimple_cond_code (inner_cond);
1252- enum tree_code code2 = gimple_cond_code (outer_cond);
1253 tree t;
1254
1255- if (!(t = combine_comparisons (UNKNOWN_LOCATION,
1256- TRUTH_ORIF_EXPR, code1, code2,
1257- boolean_type_node,
1258- gimple_cond_lhs (outer_cond),
1259- gimple_cond_rhs (outer_cond))))
1260+ if (!(t = maybe_fold_or_comparisons (gimple_cond_code (inner_cond),
1261+ gimple_cond_lhs (inner_cond),
1262+ gimple_cond_rhs (inner_cond),
1263+ gimple_cond_code (outer_cond),
1264+ gimple_cond_lhs (outer_cond),
1265+ gimple_cond_rhs (outer_cond))))
1266 return false;
1267 t = canonicalize_cond_expr_cond (t);
1268 if (!t)
1269
1270=== modified file 'gcc/tree-ssa-reassoc.c'
1271--- old/gcc/tree-ssa-reassoc.c 2010-01-13 15:04:38 +0000
1272+++ new/gcc/tree-ssa-reassoc.c 2010-07-30 13:21:51 +0000
1273@@ -1159,6 +1159,117 @@
1274 return changed;
1275 }
1276
1277+/* If OPCODE is BIT_IOR_EXPR or BIT_AND_EXPR and CURR is a comparison
1278+ expression, examine the other OPS to see if any of them are comparisons
1279+ of the same values, which we may be able to combine or eliminate.
1280+ For example, we can rewrite (a < b) | (a == b) as (a <= b). */
1281+
1282+static bool
1283+eliminate_redundant_comparison (enum tree_code opcode,
1284+ VEC (operand_entry_t, heap) **ops,
1285+ unsigned int currindex,
1286+ operand_entry_t curr)
1287+{
1288+ tree op1, op2;
1289+ enum tree_code lcode, rcode;
1290+ gimple def1, def2;
1291+ int i;
1292+ operand_entry_t oe;
1293+
1294+ if (opcode != BIT_IOR_EXPR && opcode != BIT_AND_EXPR)
1295+ return false;
1296+
1297+ /* Check that CURR is a comparison. */
1298+ if (TREE_CODE (curr->op) != SSA_NAME)
1299+ return false;
1300+ def1 = SSA_NAME_DEF_STMT (curr->op);
1301+ if (!is_gimple_assign (def1))
1302+ return false;
1303+ lcode = gimple_assign_rhs_code (def1);
1304+ if (TREE_CODE_CLASS (lcode) != tcc_comparison)
1305+ return false;
1306+ op1 = gimple_assign_rhs1 (def1);
1307+ op2 = gimple_assign_rhs2 (def1);
1308+
1309+ /* Now look for a similar comparison in the remaining OPS. */
1310+ for (i = currindex + 1;
1311+ VEC_iterate (operand_entry_t, *ops, i, oe);
1312+ i++)
1313+ {
1314+ tree t;
1315+
1316+ if (TREE_CODE (oe->op) != SSA_NAME)
1317+ continue;
1318+ def2 = SSA_NAME_DEF_STMT (oe->op);
1319+ if (!is_gimple_assign (def2))
1320+ continue;
1321+ rcode = gimple_assign_rhs_code (def2);
1322+ if (TREE_CODE_CLASS (rcode) != tcc_comparison)
1323+ continue;
1324+
1325+ /* If we got here, we have a match. See if we can combine the
1326+ two comparisons. */
1327+ if (opcode == BIT_IOR_EXPR)
1328+ t = maybe_fold_or_comparisons (lcode, op1, op2,
1329+ rcode, gimple_assign_rhs1 (def2),
1330+ gimple_assign_rhs2 (def2));
1331+ else
1332+ t = maybe_fold_and_comparisons (lcode, op1, op2,
1333+ rcode, gimple_assign_rhs1 (def2),
1334+ gimple_assign_rhs2 (def2));
1335+ if (!t)
1336+ continue;
1337+
1338+ /* maybe_fold_and_comparisons and maybe_fold_or_comparisons
1339+ always give us a boolean_type_node value back. If the original
1340+ BIT_AND_EXPR or BIT_IOR_EXPR was of a wider integer type,
1341+ we need to convert. */
1342+ if (!useless_type_conversion_p (TREE_TYPE (curr->op), TREE_TYPE (t)))
1343+ t = fold_convert (TREE_TYPE (curr->op), t);
1344+
1345+ if (dump_file && (dump_flags & TDF_DETAILS))
1346+ {
1347+ fprintf (dump_file, "Equivalence: ");
1348+ print_generic_expr (dump_file, curr->op, 0);
1349+ fprintf (dump_file, " %s ", op_symbol_code (opcode));
1350+ print_generic_expr (dump_file, oe->op, 0);
1351+ fprintf (dump_file, " -> ");
1352+ print_generic_expr (dump_file, t, 0);
1353+ fprintf (dump_file, "\n");
1354+ }
1355+
1356+ /* Now we can delete oe, as it has been subsumed by the new combined
1357+ expression t. */
1358+ VEC_ordered_remove (operand_entry_t, *ops, i);
1359+ reassociate_stats.ops_eliminated ++;
1360+
1361+ /* If t is the same as curr->op, we're done. Otherwise we must
1362+ replace curr->op with t. Special case is if we got a constant
1363+ back, in which case we add it to the end instead of in place of
1364+ the current entry. */
1365+ if (TREE_CODE (t) == INTEGER_CST)
1366+ {
1367+ VEC_ordered_remove (operand_entry_t, *ops, currindex);
1368+ add_to_ops_vec (ops, t);
1369+ }
1370+ else if (!operand_equal_p (t, curr->op, 0))
1371+ {
1372+ tree tmpvar;
1373+ gimple sum;
1374+ enum tree_code subcode;
1375+ tree newop1;
1376+ tree newop2;
1377+ tmpvar = create_tmp_var (TREE_TYPE (t), NULL);
1378+ add_referenced_var (tmpvar);
1379+ extract_ops_from_tree (t, &subcode, &newop1, &newop2);
1380+ sum = build_and_add_sum (tmpvar, newop1, newop2, subcode);
1381+ curr->op = gimple_get_lhs (sum);
1382+ }
1383+ return true;
1384+ }
1385+
1386+ return false;
1387+}
1388
1389 /* Perform various identities and other optimizations on the list of
1390 operand entries, stored in OPS. The tree code for the binary
1391@@ -1220,7 +1331,8 @@
1392 if (eliminate_not_pairs (opcode, ops, i, oe))
1393 return;
1394 if (eliminate_duplicate_pair (opcode, ops, &done, i, oe, oelast)
1395- || (!done && eliminate_plus_minus_pair (opcode, ops, i, oe)))
1396+ || (!done && eliminate_plus_minus_pair (opcode, ops, i, oe))
1397+ || (!done && eliminate_redundant_comparison (opcode, ops, i, oe)))
1398 {
1399 if (done)
1400 return;
1401