blob: 2d70e111aab85beff3579d2cd71bc7edd9cd1aee [file] [log] [blame]
Alexandre Ramesca0e3a02016-02-03 10:54:07 +00001/*
Roland Levillainfb7fc7b2016-02-24 15:41:20 +00002 * Copyright (C) 2016 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
Alexandre Ramesca0e3a02016-02-03 10:54:07 +000016
17public class Main {
18
19 // A dummy value to defeat inlining of these routines.
20 static boolean doThrow = false;
21
22 public static void assertIntEquals(int expected, int result) {
23 if (expected != result) {
24 throw new Error("Expected: " + expected + ", found: " + result);
25 }
26 }
27
28 public static void assertLongEquals(long expected, long result) {
29 if (expected != result) {
30 throw new Error("Expected: " + expected + ", found: " + result);
31 }
32 }
33
34 /**
35 * Test transformation of Not/Not/And into Or/Not.
36 */
37
38 // Note: before the instruction_simplifier pass, Xor's are used instead of
39 // Not's (the simplification happens during the same pass).
Alexandre Ramesa211a022016-02-04 13:16:08 +000040 /// CHECK-START: int Main.$opt$noinline$andToOr(int, int) instruction_simplifier (before)
Alexandre Ramesca0e3a02016-02-03 10:54:07 +000041 /// CHECK: <<P1:i\d+>> ParameterValue
42 /// CHECK: <<P2:i\d+>> ParameterValue
43 /// CHECK: <<CstM1:i\d+>> IntConstant -1
44 /// CHECK: <<Not1:i\d+>> Xor [<<P1>>,<<CstM1>>]
45 /// CHECK: <<Not2:i\d+>> Xor [<<P2>>,<<CstM1>>]
46 /// CHECK: <<And:i\d+>> And [<<Not1>>,<<Not2>>]
47 /// CHECK: Return [<<And>>]
48
Alexandre Ramesa211a022016-02-04 13:16:08 +000049 /// CHECK-START: int Main.$opt$noinline$andToOr(int, int) instruction_simplifier (after)
Alexandre Ramesca0e3a02016-02-03 10:54:07 +000050 /// CHECK: <<P1:i\d+>> ParameterValue
51 /// CHECK: <<P2:i\d+>> ParameterValue
52 /// CHECK: <<Or:i\d+>> Or [<<P1>>,<<P2>>]
53 /// CHECK: <<Not:i\d+>> Not [<<Or>>]
54 /// CHECK: Return [<<Not>>]
55
Alexandre Ramesa211a022016-02-04 13:16:08 +000056 /// CHECK-START: int Main.$opt$noinline$andToOr(int, int) instruction_simplifier (after)
Alexandre Ramesca0e3a02016-02-03 10:54:07 +000057 /// CHECK: Not
58 /// CHECK-NOT: Not
Alexandre Rames9f980252016-02-05 14:00:28 +000059
60 /// CHECK-START: int Main.$opt$noinline$andToOr(int, int) instruction_simplifier (after)
Alexandre Ramesca0e3a02016-02-03 10:54:07 +000061 /// CHECK-NOT: And
62
63 public static int $opt$noinline$andToOr(int a, int b) {
64 if (doThrow) throw new Error();
65 return ~a & ~b;
66 }
67
68 /**
Alexandre Rames9f980252016-02-05 14:00:28 +000069 * Test transformation of Not/Not/And into Or/Not for boolean negations.
70 * Note that the graph before this instruction simplification pass does not
71 * contain `HBooleanNot` instructions. This is because this transformation
72 * follows the optimization of `HSelect` to `HBooleanNot` occurring in the
73 * same pass.
74 */
75
76 /// CHECK-START: boolean Main.$opt$noinline$booleanAndToOr(boolean, boolean) instruction_simplifier_after_bce (before)
77 /// CHECK: <<P1:z\d+>> ParameterValue
78 /// CHECK: <<P2:z\d+>> ParameterValue
79 /// CHECK-DAG: <<Const0:i\d+>> IntConstant 0
80 /// CHECK-DAG: <<Const1:i\d+>> IntConstant 1
81 /// CHECK: <<Select1:i\d+>> Select [<<Const1>>,<<Const0>>,<<P1>>]
82 /// CHECK: <<Select2:i\d+>> Select [<<Const1>>,<<Const0>>,<<P2>>]
83 /// CHECK: <<And:i\d+>> And [<<Select2>>,<<Select1>>]
84 /// CHECK: Return [<<And>>]
85
86 /// CHECK-START: boolean Main.$opt$noinline$booleanAndToOr(boolean, boolean) instruction_simplifier_after_bce (after)
87 /// CHECK: <<Cond1:z\d+>> ParameterValue
88 /// CHECK: <<Cond2:z\d+>> ParameterValue
89 /// CHECK: <<Or:i\d+>> Or [<<Cond2>>,<<Cond1>>]
90 /// CHECK: <<BooleanNot:z\d+>> BooleanNot [<<Or>>]
91 /// CHECK: Return [<<BooleanNot>>]
92
93 /// CHECK-START: boolean Main.$opt$noinline$booleanAndToOr(boolean, boolean) instruction_simplifier_after_bce (after)
94 /// CHECK: BooleanNot
95 /// CHECK-NOT: BooleanNot
96
97 /// CHECK-START: boolean Main.$opt$noinline$booleanAndToOr(boolean, boolean) instruction_simplifier_after_bce (after)
98 /// CHECK-NOT: And
99
100 public static boolean $opt$noinline$booleanAndToOr(boolean a, boolean b) {
101 if (doThrow) throw new Error();
102 return !a & !b;
103 }
104
105 /**
Alexandre Ramesca0e3a02016-02-03 10:54:07 +0000106 * Test transformation of Not/Not/Or into And/Not.
107 */
108
109 // See note above.
110 // The second Xor has its arguments reversed for no obvious reason.
Alexandre Ramesa211a022016-02-04 13:16:08 +0000111 /// CHECK-START: long Main.$opt$noinline$orToAnd(long, long) instruction_simplifier (before)
Alexandre Ramesca0e3a02016-02-03 10:54:07 +0000112 /// CHECK: <<P1:j\d+>> ParameterValue
113 /// CHECK: <<P2:j\d+>> ParameterValue
114 /// CHECK: <<CstM1:j\d+>> LongConstant -1
115 /// CHECK: <<Not1:j\d+>> Xor [<<P1>>,<<CstM1>>]
116 /// CHECK: <<Not2:j\d+>> Xor [<<CstM1>>,<<P2>>]
117 /// CHECK: <<Or:j\d+>> Or [<<Not1>>,<<Not2>>]
118 /// CHECK: Return [<<Or>>]
119
Alexandre Ramesa211a022016-02-04 13:16:08 +0000120 /// CHECK-START: long Main.$opt$noinline$orToAnd(long, long) instruction_simplifier (after)
Alexandre Ramesca0e3a02016-02-03 10:54:07 +0000121 /// CHECK: <<P1:j\d+>> ParameterValue
122 /// CHECK: <<P2:j\d+>> ParameterValue
123 /// CHECK: <<And:j\d+>> And [<<P1>>,<<P2>>]
124 /// CHECK: <<Not:j\d+>> Not [<<And>>]
125 /// CHECK: Return [<<Not>>]
126
Alexandre Ramesa211a022016-02-04 13:16:08 +0000127 /// CHECK-START: long Main.$opt$noinline$orToAnd(long, long) instruction_simplifier (after)
Alexandre Ramesca0e3a02016-02-03 10:54:07 +0000128 /// CHECK: Not
129 /// CHECK-NOT: Not
Alexandre Rames9f980252016-02-05 14:00:28 +0000130
131 /// CHECK-START: long Main.$opt$noinline$orToAnd(long, long) instruction_simplifier (after)
Alexandre Ramesca0e3a02016-02-03 10:54:07 +0000132 /// CHECK-NOT: Or
133
134 public static long $opt$noinline$orToAnd(long a, long b) {
135 if (doThrow) throw new Error();
136 return ~a | ~b;
137 }
138
139 /**
Alexandre Rames9f980252016-02-05 14:00:28 +0000140 * Test transformation of Not/Not/Or into Or/And for boolean negations.
141 * Note that the graph before this instruction simplification pass does not
142 * contain `HBooleanNot` instructions. This is because this transformation
143 * follows the optimization of `HSelect` to `HBooleanNot` occurring in the
144 * same pass.
145 */
146
147 /// CHECK-START: boolean Main.$opt$noinline$booleanOrToAnd(boolean, boolean) instruction_simplifier_after_bce (before)
148 /// CHECK: <<P1:z\d+>> ParameterValue
149 /// CHECK: <<P2:z\d+>> ParameterValue
150 /// CHECK-DAG: <<Const0:i\d+>> IntConstant 0
151 /// CHECK-DAG: <<Const1:i\d+>> IntConstant 1
152 /// CHECK: <<Select1:i\d+>> Select [<<Const1>>,<<Const0>>,<<P1>>]
153 /// CHECK: <<Select2:i\d+>> Select [<<Const1>>,<<Const0>>,<<P2>>]
154 /// CHECK: <<Or:i\d+>> Or [<<Select2>>,<<Select1>>]
155 /// CHECK: Return [<<Or>>]
156
157 /// CHECK-START: boolean Main.$opt$noinline$booleanOrToAnd(boolean, boolean) instruction_simplifier_after_bce (after)
158 /// CHECK: <<Cond1:z\d+>> ParameterValue
159 /// CHECK: <<Cond2:z\d+>> ParameterValue
160 /// CHECK: <<And:i\d+>> And [<<Cond2>>,<<Cond1>>]
161 /// CHECK: <<BooleanNot:z\d+>> BooleanNot [<<And>>]
162 /// CHECK: Return [<<BooleanNot>>]
163
164 /// CHECK-START: boolean Main.$opt$noinline$booleanOrToAnd(boolean, boolean) instruction_simplifier_after_bce (after)
165 /// CHECK: BooleanNot
166 /// CHECK-NOT: BooleanNot
167
168 /// CHECK-START: boolean Main.$opt$noinline$booleanOrToAnd(boolean, boolean) instruction_simplifier_after_bce (after)
169 /// CHECK-NOT: Or
170
171 public static boolean $opt$noinline$booleanOrToAnd(boolean a, boolean b) {
172 if (doThrow) throw new Error();
173 return !a | !b;
174 }
175
176 /**
Alexandre Ramesca0e3a02016-02-03 10:54:07 +0000177 * Test that the transformation copes with inputs being separated from the
178 * bitwise operations.
179 * This is a regression test. The initial logic was inserting the new bitwise
180 * operation incorrectly.
181 */
182
Alexandre Ramesa211a022016-02-04 13:16:08 +0000183 /// CHECK-START: int Main.$opt$noinline$regressInputsAway(int, int) instruction_simplifier (before)
Alexandre Ramesca0e3a02016-02-03 10:54:07 +0000184 /// CHECK: <<P1:i\d+>> ParameterValue
185 /// CHECK: <<P2:i\d+>> ParameterValue
186 /// CHECK-DAG: <<Cst1:i\d+>> IntConstant 1
187 /// CHECK-DAG: <<CstM1:i\d+>> IntConstant -1
188 /// CHECK: <<AddP1:i\d+>> Add [<<P1>>,<<Cst1>>]
189 /// CHECK: <<Not1:i\d+>> Xor [<<AddP1>>,<<CstM1>>]
190 /// CHECK: <<AddP2:i\d+>> Add [<<P2>>,<<Cst1>>]
191 /// CHECK: <<Not2:i\d+>> Xor [<<AddP2>>,<<CstM1>>]
192 /// CHECK: <<Or:i\d+>> Or [<<Not1>>,<<Not2>>]
193 /// CHECK: Return [<<Or>>]
194
Alexandre Ramesa211a022016-02-04 13:16:08 +0000195 /// CHECK-START: int Main.$opt$noinline$regressInputsAway(int, int) instruction_simplifier (after)
Alexandre Ramesca0e3a02016-02-03 10:54:07 +0000196 /// CHECK: <<P1:i\d+>> ParameterValue
197 /// CHECK: <<P2:i\d+>> ParameterValue
198 /// CHECK: <<Cst1:i\d+>> IntConstant 1
199 /// CHECK: <<AddP1:i\d+>> Add [<<P1>>,<<Cst1>>]
200 /// CHECK: <<AddP2:i\d+>> Add [<<P2>>,<<Cst1>>]
201 /// CHECK: <<And:i\d+>> And [<<AddP1>>,<<AddP2>>]
202 /// CHECK: <<Not:i\d+>> Not [<<And>>]
203 /// CHECK: Return [<<Not>>]
204
Alexandre Ramesa211a022016-02-04 13:16:08 +0000205 /// CHECK-START: int Main.$opt$noinline$regressInputsAway(int, int) instruction_simplifier (after)
Alexandre Ramesca0e3a02016-02-03 10:54:07 +0000206 /// CHECK: Not
207 /// CHECK-NOT: Not
Alexandre Rames9f980252016-02-05 14:00:28 +0000208
209 /// CHECK-START: int Main.$opt$noinline$regressInputsAway(int, int) instruction_simplifier (after)
Alexandre Ramesca0e3a02016-02-03 10:54:07 +0000210 /// CHECK-NOT: Or
211
212 public static int $opt$noinline$regressInputsAway(int a, int b) {
213 if (doThrow) throw new Error();
214 int a1 = a + 1;
215 int not_a1 = ~a1;
216 int b1 = b + 1;
217 int not_b1 = ~b1;
218 return not_a1 | not_b1;
219 }
220
221 /**
222 * Test transformation of Not/Not/Xor into Xor.
223 */
224
225 // See first note above.
Alexandre Ramesa211a022016-02-04 13:16:08 +0000226 /// CHECK-START: int Main.$opt$noinline$notXorToXor(int, int) instruction_simplifier (before)
Alexandre Ramesca0e3a02016-02-03 10:54:07 +0000227 /// CHECK: <<P1:i\d+>> ParameterValue
228 /// CHECK: <<P2:i\d+>> ParameterValue
229 /// CHECK: <<CstM1:i\d+>> IntConstant -1
230 /// CHECK: <<Not1:i\d+>> Xor [<<P1>>,<<CstM1>>]
231 /// CHECK: <<Not2:i\d+>> Xor [<<P2>>,<<CstM1>>]
232 /// CHECK: <<Xor:i\d+>> Xor [<<Not1>>,<<Not2>>]
233 /// CHECK: Return [<<Xor>>]
234
Alexandre Ramesa211a022016-02-04 13:16:08 +0000235 /// CHECK-START: int Main.$opt$noinline$notXorToXor(int, int) instruction_simplifier (after)
Alexandre Ramesca0e3a02016-02-03 10:54:07 +0000236 /// CHECK: <<P1:i\d+>> ParameterValue
237 /// CHECK: <<P2:i\d+>> ParameterValue
238 /// CHECK: <<Xor:i\d+>> Xor [<<P1>>,<<P2>>]
239 /// CHECK: Return [<<Xor>>]
240
Alexandre Ramesa211a022016-02-04 13:16:08 +0000241 /// CHECK-START: int Main.$opt$noinline$notXorToXor(int, int) instruction_simplifier (after)
Alexandre Ramesca0e3a02016-02-03 10:54:07 +0000242 /// CHECK-NOT: Not
243
244 public static int $opt$noinline$notXorToXor(int a, int b) {
245 if (doThrow) throw new Error();
246 return ~a ^ ~b;
247 }
248
249 /**
Alexandre Rames9f980252016-02-05 14:00:28 +0000250 * Test transformation of Not/Not/Xor into Xor for boolean negations.
251 * Note that the graph before this instruction simplification pass does not
252 * contain `HBooleanNot` instructions. This is because this transformation
253 * follows the optimization of `HSelect` to `HBooleanNot` occurring in the
254 * same pass.
255 */
256
257 /// CHECK-START: boolean Main.$opt$noinline$booleanNotXorToXor(boolean, boolean) instruction_simplifier_after_bce (before)
258 /// CHECK: <<P1:z\d+>> ParameterValue
259 /// CHECK: <<P2:z\d+>> ParameterValue
260 /// CHECK-DAG: <<Const0:i\d+>> IntConstant 0
261 /// CHECK-DAG: <<Const1:i\d+>> IntConstant 1
262 /// CHECK: <<Select1:i\d+>> Select [<<Const1>>,<<Const0>>,<<P1>>]
263 /// CHECK: <<Select2:i\d+>> Select [<<Const1>>,<<Const0>>,<<P2>>]
264 /// CHECK: <<Xor:i\d+>> Xor [<<Select2>>,<<Select1>>]
265 /// CHECK: Return [<<Xor>>]
266
267 /// CHECK-START: boolean Main.$opt$noinline$booleanNotXorToXor(boolean, boolean) instruction_simplifier_after_bce (after)
268 /// CHECK: <<Cond1:z\d+>> ParameterValue
269 /// CHECK: <<Cond2:z\d+>> ParameterValue
270 /// CHECK: <<Xor:i\d+>> Xor [<<Cond2>>,<<Cond1>>]
271 /// CHECK: Return [<<Xor>>]
272
273 /// CHECK-START: boolean Main.$opt$noinline$booleanNotXorToXor(boolean, boolean) instruction_simplifier_after_bce (after)
274 /// CHECK-NOT: BooleanNot
275
276 public static boolean $opt$noinline$booleanNotXorToXor(boolean a, boolean b) {
277 if (doThrow) throw new Error();
278 return !a ^ !b;
279 }
280
281 /**
Alexandre Ramesca0e3a02016-02-03 10:54:07 +0000282 * Check that no transformation is done when one Not has multiple uses.
283 */
284
Alexandre Ramesa211a022016-02-04 13:16:08 +0000285 /// CHECK-START: int Main.$opt$noinline$notMultipleUses(int, int) instruction_simplifier (before)
Alexandre Ramesca0e3a02016-02-03 10:54:07 +0000286 /// CHECK: <<P1:i\d+>> ParameterValue
287 /// CHECK: <<P2:i\d+>> ParameterValue
288 /// CHECK: <<CstM1:i\d+>> IntConstant -1
289 /// CHECK: <<One:i\d+>> IntConstant 1
290 /// CHECK: <<Not2:i\d+>> Xor [<<P2>>,<<CstM1>>]
291 /// CHECK: <<And2:i\d+>> And [<<Not2>>,<<One>>]
292 /// CHECK: <<Not1:i\d+>> Xor [<<P1>>,<<CstM1>>]
293 /// CHECK: <<And1:i\d+>> And [<<Not1>>,<<Not2>>]
294 /// CHECK: <<Add:i\d+>> Add [<<And2>>,<<And1>>]
295 /// CHECK: Return [<<Add>>]
296
Alexandre Ramesa211a022016-02-04 13:16:08 +0000297 /// CHECK-START: int Main.$opt$noinline$notMultipleUses(int, int) instruction_simplifier (after)
Alexandre Ramesca0e3a02016-02-03 10:54:07 +0000298 /// CHECK: <<P1:i\d+>> ParameterValue
299 /// CHECK: <<P2:i\d+>> ParameterValue
300 /// CHECK: <<One:i\d+>> IntConstant 1
301 /// CHECK: <<Not2:i\d+>> Not [<<P2>>]
302 /// CHECK: <<And2:i\d+>> And [<<Not2>>,<<One>>]
303 /// CHECK: <<Not1:i\d+>> Not [<<P1>>]
304 /// CHECK: <<And1:i\d+>> And [<<Not1>>,<<Not2>>]
305 /// CHECK: <<Add:i\d+>> Add [<<And2>>,<<And1>>]
306 /// CHECK: Return [<<Add>>]
307
Alexandre Ramesa211a022016-02-04 13:16:08 +0000308 /// CHECK-START: int Main.$opt$noinline$notMultipleUses(int, int) instruction_simplifier (after)
Alexandre Ramesca0e3a02016-02-03 10:54:07 +0000309 /// CHECK-NOT: Or
310
311 public static int $opt$noinline$notMultipleUses(int a, int b) {
312 if (doThrow) throw new Error();
313 int tmp = ~b;
314 return (tmp & 0x1) + (~a & tmp);
315 }
316
317 public static void main(String[] args) {
318 assertIntEquals(~0xff, $opt$noinline$andToOr(0xf, 0xff));
319 assertLongEquals(~0xf, $opt$noinline$orToAnd(0xf, 0xff));
320 assertIntEquals(0xf0, $opt$noinline$notXorToXor(0xf, 0xff));
321 assertIntEquals(~0xff, $opt$noinline$notMultipleUses(0xf, 0xff));
322 }
323}