aboutsummaryrefslogtreecommitdiffstats
path: root/meta-oe/recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99452.patch
blob: 6cfc01feff5d70b9b235aa99f4f271072652b06c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
2010-12-14  Sandra Loosemore  <sandra@codesourcery.com>

	Backport from mainline:

	2010-12-14  Jakub Jelinek  <jakub@redhat.com>

	PR tree-optimization/46909

	gcc/
	* tree-ssa-ccp.c (and_var_with_comparison_1): Save partial
	result even in the is_and case, if both partial results
	are the same, return it.
	(or_var_with_comparison_1): Use is_or predicate instead of
	innercode == TRUTH_OR_EXPR test.  Save partial result
	even in the is_or case, if both partial results are the
	same, return it.  In the !is_or case when both partial
	results are the same, return the partial result instead
	of boolean_true_node.

	gcc/testsuite/
	* gcc.c-torture/execute/pr46909-1.c: New test.
	* gcc.c-torture/execute/pr46909-2.c: New test.
	* gcc.dg/pr46909.c: New test.

=== added file 'gcc/testsuite/gcc.c-torture/execute/pr46909-1.c'
--- old/gcc/testsuite/gcc.c-torture/execute/pr46909-1.c	1970-01-01 00:00:00 +0000
+++ new/gcc/testsuite/gcc.c-torture/execute/pr46909-1.c	2011-01-05 11:27:00 +0000
@@ -0,0 +1,22 @@
+/* PR tree-optimization/46909 */
+
+extern void abort ();
+
+int
+__attribute__ ((__noinline__))
+foo (unsigned int x)
+{
+  if (! (x == 4 || x == 6) || (x == 2 || x == 6))
+    return 1;
+  return -1;
+}
+
+int
+main ()
+{
+  int i;
+  for (i = -10; i < 10; i++)
+    if (foo (i) != 1 - 2 * (i == 4))
+      abort ();
+  return 0;
+}

=== added file 'gcc/testsuite/gcc.c-torture/execute/pr46909-2.c'
--- old/gcc/testsuite/gcc.c-torture/execute/pr46909-2.c	1970-01-01 00:00:00 +0000
+++ new/gcc/testsuite/gcc.c-torture/execute/pr46909-2.c	2011-01-05 11:27:00 +0000
@@ -0,0 +1,22 @@
+/* PR tree-optimization/46909 */
+
+extern void abort (void);
+
+int
+__attribute__((noinline))
+foo (int x)
+{
+  if ((x != 0 && x != 13) || x == 5 || x == 20)
+    return 1;
+  return -1;
+}
+
+int
+main (void)
+{
+  int i;
+  for (i = -10; i < 30; i++)
+    if (foo (i) != 1 - 2 * (i == 0) - 2 * (i == 13))
+      abort ();
+  return 0;
+}

=== added file 'gcc/testsuite/gcc.dg/pr46909.c'
--- old/gcc/testsuite/gcc.dg/pr46909.c	1970-01-01 00:00:00 +0000
+++ new/gcc/testsuite/gcc.dg/pr46909.c	2011-01-05 11:27:00 +0000
@@ -0,0 +1,17 @@
+/* PR tree-optimization/46909 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-ifcombine" } */
+
+extern void abort ();
+
+int
+__attribute__ ((__noinline__))
+foo (unsigned int x)
+{
+  if (! (x == 4 || x == 6) || (x == 2 || x == 6))
+    return 1;
+  return -1;
+}
+
+/* { dg-final { scan-tree-dump "optimizing two comparisons to x_\[0-9\]+\\(D\\) != 4" "ifcombine" } } */
+/* { dg-final { cleanup-tree-dump "ifcombine" } } */

=== modified file 'gcc/tree-ssa-ccp.c'
--- old/gcc/tree-ssa-ccp.c	2010-09-16 09:15:46 +0000
+++ new/gcc/tree-ssa-ccp.c	2011-01-05 11:27:00 +0000
@@ -3508,14 +3508,11 @@
 	  /* 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;
-	    }
+	  else if (integer_onep (t))
+	    return boolean_true_node;
+
+	  /* Save partial result for later.  */
+	  partial = t;
 	}
       
       /* Compute the second partial result, (inner2 AND (op2a code op2b)) */
@@ -3536,6 +3533,10 @@
 		return inner1;
 	      else if (integer_zerop (t))
 		return boolean_false_node;
+	      /* If both are the same, we can apply the identity
+		 (x AND x) == x.  */
+	      else if (partial && same_bool_result_p (t, partial))
+		return t;
 	    }
 
 	  /* Handle the OR case. where we are redistributing:
@@ -3945,7 +3946,7 @@
 	     => (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 (is_or)
 	    {
 	      if (integer_onep (t))
 		return boolean_true_node;
@@ -3956,14 +3957,11 @@
 	  /* 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;
-	    }
+	  else if (integer_zerop (t))
+	    return boolean_false_node;
+
+	  /* Save partial result for later.  */
+	  partial = t;
 	}
       
       /* Compute the second partial result, (inner2 OR (op2a code op2b)) */
@@ -3977,13 +3975,18 @@
 	{
 	  /* Handle the OR case, where we are reassociating:
 	     (inner1 OR inner2) OR (op2a code2 op2b)
-	     => (inner1 OR t)  */
-	  if (innercode == TRUTH_OR_EXPR)
+	     => (inner1 OR t)
+	     => (t OR partial)  */
+	  if (is_or)
 	    {
 	      if (integer_zerop (t))
 		return inner1;
 	      else if (integer_onep (t))
 		return boolean_true_node;
+	      /* If both are the same, we can apply the identity
+		 (x OR x) == x.  */
+	      else if (partial && same_bool_result_p (t, partial))
+		return t;
 	    }
 	  
 	  /* Handle the AND case, where we are redistributing:
@@ -4000,13 +4003,13 @@
 		     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.  */
+		     (x AND x) == x.  */
 		  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 t;
 		}
 	    }
 	}