1 /*
2  * Copyright (C) 2020 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 
17 public class RemTest {
expectEquals(int expected, int result)18   private static void expectEquals(int expected, int result) {
19     if (expected != result) {
20       throw new Error("Expected: " + expected + ", found: " + result);
21     }
22   }
23 
expectEquals(long expected, long result)24   private static void expectEquals(long expected, long result) {
25     if (expected != result) {
26       throw new Error("Expected: " + expected + ", found: " + result);
27     }
28   }
29 
main()30   public static void main() {
31     remInt();
32     remLong();
33   }
34 
remInt()35   private static void remInt() {
36     expectEquals(0, $noinline$IntRemBy18(0));
37     expectEquals(1, $noinline$IntRemBy18(1));
38     expectEquals(-1, $noinline$IntRemBy18(-1));
39     expectEquals(0, $noinline$IntRemBy18(18));
40     expectEquals(0, $noinline$IntRemBy18(-18));
41     expectEquals(11, $noinline$IntRemBy18(65));
42     expectEquals(-11, $noinline$IntRemBy18(-65));
43 
44     expectEquals(0, $noinline$IntALenRemBy18(new int[0]));
45     expectEquals(1, $noinline$IntALenRemBy18(new int[1]));
46     expectEquals(0, $noinline$IntALenRemBy18(new int[18]));
47     expectEquals(11, $noinline$IntALenRemBy18(new int[65]));
48 
49     expectEquals(0, $noinline$IntRemByMinus18(0));
50     expectEquals(1, $noinline$IntRemByMinus18(1));
51     expectEquals(-1, $noinline$IntRemByMinus18(-1));
52     expectEquals(0, $noinline$IntRemByMinus18(18));
53     expectEquals(0, $noinline$IntRemByMinus18(-18));
54     expectEquals(11, $noinline$IntRemByMinus18(65));
55     expectEquals(-11, $noinline$IntRemByMinus18(-65));
56 
57     expectEquals(0, $noinline$IntRemBy7(0));
58     expectEquals(1, $noinline$IntRemBy7(1));
59     expectEquals(-1, $noinline$IntRemBy7(-1));
60     expectEquals(0, $noinline$IntRemBy7(7));
61     expectEquals(0, $noinline$IntRemBy7(-7));
62     expectEquals(1, $noinline$IntRemBy7(22));
63     expectEquals(-1, $noinline$IntRemBy7(-22));
64 
65     expectEquals(0, $noinline$IntALenRemBy7(new int[0]));
66     expectEquals(1, $noinline$IntALenRemBy7(new int[1]));
67     expectEquals(0, $noinline$IntALenRemBy7(new int[7]));
68     expectEquals(1, $noinline$IntALenRemBy7(new int[22]));
69 
70     expectEquals(0, $noinline$IntRemByMinus7(0));
71     expectEquals(1, $noinline$IntRemByMinus7(1));
72     expectEquals(-1, $noinline$IntRemByMinus7(-1));
73     expectEquals(0, $noinline$IntRemByMinus7(7));
74     expectEquals(0, $noinline$IntRemByMinus7(-7));
75     expectEquals(1, $noinline$IntRemByMinus7(22));
76     expectEquals(-1, $noinline$IntRemByMinus7(-22));
77 
78     expectEquals(0, $noinline$IntRemBy6(0));
79     expectEquals(1, $noinline$IntRemBy6(1));
80     expectEquals(-1, $noinline$IntRemBy6(-1));
81     expectEquals(0, $noinline$IntRemBy6(6));
82     expectEquals(0, $noinline$IntRemBy6(-6));
83     expectEquals(1, $noinline$IntRemBy6(19));
84     expectEquals(-1, $noinline$IntRemBy6(-19));
85 
86     expectEquals(0, $noinline$IntALenRemBy6(new int[0]));
87     expectEquals(1, $noinline$IntALenRemBy6(new int[1]));
88     expectEquals(0, $noinline$IntALenRemBy6(new int[6]));
89     expectEquals(1, $noinline$IntALenRemBy6(new int[19]));
90 
91     expectEquals(0, $noinline$IntRemByMinus6(0));
92     expectEquals(1, $noinline$IntRemByMinus6(1));
93     expectEquals(-1, $noinline$IntRemByMinus6(-1));
94     expectEquals(0, $noinline$IntRemByMinus6(6));
95     expectEquals(0, $noinline$IntRemByMinus6(-6));
96     expectEquals(1, $noinline$IntRemByMinus6(19));
97     expectEquals(-1, $noinline$IntRemByMinus6(-19));
98 
99     expectEquals(1, $noinline$UnsignedIntRem01(13));
100     expectEquals(1, $noinline$UnsignedIntRem02(13));
101     expectEquals(1, $noinline$UnsignedIntRem03(13));
102     expectEquals(1, $noinline$UnsignedIntRem04(13));
103     expectEquals(1, $noinline$UnsignedIntRem05(101));
104     expectEquals(11, $noinline$UnsignedIntRem06(101));
105 
106     expectEquals(-1, $noinline$SignedIntRem01(-13));
107     expectEquals(-1, $noinline$SignedIntRem02(-13));
108     expectEquals(1, $noinline$SignedIntRem03(-13));
109     expectEquals(1, $noinline$SignedIntRem04(-13, true));
110     expectEquals(0, $noinline$SignedIntRem05(-12, 0,-13));
111     expectEquals(-1, $noinline$SignedIntRem06(-13));
112   }
113 
114   // A test case to check that 'lsr' and 'asr' are combined into one 'asr'.
115   // For divisor 18 seen in an MP3 decoding workload there is no need
116   // to correct the result of get_high(dividend * magic). So there are no
117   // instructions between 'lsr' and 'asr'. In such a case they can be combined
118   // into one 'asr'.
119   //
120   /// CHECK-START-ARM64: int RemTest.$noinline$IntRemBy18(int) disassembly (after)
121   /// CHECK:                 asr x{{\d+}}, x{{\d+}}, #34
122   /// CHECK-NEXT:            add w{{\d+}}, w{{\d+}}, w{{\d+}}, lsr #31
123   /// CHECK-NEXT:            mov w{{\d+}}, #0x12
124   /// CHECK-NEXT:            msub w{{\d+}}, w{{\d+}}, w{{\d+}}, w{{\d+}}
$noinline$IntRemBy18(int v)125   private static int $noinline$IntRemBy18(int v) {
126     int r = v % 18;
127     return r;
128   }
129 
130   // A test case to check that a correcting 'add' is not generated for a non-negative
131   // dividend and a positive divisor.
132   //
133   /// CHECK-START-ARM:   int RemTest.$noinline$IntALenRemBy18(int[]) disassembly (after)
134   /// CHECK:                 smull     r{{\d+}}, r{{\d+}}, r{{\d+}}, r{{\d+}}
135   /// CHECK-NEXT:            lsr{{s?}} r{{\d+}}, #2
136   /// CHECK-NEXT:            mov{{s?}} r{{\d+}}, #18
137   /// CHECK-NEXT:            mls       r{{\d+}}, r{{\d+}}, r{{\d+}}, r{{\d+}}
138   //
139   /// CHECK-START-ARM64: int RemTest.$noinline$IntALenRemBy18(int[]) disassembly (after)
140   /// CHECK:                 lsr x{{\d+}}, x{{\d+}}, #34
141   /// CHECK-NEXT:            mov w{{\d+}}, #0x12
142   /// CHECK-NEXT:            msub w{{\d+}}, w{{\d+}}, w{{\d+}}, w{{\d+}}
$noinline$IntALenRemBy18(int[] arr)143   private static int $noinline$IntALenRemBy18(int[] arr) {
144     int r = arr.length % 18;
145     return r;
146   }
147 
148   // A test case to check that 'lsr' and 'asr' are combined into one 'asr'.
149   // Divisor -18 has the same property as divisor 18: no need to correct the
150   // result of get_high(dividend * magic). So there are no
151   // instructions between 'lsr' and 'asr'. In such a case they can be combined
152   // into one 'asr'.
153   //
154   /// CHECK-START-ARM64: int RemTest.$noinline$IntRemByMinus18(int) disassembly (after)
155   /// CHECK:                 asr x{{\d+}}, x{{\d+}}, #34
156   /// CHECK-NEXT:            add w{{\d+}}, w{{\d+}}, w{{\d+}}, lsr #31
157   /// CHECK-NEXT:            mov w{{\d+}}, #0xffffffee
158   /// CHECK-NEXT:            msub w{{\d+}}, w{{\d+}}, w{{\d+}}, w{{\d+}}
$noinline$IntRemByMinus18(int v)159   private static int $noinline$IntRemByMinus18(int v) {
160     int r = v % -18;
161     return r;
162   }
163 
164   // A test case to check that 'lsr' and 'add' are combined into one 'adds'.
165   // For divisor 7 seen in the core library the result of get_high(dividend * magic)
166   // must be corrected by the 'add' instruction.
167   //
168   // The test case also checks 'add' and 'add_shift' are optimized into 'adds' and 'cinc'.
169   //
170   /// CHECK-START-ARM64: int RemTest.$noinline$IntRemBy7(int) disassembly (after)
171   /// CHECK:                 adds x{{\d+}}, x{{\d+}}, x{{\d+}}, lsl #32
172   /// CHECK-NEXT:            asr  x{{\d+}}, x{{\d+}}, #34
173   /// CHECK-NEXT:            cinc w{{\d+}}, w{{\d+}}, mi
174   /// CHECK-NEXT:            mov w{{\d+}}, #0x7
175   /// CHECK-NEXT:            msub w{{\d+}}, w{{\d+}}, w{{\d+}}, w{{\d+}}
$noinline$IntRemBy7(int v)176   private static int $noinline$IntRemBy7(int v) {
177     int r = v % 7;
178     return r;
179   }
180 
181   // A test case to check that a correcting 'add' is not generated for a non-negative
182   // dividend and a positive divisor.
183   //
184   /// CHECK-START-ARM:   int RemTest.$noinline$IntALenRemBy7(int[]) disassembly (after)
185   /// CHECK:                 smull     r{{\d+}}, r{{\d+}}, r{{\d+}}, r{{\d+}}
186   /// CHECK-NEXT:            add{{s?}} r{{\d+}}, r{{\d+}}
187   /// CHECK-NEXT:            lsr{{s?}} r{{\d+}}, #2
188   /// CHECK-NEXT:            mov{{s?}} r{{\d+}}, #7
189   /// CHECK-NEXT:            mls       r{{\d+}}, r{{\d+}}, r{{\d+}}, r{{\d+}}
190   //
191   /// CHECK-START-ARM64: int RemTest.$noinline$IntALenRemBy7(int[]) disassembly (after)
192   /// CHECK:                 lsr x{{\d+}}, x{{\d+}}, #34
193   /// CHECK-NEXT:            mov w{{\d+}}, #0x7
194   /// CHECK-NEXT:            msub w{{\d+}}, w{{\d+}}, w{{\d+}}, w{{\d+}}
$noinline$IntALenRemBy7(int[] arr)195   private static int $noinline$IntALenRemBy7(int[] arr) {
196     int r = arr.length % 7;
197     return r;
198   }
199 
200   // A test case to check that 'lsr' and 'add' are combined into one 'adds'.
201   // Divisor -7 has the same property as divisor 7: the result of get_high(dividend * magic)
202   // must be corrected. In this case it is a 'sub' instruction.
203   //
204   // The test case also checks 'sub' and 'add_shift' are optimized into 'subs' and 'cinc'.
205   //
206   /// CHECK-START-ARM64: int RemTest.$noinline$IntRemByMinus7(int) disassembly (after)
207   /// CHECK:                 subs x{{\d+}}, x{{\d+}}, x{{\d+}}, lsl #32
208   /// CHECK-NEXT:            asr  x{{\d+}}, x{{\d+}}, #34
209   /// CHECK-NEXT:            cinc w{{\d+}}, w{{\d+}}, mi
210   /// CHECK-NEXT:            mov w{{\d+}}, #0xfffffff9
211   /// CHECK-NEXT:            msub w{{\d+}}, w{{\d+}}, w{{\d+}}, w{{\d+}}
$noinline$IntRemByMinus7(int v)212   private static int $noinline$IntRemByMinus7(int v) {
213     int r = v % -7;
214     return r;
215   }
216 
217   // A test case to check that 'asr' is used to get the high 32 bits of the result of
218   // 'dividend * magic'.
219   // For divisor 6 seen in the core library there is no need to correct the result of
220   // get_high(dividend * magic). Also there is no 'asr' before the final 'add' instruction
221   // which uses only the high 32 bits of the result. In such a case 'asr' getting the high
222   // 32 bits can be used as well.
223   //
224   /// CHECK-START-ARM64: int RemTest.$noinline$IntRemBy6(int) disassembly (after)
225   /// CHECK:                 asr x{{\d+}}, x{{\d+}}, #32
226   /// CHECK-NEXT:            add w{{\d+}}, w{{\d+}}, w{{\d+}}, lsr #31
227   /// CHECK-NEXT:            mov w{{\d+}}, #0x6
228   /// CHECK-NEXT:            msub w{{\d+}}, w{{\d+}}, w{{\d+}}, w{{\d+}}
$noinline$IntRemBy6(int v)229   private static int $noinline$IntRemBy6(int v) {
230     int r = v % 6;
231     return r;
232   }
233 
234   // A test case to check that a correcting 'add' is not generated for a non-negative
235   // dividend and a positive divisor.
236   //
237   /// CHECK-START-ARM:   int RemTest.$noinline$IntALenRemBy6(int[]) disassembly (after)
238   /// CHECK:                 smull     r{{\d+}}, r{{\d+}}, r{{\d+}}, r{{\d+}}
239   /// CHECK-NEXT:            mov{{s?}} r{{\d+}}, #6
240   /// CHECK-NEXT:            mls       r{{\d+}}, r{{\d+}}, r{{\d+}}, r{{\d+}}
241   //
242   /// CHECK-START-ARM64: int RemTest.$noinline$IntALenRemBy6(int[]) disassembly (after)
243   /// CHECK:                 lsr x{{\d+}}, x{{\d+}}, #32
244   /// CHECK-NEXT:            mov w{{\d+}}, #0x6
245   /// CHECK-NEXT:            msub w{{\d+}}, w{{\d+}}, w{{\d+}}, w{{\d+}}
$noinline$IntALenRemBy6(int[] arr)246   private static int $noinline$IntALenRemBy6(int[] arr) {
247     int r = arr.length % 6;
248     return r;
249   }
250 
251   // A test case to check that 'asr' is used to get the high 32 bits of the result of
252   // 'dividend * magic'.
253   // Divisor -6 has the same property as divisor 6: no need to correct the result of
254   // get_high(dividend * magic) and no 'asr' before the final 'add' instruction
255   // which uses only the high 32 bits of the result. In such a case 'asr' getting the high
256   // 32 bits can be used as well.
257   //
258   /// CHECK-START-ARM64: int RemTest.$noinline$IntRemByMinus6(int) disassembly (after)
259   /// CHECK:                 asr x{{\d+}}, x{{\d+}}, #32
260   /// CHECK-NEXT:            add w{{\d+}}, w{{\d+}}, w{{\d+}}, lsr #31
261   /// CHECK-NEXT:            mov w{{\d+}}, #0xfffffffa
262   /// CHECK-NEXT:            msub w{{\d+}}, w{{\d+}}, w{{\d+}}, w{{\d+}}
$noinline$IntRemByMinus6(int v)263   private static int $noinline$IntRemByMinus6(int v) {
264     int r = v % -6;
265     return r;
266   }
267 
$noinline$Negate(int v)268   private static int $noinline$Negate(int v) {
269     return -v;
270   }
271 
$noinline$Decrement(int v)272   private static int $noinline$Decrement(int v) {
273     return v - 1;
274   }
275 
$noinline$Increment(int v)276   private static int $noinline$Increment(int v) {
277     return v + 1;
278   }
279 
280   // A test case to check that a correcting 'add' is not generated for a non-negative
281   // dividend and a positive divisor.
282   //
283   /// CHECK-START-ARM:   int RemTest.$noinline$UnsignedIntRem01(int) disassembly (after)
284   /// CHECK:                 smull     r{{\d+}}, r{{\d+}}, r{{\d+}}, r{{\d+}}
285   /// CHECK-NEXT:            mov{{s?}} r{{\d+}}, #6
286   /// CHECK-NEXT:            mls       r{{\d+}}, r{{\d+}}, r{{\d+}}, r{{\d+}}
287   //
288   /// CHECK-START-ARM64: int RemTest.$noinline$UnsignedIntRem01(int) disassembly (after)
289   /// CHECK:                 lsr x{{\d+}}, x{{\d+}}, #32
290   /// CHECK-NEXT:            mov w{{\d+}}, #0x6
291   /// CHECK-NEXT:            msub w{{\d+}}, w{{\d+}}, w{{\d+}}, w{{\d+}}
$noinline$UnsignedIntRem01(int v)292   private static int $noinline$UnsignedIntRem01(int v) {
293     int c = 0;
294     if (v > 0) {
295       c = v % 6;
296     } else {
297       c = $noinline$Negate(v); // This is to prevent from using Select.
298     }
299     return c;
300   }
301 
302   // A test case to check that a correcting 'add' is not generated for a non-negative
303   // dividend and a positive divisor.
304   //
305   /// CHECK-START-ARM:   int RemTest.$noinline$UnsignedIntRem02(int) disassembly (after)
306   /// CHECK:                 smull     r{{\d+}}, r{{\d+}}, r{{\d+}}, r{{\d+}}
307   /// CHECK-NEXT:            mov{{s?}} r{{\d+}}, #6
308   /// CHECK-NEXT:            mls       r{{\d+}}, r{{\d+}}, r{{\d+}}, r{{\d+}}
309   //
310   /// CHECK-START-ARM64: int RemTest.$noinline$UnsignedIntRem02(int) disassembly (after)
311   /// CHECK:                 lsr x{{\d+}}, x{{\d+}}, #32
312   /// CHECK-NEXT:            mov w{{\d+}}, #0x6
313   /// CHECK-NEXT:            msub w{{\d+}}, w{{\d+}}, w{{\d+}}, w{{\d+}}
$noinline$UnsignedIntRem02(int v)314   private static int $noinline$UnsignedIntRem02(int v) {
315     int c = 0;
316     if (0 < v) {
317       c = v % 6;
318     } else {
319       c = $noinline$Negate(v); // This is to prevent from using Select.
320     }
321     return c;
322   }
323 
324   // A test case to check that a correcting 'add' is not generated for a non-negative
325   // dividend and a positive divisor.
326   //
327   /// CHECK-START-ARM:   int RemTest.$noinline$UnsignedIntRem03(int) disassembly (after)
328   /// CHECK:                 smull     r{{\d+}}, r{{\d+}}, r{{\d+}}, r{{\d+}}
329   /// CHECK-NEXT:            mov{{s?}} r{{\d+}}, #6
330   /// CHECK-NEXT:            mls       r{{\d+}}, r{{\d+}}, r{{\d+}}, r{{\d+}}
331   //
332   /// CHECK-START-ARM64: int RemTest.$noinline$UnsignedIntRem03(int) disassembly (after)
333   /// CHECK:                 lsr x{{\d+}}, x{{\d+}}, #32
334   /// CHECK-NEXT:            mov w{{\d+}}, #0x6
335   /// CHECK-NEXT:            msub w{{\d+}}, w{{\d+}}, w{{\d+}}, w{{\d+}}
$noinline$UnsignedIntRem03(int v)336   private static int $noinline$UnsignedIntRem03(int v) {
337     int c = 0;
338     if (v >= 0) {
339       c = v % 6;
340     } else {
341       c = $noinline$Negate(v); // This is to prevent from using Select.
342     }
343     return c;
344   }
345 
346   // A test case to check that a correcting 'add' is not generated for a non-negative
347   // dividend and a positive divisor.
348   //
349   /// CHECK-START-ARM:   int RemTest.$noinline$UnsignedIntRem04(int) disassembly (after)
350   /// CHECK:                 smull     r{{\d+}}, r{{\d+}}, r{{\d+}}, r{{\d+}}
351   /// CHECK-NEXT:            mov{{s?}} r{{\d+}}, #6
352   /// CHECK-NEXT:            mls       r{{\d+}}, r{{\d+}}, r{{\d+}}, r{{\d+}}
353   //
354   /// CHECK-START-ARM64: int RemTest.$noinline$UnsignedIntRem04(int) disassembly (after)
355   /// CHECK:                 lsr x{{\d+}}, x{{\d+}}, #32
356   /// CHECK-NEXT:            mov w{{\d+}}, #0x6
357   /// CHECK-NEXT:            msub w{{\d+}}, w{{\d+}}, w{{\d+}}, w{{\d+}}
$noinline$UnsignedIntRem04(int v)358   private static int $noinline$UnsignedIntRem04(int v) {
359     int c = 0;
360     if (0 <= v) {
361       c = v % 6;
362     } else {
363       c = $noinline$Negate(v); // This is to prevent from using Select.
364     }
365     return c;
366   }
367 
368   // A test case to check that a correcting 'add' is not generated for a non-negative
369   // dividend and a positive divisor.
370   //
371   /// CHECK-START-ARM:   int RemTest.$noinline$UnsignedIntRem05(int) disassembly (after)
372   /// CHECK:                 smull     r{{\d+}}, r{{\d+}}, r{{\d+}}, r{{\d+}}
373   /// CHECK-NEXT:            lsr{{s?}} r{{\d+}}, #2
374   /// CHECK-NEXT:            mov{{s?}} r{{\d+}}, #10
375   /// CHECK-NEXT:            mls       r{{\d+}}, r{{\d+}}, r{{\d+}}, r{{\d+}}
376   //
377   /// CHECK-START-ARM64: int RemTest.$noinline$UnsignedIntRem05(int) disassembly (after)
378   /// CHECK:                 lsr x{{\d+}}, x{{\d+}}, #34
379   /// CHECK-NEXT:            mov w{{\d+}}, #0xa
380   /// CHECK-NEXT:            msub w{{\d+}}, w{{\d+}}, w{{\d+}}, w{{\d+}}
$noinline$UnsignedIntRem05(int v)381   private static int $noinline$UnsignedIntRem05(int v) {
382     int c = 0;
383     for(; v > 100; ++c) {
384       v %= 10;
385     }
386     return c;
387   }
388 
389   // A test case to check that a correcting 'add' is not generated for a non-negative
390   // dividend and a positive divisor.
391   //
392   /// CHECK-START-ARM:   int RemTest.$noinline$UnsignedIntRem06(int) disassembly (after)
393   /// CHECK:                 smull     r{{\d+}}, r{{\d+}}, r{{\d+}}, r{{\d+}}
394   /// CHECK-NEXT:            lsr{{s?}} r{{\d+}}, r{{\d+}}, #2
395   /// CHECK:                 mls       r{{\d+}}, r{{\d+}}, r{{\d+}}, r{{\d+}}
396   //
397   /// CHECK-START-ARM64: int RemTest.$noinline$UnsignedIntRem06(int) disassembly (after)
398   /// CHECK:                 smull x{{\d+}}, w{{\d+}}, w{{\d+}}
399   /// CHECK-NEXT:            lsr x{{\d+}}, x{{\d+}}, #34
400   /// CHECK:                 msub w{{\d+}}, w{{\d+}}, w{{\d+}}, w{{\d+}}
$noinline$UnsignedIntRem06(int v)401   private static int $noinline$UnsignedIntRem06(int v) {
402     if (v < 10) {
403       v = $noinline$Negate(v); // This is to prevent from using Select.
404     } else {
405       v = (v % 10) + (v / 10);
406     }
407     return v;
408   }
409 
410   // A test case to check that a correcting 'add' is generated for a negative
411   // dividend and a positive divisor.
412   //
413   /// CHECK-START-ARM:   int RemTest.$noinline$SignedIntRem01(int) disassembly (after)
414   /// CHECK:                 smull     r{{\d+}}, r{{\d+}}, r{{\d+}}, r{{\d+}}
415   /// CHECK-NEXT:            sub       r{{\d+}}, r{{\d+}}, asr #31
416   /// CHECK-NEXT:            mov{{s?}} r{{\d+}}, #6
417   /// CHECK-NEXT:            mls       r{{\d+}}, r{{\d+}}, r{{\d+}}, r{{\d+}}
418   //
419   /// CHECK-START-ARM64: int RemTest.$noinline$SignedIntRem01(int) disassembly (after)
420   /// CHECK:                 asr x{{\d+}}, x{{\d+}}, #32
421   /// CHECK-NEXT:            add w{{\d+}}, w{{\d+}}, w{{\d+}}, lsr #31
$noinline$SignedIntRem01(int v)422   private static int $noinline$SignedIntRem01(int v) {
423     int c = 0;
424     if (v < 0) {
425       c = v % 6;
426     } else {
427       c = $noinline$Decrement(v); // This is to prevent from using Select.
428     }
429     return c;
430   }
431 
432   // A test case to check that a correcting 'add' is generated for a negative
433   // dividend and a positive divisor.
434   //
435   /// CHECK-START-ARM:   int RemTest.$noinline$SignedIntRem02(int) disassembly (after)
436   /// CHECK:                 smull     r{{\d+}}, r{{\d+}}, r{{\d+}}, r{{\d+}}
437   /// CHECK-NEXT:            sub       r{{\d+}}, r{{\d+}}, asr #31
438   /// CHECK-NEXT:            mov{{s?}} r{{\d+}}, #6
439   /// CHECK-NEXT:            mls       r{{\d+}}, r{{\d+}}, r{{\d+}}, r{{\d+}}
440   //
441   /// CHECK-START-ARM64: int RemTest.$noinline$SignedIntRem02(int) disassembly (after)
442   /// CHECK:                 asr x{{\d+}}, x{{\d+}}, #32
443   /// CHECK-NEXT:            add w{{\d+}}, w{{\d+}}, w{{\d+}}, lsr #31
$noinline$SignedIntRem02(int v)444   private static int $noinline$SignedIntRem02(int v) {
445     int c = 0;
446     if (v <= 0) {
447       c = v % 6;
448     } else {
449       c = $noinline$Decrement(v); // This is to prevent from using Select.
450     }
451     return c;
452   }
453 
454   // A test case to check that a correcting 'add' is generated for signed division.
455   //
456   /// CHECK-START-ARM:   int RemTest.$noinline$SignedIntRem03(int) disassembly (after)
457   /// CHECK:                 smull     r{{\d+}}, r{{\d+}}, r{{\d+}}, r{{\d+}}
458   /// CHECK-NEXT:            sub       r{{\d+}}, r{{\d+}}, asr #31
459   /// CHECK-NEXT:            mov{{s?}} r{{\d+}}, #6
460   /// CHECK-NEXT:            mls       r{{\d+}}, r{{\d+}}, r{{\d+}}, r{{\d+}}
461   //
462   /// CHECK-START-ARM64: int RemTest.$noinline$SignedIntRem03(int) disassembly (after)
463   /// CHECK:                 asr x{{\d+}}, x{{\d+}}, #32
464   /// CHECK-NEXT:            add w{{\d+}}, w{{\d+}}, w{{\d+}}, lsr #31
$noinline$SignedIntRem03(int v)465   private static int $noinline$SignedIntRem03(int v) {
466     boolean positive = (v > 0);
467     int c = v % 6;
468     if (!positive) {
469       c = $noinline$Negate(c); // This is to prevent from using Select.
470     }
471     return c;
472   }
473 
474   // A test case to check that a correcting 'add' is generated for signed division.
475   //
476   /// CHECK-START-ARM:   int RemTest.$noinline$SignedIntRem04(int, boolean) disassembly (after)
477   /// CHECK:                 smull     r{{\d+}}, r{{\d+}}, r{{\d+}}, r{{\d+}}
478   /// CHECK-NEXT:            sub       r{{\d+}}, r{{\d+}}, asr #31
479   /// CHECK-NEXT:            mov{{s?}} r{{\d+}}, #6
480   /// CHECK-NEXT:            mls       r{{\d+}}, r{{\d+}}, r{{\d+}}, r{{\d+}}
481   //
482   /// CHECK-START-ARM64: int RemTest.$noinline$SignedIntRem04(int, boolean) disassembly (after)
483   /// CHECK:                 asr x{{\d+}}, x{{\d+}}, #32
484   /// CHECK-NEXT:            add w{{\d+}}, w{{\d+}}, w{{\d+}}, lsr #31
$noinline$SignedIntRem04(int v, boolean apply_rem)485   private static int $noinline$SignedIntRem04(int v, boolean apply_rem) {
486     int c = 0;
487     boolean positive = (v > 0);
488     if (apply_rem) {
489       c = v % 6;
490     } else {
491       c = $noinline$Decrement(v); // This is to prevent from using Select.
492     }
493     if (!positive) {
494       c = $noinline$Negate(c); // This is to prevent from using Select.
495     }
496     return c;
497   }
498 
499   // A test case to check that a correcting 'add' is generated for signed division.
500   //
501   /// CHECK-START-ARM:   int RemTest.$noinline$SignedIntRem05(int, int, int) disassembly (after)
502   /// CHECK:                 smull     r{{\d+}}, r{{\d+}}, r{{\d+}}, r{{\d+}}
503   /// CHECK-NEXT:            sub       r{{\d+}}, r{{\d+}}, asr #31
504   /// CHECK-NEXT:            mov{{s?}} r{{\d+}}, #6
505   /// CHECK-NEXT:            mls       r{{\d+}}, r{{\d+}}, r{{\d+}}, r{{\d+}}
506   //
507   /// CHECK-START-ARM64: int RemTest.$noinline$SignedIntRem05(int, int, int) disassembly (after)
508   /// CHECK:                 asr x{{\d+}}, x{{\d+}}, #32
509   /// CHECK-NEXT:            add w{{\d+}}, w{{\d+}}, w{{\d+}}, lsr #31
$noinline$SignedIntRem05(int v, int a, int b)510   private static int $noinline$SignedIntRem05(int v, int a, int b) {
511     int c = 0;
512 
513     if (v < a)
514       c = $noinline$Increment(c); // This is to prevent from using Select.
515 
516     if (b < a)
517       c = $noinline$Increment(c); // This is to prevent from using Select.
518 
519     if (v > b) {
520       c = v % 6;
521     } else {
522       c = $noinline$Increment(c); // This is to prevent from using Select.
523     }
524 
525     return c;
526   }
527 
528   // A test case to check that a correcting 'add' is generated for signed division.
529   //
530   /// CHECK-START-ARM:   int RemTest.$noinline$SignedIntRem06(int) disassembly (after)
531   /// CHECK:                 smull     r{{\d+}}, r{{\d+}}, r{{\d+}}, r{{\d+}}
532   /// CHECK-NEXT:            sub       r{{\d+}}, r{{\d+}}, asr #31
533   /// CHECK-NEXT:            mov{{s?}} r{{\d+}}, #6
534   /// CHECK-NEXT:            mls       r{{\d+}}, r{{\d+}}, r{{\d+}}, r{{\d+}}
535   //
536   /// CHECK-START-ARM64: int RemTest.$noinline$SignedIntRem06(int) disassembly (after)
537   /// CHECK:                 asr x{{\d+}}, x{{\d+}}, #32
538   /// CHECK-NEXT:            add w{{\d+}}, w{{\d+}}, w{{\d+}}, lsr #31
$noinline$SignedIntRem06(int v)539   private static int $noinline$SignedIntRem06(int v) {
540     int c = v % 6;
541 
542     if (v > 0) {
543       c = $noinline$Negate(c); // This is to prevent from using Select.
544     }
545 
546     return c;
547   }
548 
remLong()549   private static void remLong() {
550     expectEquals(0L, $noinline$LongRemBy18(0L));
551     expectEquals(1L, $noinline$LongRemBy18(1L));
552     expectEquals(-1L, $noinline$LongRemBy18(-1L));
553     expectEquals(0L, $noinline$LongRemBy18(18L));
554     expectEquals(0L, $noinline$LongRemBy18(-18L));
555     expectEquals(11L, $noinline$LongRemBy18(65L));
556     expectEquals(-11L, $noinline$LongRemBy18(-65L));
557 
558     expectEquals(0L, $noinline$LongRemByMinus18(0L));
559     expectEquals(1L, $noinline$LongRemByMinus18(1L));
560     expectEquals(-1L, $noinline$LongRemByMinus18(-1L));
561     expectEquals(0L, $noinline$LongRemByMinus18(18L));
562     expectEquals(0L, $noinline$LongRemByMinus18(-18L));
563     expectEquals(11L, $noinline$LongRemByMinus18(65L));
564     expectEquals(-11L, $noinline$LongRemByMinus18(-65L));
565 
566     expectEquals(0L, $noinline$LongRemBy7(0L));
567     expectEquals(1L, $noinline$LongRemBy7(1L));
568     expectEquals(-1L, $noinline$LongRemBy7(-1L));
569     expectEquals(0L, $noinline$LongRemBy7(7L));
570     expectEquals(0L, $noinline$LongRemBy7(-7L));
571     expectEquals(1L, $noinline$LongRemBy7(22L));
572     expectEquals(-1L, $noinline$LongRemBy7(-22L));
573 
574     expectEquals(0L, $noinline$LongRemByMinus7(0L));
575     expectEquals(1L, $noinline$LongRemByMinus7(1L));
576     expectEquals(-1L, $noinline$LongRemByMinus7(-1L));
577     expectEquals(0L, $noinline$LongRemByMinus7(7L));
578     expectEquals(0L, $noinline$LongRemByMinus7(-7L));
579     expectEquals(1L, $noinline$LongRemByMinus7(22L));
580     expectEquals(-1L, $noinline$LongRemByMinus7(-22L));
581 
582     expectEquals(0L, $noinline$LongRemBy6(0L));
583     expectEquals(1L, $noinline$LongRemBy6(1L));
584     expectEquals(-1L, $noinline$LongRemBy6(-1L));
585     expectEquals(0L, $noinline$LongRemBy6(6L));
586     expectEquals(0L, $noinline$LongRemBy6(-6L));
587     expectEquals(1L, $noinline$LongRemBy6(19L));
588     expectEquals(-1L, $noinline$LongRemBy6(-19L));
589 
590     expectEquals(0L, $noinline$LongRemByMinus6(0L));
591     expectEquals(1L, $noinline$LongRemByMinus6(1L));
592     expectEquals(-1L, $noinline$LongRemByMinus6(-1L));
593     expectEquals(0L, $noinline$LongRemByMinus6(6L));
594     expectEquals(0L, $noinline$LongRemByMinus6(-6L));
595     expectEquals(1L, $noinline$LongRemByMinus6(19L));
596     expectEquals(-1L, $noinline$LongRemByMinus6(-19L));
597 
598     expectEquals(0L, $noinline$LongRemBy100(0L));
599     expectEquals(1L, $noinline$LongRemBy100(1L));
600     expectEquals(-1L, $noinline$LongRemBy100(-1L));
601     expectEquals(0L, $noinline$LongRemBy100(100L));
602     expectEquals(0L, $noinline$LongRemBy100(-100L));
603     expectEquals(1L, $noinline$LongRemBy100(101L));
604     expectEquals(-1L, $noinline$LongRemBy100(-101L));
605 
606     expectEquals(0L, $noinline$LongRemByMinus100(0L));
607     expectEquals(1L, $noinline$LongRemByMinus100(1L));
608     expectEquals(-1L, $noinline$LongRemByMinus100(-1L));
609     expectEquals(0L, $noinline$LongRemByMinus100(100L));
610     expectEquals(0L, $noinline$LongRemByMinus100(-100L));
611     expectEquals(1L, $noinline$LongRemByMinus100(101L));
612     expectEquals(-1L, $noinline$LongRemByMinus100(-101L));
613 
614     expectEquals(1L, $noinline$UnsignedLongRem01(13L));
615     expectEquals(1L, $noinline$UnsignedLongRem02(13L));
616     expectEquals(1L, $noinline$UnsignedLongRem03(13L));
617     expectEquals(1L, $noinline$UnsignedLongRem04(13L));
618     expectEquals(1L, $noinline$UnsignedLongRem05(101L));
619     expectEquals(11L, $noinline$UnsignedLongRem06(101L));
620 
621     expectEquals(-1L, $noinline$SignedLongRem01(-13L));
622     expectEquals(-1L, $noinline$SignedLongRem02(-13L));
623     expectEquals(1L, $noinline$SignedLongRem03(-13L));
624     expectEquals(1L, $noinline$SignedLongRem04(-13L, true));
625     expectEquals(0L, $noinline$SignedLongRem05(-12L, 0L,-13L));
626     expectEquals(-1L, $noinline$SignedLongRem06(-13L));
627   }
628 
629   // Test cases for Int64 HDiv/HRem to check that optimizations implemented for Int32 are not
630   // used for Int64. The same divisors 18, -18, 7, -7, 6 and -6 are used.
631 
632   /// CHECK-START-ARM64: long RemTest.$noinline$LongRemBy18(long) disassembly (after)
633   /// CHECK:                 smulh x{{\d+}}, x{{\d+}}, x{{\d+}}
634   /// CHECK-NEXT:            add x{{\d+}}, x{{\d+}}, x{{\d+}}, lsr #63
635   /// CHECK-NEXT:            mov x{{\d+}}, #0x12
636   /// CHECK-NEXT:            msub x{{\d+}}, x{{\d+}}, x{{\d+}}, x{{\d+}}
$noinline$LongRemBy18(long v)637   private static long $noinline$LongRemBy18(long v) {
638     long r = v % 18L;
639     return r;
640   }
641 
642   /// CHECK-START-ARM64: long RemTest.$noinline$LongRemByMinus18(long) disassembly (after)
643   /// CHECK:                 smulh x{{\d+}}, x{{\d+}}, x{{\d+}}
644   /// CHECK-NEXT:            add x{{\d+}}, x{{\d+}}, x{{\d+}}, lsr #63
645   /// CHECK-NEXT:            mov x{{\d+}}, #0xffffffffffffffee
646   /// CHECK-NEXT:            msub x{{\d+}}, x{{\d+}}, x{{\d+}}, x{{\d+}}
$noinline$LongRemByMinus18(long v)647   private static long $noinline$LongRemByMinus18(long v) {
648     long r = v % -18L;
649     return r;
650   }
651 
652   /// CHECK-START-ARM64: long RemTest.$noinline$LongRemBy7(long) disassembly (after)
653   /// CHECK:                 smulh x{{\d+}}, x{{\d+}}, x{{\d+}}
654   /// CHECK-NEXT:            asr x{{\d+}}, x{{\d+}}, #1
655   /// CHECK-NEXT:            add x{{\d+}}, x{{\d+}}, x{{\d+}}, lsr #63
656   /// CHECK-NEXT:            mov x{{\d+}}, #0x7
657   /// CHECK-NEXT:            msub x{{\d+}}, x{{\d+}}, x{{\d+}}, x{{\d+}}
$noinline$LongRemBy7(long v)658   private static long $noinline$LongRemBy7(long v) {
659     long r = v % 7L;
660     return r;
661   }
662 
663   /// CHECK-START-ARM64: long RemTest.$noinline$LongRemByMinus7(long) disassembly (after)
664   /// CHECK:                 smulh x{{\d+}}, x{{\d+}}, x{{\d+}}
665   /// CHECK-NEXT:            asr x{{\d+}}, x{{\d+}}, #1
666   /// CHECK-NEXT:            add x{{\d+}}, x{{\d+}}, x{{\d+}}, lsr #63
667   /// CHECK-NEXT:            mov x{{\d+}}, #0xfffffffffffffff9
668   /// CHECK-NEXT:            msub x{{\d+}}, x{{\d+}}, x{{\d+}}, x{{\d+}}
$noinline$LongRemByMinus7(long v)669   private static long $noinline$LongRemByMinus7(long v) {
670     long r = v % -7L;
671     return r;
672   }
673 
674   /// CHECK-START-ARM64: long RemTest.$noinline$LongRemBy6(long) disassembly (after)
675   /// CHECK:                 smulh x{{\d+}}, x{{\d+}}, x{{\d+}}
676   /// CHECK-NEXT:            add x{{\d+}}, x{{\d+}}, x{{\d+}}, lsr #63
677   /// CHECK-NEXT:            mov x{{\d+}}, #0x6
678   /// CHECK-NEXT:            msub x{{\d+}}, x{{\d+}}, x{{\d+}}, x{{\d+}}
$noinline$LongRemBy6(long v)679   private static long $noinline$LongRemBy6(long v) {
680     long r = v % 6L;
681     return r;
682   }
683 
684   /// CHECK-START-ARM64: long RemTest.$noinline$LongRemByMinus6(long) disassembly (after)
685   /// CHECK:                 smulh x{{\d+}}, x{{\d+}}, x{{\d+}}
686   /// CHECK-NEXT:            add x{{\d+}}, x{{\d+}}, x{{\d+}}, lsr #63
687   /// CHECK-NEXT:            mov x{{\d+}}, #0xfffffffffffffffa
688   /// CHECK-NEXT:            msub x{{\d+}}, x{{\d+}}, x{{\d+}}, x{{\d+}}
$noinline$LongRemByMinus6(long v)689   private static long $noinline$LongRemByMinus6(long v) {
690     long r = v % -6L;
691     return r;
692   }
693 
694   // A test to check 'add' and 'add_shift' are optimized into 'adds' and 'cinc'.
695   //
696   /// CHECK-START-ARM64: long RemTest.$noinline$LongRemBy100(long) disassembly (after)
697   /// CHECK:                 smulh x{{\d+}}, x{{\d+}}, x{{\d+}}
698   /// CHECK-NEXT:            adds  x{{\d+}}, x{{\d+}}, x{{\d+}}
699   /// CHECK-NEXT:            asr   x{{\d+}}, x{{\d+}}, #6
700   /// CHECK-NEXT:            cinc  x{{\d+}}, x{{\d+}}, mi
701   /// CHECK-NEXT:            mov x{{\d+}}, #0x64
702   /// CHECK-NEXT:            msub x{{\d+}}, x{{\d+}}, x{{\d+}}, x{{\d+}}
$noinline$LongRemBy100(long v)703   private static long $noinline$LongRemBy100(long v) {
704     long r = v % 100L;
705     return r;
706   }
707 
708   // A test to check 'sub' and 'add_shift' are optimized into 'subs' and 'cinc'.
709   //
710   /// CHECK-START-ARM64: long RemTest.$noinline$LongRemByMinus100(long) disassembly (after)
711   /// CHECK:                 smulh x{{\d+}}, x{{\d+}}, x{{\d+}}
712   /// CHECK-NEXT:            subs  x{{\d+}}, x{{\d+}}, x{{\d+}}
713   /// CHECK-NEXT:            asr   x{{\d+}}, x{{\d+}}, #6
714   /// CHECK-NEXT:            cinc  x{{\d+}}, x{{\d+}}, mi
715   /// CHECK-NEXT:            mov x{{\d+}}, #0xffffffffffffff9c
716   /// CHECK-NEXT:            msub x{{\d+}}, x{{\d+}}, x{{\d+}}, x{{\d+}}
$noinline$LongRemByMinus100(long v)717   private static long $noinline$LongRemByMinus100(long v) {
718     long r = v % -100L;
719     return r;
720   }
721 
$noinline$Negate(long v)722   private static long $noinline$Negate(long v) {
723     return -v;
724   }
725 
$noinline$Decrement(long v)726   private static long $noinline$Decrement(long v) {
727     return v - 1;
728   }
729 
$noinline$Increment(long v)730   private static long $noinline$Increment(long v) {
731     return v + 1;
732   }
733 
734   // A test case to check that a correcting 'add' is not generated for a non-negative
735   // dividend and a positive divisor.
736   //
737   /// CHECK-START-ARM64: long RemTest.$noinline$UnsignedLongRem01(long) disassembly (after)
738   /// CHECK:                 smulh x{{\d+}}, x{{\d+}}, x{{\d+}}
739   /// CHECK-NEXT:            mov x{{\d+}}, #0x6
740   /// CHECK-NEXT:            msub x{{\d+}}, x{{\d+}}, x{{\d+}}, x{{\d+}}
$noinline$UnsignedLongRem01(long v)741   private static long $noinline$UnsignedLongRem01(long v) {
742     long c = 0;
743     if (v > 0) {
744       c = v % 6;
745     } else {
746       c = $noinline$Negate(v); // This is to prevent from using Select.
747     }
748     return c;
749   }
750 
751   // A test case to check that a correcting 'add' is not generated for a non-negative
752   // dividend and a positive divisor.
753   //
754   /// CHECK-START-ARM64: long RemTest.$noinline$UnsignedLongRem02(long) disassembly (after)
755   /// CHECK:                 smulh x{{\d+}}, x{{\d+}}, x{{\d+}}
756   /// CHECK-NEXT:            mov x{{\d+}}, #0x6
757   /// CHECK-NEXT:            msub x{{\d+}}, x{{\d+}}, x{{\d+}}, x{{\d+}}
$noinline$UnsignedLongRem02(long v)758   private static long $noinline$UnsignedLongRem02(long v) {
759     long c = 0;
760     if (0 < v) {
761       c = v % 6;
762     } else {
763       c = $noinline$Negate(v); // This is to prevent from using Select.
764     }
765     return c;
766   }
767 
768   // A test case to check that a correcting 'add' is not generated for a non-negative
769   // dividend and a positive divisor.
770   //
771   /// CHECK-START-ARM64: long RemTest.$noinline$UnsignedLongRem03(long) disassembly (after)
772   /// CHECK:                 smulh x{{\d+}}, x{{\d+}}, x{{\d+}}
773   /// CHECK-NEXT:            mov x{{\d+}}, #0x6
774   /// CHECK-NEXT:            msub x{{\d+}}, x{{\d+}}, x{{\d+}}, x{{\d+}}
$noinline$UnsignedLongRem03(long v)775   private static long $noinline$UnsignedLongRem03(long v) {
776     long c = 0;
777     if (v >= 0) {
778       c = v % 6;
779     } else {
780       c = $noinline$Negate(v); // This is to prevent from using Select.
781     }
782     return c;
783   }
784 
785   // A test case to check that a correcting 'add' is not generated for a non-negative
786   // dividend and a positive divisor.
787   //
788   /// CHECK-START-ARM64: long RemTest.$noinline$UnsignedLongRem04(long) disassembly (after)
789   /// CHECK:                 smulh x{{\d+}}, x{{\d+}}, x{{\d+}}
790   /// CHECK-NEXT:            mov x{{\d+}}, #0x6
791   /// CHECK-NEXT:            msub x{{\d+}}, x{{\d+}}, x{{\d+}}, x{{\d+}}
$noinline$UnsignedLongRem04(long v)792   private static long $noinline$UnsignedLongRem04(long v) {
793     long c = 0;
794     if (0 <= v) {
795       c = v % 6;
796     } else {
797       c = $noinline$Negate(v); // This is to prevent from using Select.
798     }
799     return c;
800   }
801 
802   // A test case to check that a correcting 'add' is not generated for a non-negative
803   // dividend and a positive divisor.
804   //
805   /// CHECK-START-ARM64: long RemTest.$noinline$UnsignedLongRem05(long) disassembly (after)
806   /// CHECK:                 smulh x{{\d+}}, x{{\d+}}, x{{\d+}}
807   /// CHECK-NEXT:            lsr x{{\d+}}, x{{\d+}}, #2
808   /// CHECK-NEXT:            mov x{{\d+}}, #0xa
809   /// CHECK-NEXT:            msub x{{\d+}}, x{{\d+}}, x{{\d+}}, x{{\d+}}
$noinline$UnsignedLongRem05(long v)810   private static long $noinline$UnsignedLongRem05(long v) {
811     long c = 0;
812     for(; v > 100; ++c) {
813       v %= 10;
814     }
815     return c;
816   }
817 
818   // A test case to check that a correcting 'add' is not generated for a non-negative
819   // dividend and a positive divisor.
820   //
821   /// CHECK-START-ARM64: long RemTest.$noinline$UnsignedLongRem06(long) disassembly (after)
822   /// CHECK:                 smulh x{{\d+}}, x{{\d+}}, x{{\d+}}
823   /// CHECK-NEXT:            lsr x{{\d+}}, x{{\d+}}, #2
824   /// CHECK:                 msub x{{\d+}}, x{{\d+}}, x{{\d+}}, x{{\d+}}
$noinline$UnsignedLongRem06(long v)825   private static long $noinline$UnsignedLongRem06(long v) {
826     if (v < 10) {
827       v = $noinline$Negate(v); // This is to prevent from using Select.
828     } else {
829       v = (v % 10) + (v / 10);
830     }
831     return v;
832   }
833 
834   // A test case to check that a correcting 'add' is generated for a negative
835   // dividend and a positive divisor.
836   //
837   /// CHECK-START-ARM64: long RemTest.$noinline$SignedLongRem01(long) disassembly (after)
838   /// CHECK:                 smulh x{{\d+}}, x{{\d+}}, x{{\d+}}
839   /// CHECK-NEXT:            add x{{\d+}}, x{{\d+}}, x{{\d+}}, lsr #63
840   /// CHECK-NEXT:            mov x{{\d+}}, #0x6
841   /// CHECK-NEXT:            msub x{{\d+}}, x{{\d+}}, x{{\d+}}, x{{\d+}}
$noinline$SignedLongRem01(long v)842   private static long $noinline$SignedLongRem01(long v) {
843     long c = 0;
844     if (v < 0) {
845       c = v % 6;
846     } else {
847       c = $noinline$Decrement(v); // This is to prevent from using Select.
848     }
849     return c;
850   }
851 
852   // A test case to check that a correcting 'add' is generated for a negative
853   // dividend and a positive divisor.
854   //
855   /// CHECK-START-ARM64: long RemTest.$noinline$SignedLongRem02(long) disassembly (after)
856   /// CHECK:                 smulh x{{\d+}}, x{{\d+}}, x{{\d+}}
857   /// CHECK-NEXT:            add x{{\d+}}, x{{\d+}}, x{{\d+}}, lsr #63
858   /// CHECK-NEXT:            mov x{{\d+}}, #0x6
859   /// CHECK-NEXT:            msub x{{\d+}}, x{{\d+}}, x{{\d+}}, x{{\d+}}
$noinline$SignedLongRem02(long v)860   private static long $noinline$SignedLongRem02(long v) {
861     long c = 0;
862     if (v <= 0) {
863       c = v % 6;
864     } else {
865       c = $noinline$Decrement(v); // This is to prevent from using Select.
866     }
867     return c;
868   }
869 
870   // A test case to check that a correcting 'add' is generated for signed division.
871   //
872   /// CHECK-START-ARM64: long RemTest.$noinline$SignedLongRem03(long) disassembly (after)
873   /// CHECK:                 smulh x{{\d+}}, x{{\d+}}, x{{\d+}}
874   /// CHECK-NEXT:            add x{{\d+}}, x{{\d+}}, x{{\d+}}, lsr #63
875   /// CHECK-NEXT:            mov x{{\d+}}, #0x6
876   /// CHECK-NEXT:            msub x{{\d+}}, x{{\d+}}, x{{\d+}}, x{{\d+}}
$noinline$SignedLongRem03(long v)877   private static long $noinline$SignedLongRem03(long v) {
878     boolean positive = (v > 0);
879     long c = v % 6;
880     if (!positive) {
881       c = $noinline$Negate(c); // This is to prevent from using Select.
882     }
883     return c;
884   }
885 
886   // A test case to check that a correcting 'add' is generated for signed division.
887   //
888   /// CHECK-START-ARM64: long RemTest.$noinline$SignedLongRem04(long, boolean) disassembly (after)
889   /// CHECK:                 smulh x{{\d+}}, x{{\d+}}, x{{\d+}}
890   /// CHECK-NEXT:            add x{{\d+}}, x{{\d+}}, x{{\d+}}, lsr #63
891   /// CHECK-NEXT:            mov x{{\d+}}, #0x6
892   /// CHECK-NEXT:            msub x{{\d+}}, x{{\d+}}, x{{\d+}}, x{{\d+}}
$noinline$SignedLongRem04(long v, boolean apply_rem)893   private static long $noinline$SignedLongRem04(long v, boolean apply_rem) {
894     long c = 0;
895     boolean positive = (v > 0);
896     if (apply_rem) {
897       c = v % 6;
898     } else {
899       c = $noinline$Decrement(v); // This is to prevent from using Select.
900     }
901     if (!positive) {
902       c = $noinline$Negate(c); // This is to prevent from using Select.
903     }
904     return c;
905   }
906 
907   // A test case to check that a correcting 'add' is generated for signed division.
908   //
909   /// CHECK-START-ARM64: long RemTest.$noinline$SignedLongRem05(long, long, long) disassembly (after)
910   /// CHECK:                 smulh x{{\d+}}, x{{\d+}}, x{{\d+}}
911   /// CHECK-NEXT:            add x{{\d+}}, x{{\d+}}, x{{\d+}}, lsr #63
912   /// CHECK-NEXT:            mov x{{\d+}}, #0x6
913   /// CHECK-NEXT:            msub x{{\d+}}, x{{\d+}}, x{{\d+}}, x{{\d+}}
$noinline$SignedLongRem05(long v, long a, long b)914   private static long $noinline$SignedLongRem05(long v, long a, long b) {
915     long c = 0;
916 
917     if (v < a)
918       c = $noinline$Increment(c); // This is to prevent from using Select.
919 
920     if (b < a)
921       c = $noinline$Increment(c); // This is to prevent from using Select.
922 
923     if (v > b) {
924       c = v % 6;
925     } else {
926       c = $noinline$Increment(c); // This is to prevent from using Select.
927     }
928 
929     return c;
930   }
931 
932   // A test case to check that a correcting 'add' is generated for signed division.
933   //
934   /// CHECK-START-ARM64: long RemTest.$noinline$SignedLongRem06(long) disassembly (after)
935   /// CHECK:                 smulh x{{\d+}}, x{{\d+}}, x{{\d+}}
936   /// CHECK-NEXT:            add x{{\d+}}, x{{\d+}}, x{{\d+}}, lsr #63
937   /// CHECK-NEXT:            mov x{{\d+}}, #0x6
938   /// CHECK-NEXT:            msub x{{\d+}}, x{{\d+}}, x{{\d+}}, x{{\d+}}
$noinline$SignedLongRem06(long v)939   private static long $noinline$SignedLongRem06(long v) {
940     long c = v % 6;
941 
942     if (v > 0) {
943       c = $noinline$Negate(c); // This is to prevent from using Select.
944     }
945 
946     return c;
947   }
948 }
949