1/*
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  // 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
50  /// CHECK:       <<MulAdd:i\d+>>      MultiplyAccumulate [<<Acc>>,<<Left>>,<<Right>>] kind:Add
51  /// 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
60  /// 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
82  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
103  /// CHECK:       <<MulSub:j\d+>>      MultiplyAccumulate [<<Acc>>,<<Left>>,<<Right>>] kind:Sub
104  /// 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
113  /// 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
124  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)
153  /// 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
175
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)
208  /// 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
232
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
256  /// CHECK:       <<MulAdd:i\d+>>      MultiplyAccumulate [<<Acc>>,<<Acc>>,<<Var>>] kind:Add
257  /// 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
266  /// 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
287  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
308  /// CHECK:       <<MulSub:j\d+>>      MultiplyAccumulate [<<Acc>>,<<Acc>>,<<Var>>] kind:Sub
309  /// 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
318  /// 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
328  public static long $opt$noinline$mulMinusOne(long acc, long var) {
329    if (doThrow) throw new Error();
330    return acc * (1 - var);
331  }
332
333  /**
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  }
426
427  public static void main(String[] args) {
428    assertIntEquals(7, $opt$noinline$mulAdd(1, 2, 3));
429    assertLongEquals(-26, $opt$noinline$mulSub(4, 5, 6));
430    assertIntEquals(79, $opt$noinline$multipleUses1(7, 8, 9));
431    assertLongEquals(20, $opt$noinline$multipleUses2(10, 11, 12));
432    assertIntEquals(195, $opt$noinline$mulPlusOne(13, 14));
433    assertLongEquals(-225, $opt$noinline$mulMinusOne(15, 16));
434    assertIntEquals(-306, $opt$noinline$mulNeg(17, 18));
435    assertLongEquals(-380, $opt$noinline$mulNeg(19, 20));
436  }
437}
438