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 Main {
expectEquals(long expected, long result)18   private static void expectEquals(long expected, long result) {
19     if (expected != result) {
20       throw new Error("Expected: " + expected + ", found: " + result);
21     }
22   }
23 
remInt()24   private static void remInt() {
25     expectEquals(1L << 32, $noinline$IntRemBy3(3));
26     expectEquals((3L << 32) | 6, $noinline$IntRemBy7(27));
27     expectEquals((1L << 32) | 1, $noinline$IntRemBy12(13));
28     expectEquals((1L << 32) | 1, $noinline$IntRemBy12A(13));
29   }
30 
31   // A test case to check:
32   //  BCE detects the optimized 'v % 3' and eliminates bounds checks.
33   //
34   /// CHECK-START:       long Main.$noinline$IntRemBy3(int) BCE (before)
35   /// CHECK:                 Div
36   /// CHECK-NEXT:            Shl
37   /// CHECK-NEXT:            Add
38   /// CHECK-NEXT:            Sub
39   /// CHECK:                 BoundsCheck
40   /// CHECK-NEXT:            ArrayGet
41   //
42   /// CHECK-START:       long Main.$noinline$IntRemBy3(int) BCE (after)
43   /// CHECK:                 Div
44   /// CHECK-NEXT:            Shl
45   /// CHECK-NEXT:            Add
46   /// CHECK-NEXT:            Sub
47   /// CHECK-NOT:             BoundsCheck
48   /// CHECK:                 ArrayGet
$noinline$IntRemBy3(int v)49   private static long $noinline$IntRemBy3(int v) {
50     int[] values = {0, 1, 2};
51     if (v > 0) {
52       int q = v / 3;
53       int r = v % 3;
54       return ((long)q << 32) | values[r];
55     } else {
56       return -1;
57     }
58   }
59 
60   // A test case to check:
61   //  BCE detects the optimized 'v % 7' and eliminates bounds checks.
62   //
63   /// CHECK-START:       long Main.$noinline$IntRemBy7(int) BCE (before)
64   /// CHECK:                 Div
65   /// CHECK-NEXT:            Shl
66   /// CHECK-NEXT:            Sub
67   /// CHECK-NEXT:            Sub
68   /// CHECK:                 BoundsCheck
69   /// CHECK-NEXT:            ArrayGet
70   //
71   /// CHECK-START:       long Main.$noinline$IntRemBy7(int) BCE (after)
72   /// CHECK:                 Div
73   /// CHECK-NEXT:            Shl
74   /// CHECK-NEXT:            Sub
75   /// CHECK-NEXT:            Sub
76   /// CHECK-NOT:             BoundsCheck
77   /// CHECK:                 ArrayGet
$noinline$IntRemBy7(int v)78   private static long $noinline$IntRemBy7(int v) {
79     int[] values = {0, 1, 2, 3, 4, 5, 6};
80     if (v > 0) {
81       int q = v / 7;
82       int r = v % 7;
83       return ((long)q << 32) | values[r];
84     } else {
85       return -1;
86     }
87   }
88 
89   // A test case to check:
90   //  BCE detects the optimized 'v % 12' and eliminates bounds checks.
91   //
92   /// CHECK-START:       long Main.$noinline$IntRemBy12(int) BCE (before)
93   /// CHECK:                 Div
94   /// CHECK-NEXT:            Mul
95   /// CHECK-NEXT:            Sub
96   /// CHECK:                 BoundsCheck
97   /// CHECK-NEXT:            ArrayGet
98   //
99   /// CHECK-START:       long Main.$noinline$IntRemBy12(int) BCE (after)
100   /// CHECK:                 Div
101   /// CHECK-NEXT:            Mul
102   /// CHECK-NEXT:            Sub
103   /// CHECK-NOT:             BoundsCheck
104   /// CHECK:                 ArrayGet
$noinline$IntRemBy12(int v)105   private static long $noinline$IntRemBy12(int v) {
106     int[] values = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};
107     if (v > 0) {
108       int q = v / 12;
109       int r = v % 12;
110       return ((long)q << 32) | values[r];
111     } else {
112       return -1;
113     }
114   }
115 
116   // A test case to check:
117   //  BCE detects the optimized 'v % 12' and eliminates bounds checks.
118   //
119   /// CHECK-START:       long Main.$noinline$IntRemBy12A(int) BCE (before)
120   /// CHECK:                 Div
121   /// CHECK-NEXT:            Mul
122   /// CHECK-NEXT:            Sub
123   /// CHECK:                 BoundsCheck
124   /// CHECK-NEXT:            ArrayGet
125   //
126   /// CHECK-START:       long Main.$noinline$IntRemBy12A(int) BCE (after)
127   /// CHECK:                 Div
128   /// CHECK-NEXT:            Mul
129   /// CHECK-NEXT:            Sub
130   /// CHECK-NOT:             BoundsCheck
131   /// CHECK:                 ArrayGet
$noinline$IntRemBy12A(int v)132   private static long $noinline$IntRemBy12A(int v) {
133     int[] values = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};
134     if (v > 0) {
135       int q = v / 12;
136       int t = q * 12;
137       int r = v  - t;
138       return ((long)q << 32) | values[r];
139     } else {
140       return -1;
141     }
142   }
143 
144   // A test case to check:
145   //  BCE detects the optimized 'v % Integer.MAX_VALUE' and eliminates bounds checks.
146   //
147   /// CHECK-START:       int Main.$noinline$IntRemByMaxInt(int) BCE (before)
148   /// CHECK:                 Div
149   /// CHECK-NEXT:            Shl
150   /// CHECK-NEXT:            Sub
151   /// CHECK-NEXT:            Sub
152   /// CHECK:                 BoundsCheck
153   /// CHECK-NEXT:            ArrayGet
154   //
155   /// CHECK-START:       int Main.$noinline$IntRemByMaxInt(int) BCE (after)
156   /// CHECK:                 Div
157   /// CHECK-NEXT:            Shl
158   /// CHECK-NEXT:            Sub
159   /// CHECK-NEXT:            Sub
160   /// CHECK-NOT:             BoundsCheck
161   /// CHECK:                 ArrayGet
$noinline$IntRemByMaxInt(int v)162   private static int $noinline$IntRemByMaxInt(int v) {
163     int[] values = new int[Integer.MAX_VALUE];
164     if (v > 0) {
165       int q = v / Integer.MAX_VALUE;
166       int r = v % Integer.MAX_VALUE;
167       return values[v % Integer.MAX_VALUE] + q;
168     } else {
169       return -1;
170     }
171   }
172 
173   // A test case to check:
174   //  BCE detects the optimized 'v % Integer.MIN_VALUE' and eliminates bounds checks.
175   //
176   /// CHECK-START:       int Main.$noinline$IntRemByMinInt(int) BCE (before)
177   /// CHECK:                 Div
178   /// CHECK-NEXT:            Mul
179   /// CHECK-NEXT:            Sub
180   /// CHECK:                 BoundsCheck
181   /// CHECK-NEXT:            ArrayGet
182   //
183   /// CHECK-START:       int Main.$noinline$IntRemByMinInt(int) BCE (after)
184   /// CHECK:                 Div
185   /// CHECK-NEXT:            Mul
186   /// CHECK-NEXT:            Sub
187   /// CHECK-NOT:             BoundsCheck
188   /// CHECK:                 ArrayGet
$noinline$IntRemByMinInt(int v)189   private static int $noinline$IntRemByMinInt(int v) {
190     int[] values = new int[Integer.MAX_VALUE];
191     if (v > 0) {
192       int q = v / Integer.MIN_VALUE;
193       int t = q * Integer.MIN_VALUE;
194       int r = v - t;
195       return values[r - 1];
196     } else {
197       return -1;
198     }
199   }
200 
201   // A test case to check:
202   //  Bounds checks are not eliminated if the checked value is not an optimized HDiv+HRem.
203   //
204   /// CHECK-START:       int Main.$noinline$NoRem01(int, int) BCE (before)
205   /// CHECK:                 Mul
206   /// CHECK-NEXT:            Sub
207   /// CHECK-NEXT:            BoundsCheck
208   /// CHECK-NEXT:            ArrayGet
209   //
210   /// CHECK-START:       int Main.$noinline$NoRem01(int, int) BCE (after)
211   /// CHECK:                 Mul
212   /// CHECK-NEXT:            Sub
213   /// CHECK-NEXT:            BoundsCheck
214   /// CHECK-NEXT:            ArrayGet
$noinline$NoRem01(int v, int s)215   private static int $noinline$NoRem01(int v, int s) {
216     int[] values = {0, 1, 2};
217     if (v > 0) {
218       int a = v * 10;
219       int b = s - a;
220       return values[b];
221     } else {
222       return -1;
223     }
224   }
225 
226   // A test case to check:
227   //  Bounds checks are not eliminated if the checked value is not an optimized HDiv+HRem.
228   //
229   /// CHECK-START:       int Main.$noinline$NoRem02(int, int) BCE (before)
230   /// CHECK:                 Div
231   /// CHECK-NEXT:            Mul
232   /// CHECK-NEXT:            Sub
233   /// CHECK-NEXT:            BoundsCheck
234   /// CHECK-NEXT:            ArrayGet
235   //
236   /// CHECK-START:       int Main.$noinline$NoRem02(int, int) BCE (after)
237   /// CHECK:                 Div
238   /// CHECK-NEXT:            Mul
239   /// CHECK-NEXT:            Sub
240   /// CHECK-NEXT:            BoundsCheck
241   /// CHECK-NEXT:            ArrayGet
$noinline$NoRem02(int v, int s)242   private static int $noinline$NoRem02(int v, int s) {
243     int[] values = {0, 1, 2};
244     if (v > 0) {
245       int q = v / 10;
246       int a = q * s;
247       int b = v - a;
248       return values[b];
249     } else {
250       return -1;
251     }
252   }
253 
254   // A test case to check:
255   //  Bounds checks are not eliminated if the checked value is not an optimized HDiv+HRem.
256   //
257   /// CHECK-START:       int Main.$noinline$NoRem03(int, int) BCE (before)
258   /// CHECK:                 Div
259   /// CHECK-NEXT:            Add
260   /// CHECK-NEXT:            Sub
261   /// CHECK-NEXT:            BoundsCheck
262   /// CHECK-NEXT:            ArrayGet
263   //
264   /// CHECK-START:       int Main.$noinline$NoRem03(int, int) BCE (after)
265   /// CHECK:                 Div
266   /// CHECK-NEXT:            Add
267   /// CHECK-NEXT:            Sub
268   /// CHECK-NEXT:            BoundsCheck
269   /// CHECK-NEXT:            ArrayGet
$noinline$NoRem03(int v, int s)270   private static int $noinline$NoRem03(int v, int s) {
271     int[] values = {0, 1, 2};
272     if (v > 0) {
273       int q = v / 10;
274       int a = q + s;
275       int b = v - a;
276       return values[b];
277     } else {
278       return -1;
279     }
280   }
281 
282   // A test case to check:
283   //  Bounds checks are not eliminated if the checked value is not an optimized HDiv+HRem.
284   //
285   /// CHECK-START:       int Main.$noinline$NoRem04(int, int) BCE (before)
286   /// CHECK:                 Div
287   /// CHECK-NEXT:            Shl
288   /// CHECK-NEXT:            Add
289   /// CHECK-NEXT:            Sub
290   /// CHECK-NEXT:            BoundsCheck
291   /// CHECK-NEXT:            ArrayGet
292   //
293   /// CHECK-START:       int Main.$noinline$NoRem04(int, int) BCE (after)
294   /// CHECK:                 Div
295   /// CHECK-NEXT:            Shl
296   /// CHECK-NEXT:            Add
297   /// CHECK-NEXT:            Sub
298   /// CHECK-NEXT:            BoundsCheck
299   /// CHECK-NEXT:            ArrayGet
$noinline$NoRem04(int v, int s)300   private static int $noinline$NoRem04(int v, int s) {
301     int[] values = {0, 1, 2};
302     if (v > 0) {
303       int q = v / 10;
304       int t = q << s;
305       int a = q + t;
306       int b = v - a;
307       return values[b];
308     } else {
309       return -1;
310     }
311   }
312 
313   // A test case to check:
314   //  Bounds checks are not eliminated if the checked value is not an optimized HDiv+HRem.
315   //
316   /// CHECK-START:       int Main.$noinline$NoRem05(int, int) BCE (before)
317   /// CHECK:                 Div
318   /// CHECK-NEXT:            Shl
319   /// CHECK-NEXT:            Add
320   /// CHECK-NEXT:            Sub
321   /// CHECK-NEXT:            BoundsCheck
322   /// CHECK-NEXT:            ArrayGet
323   //
324   /// CHECK-START:       int Main.$noinline$NoRem05(int, int) BCE (after)
325   /// CHECK:                 Div
326   /// CHECK-NEXT:            Shl
327   /// CHECK-NEXT:            Add
328   /// CHECK-NEXT:            Sub
329   /// CHECK-NEXT:            BoundsCheck
330   /// CHECK-NEXT:            ArrayGet
$noinline$NoRem05(int v, int s)331   private static int $noinline$NoRem05(int v, int s) {
332     int[] values = {0, 1, 2};
333     if (v > 0) {
334       int q = v / 10;
335       int t = s << 1;
336       int a = q + t;
337       int b = v - a;
338       return values[b];
339     } else {
340       return -1;
341     }
342   }
343 
344   // A test case to check:
345   //  Bounds checks are not eliminated if the checked value is not an optimized HDiv+HRem.
346   //
347   /// CHECK-START:       int Main.$noinline$NoRem06(int, int) BCE (before)
348   /// CHECK:                 Div
349   /// CHECK-NEXT:            Mul
350   /// CHECK-NEXT:            Sub
351   /// CHECK-NEXT:            BoundsCheck
352   /// CHECK-NEXT:            ArrayGet
353   //
354   /// CHECK-START:       int Main.$noinline$NoRem06(int, int) BCE (after)
355   /// CHECK:                 Div
356   /// CHECK-NEXT:            Mul
357   /// CHECK-NEXT:            Sub
358   /// CHECK-NEXT:            BoundsCheck
359   /// CHECK-NEXT:            ArrayGet
$noinline$NoRem06(int v, int s)360   private static int $noinline$NoRem06(int v, int s) {
361     int[] values = {0, 1, 2};
362     if (v > 0) {
363       int q = v / 10;
364       int a = q * 11;
365       int b = v - a;
366       return values[b];
367     } else {
368       return -1;
369     }
370   }
371 
372   // A test case to check:
373   //  Bounds checks are not eliminated if the checked value is not an optimized HDiv+HRem.
374   //
375   /// CHECK-START:       int Main.$noinline$NoRem07(int, int) BCE (before)
376   /// CHECK:                 Div
377   /// CHECK-NEXT:            Shl
378   /// CHECK-NEXT:            Add
379   /// CHECK-NEXT:            Sub
380   /// CHECK-NEXT:            BoundsCheck
381   /// CHECK-NEXT:            ArrayGet
382   //
383   /// CHECK-START:       int Main.$noinline$NoRem07(int, int) BCE (after)
384   /// CHECK:                 Div
385   /// CHECK-NEXT:            Shl
386   /// CHECK-NEXT:            Add
387   /// CHECK-NEXT:            Sub
388   /// CHECK-NEXT:            BoundsCheck
389   /// CHECK-NEXT:            ArrayGet
$noinline$NoRem07(int v, int s)390   private static int $noinline$NoRem07(int v, int s) {
391     int[] values = {0, 1, 2};
392     if (v > 0) {
393       int q = v / 10;
394       int t = q << 1;
395       int a = s + t;
396       int b = v - a;
397       return values[b];
398     } else {
399       return -1;
400     }
401   }
402 
403   // A test case to check:
404   //  Bounds checks are not eliminated if the checked value is not an optimized HDiv+HRem.
405   //
406   /// CHECK-START:       int Main.$noinline$NoRem08(int, int) BCE (before)
407   /// CHECK:                 Div
408   /// CHECK-NEXT:            Shl
409   /// CHECK-NEXT:            Add
410   /// CHECK-NEXT:            Sub
411   /// CHECK-NEXT:            BoundsCheck
412   /// CHECK-NEXT:            ArrayGet
413   //
414   /// CHECK-START:       int Main.$noinline$NoRem08(int, int) BCE (after)
415   /// CHECK:                 Div
416   /// CHECK-NEXT:            Shl
417   /// CHECK-NEXT:            Add
418   /// CHECK-NEXT:            Sub
419   /// CHECK-NEXT:            BoundsCheck
420   /// CHECK-NEXT:            ArrayGet
$noinline$NoRem08(int v, int s)421   private static int $noinline$NoRem08(int v, int s) {
422     int[] values = {0, 1, 2};
423     if (v > 0) {
424       int q = v / 10;
425       int t = q << 31;
426       int a = q + t;
427       int b = v - a;
428       return values[b];
429     } else {
430       return -1;
431     }
432   }
433 
434   // A test case to check:
435   //  Bounds checks are not eliminated if the checked value is not an optimized HDiv+HRem.
436   //
437   /// CHECK-START:       int Main.$noinline$NoRem09(int, int) BCE (before)
438   /// CHECK:                 Div
439   /// CHECK-NEXT:            Shl
440   /// CHECK-NEXT:            Add
441   /// CHECK-NEXT:            Sub
442   /// CHECK-NEXT:            BoundsCheck
443   /// CHECK-NEXT:            ArrayGet
444   //
445   /// CHECK-START:       int Main.$noinline$NoRem09(int, int) BCE (after)
446   /// CHECK:                 Div
447   /// CHECK-NEXT:            Shl
448   /// CHECK-NEXT:            Add
449   /// CHECK-NEXT:            Sub
450   /// CHECK-NEXT:            BoundsCheck
451   /// CHECK-NEXT:            ArrayGet
$noinline$NoRem09(int v, int s)452   private static int $noinline$NoRem09(int v, int s) {
453     int[] values = {0, 1, 2};
454     if (v > 0) {
455       int q = v / 10;
456       int t = q << 1;
457       int a = q + t;
458       int b = v - a;
459       return values[b];
460     } else {
461       return -1;
462     }
463   }
464 
465   // A test case to check:
466   //  Bounds checks are not eliminated if the checked value is not an optimized HDiv+HRem.
467   //
468   /// CHECK-START:       int Main.$noinline$NoRem10(int, int) BCE (before)
469   /// CHECK:                 Div
470   /// CHECK-NEXT:            Shl
471   /// CHECK-NEXT:            Sub
472   /// CHECK-NEXT:            Sub
473   /// CHECK-NEXT:            BoundsCheck
474   /// CHECK-NEXT:            ArrayGet
475   //
476   /// CHECK-START:       int Main.$noinline$NoRem10(int, int) BCE (after)
477   /// CHECK:                 Div
478   /// CHECK-NEXT:            Shl
479   /// CHECK-NEXT:            Sub
480   /// CHECK-NEXT:            Sub
481   /// CHECK-NEXT:            BoundsCheck
482   /// CHECK-NEXT:            ArrayGet
$noinline$NoRem10(int v, int s)483   private static int $noinline$NoRem10(int v, int s) {
484     int[] values = {0, 1, 2};
485     if (v > 0) {
486       int q = v / 10;
487       int t = q << s;
488       int a = t - q;
489       int b = v - a;
490       return values[b];
491     } else {
492       return -1;
493     }
494   }
495 
496   // A test case to check:
497   //  Bounds checks are not eliminated if the checked value is not an optimized HDiv+HRem.
498   //
499   /// CHECK-START:       int Main.$noinline$NoRem11(int, int) BCE (before)
500   /// CHECK:                 Div
501   /// CHECK-NEXT:            Shl
502   /// CHECK-NEXT:            Sub
503   /// CHECK-NEXT:            Sub
504   /// CHECK-NEXT:            BoundsCheck
505   /// CHECK-NEXT:            ArrayGet
506   //
507   /// CHECK-START:       int Main.$noinline$NoRem11(int, int) BCE (after)
508   /// CHECK:                 Div
509   /// CHECK-NEXT:            Shl
510   /// CHECK-NEXT:            Sub
511   /// CHECK-NEXT:            Sub
512   /// CHECK-NEXT:            BoundsCheck
513   /// CHECK-NEXT:            ArrayGet
$noinline$NoRem11(int v, int s)514   private static int $noinline$NoRem11(int v, int s) {
515     int[] values = {0, 1, 2};
516     if (v > 0) {
517       int q = v / 10;
518       int t = s << 1;
519       int a = t - q;
520       int b = v - a;
521       return values[b];
522     } else {
523       return -1;
524     }
525   }
526 
527   // A test case to check:
528   //  Bounds checks are not eliminated if the checked value is not an optimized HDiv+HRem.
529   //
530   /// CHECK-START:       int Main.$noinline$NoRem12(int, int) BCE (before)
531   /// CHECK:                 Div
532   /// CHECK-NEXT:            Shl
533   /// CHECK-NEXT:            Sub
534   /// CHECK-NEXT:            Sub
535   /// CHECK-NEXT:            BoundsCheck
536   /// CHECK-NEXT:            ArrayGet
537   //
538   /// CHECK-START:       int Main.$noinline$NoRem12(int, int) BCE (after)
539   /// CHECK:                 Div
540   /// CHECK-NEXT:            Shl
541   /// CHECK-NEXT:            Sub
542   /// CHECK-NEXT:            Sub
543   /// CHECK-NEXT:            BoundsCheck
544   /// CHECK-NEXT:            ArrayGet
$noinline$NoRem12(int v, int s)545   private static int $noinline$NoRem12(int v, int s) {
546     int[] values = {0, 1, 2};
547     if (v > 0) {
548       int q = v / 10;
549       int t = q << 1;
550       int a = t - s;
551       int b = v - a;
552       return values[b];
553     } else {
554       return -1;
555     }
556   }
557 
558   // A test case to check:
559   //  Bounds checks are not eliminated if the checked value is not an optimized HDiv+HRem.
560   //
561   /// CHECK-START:       int Main.$noinline$NoRem13(int, int) BCE (before)
562   /// CHECK:                 Div
563   /// CHECK-NEXT:            Shl
564   /// CHECK-NEXT:            Sub
565   /// CHECK-NEXT:            Sub
566   /// CHECK-NEXT:            BoundsCheck
567   /// CHECK-NEXT:            ArrayGet
568   //
569   /// CHECK-START:       int Main.$noinline$NoRem13(int, int) BCE (after)
570   /// CHECK:                 Div
571   /// CHECK-NEXT:            Shl
572   /// CHECK-NEXT:            Sub
573   /// CHECK-NEXT:            Sub
574   /// CHECK-NEXT:            BoundsCheck
575   /// CHECK-NEXT:            ArrayGet
$noinline$NoRem13(int v, int s)576   private static int $noinline$NoRem13(int v, int s) {
577     int[] values = {0, 1, 2};
578     if (v > 0) {
579       int q = v / 10;
580       int t = q << 31;
581       int a = t - q;
582       int b = v - a;
583       return values[b];
584     } else {
585       return -1;
586     }
587   }
588 
589   // A test case to check:
590   //  Bounds checks are not eliminated if the checked value is not an optimized HDiv+HRem.
591   //
592   /// CHECK-START:       int Main.$noinline$NoRem14(int, int) BCE (before)
593   /// CHECK:                 Div
594   /// CHECK-NEXT:            Sub
595   /// CHECK-NEXT:            BoundsCheck
596   /// CHECK-NEXT:            ArrayGet
597   //
598   /// CHECK-START:       int Main.$noinline$NoRem14(int, int) BCE (after)
599   /// CHECK:                 Div
600   /// CHECK-NEXT:            Sub
601   /// CHECK-NEXT:            BoundsCheck
602   /// CHECK-NEXT:            ArrayGet
$noinline$NoRem14(int v, int s)603   private static int $noinline$NoRem14(int v, int s) {
604     int[] values = {0, 1, 2};
605     if (v > 0) {
606       int a = v / 10;
607       int b = s - a;
608       return values[b];
609     } else {
610       return -1;
611     }
612   }
613 
614   // A test case to check:
615   //  Bounds checks are not eliminated if the checked value is not an optimized HDiv+HRem.
616   //
617   /// CHECK-START:       int Main.$noinline$NoRem15(int, int) BCE (before)
618   /// CHECK:                 Div
619   /// CHECK-NEXT:            Mul
620   /// CHECK-NEXT:            Sub
621   /// CHECK-NEXT:            BoundsCheck
622   /// CHECK-NEXT:            ArrayGet
623   //
624   /// CHECK-START:       int Main.$noinline$NoRem15(int, int) BCE (after)
625   /// CHECK:                 Div
626   /// CHECK-NEXT:            Mul
627   /// CHECK-NEXT:            Sub
628   /// CHECK-NEXT:            BoundsCheck
629   /// CHECK-NEXT:            ArrayGet
$noinline$NoRem15(int v, int s)630   private static int $noinline$NoRem15(int v, int s) {
631     int[] values = {0, 1, 2};
632     if (v > 0) {
633       int q = v / 10;
634       int a = q * 10;
635       int b = s - a;
636       return values[b];
637     } else {
638       return -1;
639     }
640   }
641 
642   /// CHECK-START:       int Main.$noinline$noRemNonConst(int, int) BCE (after)
643   /// CHECK:                 BoundsCheck
$noinline$noRemNonConst(int v, int s)644   private static int $noinline$noRemNonConst(int v, int s) {
645     // Regression test for compiler crash, b/169669115.
646     int[] values = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
647     if (v > 0) {
648       int q = v / s;  // Non-constant divisor.
649       int a = q * 10;  // Constant unrelated to the divisor above.
650       int b = s - a;
651       return values[b];
652     } else {
653       return -1;
654     }
655   }
656 
main(String args[])657   public static void main(String args[]) {
658     remInt();
659   }
660 }
661