blob: 810f0faaa6f4361ce3e73af64a39fc78bddc13d5 [file] [log] [blame]
Alexandre Rames418318f2015-11-20 15:55:47 +00001/*
Roland Levillainfb7fc7b2016-02-24 15:41:20 +00002 * 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 */
Alexandre Rames418318f2015-11-20 15:55:47 +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 basic merging of `MUL+ADD` into `MULADD`.
36 */
37
38 /// CHECK-START-ARM64: int Main.$opt$noinline$mulAdd(int, int, int) instruction_simplifier_arm64 (before)
39 /// CHECK: <<Acc:i\d+>> ParameterValue
40 /// CHECK: <<Left:i\d+>> ParameterValue
41 /// CHECK: <<Right:i\d+>> ParameterValue
42 /// CHECK: <<Mul:i\d+>> Mul [<<Left>>,<<Right>>]
43 /// CHECK: <<Add:i\d+>> Add [<<Acc>>,<<Mul>>]
44 /// CHECK: Return [<<Add>>]
45
46 /// CHECK-START-ARM64: int Main.$opt$noinline$mulAdd(int, int, int) instruction_simplifier_arm64 (after)
47 /// CHECK: <<Acc:i\d+>> ParameterValue
48 /// CHECK: <<Left:i\d+>> ParameterValue
49 /// CHECK: <<Right:i\d+>> ParameterValue
Artem Udovichenko4a0dad62016-01-26 12:28:31 +030050 /// CHECK: <<MulAdd:i\d+>> MultiplyAccumulate [<<Acc>>,<<Left>>,<<Right>>] kind:Add
Alexandre Rames418318f2015-11-20 15:55:47 +000051 /// CHECK: Return [<<MulAdd>>]
52
53 /// CHECK-START-ARM64: int Main.$opt$noinline$mulAdd(int, int, int) instruction_simplifier_arm64 (after)
54 /// CHECK-NOT: Mul
55 /// CHECK-NOT: Add
56
57 /// CHECK-START-ARM64: int Main.$opt$noinline$mulAdd(int, int, int) disassembly (after)
58 /// CHECK: madd w{{\d+}}, w{{\d+}}, w{{\d+}}, w{{\d+}}
59
Artem Udovichenko4a0dad62016-01-26 12:28:31 +030060 /// CHECK-START-ARM: int Main.$opt$noinline$mulAdd(int, int, int) instruction_simplifier_arm (before)
61 /// CHECK: <<Acc:i\d+>> ParameterValue
62 /// CHECK: <<Left:i\d+>> ParameterValue
63 /// CHECK: <<Right:i\d+>> ParameterValue
64 /// CHECK: <<Mul:i\d+>> Mul [<<Left>>,<<Right>>]
65 /// CHECK: <<Add:i\d+>> Add [<<Acc>>,<<Mul>>]
66 /// CHECK: Return [<<Add>>]
67
68 /// CHECK-START-ARM: int Main.$opt$noinline$mulAdd(int, int, int) instruction_simplifier_arm (after)
69 /// CHECK: <<Acc:i\d+>> ParameterValue
70 /// CHECK: <<Left:i\d+>> ParameterValue
71 /// CHECK: <<Right:i\d+>> ParameterValue
72 /// CHECK: <<MulAdd:i\d+>> MultiplyAccumulate [<<Acc>>,<<Left>>,<<Right>>] kind:Add
73 /// CHECK: Return [<<MulAdd>>]
74
75 /// CHECK-START-ARM: int Main.$opt$noinline$mulAdd(int, int, int) instruction_simplifier_arm (after)
76 /// CHECK-NOT: Mul
77 /// CHECK-NOT: Add
78
79 /// CHECK-START-ARM: int Main.$opt$noinline$mulAdd(int, int, int) disassembly (after)
80 /// CHECK: mla r{{\d+}}, r{{\d+}}, r{{\d+}}, r{{\d+}}
81
Alexandre Rames418318f2015-11-20 15:55:47 +000082 public static int $opt$noinline$mulAdd(int acc, int left, int right) {
83 if (doThrow) throw new Error();
84 return acc + left * right;
85 }
86
87 /**
88 * Test basic merging of `MUL+SUB` into `MULSUB`.
89 */
90
91 /// CHECK-START-ARM64: long Main.$opt$noinline$mulSub(long, long, long) instruction_simplifier_arm64 (before)
92 /// CHECK: <<Acc:j\d+>> ParameterValue
93 /// CHECK: <<Left:j\d+>> ParameterValue
94 /// CHECK: <<Right:j\d+>> ParameterValue
95 /// CHECK: <<Mul:j\d+>> Mul [<<Left>>,<<Right>>]
96 /// CHECK: <<Sub:j\d+>> Sub [<<Acc>>,<<Mul>>]
97 /// CHECK: Return [<<Sub>>]
98
99 /// CHECK-START-ARM64: long Main.$opt$noinline$mulSub(long, long, long) instruction_simplifier_arm64 (after)
100 /// CHECK: <<Acc:j\d+>> ParameterValue
101 /// CHECK: <<Left:j\d+>> ParameterValue
102 /// CHECK: <<Right:j\d+>> ParameterValue
Artem Udovichenko4a0dad62016-01-26 12:28:31 +0300103 /// CHECK: <<MulSub:j\d+>> MultiplyAccumulate [<<Acc>>,<<Left>>,<<Right>>] kind:Sub
Alexandre Rames418318f2015-11-20 15:55:47 +0000104 /// CHECK: Return [<<MulSub>>]
105
106 /// CHECK-START-ARM64: long Main.$opt$noinline$mulSub(long, long, long) instruction_simplifier_arm64 (after)
107 /// CHECK-NOT: Mul
108 /// CHECK-NOT: Sub
109
110 /// CHECK-START-ARM64: long Main.$opt$noinline$mulSub(long, long, long) disassembly (after)
111 /// CHECK: msub x{{\d+}}, x{{\d+}}, x{{\d+}}, x{{\d+}}
112
Artem Udovichenko4a0dad62016-01-26 12:28:31 +0300113 /// CHECK-START-ARM: long Main.$opt$noinline$mulSub(long, long, long) instruction_simplifier_arm (before)
114 /// CHECK: <<Acc:j\d+>> ParameterValue
115 /// CHECK: <<Left:j\d+>> ParameterValue
116 /// CHECK: <<Right:j\d+>> ParameterValue
117 /// CHECK: <<Mul:j\d+>> Mul [<<Left>>,<<Right>>]
118 /// CHECK: <<Sub:j\d+>> Sub [<<Acc>>,<<Mul>>]
119 /// CHECK: Return [<<Sub>>]
120
121 /// CHECK-START-ARM: long Main.$opt$noinline$mulSub(long, long, long) instruction_simplifier_arm (after)
122 /// CHECK-NOT: MultiplyAccumulate
123
Alexandre Rames418318f2015-11-20 15:55:47 +0000124 public static long $opt$noinline$mulSub(long acc, long left, long right) {
125 if (doThrow) throw new Error();
126 return acc - left * right;
127 }
128
129 /**
130 * Test that we do not create a multiply-accumulate instruction when there
131 * are other uses of the multiplication that cannot merge it.
132 */
133
134 /// CHECK-START-ARM64: int Main.$opt$noinline$multipleUses1(int, int, int) instruction_simplifier_arm64 (before)
135 /// CHECK: <<Acc:i\d+>> ParameterValue
136 /// CHECK: <<Left:i\d+>> ParameterValue
137 /// CHECK: <<Right:i\d+>> ParameterValue
138 /// CHECK: <<Mul:i\d+>> Mul [<<Left>>,<<Right>>]
139 /// CHECK: <<Add:i\d+>> Add [<<Acc>>,<<Mul>>]
140 /// CHECK: <<Or:i\d+>> Or [<<Mul>>,<<Add>>]
141 /// CHECK: Return [<<Or>>]
142
143 /// CHECK-START-ARM64: int Main.$opt$noinline$multipleUses1(int, int, int) instruction_simplifier_arm64 (after)
144 /// CHECK: <<Acc:i\d+>> ParameterValue
145 /// CHECK: <<Left:i\d+>> ParameterValue
146 /// CHECK: <<Right:i\d+>> ParameterValue
147 /// CHECK: <<Mul:i\d+>> Mul [<<Left>>,<<Right>>]
148 /// CHECK: <<Add:i\d+>> Add [<<Acc>>,<<Mul>>]
149 /// CHECK: <<Or:i\d+>> Or [<<Mul>>,<<Add>>]
150 /// CHECK: Return [<<Or>>]
151
152 /// CHECK-START-ARM64: int Main.$opt$noinline$multipleUses1(int, int, int) instruction_simplifier_arm64 (after)
Artem Udovichenko4a0dad62016-01-26 12:28:31 +0300153 /// CHECK-NOT: MultiplyAccumulate
154
155 /// CHECK-START-ARM: int Main.$opt$noinline$multipleUses1(int, int, int) instruction_simplifier_arm (before)
156 /// CHECK: <<Acc:i\d+>> ParameterValue
157 /// CHECK: <<Left:i\d+>> ParameterValue
158 /// CHECK: <<Right:i\d+>> ParameterValue
159 /// CHECK: <<Mul:i\d+>> Mul [<<Left>>,<<Right>>]
160 /// CHECK: <<Add:i\d+>> Add [<<Acc>>,<<Mul>>]
161 /// CHECK: <<Or:i\d+>> Or [<<Mul>>,<<Add>>]
162 /// CHECK: Return [<<Or>>]
163
164 /// CHECK-START-ARM: int Main.$opt$noinline$multipleUses1(int, int, int) instruction_simplifier_arm (after)
165 /// CHECK: <<Acc:i\d+>> ParameterValue
166 /// CHECK: <<Left:i\d+>> ParameterValue
167 /// CHECK: <<Right:i\d+>> ParameterValue
168 /// CHECK: <<Mul:i\d+>> Mul [<<Left>>,<<Right>>]
169 /// CHECK: <<Add:i\d+>> Add [<<Acc>>,<<Mul>>]
170 /// CHECK: <<Or:i\d+>> Or [<<Mul>>,<<Add>>]
171 /// CHECK: Return [<<Or>>]
172
173 /// CHECK-START-ARM: int Main.$opt$noinline$multipleUses1(int, int, int) instruction_simplifier_arm (after)
174 /// CHECK-NOT: MultiplyAccumulate
Alexandre Rames418318f2015-11-20 15:55:47 +0000175
176 public static int $opt$noinline$multipleUses1(int acc, int left, int right) {
177 if (doThrow) throw new Error();
178 int temp = left * right;
179 return temp | (acc + temp);
180 }
181
182 /**
183 * Test that we do not create a multiply-accumulate instruction even when all
184 * uses of the multiplication can merge it.
185 */
186
187 /// CHECK-START-ARM64: long Main.$opt$noinline$multipleUses2(long, long, long) instruction_simplifier_arm64 (before)
188 /// CHECK: <<Acc:j\d+>> ParameterValue
189 /// CHECK: <<Left:j\d+>> ParameterValue
190 /// CHECK: <<Right:j\d+>> ParameterValue
191 /// CHECK: <<Mul:j\d+>> Mul [<<Left>>,<<Right>>]
192 /// CHECK: <<Add:j\d+>> Add [<<Acc>>,<<Mul>>]
193 /// CHECK: <<Sub:j\d+>> Sub [<<Acc>>,<<Mul>>]
194 /// CHECK: <<Res:j\d+>> Add [<<Add>>,<<Sub>>]
195 /// CHECK: Return [<<Res>>]
196
197 /// CHECK-START-ARM64: long Main.$opt$noinline$multipleUses2(long, long, long) instruction_simplifier_arm64 (after)
198 /// CHECK: <<Acc:j\d+>> ParameterValue
199 /// CHECK: <<Left:j\d+>> ParameterValue
200 /// CHECK: <<Right:j\d+>> ParameterValue
201 /// CHECK: <<Mul:j\d+>> Mul [<<Left>>,<<Right>>]
202 /// CHECK: <<Add:j\d+>> Add [<<Acc>>,<<Mul>>]
203 /// CHECK: <<Sub:j\d+>> Sub [<<Acc>>,<<Mul>>]
204 /// CHECK: <<Res:j\d+>> Add [<<Add>>,<<Sub>>]
205 /// CHECK: Return [<<Res>>]
206
207 /// CHECK-START-ARM64: long Main.$opt$noinline$multipleUses2(long, long, long) instruction_simplifier_arm64 (after)
Artem Udovichenko4a0dad62016-01-26 12:28:31 +0300208 /// CHECK-NOT: MultiplyAccumulate
209
210 /// CHECK-START-ARM: long Main.$opt$noinline$multipleUses2(long, long, long) instruction_simplifier_arm (before)
211 /// CHECK: <<Acc:j\d+>> ParameterValue
212 /// CHECK: <<Left:j\d+>> ParameterValue
213 /// CHECK: <<Right:j\d+>> ParameterValue
214 /// CHECK: <<Mul:j\d+>> Mul [<<Left>>,<<Right>>]
215 /// CHECK: <<Add:j\d+>> Add [<<Acc>>,<<Mul>>]
216 /// CHECK: <<Sub:j\d+>> Sub [<<Acc>>,<<Mul>>]
217 /// CHECK: <<Res:j\d+>> Add [<<Add>>,<<Sub>>]
218 /// CHECK: Return [<<Res>>]
219
220 /// CHECK-START-ARM: long Main.$opt$noinline$multipleUses2(long, long, long) instruction_simplifier_arm (after)
221 /// CHECK: <<Acc:j\d+>> ParameterValue
222 /// CHECK: <<Left:j\d+>> ParameterValue
223 /// CHECK: <<Right:j\d+>> ParameterValue
224 /// CHECK: <<Mul:j\d+>> Mul [<<Left>>,<<Right>>]
225 /// CHECK: <<Add:j\d+>> Add [<<Acc>>,<<Mul>>]
226 /// CHECK: <<Sub:j\d+>> Sub [<<Acc>>,<<Mul>>]
227 /// CHECK: <<Res:j\d+>> Add [<<Add>>,<<Sub>>]
228 /// CHECK: Return [<<Res>>]
229
230 /// CHECK-START-ARM: long Main.$opt$noinline$multipleUses2(long, long, long) instruction_simplifier_arm (after)
231 /// CHECK-NOT: MultiplyAccumulate
Alexandre Rames418318f2015-11-20 15:55:47 +0000232
233
234 public static long $opt$noinline$multipleUses2(long acc, long left, long right) {
235 if (doThrow) throw new Error();
236 long temp = left * right;
237 return (acc + temp) + (acc - temp);
238 }
239
240
241 /**
242 * Test the interpretation of `a * (b + 1)` as `a + (a * b)`.
243 */
244
245 /// CHECK-START-ARM64: int Main.$opt$noinline$mulPlusOne(int, int) instruction_simplifier_arm64 (before)
246 /// CHECK: <<Acc:i\d+>> ParameterValue
247 /// CHECK: <<Var:i\d+>> ParameterValue
248 /// CHECK: <<Const1:i\d+>> IntConstant 1
249 /// CHECK: <<Add:i\d+>> Add [<<Var>>,<<Const1>>]
250 /// CHECK: <<Mul:i\d+>> Mul [<<Acc>>,<<Add>>]
251 /// CHECK: Return [<<Mul>>]
252
253 /// CHECK-START-ARM64: int Main.$opt$noinline$mulPlusOne(int, int) instruction_simplifier_arm64 (after)
254 /// CHECK: <<Acc:i\d+>> ParameterValue
255 /// CHECK: <<Var:i\d+>> ParameterValue
Artem Udovichenko4a0dad62016-01-26 12:28:31 +0300256 /// CHECK: <<MulAdd:i\d+>> MultiplyAccumulate [<<Acc>>,<<Acc>>,<<Var>>] kind:Add
Alexandre Rames418318f2015-11-20 15:55:47 +0000257 /// CHECK: Return [<<MulAdd>>]
258
259 /// CHECK-START-ARM64: int Main.$opt$noinline$mulPlusOne(int, int) instruction_simplifier_arm64 (after)
260 /// CHECK-NOT: Mul
261 /// CHECK-NOT: Add
262
263 /// CHECK-START-ARM64: int Main.$opt$noinline$mulPlusOne(int, int) disassembly (after)
264 /// CHECK: madd w{{\d+}}, w{{\d+}}, w{{\d+}}, w{{\d+}}
265
Artem Udovichenko4a0dad62016-01-26 12:28:31 +0300266 /// CHECK-START-ARM: int Main.$opt$noinline$mulPlusOne(int, int) instruction_simplifier_arm (before)
267 /// CHECK: <<Acc:i\d+>> ParameterValue
268 /// CHECK: <<Var:i\d+>> ParameterValue
269 /// CHECK: <<Const1:i\d+>> IntConstant 1
270 /// CHECK: <<Add:i\d+>> Add [<<Var>>,<<Const1>>]
271 /// CHECK: <<Mul:i\d+>> Mul [<<Acc>>,<<Add>>]
272 /// CHECK: Return [<<Mul>>]
273
274 /// CHECK-START-ARM: int Main.$opt$noinline$mulPlusOne(int, int) instruction_simplifier_arm (after)
275 /// CHECK: <<Acc:i\d+>> ParameterValue
276 /// CHECK: <<Var:i\d+>> ParameterValue
277 /// CHECK: <<MulAdd:i\d+>> MultiplyAccumulate [<<Acc>>,<<Acc>>,<<Var>>] kind:Add
278 /// CHECK: Return [<<MulAdd>>]
279
280 /// CHECK-START-ARM: int Main.$opt$noinline$mulPlusOne(int, int) instruction_simplifier_arm (after)
281 /// CHECK-NOT: Mul
282 /// CHECK-NOT: Add
283
284 /// CHECK-START-ARM: int Main.$opt$noinline$mulPlusOne(int, int) disassembly (after)
285 /// CHECK: mla r{{\d+}}, r{{\d+}}, r{{\d+}}, r{{\d+}}
286
Alexandre Rames418318f2015-11-20 15:55:47 +0000287 public static int $opt$noinline$mulPlusOne(int acc, int var) {
288 if (doThrow) throw new Error();
289 return acc * (var + 1);
290 }
291
292
293 /**
294 * Test the interpretation of `a * (1 - b)` as `a - (a * b)`.
295 */
296
297 /// CHECK-START-ARM64: long Main.$opt$noinline$mulMinusOne(long, long) instruction_simplifier_arm64 (before)
298 /// CHECK: <<Acc:j\d+>> ParameterValue
299 /// CHECK: <<Var:j\d+>> ParameterValue
300 /// CHECK: <<Const1:j\d+>> LongConstant 1
301 /// CHECK: <<Sub:j\d+>> Sub [<<Const1>>,<<Var>>]
302 /// CHECK: <<Mul:j\d+>> Mul [<<Acc>>,<<Sub>>]
303 /// CHECK: Return [<<Mul>>]
304
305 /// CHECK-START-ARM64: long Main.$opt$noinline$mulMinusOne(long, long) instruction_simplifier_arm64 (after)
306 /// CHECK: <<Acc:j\d+>> ParameterValue
307 /// CHECK: <<Var:j\d+>> ParameterValue
Artem Udovichenko4a0dad62016-01-26 12:28:31 +0300308 /// CHECK: <<MulSub:j\d+>> MultiplyAccumulate [<<Acc>>,<<Acc>>,<<Var>>] kind:Sub
Alexandre Rames418318f2015-11-20 15:55:47 +0000309 /// CHECK: Return [<<MulSub>>]
310
311 /// CHECK-START-ARM64: long Main.$opt$noinline$mulMinusOne(long, long) instruction_simplifier_arm64 (after)
312 /// CHECK-NOT: Mul
313 /// CHECK-NOT: Sub
314
315 /// CHECK-START-ARM64: long Main.$opt$noinline$mulMinusOne(long, long) disassembly (after)
316 /// CHECK: msub x{{\d+}}, x{{\d+}}, x{{\d+}}, x{{\d+}}
317
Artem Udovichenko4a0dad62016-01-26 12:28:31 +0300318 /// CHECK-START-ARM: long Main.$opt$noinline$mulMinusOne(long, long) instruction_simplifier_arm (before)
319 /// CHECK: <<Acc:j\d+>> ParameterValue
320 /// CHECK: <<Var:j\d+>> ParameterValue
321 /// CHECK: <<Const1:j\d+>> LongConstant 1
322 /// CHECK: <<Sub:j\d+>> Sub [<<Const1>>,<<Var>>]
323 /// CHECK: <<Mul:j\d+>> Mul [<<Acc>>,<<Sub>>]
324 /// CHECK: Return [<<Mul>>]
325
326 /// CHECK-START-ARM: long Main.$opt$noinline$mulMinusOne(long, long) instruction_simplifier_arm (after)
327 /// CHECK-NOT: MultiplyAccumulate
Alexandre Rames418318f2015-11-20 15:55:47 +0000328 public static long $opt$noinline$mulMinusOne(long acc, long var) {
329 if (doThrow) throw new Error();
330 return acc * (1 - var);
331 }
332
Artem Udovichenko4a0dad62016-01-26 12:28:31 +0300333 /**
334 * Test basic merging of `MUL+NEG` into `MULNEG`.
335 */
336
337 /// CHECK-START-ARM64: int Main.$opt$noinline$mulNeg(int, int) instruction_simplifier_arm64 (before)
338 /// CHECK: <<Left:i\d+>> ParameterValue
339 /// CHECK: <<Right:i\d+>> ParameterValue
340 /// CHECK: <<Mul:i\d+>> Mul [<<Left>>,<<Right>>]
341 /// CHECK: <<Neg:i\d+>> Neg [<<Mul>>]
342 /// CHECK: Return [<<Neg>>]
343
344 /// CHECK-START-ARM64: int Main.$opt$noinline$mulNeg(int, int) instruction_simplifier_arm64 (after)
345 /// CHECK: <<Left:i\d+>> ParameterValue
346 /// CHECK: <<Right:i\d+>> ParameterValue
347 /// CHECK: <<Const0:i\d+>> IntConstant 0
348 /// CHECK: <<MulNeg:i\d+>> MultiplyAccumulate [<<Const0>>,<<Left>>,<<Right>>] kind:Sub
349 /// CHECK: Return [<<MulNeg>>]
350
351 /// CHECK-START-ARM64: int Main.$opt$noinline$mulNeg(int, int) instruction_simplifier_arm64 (after)
352 /// CHECK-NOT: Mul
353 /// CHECK-NOT: Neg
354
355 /// CHECK-START-ARM64: int Main.$opt$noinline$mulNeg(int, int) disassembly (after)
356 /// CHECK: mneg w{{\d+}}, w{{\d+}}, w{{\d+}}
357
358 /// CHECK-START-ARM: int Main.$opt$noinline$mulNeg(int, int) instruction_simplifier_arm (before)
359 /// CHECK: <<Left:i\d+>> ParameterValue
360 /// CHECK: <<Right:i\d+>> ParameterValue
361 /// CHECK: <<Mul:i\d+>> Mul [<<Left>>,<<Right>>]
362 /// CHECK: <<Neg:i\d+>> Neg [<<Mul>>]
363 /// CHECK: Return [<<Neg>>]
364
365 /// CHECK-START-ARM: int Main.$opt$noinline$mulNeg(int, int) instruction_simplifier_arm (after)
366 /// CHECK: <<Left:i\d+>> ParameterValue
367 /// CHECK: <<Right:i\d+>> ParameterValue
368 /// CHECK: <<Mul:i\d+>> Mul [<<Left>>,<<Right>>]
369 /// CHECK: <<Neg:i\d+>> Neg [<<Mul>>]
370 /// CHECK: Return [<<Neg>>]
371
372 /// CHECK-START-ARM: int Main.$opt$noinline$mulNeg(int, int) instruction_simplifier_arm (after)
373 /// CHECK-NOT: MultiplyAccumulate
374
375 public static int $opt$noinline$mulNeg(int left, int right) {
376 if (doThrow) throw new Error();
377 return - (left * right);
378 }
379
380 /**
381 * Test basic merging of `MUL+NEG` into `MULNEG`.
382 */
383
384 /// CHECK-START-ARM64: long Main.$opt$noinline$mulNeg(long, long) instruction_simplifier_arm64 (before)
385 /// CHECK: <<Left:j\d+>> ParameterValue
386 /// CHECK: <<Right:j\d+>> ParameterValue
387 /// CHECK: <<Mul:j\d+>> Mul [<<Left>>,<<Right>>]
388 /// CHECK: <<Neg:j\d+>> Neg [<<Mul>>]
389 /// CHECK: Return [<<Neg>>]
390
391 /// CHECK-START-ARM64: long Main.$opt$noinline$mulNeg(long, long) instruction_simplifier_arm64 (after)
392 /// CHECK: <<Left:j\d+>> ParameterValue
393 /// CHECK: <<Right:j\d+>> ParameterValue
394 /// CHECK: <<Const0:j\d+>> LongConstant 0
395 /// CHECK: <<MulNeg:j\d+>> MultiplyAccumulate [<<Const0>>,<<Left>>,<<Right>>] kind:Sub
396 /// CHECK: Return [<<MulNeg>>]
397
398 /// CHECK-START-ARM64: long Main.$opt$noinline$mulNeg(long, long) instruction_simplifier_arm64 (after)
399 /// CHECK-NOT: Mul
400 /// CHECK-NOT: Neg
401
402 /// CHECK-START-ARM64: long Main.$opt$noinline$mulNeg(long, long) disassembly (after)
403 /// CHECK: mneg x{{\d+}}, x{{\d+}}, x{{\d+}}
404
405 /// CHECK-START-ARM: long Main.$opt$noinline$mulNeg(long, long) instruction_simplifier_arm (before)
406 /// CHECK: <<Left:j\d+>> ParameterValue
407 /// CHECK: <<Right:j\d+>> ParameterValue
408 /// CHECK: <<Mul:j\d+>> Mul [<<Left>>,<<Right>>]
409 /// CHECK: <<Neg:j\d+>> Neg [<<Mul>>]
410 /// CHECK: Return [<<Neg>>]
411
412 /// CHECK-START-ARM: long Main.$opt$noinline$mulNeg(long, long) instruction_simplifier_arm (after)
413 /// CHECK: <<Left:j\d+>> ParameterValue
414 /// CHECK: <<Right:j\d+>> ParameterValue
415 /// CHECK: <<Mul:j\d+>> Mul [<<Left>>,<<Right>>]
416 /// CHECK: <<Neg:j\d+>> Neg [<<Mul>>]
417 /// CHECK: Return [<<Neg>>]
418
419 /// CHECK-START-ARM: long Main.$opt$noinline$mulNeg(long, long) instruction_simplifier_arm (after)
420 /// CHECK-NOT: MultiplyAccumulate
421
422 public static long $opt$noinline$mulNeg(long left, long right) {
423 if (doThrow) throw new Error();
424 return - (left * right);
425 }
Alexandre Rames418318f2015-11-20 15:55:47 +0000426
Artem Serovf34dd202017-04-10 17:41:46 +0100427 /// CHECK-START-ARM64: void Main.SimdMulAdd(int[], int[]) instruction_simplifier_arm64 (before)
428 /// CHECK-DAG: Phi loop:<<Loop:B\d+>> outer_loop:none
429 /// CHECK-DAG: VecMul loop:<<Loop>> outer_loop:none
430 /// CHECK-DAG: VecAdd loop:<<Loop>> outer_loop:none
431
432 /// CHECK-START-ARM64: void Main.SimdMulAdd(int[], int[]) instruction_simplifier_arm64 (after)
433 /// CHECK-DAG: Phi loop:<<Loop:B\d+>> outer_loop:none
434 /// CHECK-DAG: VecMultiplyAccumulate kind:Add loop:<<Loop>> outer_loop:none
435
436 /// CHECK-START-ARM64: void Main.SimdMulAdd(int[], int[]) instruction_simplifier_arm64 (after)
437 /// CHECK-NOT: VecMull
438 /// CHECK-NOT: VecAdd
439 public static void SimdMulAdd(int[] array1, int[] array2) {
440 for (int j = 0; j < 100; j++) {
441 array2[j] += 12345 * array1[j];
442 }
443 }
444
445 /// CHECK-START-ARM64: void Main.SimdMulSub(int[], int[]) instruction_simplifier_arm64 (before)
446 /// CHECK-DAG: Phi loop:<<Loop:B\d+>> outer_loop:none
447 /// CHECK-DAG: VecMul loop:<<Loop>> outer_loop:none
448 /// CHECK-DAG: VecSub loop:<<Loop>> outer_loop:none
449
450 /// CHECK-START-ARM64: void Main.SimdMulSub(int[], int[]) instruction_simplifier_arm64 (after)
451 /// CHECK-DAG: Phi loop:<<Loop:B\d+>> outer_loop:none
452 /// CHECK-DAG: VecMultiplyAccumulate kind:Sub loop:<<Loop>> outer_loop:none
453
454 /// CHECK-START-ARM64: void Main.SimdMulSub(int[], int[]) instruction_simplifier_arm64 (after)
455 /// CHECK-NOT: VecMull
456 /// CHECK-NOT: VecSub
457 public static void SimdMulSub(int[] array1, int[] array2) {
458 for (int j = 0; j < 100; j++) {
459 array2[j] -= 12345 * array1[j];
460 }
461 }
462
463 /// CHECK-START-ARM64: void Main.SimdMulMultipleUses(int[], int[]) instruction_simplifier_arm64 (before)
464 /// CHECK-DAG: Phi loop:<<Loop:B\d+>> outer_loop:none
465 /// CHECK-DAG: VecMul loop:<<Loop>> outer_loop:none
466 /// CHECK-DAG: VecSub loop:<<Loop>> outer_loop:none
467
468 /// CHECK-START-ARM64: void Main.SimdMulMultipleUses(int[], int[]) instruction_simplifier_arm64 (after)
469 /// CHECK-NOT: VecMultiplyAccumulate
470 public static void SimdMulMultipleUses(int[] array1, int[] array2) {
471 for (int j = 0; j < 100; j++) {
472 int temp = 12345 * array1[j];
473 array2[j] -= temp;
474 array1[j] = temp;
475 }
476 }
477
478 public static final int ARRAY_SIZE = 1000;
479
480 public static void initArray(int[] array) {
481 for (int i = 0; i < ARRAY_SIZE; i++) {
482 array[i] = i;
483 }
484 }
485
486 public static int calcArraySum(int[] array) {
487 int sum = 0;
488 for (int i = 0; i < ARRAY_SIZE; i++) {
489 sum += array[i];
490 }
491 return sum;
492 }
493
494 public static void testSimdMultiplyAccumulate() {
495 int[] array1 = new int[ARRAY_SIZE];
496 int[] array2 = new int[ARRAY_SIZE];
497
498 initArray(array1);
499 initArray(array2);
500 SimdMulSub(array1, array2);
501 assertIntEquals(-60608250, calcArraySum(array2));
502
503 initArray(array1);
504 initArray(array2);
505 SimdMulAdd(array1, array2);
506 assertIntEquals(61607250, calcArraySum(array2));
507 }
508
Alexandre Rames418318f2015-11-20 15:55:47 +0000509 public static void main(String[] args) {
510 assertIntEquals(7, $opt$noinline$mulAdd(1, 2, 3));
511 assertLongEquals(-26, $opt$noinline$mulSub(4, 5, 6));
512 assertIntEquals(79, $opt$noinline$multipleUses1(7, 8, 9));
513 assertLongEquals(20, $opt$noinline$multipleUses2(10, 11, 12));
514 assertIntEquals(195, $opt$noinline$mulPlusOne(13, 14));
515 assertLongEquals(-225, $opt$noinline$mulMinusOne(15, 16));
Artem Udovichenko4a0dad62016-01-26 12:28:31 +0300516 assertIntEquals(-306, $opt$noinline$mulNeg(17, 18));
517 assertLongEquals(-380, $opt$noinline$mulNeg(19, 20));
Artem Serovf34dd202017-04-10 17:41:46 +0100518
519 testSimdMultiplyAccumulate();
Alexandre Rames418318f2015-11-20 15:55:47 +0000520 }
521}