blob: 56ceadfa6c1486069f9543b4ed5fbd44eb517ffa [file] [log] [blame]
Alexandre Ramesb2fd7bc2015-03-11 16:48:16 +00001/*
2* Copyright (C) 2015 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*/
16
17public class Main {
18
19 public static void assertIntEquals(int expected, int result) {
20 if (expected != result) {
21 throw new Error("Expected: " + expected + ", found: " + result);
22 }
23 }
24
25 public static void assertLongEquals(long expected, long result) {
26 if (expected != result) {
27 throw new Error("Expected: " + expected + ", found: " + result);
28 }
29 }
30
31 /**
32 * Tiny programs exercising optimizations of arithmetic identities.
33 */
34
35 // CHECK-START: long Main.Add0(long) instruction_simplifier (before)
36 // CHECK-DAG: [[Arg:j\d+]] ParameterValue
37 // CHECK-DAG: [[Const0:j\d+]] LongConstant 0
38 // CHECK-DAG: [[Add:j\d+]] Add [ [[Const0]] [[Arg]] ]
39 // CHECK-DAG: Return [ [[Add]] ]
40
41 // CHECK-START: long Main.Add0(long) instruction_simplifier (after)
42 // CHECK-DAG: [[Arg:j\d+]] ParameterValue
Alexandre Ramesb2fd7bc2015-03-11 16:48:16 +000043 // CHECK-DAG: Return [ [[Arg]] ]
Alexandre Rames74417692015-04-09 15:21:41 +010044 //
45 // CHECK-START: long Main.Add0(long) instruction_simplifier (after)
46 // CHECK-NOT: Add
Alexandre Ramesb2fd7bc2015-03-11 16:48:16 +000047
48 public static long Add0(long arg) {
49 return 0 + arg;
50 }
51
52 // CHECK-START: int Main.AndAllOnes(int) instruction_simplifier (before)
53 // CHECK-DAG: [[Arg:i\d+]] ParameterValue
54 // CHECK-DAG: [[ConstF:i\d+]] IntConstant -1
55 // CHECK-DAG: [[And:i\d+]] And [ [[Arg]] [[ConstF]] ]
56 // CHECK-DAG: Return [ [[And]] ]
57
58 // CHECK-START: int Main.AndAllOnes(int) instruction_simplifier (after)
59 // CHECK-DAG: [[Arg:i\d+]] ParameterValue
Alexandre Ramesb2fd7bc2015-03-11 16:48:16 +000060 // CHECK-DAG: Return [ [[Arg]] ]
61
Alexandre Rames74417692015-04-09 15:21:41 +010062 // CHECK-START: int Main.AndAllOnes(int) instruction_simplifier (after)
63 // CHECK-NOT: And
64
Alexandre Ramesb2fd7bc2015-03-11 16:48:16 +000065 public static int AndAllOnes(int arg) {
66 return arg & -1;
67 }
68
69 // CHECK-START: long Main.Div1(long) instruction_simplifier (before)
70 // CHECK-DAG: [[Arg:j\d+]] ParameterValue
71 // CHECK-DAG: [[Const1:j\d+]] LongConstant 1
72 // CHECK-DAG: [[Div:j\d+]] Div [ [[Arg]] [[Const1]] ]
73 // CHECK-DAG: Return [ [[Div]] ]
74
75 // CHECK-START: long Main.Div1(long) instruction_simplifier (after)
76 // CHECK-DAG: [[Arg:j\d+]] ParameterValue
Alexandre Ramesb2fd7bc2015-03-11 16:48:16 +000077 // CHECK-DAG: Return [ [[Arg]] ]
78
Alexandre Rames74417692015-04-09 15:21:41 +010079 // CHECK-START: long Main.Div1(long) instruction_simplifier (after)
80 // CHECK-NOT: Div
81
Alexandre Ramesb2fd7bc2015-03-11 16:48:16 +000082 public static long Div1(long arg) {
83 return arg / 1;
84 }
85
86 // CHECK-START: int Main.DivN1(int) instruction_simplifier (before)
87 // CHECK-DAG: [[Arg:i\d+]] ParameterValue
88 // CHECK-DAG: [[ConstN1:i\d+]] IntConstant -1
89 // CHECK-DAG: [[Div:i\d+]] Div [ [[Arg]] [[ConstN1]] ]
90 // CHECK-DAG: Return [ [[Div]] ]
91
92 // CHECK-START: int Main.DivN1(int) instruction_simplifier (after)
93 // CHECK-DAG: [[Arg:i\d+]] ParameterValue
94 // CHECK-DAG: [[Neg:i\d+]] Neg [ [[Arg]] ]
Alexandre Ramesb2fd7bc2015-03-11 16:48:16 +000095 // CHECK-DAG: Return [ [[Neg]] ]
96
Alexandre Rames74417692015-04-09 15:21:41 +010097 // CHECK-START: int Main.DivN1(int) instruction_simplifier (after)
98 // CHECK-NOT: Div
99
Alexandre Ramesb2fd7bc2015-03-11 16:48:16 +0000100 public static int DivN1(int arg) {
101 return arg / -1;
102 }
103
104 // CHECK-START: long Main.Mul1(long) instruction_simplifier (before)
105 // CHECK-DAG: [[Arg:j\d+]] ParameterValue
106 // CHECK-DAG: [[Const1:j\d+]] LongConstant 1
107 // CHECK-DAG: [[Mul:j\d+]] Mul [ [[Arg]] [[Const1]] ]
108 // CHECK-DAG: Return [ [[Mul]] ]
109
110 // CHECK-START: long Main.Mul1(long) instruction_simplifier (after)
111 // CHECK-DAG: [[Arg:j\d+]] ParameterValue
Alexandre Ramesb2fd7bc2015-03-11 16:48:16 +0000112 // CHECK-DAG: Return [ [[Arg]] ]
113
Alexandre Rames74417692015-04-09 15:21:41 +0100114 // CHECK-START: long Main.Mul1(long) instruction_simplifier (after)
115 // CHECK-NOT: Mul
116
Alexandre Ramesb2fd7bc2015-03-11 16:48:16 +0000117 public static long Mul1(long arg) {
118 return arg * 1;
119 }
120
121 // CHECK-START: int Main.MulN1(int) instruction_simplifier (before)
122 // CHECK-DAG: [[Arg:i\d+]] ParameterValue
123 // CHECK-DAG: [[ConstN1:i\d+]] IntConstant -1
124 // CHECK-DAG: [[Mul:i\d+]] Mul [ [[Arg]] [[ConstN1]] ]
125 // CHECK-DAG: Return [ [[Mul]] ]
126
127 // CHECK-START: int Main.MulN1(int) instruction_simplifier (after)
128 // CHECK-DAG: [[Arg:i\d+]] ParameterValue
129 // CHECK-DAG: [[Neg:i\d+]] Neg [ [[Arg]] ]
Alexandre Ramesb2fd7bc2015-03-11 16:48:16 +0000130 // CHECK-DAG: Return [ [[Neg]] ]
131
Alexandre Rames74417692015-04-09 15:21:41 +0100132 // CHECK-START: int Main.MulN1(int) instruction_simplifier (after)
133 // CHECK-NOT: Mul
134
Alexandre Ramesb2fd7bc2015-03-11 16:48:16 +0000135 public static int MulN1(int arg) {
136 return arg * -1;
137 }
138
139 // CHECK-START: long Main.MulPowerOfTwo128(long) instruction_simplifier (before)
140 // CHECK-DAG: [[Arg:j\d+]] ParameterValue
141 // CHECK-DAG: [[Const128:j\d+]] LongConstant 128
142 // CHECK-DAG: [[Mul:j\d+]] Mul [ [[Arg]] [[Const128]] ]
143 // CHECK-DAG: Return [ [[Mul]] ]
144
145 // CHECK-START: long Main.MulPowerOfTwo128(long) instruction_simplifier (after)
146 // CHECK-DAG: [[Arg:j\d+]] ParameterValue
147 // CHECK-DAG: [[Const7:i\d+]] IntConstant 7
148 // CHECK-DAG: [[Shl:j\d+]] Shl [ [[Arg]] [[Const7]] ]
Alexandre Ramesb2fd7bc2015-03-11 16:48:16 +0000149 // CHECK-DAG: Return [ [[Shl]] ]
150
Alexandre Rames74417692015-04-09 15:21:41 +0100151 // CHECK-START: long Main.MulPowerOfTwo128(long) instruction_simplifier (after)
152 // CHECK-NOT: Mul
153
Alexandre Ramesb2fd7bc2015-03-11 16:48:16 +0000154 public static long MulPowerOfTwo128(long arg) {
155 return arg * 128;
156 }
157
158 // CHECK-START: int Main.Or0(int) instruction_simplifier (before)
159 // CHECK-DAG: [[Arg:i\d+]] ParameterValue
160 // CHECK-DAG: [[Const0:i\d+]] IntConstant 0
161 // CHECK-DAG: [[Or:i\d+]] Or [ [[Arg]] [[Const0]] ]
162 // CHECK-DAG: Return [ [[Or]] ]
163
164 // CHECK-START: int Main.Or0(int) instruction_simplifier (after)
165 // CHECK-DAG: [[Arg:i\d+]] ParameterValue
Alexandre Ramesb2fd7bc2015-03-11 16:48:16 +0000166 // CHECK-DAG: Return [ [[Arg]] ]
167
Alexandre Rames74417692015-04-09 15:21:41 +0100168 // CHECK-START: int Main.Or0(int) instruction_simplifier (after)
169 // CHECK-NOT: Or
170
Alexandre Ramesb2fd7bc2015-03-11 16:48:16 +0000171 public static int Or0(int arg) {
172 return arg | 0;
173 }
174
175 // CHECK-START: long Main.OrSame(long) instruction_simplifier (before)
176 // CHECK-DAG: [[Arg:j\d+]] ParameterValue
177 // CHECK-DAG: [[Or:j\d+]] Or [ [[Arg]] [[Arg]] ]
178 // CHECK-DAG: Return [ [[Or]] ]
179
180 // CHECK-START: long Main.OrSame(long) instruction_simplifier (after)
181 // CHECK-DAG: [[Arg:j\d+]] ParameterValue
Alexandre Ramesb2fd7bc2015-03-11 16:48:16 +0000182 // CHECK-DAG: Return [ [[Arg]] ]
183
Alexandre Rames74417692015-04-09 15:21:41 +0100184 // CHECK-START: long Main.OrSame(long) instruction_simplifier (after)
185 // CHECK-NOT: Or
186
Alexandre Ramesb2fd7bc2015-03-11 16:48:16 +0000187 public static long OrSame(long arg) {
188 return arg | arg;
189 }
190
191 // CHECK-START: int Main.Shl0(int) instruction_simplifier (before)
192 // CHECK-DAG: [[Arg:i\d+]] ParameterValue
193 // CHECK-DAG: [[Const0:i\d+]] IntConstant 0
194 // CHECK-DAG: [[Shl:i\d+]] Shl [ [[Arg]] [[Const0]] ]
195 // CHECK-DAG: Return [ [[Shl]] ]
196
197 // CHECK-START: int Main.Shl0(int) instruction_simplifier (after)
198 // CHECK-DAG: [[Arg:i\d+]] ParameterValue
Alexandre Ramesb2fd7bc2015-03-11 16:48:16 +0000199 // CHECK-DAG: Return [ [[Arg]] ]
200
Alexandre Rames74417692015-04-09 15:21:41 +0100201 // CHECK-START: int Main.Shl0(int) instruction_simplifier (after)
202 // CHECK-NOT: Shl
203
Alexandre Ramesb2fd7bc2015-03-11 16:48:16 +0000204 public static int Shl0(int arg) {
205 return arg << 0;
206 }
207
208 // CHECK-START: long Main.Shr0(long) instruction_simplifier (before)
209 // CHECK-DAG: [[Arg:j\d+]] ParameterValue
210 // CHECK-DAG: [[Const0:i\d+]] IntConstant 0
211 // CHECK-DAG: [[Shr:j\d+]] Shr [ [[Arg]] [[Const0]] ]
212 // CHECK-DAG: Return [ [[Shr]] ]
213
214 // CHECK-START: long Main.Shr0(long) instruction_simplifier (after)
215 // CHECK-DAG: [[Arg:j\d+]] ParameterValue
Alexandre Ramesb2fd7bc2015-03-11 16:48:16 +0000216 // CHECK-DAG: Return [ [[Arg]] ]
217
Alexandre Rames74417692015-04-09 15:21:41 +0100218 // CHECK-START: long Main.Shr0(long) instruction_simplifier (after)
219 // CHECK-NOT: Shr
220
Alexandre Ramesb2fd7bc2015-03-11 16:48:16 +0000221 public static long Shr0(long arg) {
222 return arg >> 0;
223 }
224
225 // CHECK-START: long Main.Sub0(long) instruction_simplifier (before)
226 // CHECK-DAG: [[Arg:j\d+]] ParameterValue
227 // CHECK-DAG: [[Const0:j\d+]] LongConstant 0
228 // CHECK-DAG: [[Sub:j\d+]] Sub [ [[Arg]] [[Const0]] ]
229 // CHECK-DAG: Return [ [[Sub]] ]
230
231 // CHECK-START: long Main.Sub0(long) instruction_simplifier (after)
232 // CHECK-DAG: [[Arg:j\d+]] ParameterValue
Alexandre Ramesb2fd7bc2015-03-11 16:48:16 +0000233 // CHECK-DAG: Return [ [[Arg]] ]
234
Alexandre Rames74417692015-04-09 15:21:41 +0100235 // CHECK-START: long Main.Sub0(long) instruction_simplifier (after)
236 // CHECK-NOT: Sub
237
Alexandre Ramesb2fd7bc2015-03-11 16:48:16 +0000238 public static long Sub0(long arg) {
239 return arg - 0;
240 }
241
242 // CHECK-START: int Main.SubAliasNeg(int) instruction_simplifier (before)
243 // CHECK-DAG: [[Arg:i\d+]] ParameterValue
244 // CHECK-DAG: [[Const0:i\d+]] IntConstant 0
245 // CHECK-DAG: [[Sub:i\d+]] Sub [ [[Const0]] [[Arg]] ]
246 // CHECK-DAG: Return [ [[Sub]] ]
247
248 // CHECK-START: int Main.SubAliasNeg(int) instruction_simplifier (after)
249 // CHECK-DAG: [[Arg:i\d+]] ParameterValue
250 // CHECK-DAG: [[Neg:i\d+]] Neg [ [[Arg]] ]
Alexandre Ramesb2fd7bc2015-03-11 16:48:16 +0000251 // CHECK-DAG: Return [ [[Neg]] ]
252
Alexandre Rames74417692015-04-09 15:21:41 +0100253 // CHECK-START: int Main.SubAliasNeg(int) instruction_simplifier (after)
254 // CHECK-NOT: Sub
255
Alexandre Ramesb2fd7bc2015-03-11 16:48:16 +0000256 public static int SubAliasNeg(int arg) {
257 return 0 - arg;
258 }
259
260 // CHECK-START: long Main.UShr0(long) instruction_simplifier (before)
261 // CHECK-DAG: [[Arg:j\d+]] ParameterValue
262 // CHECK-DAG: [[Const0:i\d+]] IntConstant 0
263 // CHECK-DAG: [[UShr:j\d+]] UShr [ [[Arg]] [[Const0]] ]
264 // CHECK-DAG: Return [ [[UShr]] ]
265
266 // CHECK-START: long Main.UShr0(long) instruction_simplifier (after)
267 // CHECK-DAG: [[Arg:j\d+]] ParameterValue
Alexandre Ramesb2fd7bc2015-03-11 16:48:16 +0000268 // CHECK-DAG: Return [ [[Arg]] ]
269
Alexandre Rames74417692015-04-09 15:21:41 +0100270 // CHECK-START: long Main.UShr0(long) instruction_simplifier (after)
271 // CHECK-NOT: UShr
272
Alexandre Ramesb2fd7bc2015-03-11 16:48:16 +0000273 public static long UShr0(long arg) {
274 return arg >>> 0;
275 }
276
277 // CHECK-START: int Main.Xor0(int) instruction_simplifier (before)
278 // CHECK-DAG: [[Arg:i\d+]] ParameterValue
279 // CHECK-DAG: [[Const0:i\d+]] IntConstant 0
280 // CHECK-DAG: [[Xor:i\d+]] Xor [ [[Arg]] [[Const0]] ]
281 // CHECK-DAG: Return [ [[Xor]] ]
282
283 // CHECK-START: int Main.Xor0(int) instruction_simplifier (after)
284 // CHECK-DAG: [[Arg:i\d+]] ParameterValue
Alexandre Ramesb2fd7bc2015-03-11 16:48:16 +0000285 // CHECK-DAG: Return [ [[Arg]] ]
286
Alexandre Rames74417692015-04-09 15:21:41 +0100287 // CHECK-START: int Main.Xor0(int) instruction_simplifier (after)
288 // CHECK-NOT: Xor
289
Alexandre Ramesb2fd7bc2015-03-11 16:48:16 +0000290 public static int Xor0(int arg) {
291 return arg ^ 0;
292 }
293
294 // CHECK-START: int Main.XorAllOnes(int) instruction_simplifier (before)
295 // CHECK-DAG: [[Arg:i\d+]] ParameterValue
296 // CHECK-DAG: [[ConstF:i\d+]] IntConstant -1
297 // CHECK-DAG: [[Xor:i\d+]] Xor [ [[Arg]] [[ConstF]] ]
298 // CHECK-DAG: Return [ [[Xor]] ]
299
300 // CHECK-START: int Main.XorAllOnes(int) instruction_simplifier (after)
301 // CHECK-DAG: [[Arg:i\d+]] ParameterValue
302 // CHECK-DAG: [[Not:i\d+]] Not [ [[Arg]] ]
Alexandre Ramesb2fd7bc2015-03-11 16:48:16 +0000303 // CHECK-DAG: Return [ [[Not]] ]
304
Alexandre Rames74417692015-04-09 15:21:41 +0100305 // CHECK-START: int Main.XorAllOnes(int) instruction_simplifier (after)
306 // CHECK-NOT: Xor
307
Alexandre Ramesb2fd7bc2015-03-11 16:48:16 +0000308 public static int XorAllOnes(int arg) {
309 return arg ^ -1;
310 }
311
Alexandre Rames188d4312015-04-09 18:30:21 +0100312 /**
313 * Test that addition or subtraction operation with both inputs negated are
314 * optimized to use a single negation after the operation.
315 * The transformation tested is implemented in
316 * `InstructionSimplifierVisitor::TryMoveNegOnInputsAfterBinop`.
317 */
318
319 // CHECK-START: int Main.AddNegs1(int, int) instruction_simplifier (before)
320 // CHECK-DAG: [[Arg1:i\d+]] ParameterValue
321 // CHECK-DAG: [[Arg2:i\d+]] ParameterValue
322 // CHECK-DAG: [[Neg1:i\d+]] Neg [ [[Arg1]] ]
323 // CHECK-DAG: [[Neg2:i\d+]] Neg [ [[Arg2]] ]
324 // CHECK-DAG: [[Add:i\d+]] Add [ [[Neg1]] [[Neg2]] ]
325 // CHECK-DAG: Return [ [[Add]] ]
326
327 // CHECK-START: int Main.AddNegs1(int, int) instruction_simplifier (after)
328 // CHECK-DAG: [[Arg1:i\d+]] ParameterValue
329 // CHECK-DAG: [[Arg2:i\d+]] ParameterValue
330 // CHECK-NOT: Neg
331 // CHECK-DAG: [[Add:i\d+]] Add [ [[Arg1]] [[Arg2]] ]
332 // CHECK-DAG: [[Neg:i\d+]] Neg [ [[Add]] ]
333 // CHECK-DAG: Return [ [[Neg]] ]
334
335 public static int AddNegs1(int arg1, int arg2) {
336 return -arg1 + -arg2;
337 }
338
339 /**
340 * This is similar to the test-case AddNegs1, but the negations have
341 * multiple uses.
342 * The transformation tested is implemented in
343 * `InstructionSimplifierVisitor::TryMoveNegOnInputsAfterBinop`.
344 * The current code won't perform the previous optimization. The
345 * transformations do not look at other uses of their inputs. As they don't
346 * know what will happen with other uses, they do not take the risk of
347 * increasing the register pressure by creating or extending live ranges.
348 */
349
350 // CHECK-START: int Main.AddNegs2(int, int) instruction_simplifier (before)
351 // CHECK-DAG: [[Arg1:i\d+]] ParameterValue
352 // CHECK-DAG: [[Arg2:i\d+]] ParameterValue
353 // CHECK-DAG: [[Neg1:i\d+]] Neg [ [[Arg1]] ]
354 // CHECK-DAG: [[Neg2:i\d+]] Neg [ [[Arg2]] ]
355 // CHECK-DAG: [[Add1:i\d+]] Add [ [[Neg1]] [[Neg2]] ]
356 // CHECK-DAG: [[Add2:i\d+]] Add [ [[Neg1]] [[Neg2]] ]
357 // CHECK-DAG: [[Or:i\d+]] Or [ [[Add1]] [[Add2]] ]
358 // CHECK-DAG: Return [ [[Or]] ]
359
360 // CHECK-START: int Main.AddNegs2(int, int) instruction_simplifier (after)
361 // CHECK-DAG: [[Arg1:i\d+]] ParameterValue
362 // CHECK-DAG: [[Arg2:i\d+]] ParameterValue
363 // CHECK-DAG: [[Neg1:i\d+]] Neg [ [[Arg1]] ]
364 // CHECK-DAG: [[Neg2:i\d+]] Neg [ [[Arg2]] ]
365 // CHECK-DAG: [[Add1:i\d+]] Add [ [[Neg1]] [[Neg2]] ]
366 // CHECK-DAG: [[Add2:i\d+]] Add [ [[Neg1]] [[Neg2]] ]
367 // CHECK-NOT: Neg
368 // CHECK-DAG: [[Or:i\d+]] Or [ [[Add1]] [[Add2]] ]
369 // CHECK-DAG: Return [ [[Or]] ]
370
Alexandre Ramesb2a58472015-04-17 14:35:18 +0100371 // CHECK-START: int Main.AddNegs2(int, int) GVN (after)
372 // CHECK-DAG: [[Arg1:i\d+]] ParameterValue
373 // CHECK-DAG: [[Arg2:i\d+]] ParameterValue
374 // CHECK-DAG: [[Neg1:i\d+]] Neg [ [[Arg1]] ]
375 // CHECK-DAG: [[Neg2:i\d+]] Neg [ [[Arg2]] ]
376 // CHECK-DAG: [[Add:i\d+]] Add [ [[Neg1]] [[Neg2]] ]
377 // CHECK-DAG: [[Or:i\d+]] Or [ [[Add]] [[Add]] ]
378 // CHECK-DAG: Return [ [[Or]] ]
379
Alexandre Rames188d4312015-04-09 18:30:21 +0100380 public static int AddNegs2(int arg1, int arg2) {
381 int temp1 = -arg1;
382 int temp2 = -arg2;
383 return (temp1 + temp2) | (temp1 + temp2);
384 }
385
386 /**
387 * This follows test-cases AddNegs1 and AddNegs2.
388 * The transformation tested is implemented in
389 * `InstructionSimplifierVisitor::TryMoveNegOnInputsAfterBinop`.
390 * The optimization should not happen if it moves an additional instruction in
391 * the loop.
392 */
393
394 // CHECK-START: long Main.AddNegs3(long, long) instruction_simplifier (before)
395 // -------------- Arguments and initial negation operations.
396 // CHECK-DAG: [[Arg1:j\d+]] ParameterValue
397 // CHECK-DAG: [[Arg2:j\d+]] ParameterValue
398 // CHECK-DAG: [[Neg1:j\d+]] Neg [ [[Arg1]] ]
399 // CHECK-DAG: [[Neg2:j\d+]] Neg [ [[Arg2]] ]
400 // CHECK: Goto
401 // -------------- Loop
402 // CHECK: SuspendCheck
403 // CHECK: [[Add:j\d+]] Add [ [[Neg1]] [[Neg2]] ]
404 // CHECK: Goto
405
406 // CHECK-START: long Main.AddNegs3(long, long) instruction_simplifier (after)
407 // -------------- Arguments and initial negation operations.
408 // CHECK-DAG: [[Arg1:j\d+]] ParameterValue
409 // CHECK-DAG: [[Arg2:j\d+]] ParameterValue
410 // CHECK-DAG: [[Neg1:j\d+]] Neg [ [[Arg1]] ]
411 // CHECK-DAG: [[Neg2:j\d+]] Neg [ [[Arg2]] ]
412 // CHECK: Goto
413 // -------------- Loop
414 // CHECK: SuspendCheck
415 // CHECK: [[Add:j\d+]] Add [ [[Neg1]] [[Neg2]] ]
416 // CHECK-NOT: Neg
417 // CHECK: Goto
418
419 public static long AddNegs3(long arg1, long arg2) {
420 long res = 0;
421 long n_arg1 = -arg1;
422 long n_arg2 = -arg2;
423 for (long i = 0; i < 1; i++) {
424 res += n_arg1 + n_arg2 + i;
425 }
426 return res;
427 }
428
429 /**
430 * Test the simplification of an addition with a negated argument into a
431 * subtraction.
432 * The transformation tested is implemented in `InstructionSimplifierVisitor::VisitAdd`.
433 */
434
435 // CHECK-START: long Main.AddNeg1(long, long) instruction_simplifier (before)
436 // CHECK-DAG: [[Arg1:j\d+]] ParameterValue
437 // CHECK-DAG: [[Arg2:j\d+]] ParameterValue
438 // CHECK-DAG: [[Neg:j\d+]] Neg [ [[Arg1]] ]
439 // CHECK-DAG: [[Add:j\d+]] Add [ [[Neg]] [[Arg2]] ]
440 // CHECK-DAG: Return [ [[Add]] ]
441
442 // CHECK-START: long Main.AddNeg1(long, long) instruction_simplifier (after)
443 // CHECK-DAG: [[Arg1:j\d+]] ParameterValue
444 // CHECK-DAG: [[Arg2:j\d+]] ParameterValue
445 // CHECK-DAG: [[Sub:j\d+]] Sub [ [[Arg2]] [[Arg1]] ]
446 // CHECK-DAG: Return [ [[Sub]] ]
447
448 // CHECK-START: long Main.AddNeg1(long, long) instruction_simplifier (after)
449 // CHECK-NOT: Neg
450 // CHECK-NOT: Add
451
452 public static long AddNeg1(long arg1, long arg2) {
453 return -arg1 + arg2;
454 }
455
456 /**
457 * This is similar to the test-case AddNeg1, but the negation has two uses.
458 * The transformation tested is implemented in `InstructionSimplifierVisitor::VisitAdd`.
459 * The current code won't perform the previous optimization. The
460 * transformations do not look at other uses of their inputs. As they don't
461 * know what will happen with other uses, they do not take the risk of
462 * increasing the register pressure by creating or extending live ranges.
463 */
464
465 // CHECK-START: long Main.AddNeg2(long, long) instruction_simplifier (before)
466 // CHECK-DAG: [[Arg1:j\d+]] ParameterValue
467 // CHECK-DAG: [[Arg2:j\d+]] ParameterValue
468 // CHECK-DAG: [[Neg:j\d+]] Neg [ [[Arg2]] ]
469 // CHECK-DAG: [[Add1:j\d+]] Add [ [[Arg1]] [[Neg]] ]
470 // CHECK-DAG: [[Add2:j\d+]] Add [ [[Arg1]] [[Neg]] ]
471 // CHECK-DAG: [[Res:j\d+]] Or [ [[Add1]] [[Add2]] ]
472 // CHECK-DAG: Return [ [[Res]] ]
473
474 // CHECK-START: long Main.AddNeg2(long, long) instruction_simplifier (after)
475 // CHECK-DAG: [[Arg1:j\d+]] ParameterValue
476 // CHECK-DAG: [[Arg2:j\d+]] ParameterValue
477 // CHECK-DAG: [[Neg:j\d+]] Neg [ [[Arg2]] ]
478 // CHECK-DAG: [[Add1:j\d+]] Add [ [[Arg1]] [[Neg]] ]
479 // CHECK-DAG: [[Add2:j\d+]] Add [ [[Arg1]] [[Neg]] ]
480 // CHECK-DAG: [[Res:j\d+]] Or [ [[Add1]] [[Add2]] ]
481 // CHECK-DAG: Return [ [[Res]] ]
482
483 // CHECK-START: long Main.AddNeg2(long, long) instruction_simplifier (after)
484 // CHECK-NOT: Sub
485
486 public static long AddNeg2(long arg1, long arg2) {
487 long temp = -arg2;
488 return (arg1 + temp) | (arg1 + temp);
489 }
490
491 /**
492 * Test simplification of the `-(-var)` pattern.
493 * The transformation tested is implemented in `InstructionSimplifierVisitor::VisitNeg`.
494 */
495
496 // CHECK-START: long Main.NegNeg1(long) instruction_simplifier (before)
497 // CHECK-DAG: [[Arg:j\d+]] ParameterValue
498 // CHECK-DAG: [[Neg1:j\d+]] Neg [ [[Arg]] ]
499 // CHECK-DAG: [[Neg2:j\d+]] Neg [ [[Neg1]] ]
500 // CHECK-DAG: Return [ [[Neg2]] ]
501
502 // CHECK-START: long Main.NegNeg1(long) instruction_simplifier (after)
503 // CHECK-DAG: [[Arg:j\d+]] ParameterValue
504 // CHECK-DAG: Return [ [[Arg]] ]
505
506 // CHECK-START: long Main.NegNeg1(long) instruction_simplifier (after)
507 // CHECK-NOT: Neg
508
509 public static long NegNeg1(long arg) {
510 return -(-arg);
511 }
512
513 /**
514 * Test 'multi-step' simplification, where a first transformation yields a
515 * new simplification possibility for the current instruction.
516 * The transformations tested are implemented in `InstructionSimplifierVisitor::VisitNeg`
517 * and in `InstructionSimplifierVisitor::VisitAdd`.
518 */
519
520 // CHECK-START: int Main.NegNeg2(int) instruction_simplifier (before)
521 // CHECK-DAG: [[Arg:i\d+]] ParameterValue
522 // CHECK-DAG: [[Neg1:i\d+]] Neg [ [[Arg]] ]
523 // CHECK-DAG: [[Neg2:i\d+]] Neg [ [[Neg1]] ]
524 // CHECK-DAG: [[Add:i\d+]] Add [ [[Neg1]] [[Neg2]] ]
525 // CHECK-DAG: Return [ [[Add]] ]
526
527 // CHECK-START: int Main.NegNeg2(int) instruction_simplifier (after)
528 // CHECK-DAG: [[Arg:i\d+]] ParameterValue
529 // CHECK-DAG: [[Sub:i\d+]] Sub [ [[Arg]] [[Arg]] ]
530 // CHECK-DAG: Return [ [[Sub]] ]
531
532 // CHECK-START: int Main.NegNeg2(int) instruction_simplifier (after)
533 // CHECK-NOT: Neg
534 // CHECK-NOT: Add
535
Alexandre Ramesb2a58472015-04-17 14:35:18 +0100536 // CHECK-START: int Main.NegNeg2(int) constant_folding_after_inlining (after)
537 // CHECK: [[Const0:i\d+]] IntConstant 0
538 // CHECK-NOT: Neg
539 // CHECK-NOT: Add
540 // CHECK: Return [ [[Const0]] ]
541
Alexandre Rames188d4312015-04-09 18:30:21 +0100542 public static int NegNeg2(int arg) {
543 int temp = -arg;
544 return temp + -temp;
545 }
546
547 /**
548 * Test another 'multi-step' simplification, where a first transformation
549 * yields a new simplification possibility for the current instruction.
550 * The transformations tested are implemented in `InstructionSimplifierVisitor::VisitNeg`
551 * and in `InstructionSimplifierVisitor::VisitSub`.
552 */
553
554 // CHECK-START: long Main.NegNeg3(long) instruction_simplifier (before)
555 // CHECK-DAG: [[Arg:j\d+]] ParameterValue
556 // CHECK-DAG: [[Const0:j\d+]] LongConstant 0
557 // CHECK-DAG: [[Neg:j\d+]] Neg [ [[Arg]] ]
558 // CHECK-DAG: [[Sub:j\d+]] Sub [ [[Const0]] [[Neg]] ]
559 // CHECK-DAG: Return [ [[Sub]] ]
560
561 // CHECK-START: long Main.NegNeg3(long) instruction_simplifier (after)
562 // CHECK-DAG: [[Arg:j\d+]] ParameterValue
563 // CHECK-DAG: Return [ [[Arg]] ]
564
565 // CHECK-START: long Main.NegNeg3(long) instruction_simplifier (after)
566 // CHECK-NOT: Neg
567 // CHECK-NOT: Sub
568
569 public static long NegNeg3(long arg) {
570 return 0 - -arg;
571 }
572
573 /**
574 * Test that a negated subtraction is simplified to a subtraction with its
575 * arguments reversed.
576 * The transformation tested is implemented in `InstructionSimplifierVisitor::VisitNeg`.
577 */
578
579 // CHECK-START: int Main.NegSub1(int, int) instruction_simplifier (before)
580 // CHECK-DAG: [[Arg1:i\d+]] ParameterValue
581 // CHECK-DAG: [[Arg2:i\d+]] ParameterValue
582 // CHECK-DAG: [[Sub:i\d+]] Sub [ [[Arg1]] [[Arg2]] ]
583 // CHECK-DAG: [[Neg:i\d+]] Neg [ [[Sub]] ]
584 // CHECK-DAG: Return [ [[Neg]] ]
585
586 // CHECK-START: int Main.NegSub1(int, int) instruction_simplifier (after)
587 // CHECK-DAG: [[Arg1:i\d+]] ParameterValue
588 // CHECK-DAG: [[Arg2:i\d+]] ParameterValue
589 // CHECK-DAG: [[Sub:i\d+]] Sub [ [[Arg2]] [[Arg1]] ]
590 // CHECK-DAG: Return [ [[Sub]] ]
591
592 // CHECK-START: int Main.NegSub1(int, int) instruction_simplifier (after)
593 // CHECK-NOT: Neg
594
595 public static int NegSub1(int arg1, int arg2) {
596 return -(arg1 - arg2);
597 }
598
599 /**
600 * This is similar to the test-case NegSub1, but the subtraction has
601 * multiple uses.
602 * The transformation tested is implemented in `InstructionSimplifierVisitor::VisitNeg`.
603 * The current code won't perform the previous optimization. The
604 * transformations do not look at other uses of their inputs. As they don't
605 * know what will happen with other uses, they do not take the risk of
606 * increasing the register pressure by creating or extending live ranges.
607 */
608
609 // CHECK-START: int Main.NegSub2(int, int) instruction_simplifier (before)
610 // CHECK-DAG: [[Arg1:i\d+]] ParameterValue
611 // CHECK-DAG: [[Arg2:i\d+]] ParameterValue
612 // CHECK-DAG: [[Sub:i\d+]] Sub [ [[Arg1]] [[Arg2]] ]
613 // CHECK-DAG: [[Neg1:i\d+]] Neg [ [[Sub]] ]
614 // CHECK-DAG: [[Neg2:i\d+]] Neg [ [[Sub]] ]
615 // CHECK-DAG: [[Or:i\d+]] Or [ [[Neg1]] [[Neg2]] ]
616 // CHECK-DAG: Return [ [[Or]] ]
617
618 // CHECK-START: int Main.NegSub2(int, int) instruction_simplifier (after)
619 // CHECK-DAG: [[Arg1:i\d+]] ParameterValue
620 // CHECK-DAG: [[Arg2:i\d+]] ParameterValue
621 // CHECK-DAG: [[Sub:i\d+]] Sub [ [[Arg1]] [[Arg2]] ]
622 // CHECK-DAG: [[Neg1:i\d+]] Neg [ [[Sub]] ]
623 // CHECK-DAG: [[Neg2:i\d+]] Neg [ [[Sub]] ]
624 // CHECK-DAG: [[Or:i\d+]] Or [ [[Neg1]] [[Neg2]] ]
625 // CHECK-DAG: Return [ [[Or]] ]
626
627 public static int NegSub2(int arg1, int arg2) {
628 int temp = arg1 - arg2;
629 return -temp | -temp;
630 }
631
632 /**
633 * Test simplification of the `~~var` pattern.
634 * The transformation tested is implemented in `InstructionSimplifierVisitor::VisitNot`.
635 */
636
637 // CHECK-START: long Main.NotNot1(long) instruction_simplifier (before)
638 // CHECK-DAG: [[Arg:j\d+]] ParameterValue
639 // CHECK-DAG: [[ConstF1:j\d+]] LongConstant -1
640 // CHECK-DAG: [[Xor1:j\d+]] Xor [ [[Arg]] [[ConstF1]] ]
641 // CHECK-DAG: [[Xor2:j\d+]] Xor [ [[Xor1]] [[ConstF1]] ]
642 // CHECK-DAG: Return [ [[Xor2]] ]
643
644 // CHECK-START: long Main.NotNot1(long) instruction_simplifier (after)
645 // CHECK-DAG: [[Arg:j\d+]] ParameterValue
646 // CHECK-DAG: Return [ [[Arg]] ]
647
648 // CHECK-START: long Main.NotNot1(long) instruction_simplifier (after)
649 // CHECK-NOT: Xor
650
651 public static long NotNot1(long arg) {
652 return ~~arg;
653 }
654
655 // CHECK-START: int Main.NotNot2(int) instruction_simplifier (before)
656 // CHECK-DAG: [[Arg:i\d+]] ParameterValue
657 // CHECK-DAG: [[ConstF1:i\d+]] IntConstant -1
658 // CHECK-DAG: [[Xor1:i\d+]] Xor [ [[Arg]] [[ConstF1]] ]
659 // CHECK-DAG: [[Xor2:i\d+]] Xor [ [[Xor1]] [[ConstF1]] ]
660 // CHECK-DAG: [[Add:i\d+]] Add [ [[Xor1]] [[Xor2]] ]
661 // CHECK-DAG: Return [ [[Add]] ]
662
663 // CHECK-START: int Main.NotNot2(int) instruction_simplifier (after)
664 // CHECK-DAG: [[Arg:i\d+]] ParameterValue
665 // CHECK-DAG: [[Not:i\d+]] Not [ [[Arg]] ]
666 // CHECK-DAG: [[Add:i\d+]] Add [ [[Not]] [[Arg]] ]
667 // CHECK-DAG: Return [ [[Add]] ]
668
669 // CHECK-START: int Main.NotNot2(int) instruction_simplifier (after)
670 // CHECK-NOT: Xor
671
672 public static int NotNot2(int arg) {
673 int temp = ~arg;
674 return temp + ~temp;
675 }
676
677 /**
678 * Test the simplification of a subtraction with a negated argument.
679 * The transformation tested is implemented in `InstructionSimplifierVisitor::VisitSub`.
680 */
681
682 // CHECK-START: int Main.SubNeg1(int, int) instruction_simplifier (before)
683 // CHECK-DAG: [[Arg1:i\d+]] ParameterValue
684 // CHECK-DAG: [[Arg2:i\d+]] ParameterValue
685 // CHECK-DAG: [[Neg:i\d+]] Neg [ [[Arg1]] ]
686 // CHECK-DAG: [[Sub:i\d+]] Sub [ [[Neg]] [[Arg2]] ]
687 // CHECK-DAG: Return [ [[Sub]] ]
688
689 // CHECK-START: int Main.SubNeg1(int, int) instruction_simplifier (after)
690 // CHECK-DAG: [[Arg1:i\d+]] ParameterValue
691 // CHECK-DAG: [[Arg2:i\d+]] ParameterValue
692 // CHECK-DAG: [[Add:i\d+]] Add [ [[Arg1]] [[Arg2]] ]
693 // CHECK-DAG: [[Neg:i\d+]] Neg [ [[Add]] ]
694 // CHECK-DAG: Return [ [[Neg]] ]
695
696 // CHECK-START: int Main.SubNeg1(int, int) instruction_simplifier (after)
697 // CHECK-NOT: Sub
698
699 public static int SubNeg1(int arg1, int arg2) {
700 return -arg1 - arg2;
701 }
702
703 /**
704 * This is similar to the test-case SubNeg1, but the negation has
705 * multiple uses.
706 * The transformation tested is implemented in `InstructionSimplifierVisitor::VisitSub`.
707 * The current code won't perform the previous optimization. The
708 * transformations do not look at other uses of their inputs. As they don't
709 * know what will happen with other uses, they do not take the risk of
710 * increasing the register pressure by creating or extending live ranges.
711 */
712
713 // CHECK-START: int Main.SubNeg2(int, int) instruction_simplifier (before)
714 // CHECK-DAG: [[Arg1:i\d+]] ParameterValue
715 // CHECK-DAG: [[Arg2:i\d+]] ParameterValue
716 // CHECK-DAG: [[Neg:i\d+]] Neg [ [[Arg1]] ]
717 // CHECK-DAG: [[Sub1:i\d+]] Sub [ [[Neg]] [[Arg2]] ]
718 // CHECK-DAG: [[Sub2:i\d+]] Sub [ [[Neg]] [[Arg2]] ]
719 // CHECK-DAG: [[Or:i\d+]] Or [ [[Sub1]] [[Sub2]] ]
720 // CHECK-DAG: Return [ [[Or]] ]
721
722 // CHECK-START: int Main.SubNeg2(int, int) instruction_simplifier (after)
723 // CHECK-DAG: [[Arg1:i\d+]] ParameterValue
724 // CHECK-DAG: [[Arg2:i\d+]] ParameterValue
725 // CHECK-DAG: [[Neg:i\d+]] Neg [ [[Arg1]] ]
726 // CHECK-DAG: [[Sub1:i\d+]] Sub [ [[Neg]] [[Arg2]] ]
727 // CHECK-DAG: [[Sub2:i\d+]] Sub [ [[Neg]] [[Arg2]] ]
728 // CHECK-DAG: [[Or:i\d+]] Or [ [[Sub1]] [[Sub2]] ]
729 // CHECK-DAG: Return [ [[Or]] ]
730
731 // CHECK-START: int Main.SubNeg2(int, int) instruction_simplifier (after)
732 // CHECK-NOT: Add
733
734 public static int SubNeg2(int arg1, int arg2) {
735 int temp = -arg1;
736 return (temp - arg2) | (temp - arg2);
737 }
738
739 /**
740 * This follows test-cases SubNeg1 and SubNeg2.
741 * The transformation tested is implemented in `InstructionSimplifierVisitor::VisitSub`.
742 * The optimization should not happen if it moves an additional instruction in
743 * the loop.
744 */
745
746 // CHECK-START: long Main.SubNeg3(long, long) instruction_simplifier (before)
747 // -------------- Arguments and initial negation operation.
748 // CHECK-DAG: [[Arg1:j\d+]] ParameterValue
749 // CHECK-DAG: [[Arg2:j\d+]] ParameterValue
750 // CHECK-DAG: [[Neg:j\d+]] Neg [ [[Arg1]] ]
751 // CHECK: Goto
752 // -------------- Loop
753 // CHECK: SuspendCheck
754 // CHECK: [[Sub:j\d+]] Sub [ [[Neg]] [[Arg2]] ]
755 // CHECK: Goto
756
757 // CHECK-START: long Main.SubNeg3(long, long) instruction_simplifier (after)
758 // -------------- Arguments and initial negation operation.
759 // CHECK-DAG: [[Arg1:j\d+]] ParameterValue
760 // CHECK-DAG: [[Arg2:j\d+]] ParameterValue
761 // CHECK-DAG: [[Neg:j\d+]] Neg [ [[Arg1]] ]
762 // CHECK-DAG: Goto
763 // -------------- Loop
764 // CHECK: SuspendCheck
765 // CHECK: [[Sub:j\d+]] Sub [ [[Neg]] [[Arg2]] ]
766 // CHECK-NOT: Neg
767 // CHECK: Goto
768
769 public static long SubNeg3(long arg1, long arg2) {
770 long res = 0;
771 long temp = -arg1;
772 for (long i = 0; i < 1; i++) {
773 res += temp - arg2 - i;
774 }
775 return res;
776 }
777
Alexandre Ramesb2fd7bc2015-03-11 16:48:16 +0000778 public static void main(String[] args) {
779 int arg = 123456;
780
781 assertLongEquals(Add0(arg), arg);
782 assertIntEquals(AndAllOnes(arg), arg);
783 assertLongEquals(Div1(arg), arg);
784 assertIntEquals(DivN1(arg), -arg);
785 assertLongEquals(Mul1(arg), arg);
786 assertIntEquals(MulN1(arg), -arg);
787 assertLongEquals(MulPowerOfTwo128(arg), (128 * arg));
788 assertIntEquals(Or0(arg), arg);
789 assertLongEquals(OrSame(arg), arg);
790 assertIntEquals(Shl0(arg), arg);
791 assertLongEquals(Shr0(arg), arg);
792 assertLongEquals(Sub0(arg), arg);
793 assertIntEquals(SubAliasNeg(arg), -arg);
794 assertLongEquals(UShr0(arg), arg);
795 assertIntEquals(Xor0(arg), arg);
796 assertIntEquals(XorAllOnes(arg), ~arg);
Alexandre Rames188d4312015-04-09 18:30:21 +0100797 assertIntEquals(AddNegs1(arg, arg + 1), -(arg + arg + 1));
798 assertIntEquals(AddNegs2(arg, arg + 1), -(arg + arg + 1));
799 assertLongEquals(AddNegs3(arg, arg + 1), -(2 * arg + 1));
800 assertLongEquals(AddNeg1(arg, arg + 1), 1);
801 assertLongEquals(AddNeg2(arg, arg + 1), -1);
802 assertLongEquals(NegNeg1(arg), arg);
803 assertIntEquals(NegNeg2(arg), 0);
804 assertLongEquals(NegNeg3(arg), arg);
805 assertIntEquals(NegSub1(arg, arg + 1), 1);
806 assertIntEquals(NegSub2(arg, arg + 1), 1);
807 assertLongEquals(NotNot1(arg), arg);
808 assertIntEquals(NotNot2(arg), -1);
809 assertIntEquals(SubNeg1(arg, arg + 1), -(arg + arg + 1));
810 assertIntEquals(SubNeg2(arg, arg + 1), -(arg + arg + 1));
811 assertLongEquals(SubNeg3(arg, arg + 1), -(2 * arg + 1));
Alexandre Ramesb2fd7bc2015-03-11 16:48:16 +0000812 }
813}