1 /*
2  * Copyright (C) 2018 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 /**
18  * Functional tests for detecting min/max.
19  */
20 public class TestMinMax {
21 
22   //
23   // Direct intrinsics.
24   //
25 
26   /// CHECK-START: int TestMinMax.minI(int) builder (after)
27   /// CHECK-DAG: <<Par:i\d+>> ParameterValue
28   /// CHECK-DAG: <<Con:i\d+>> IntConstant 20
29   /// CHECK-DAG: <<Min:i\d+>> Min [<<Par>>,<<Con>>]
30   /// CHECK-DAG:              Return [<<Min>>]
31   //
32   /// CHECK-START: int TestMinMax.minI(int) builder (after)
33   /// CHECK-NOT:              InvokeStaticOrDirect
34   //
35   /// CHECK-START-ARM64: int TestMinMax.minI(int) disassembly (after)
36   /// CHECK-NOT:              mov {{w\d+}}, #0x14
37   /// CHECK:                  cmp {{w\d+}}, #0x14
38   //  Check that the constant generation was handled by VIXL.
39   /// CHECK:                  mov w16, #0x14
40   /// CHECK:                  csel {{w\d+}}, {{w\d+}}, w16, lt
minI(int a)41   public static int minI(int a) {
42     return Math.min(a, 20);
43   }
44 
45   /// CHECK-START: long TestMinMax.minL(long) builder (after)
46   /// CHECK-DAG: <<Par:j\d+>> ParameterValue
47   /// CHECK-DAG: <<Con:j\d+>> LongConstant 20
48   /// CHECK-DAG: <<Min:j\d+>> Min [<<Par>>,<<Con>>]
49   /// CHECK-DAG:              Return [<<Min>>]
50   //
51   /// CHECK-START: long TestMinMax.minL(long) builder (after)
52   /// CHECK-NOT:              InvokeStaticOrDirect
53   //
54   /// CHECK-START-ARM64: long TestMinMax.minL(long) disassembly (after)
55   /// CHECK-NOT:              mov {{x\d+}}, #0x14
56   /// CHECK:                  cmp {{x\d+}}, #0x14
57   //  Check that the constant generation was handled by VIXL.
58   /// CHECK:                  mov x16, #0x14
59   /// CHECK:                  csel {{x\d+}}, {{x\d+}}, x16, lt
minL(long a)60   public static long minL(long a) {
61     return Math.min(a, 20L);
62   }
63 
64   /// CHECK-START: int TestMinMax.maxI(int) builder (after)
65   /// CHECK-DAG: <<Par:i\d+>> ParameterValue
66   /// CHECK-DAG: <<Con:i\d+>> IntConstant 20
67   /// CHECK-DAG: <<Max:i\d+>> Max [<<Par>>,<<Con>>]
68   /// CHECK-DAG:              Return [<<Max>>]
69   //
70   /// CHECK-START: int TestMinMax.maxI(int) builder (after)
71   /// CHECK-NOT:              InvokeStaticOrDirect
72   //
73   /// CHECK-START-ARM64: int TestMinMax.maxI(int) disassembly (after)
74   /// CHECK-NOT:              mov {{w\d+}}, #0x14
75   /// CHECK:                  cmp {{w\d+}}, #0x14
76   //  Check that the constant generation was handled by VIXL.
77   /// CHECK:                  mov w16, #0x14
78   /// CHECK:                  csel {{w\d+}}, {{w\d+}}, w16, gt
maxI(int a)79   public static int maxI(int a) {
80     return Math.max(a, 20);
81   }
82 
83   /// CHECK-START: long TestMinMax.maxL(long) builder (after)
84   /// CHECK-DAG: <<Par:j\d+>> ParameterValue
85   /// CHECK-DAG: <<Con:j\d+>> LongConstant 20
86   /// CHECK-DAG: <<Max:j\d+>> Max [<<Par>>,<<Con>>]
87   /// CHECK-DAG:              Return [<<Max>>]
88   //
89   /// CHECK-START: long TestMinMax.maxL(long) builder (after)
90   /// CHECK-NOT:              InvokeStaticOrDirect
91   //
92   /// CHECK-START-ARM64: long TestMinMax.maxL(long) disassembly (after)
93   /// CHECK-NOT:              mov {{x\d+}}, #0x14
94   /// CHECK:                  cmp {{x\d+}}, #0x14
95   //  Check that the constant generation was handled by VIXL.
96   /// CHECK:                  mov x16, #0x14
97   /// CHECK:                  csel {{x\d+}}, {{x\d+}}, x16, gt
maxL(long a)98   public static long maxL(long a) {
99     return Math.max(a, 20L);
100   }
101 
102   //
103   // Special Cases
104   //
105 
106   /// CHECK-START-ARM64: int TestMinMax.minIntConstantZero(int) disassembly (after)
107   /// CHECK-NOT:        InvokeStaticOrDirect
108   /// CHECK-NOT:        mov {{w\d+}}, #0x0
109   /// CHECK:            cmp {{w\d+}}, #0x0 (0)
110   /// CHECK:            csel {{w\d+}}, {{w\d+}}, wzr, lt
111   /// CHECK:            ret
minIntConstantZero(int a)112   public static int minIntConstantZero(int a) {
113     return Math.min(a, 0);
114   }
115 
116   /// CHECK-START-ARM64: int TestMinMax.minIntConstantOne(int) disassembly (after)
117   /// CHECK-NOT:        InvokeStaticOrDirect
118   /// CHECK-NOT:        mov {{w\d+}}, #0x1
119   /// CHECK:            cmp {{w\d+}}, #0x1 (1)
120   /// CHECK:            csinc {{w\d+}}, {{w\d+}}, wzr, lt
121   /// CHECK:            ret
minIntConstantOne(int a)122   public static int minIntConstantOne(int a) {
123     return Math.min(a, 1);
124   }
125 
126   /// CHECK-START-ARM64: int TestMinMax.minIntConstantMinusOne(int) disassembly (after)
127   /// CHECK-NOT:        InvokeStaticOrDirect
128   /// CHECK-NOT:        mov {{w\d+}}, #0xffffffff
129   /// CHECK:            cmn {{w\d+}}, #0x1 (1)
130   /// CHECK:            csinv {{w\d+}}, {{w\d+}}, wzr, lt
131   /// CHECK:            ret
minIntConstantMinusOne(int a)132   public static int minIntConstantMinusOne(int a) {
133     return Math.min(a, -1);
134   }
135 
136   /// CHECK-START-ARM64: long TestMinMax.minLongConstantZero(long) disassembly (after)
137   /// CHECK-NOT:        InvokeStaticOrDirect
138   /// CHECK-NOT:        mov {{x\d+}}, #0x0
139   /// CHECK:            cmp {{x\d+}}, #0x0 (0)
140   /// CHECK:            csel {{x\d+}}, {{x\d+}}, xzr, lt
141   /// CHECK:            ret
minLongConstantZero(long a)142   public static long minLongConstantZero(long a) {
143     return Math.min(a, 0L);
144   }
145 
146   /// CHECK-START-ARM64: long TestMinMax.minLongConstantOne(long) disassembly (after)
147   /// CHECK-NOT:        InvokeStaticOrDirect
148   /// CHECK-NOT:        mov {{x\d+}}, #0x1
149   /// CHECK:            cmp {{x\d+}}, #0x1 (1)
150   /// CHECK:            csinc {{x\d+}}, {{x\d+}}, xzr, lt
151   /// CHECK:            ret
minLongConstantOne(long a)152   public static long minLongConstantOne(long a) {
153     return Math.min(a, 1L);
154   }
155 
156   /// CHECK-START-ARM64: long TestMinMax.minLongConstantMinusOne(long) disassembly (after)
157   /// CHECK-NOT:        InvokeStaticOrDirect
158   /// CHECK-NOT:        mov {{x\d+}}, #0xffffffffffffffff
159   /// CHECK:            cmn {{x\d+}}, #0x1 (1)
160   /// CHECK:            csinv {{x\d+}}, {{x\d+}}, xzr, lt
161   /// CHECK:            ret
minLongConstantMinusOne(long a)162   public static long minLongConstantMinusOne(long a) {
163     return Math.min(a, -1L);
164   }
165 
166   /// CHECK-START-ARM64: int TestMinMax.maxIntConstantZero(int) disassembly (after)
167   /// CHECK-NOT:        InvokeStaticOrDirect
168   /// CHECK-NOT:        mov {{w\d+}}, #0x0
169   /// CHECK:            cmp {{w\d+}}, #0x0 (0)
170   /// CHECK:            csel {{w\d+}}, {{w\d+}}, wzr, gt
171   /// CHECK:            ret
maxIntConstantZero(int a)172   public static int maxIntConstantZero(int a) {
173     return Math.max(a, 0);
174   }
175 
176   /// CHECK-START-ARM64: int TestMinMax.maxIntConstantOne(int) disassembly (after)
177   /// CHECK-NOT:        InvokeStaticOrDirect
178   /// CHECK-NOT:        mov {{w\d+}}, #0x1
179   /// CHECK:            cmp {{w\d+}}, #0x1 (1)
180   /// CHECK:            csinc {{w\d+}}, {{w\d+}}, wzr, gt
181   /// CHECK:            ret
maxIntConstantOne(int a)182   public static int maxIntConstantOne(int a) {
183     return Math.max(a, 1);
184   }
185 
186   /// CHECK-START-ARM64: int TestMinMax.maxIntConstantMinusOne(int) disassembly (after)
187   /// CHECK-NOT:        InvokeStaticOrDirect
188   /// CHECK-NOT:        mov {{w\d+}}, #0xffffffff
189   /// CHECK:            cmn {{w\d+}}, #0x1 (1)
190   /// CHECK:            csinv {{w\d+}}, {{w\d+}}, wzr, gt
191   /// CHECK:            ret
maxIntConstantMinusOne(int a)192   public static int maxIntConstantMinusOne(int a) {
193     return Math.max(a, -1);
194   }
195 
196   /// CHECK-START-ARM64: int TestMinMax.maxIntLargeConstant(int) disassembly (after)
197   /// CHECK-NOT:        InvokeStaticOrDirect
198   /// CHECK:            mov {{w\d+}}, #0x2001
199   /// CHECK:            cmp {{w\d+}}, {{w\d+}}
200   //  Check that constant generation was not handled by VIXL.
201   /// CHECK-NOT:        mov {{w\d+}}, #0x2001
202   /// CHECK:            csel {{w\d+}}, {{w\d+}}, {{w\d+}}, gt
203   /// CHECK:            ret
maxIntLargeConstant(int a)204   public static int maxIntLargeConstant(int a) {
205     return Math.max(a, 8193);
206   }
207 
208   /// CHECK-START-ARM64: long TestMinMax.maxLongConstantZero(long) disassembly (after)
209   /// CHECK-NOT:        InvokeStaticOrDirect
210   /// CHECK-NOT:        mov {{x\d+}}, #0x0
211   /// CHECK:            cmp {{x\d+}}, #0x0 (0)
212   /// CHECK:            csel {{x\d+}}, {{x\d+}}, xzr, gt
213   /// CHECK:            ret
maxLongConstantZero(long a)214   public static long maxLongConstantZero(long a) {
215     return Math.max(a, 0L);
216   }
217 
218   /// CHECK-START-ARM64: long TestMinMax.maxLongConstantOne(long) disassembly (after)
219   /// CHECK-NOT:        InvokeStaticOrDirect
220   /// CHECK-NOT:        mov {{x\d+}}, #0x1
221   /// CHECK:            cmp {{x\d+}}, #0x1 (1)
222   /// CHECK:            csinc {{x\d+}}, {{x\d+}}, xzr, gt
223   /// CHECK:            ret
maxLongConstantOne(long a)224   public static long maxLongConstantOne(long a) {
225     return Math.max(a, 1L);
226   }
227 
228   /// CHECK-START-ARM64: long TestMinMax.maxLongConstantMinusOne(long) disassembly (after)
229   /// CHECK-NOT:        InvokeStaticOrDirect
230   /// CHECK-NOT:        mov {{x\d+}}, #0xffffffffffffffff
231   /// CHECK:            cmn {{x\d+}}, #0x1 (1)
232   /// CHECK:            csinv {{x\d+}}, {{x\d+}}, xzr, gt
233   /// CHECK:            ret
maxLongConstantMinusOne(long a)234   public static long maxLongConstantMinusOne(long a) {
235     return Math.max(a, -1L);
236   }
237 
238   /// CHECK-START-ARM64: long TestMinMax.maxLongLargeConstant(long) disassembly (after)
239   /// CHECK-NOT:        InvokeStaticOrDirect
240   /// CHECK:            mov {{x\d+}}, #0x2001
241   /// CHECK:            cmp {{x\d+}}, {{x\d+}}
242   //  Check that constant generation was not handled by VIXL.
243   /// CHECK-NOT:        mov {{x\d+}}, #0x2001
244   /// CHECK:            csel {{x\d+}}, {{x\d+}}, {{x\d+}}, gt
245   /// CHECK:            ret
maxLongLargeConstant(long a)246   public static long maxLongLargeConstant(long a) {
247     return Math.max(a, 8193L);
248   }
249 
250   //
251   // Different types.
252   //
253 
254   /// CHECK-START: int TestMinMax.min1(int, int) instruction_simplifier$after_gvn (before)
255   /// CHECK-DAG: <<Cnd:z\d+>> GreaterThanOrEqual [<<Op1:i\d+>>,<<Op2:i\d+>>]
256   /// CHECK-DAG: <<Sel:i\d+>> Select [<<Op1>>,<<Op2>>,<<Cnd>>]
257   /// CHECK-DAG:              Return [<<Sel>>]
258   //
259   /// CHECK-START: int TestMinMax.min1(int, int) instruction_simplifier$after_gvn (after)
260   /// CHECK-DAG: <<Min:i\d+>> Min
261   /// CHECK-DAG:              Return [<<Min>>]
262   //
263   /// CHECK-START: int TestMinMax.min1(int, int) instruction_simplifier$after_gvn (after)
264   /// CHECK-NOT:              Select
min1(int a, int b)265   public static int min1(int a, int b) {
266     return a < b ? a : b;
267   }
268 
269   /// CHECK-START: int TestMinMax.min2(int, int) instruction_simplifier$after_gvn (before)
270   /// CHECK-DAG: <<Cnd:z\d+>> GreaterThan [<<Op1:i\d+>>,<<Op2:i\d+>>]
271   /// CHECK-DAG: <<Sel:i\d+>> Select [<<Op1>>,<<Op2>>,<<Cnd>>]
272   /// CHECK-DAG:              Return [<<Sel>>]
273   //
274   /// CHECK-START: int TestMinMax.min2(int, int) instruction_simplifier$after_gvn (after)
275   /// CHECK-DAG: <<Min:i\d+>> Min
276   /// CHECK-DAG:              Return [<<Min>>]
277   //
278   /// CHECK-START: int TestMinMax.min2(int, int) instruction_simplifier$after_gvn (after)
279   /// CHECK-NOT:              Select
min2(int a, int b)280   public static int min2(int a, int b) {
281     return a <= b ? a : b;
282   }
283 
284   /// CHECK-START: int TestMinMax.min3(int, int) instruction_simplifier$after_gvn (before)
285   /// CHECK-DAG: <<Cnd:z\d+>> LessThanOrEqual [<<Op1:i\d+>>,<<Op2:i\d+>>]
286   /// CHECK-DAG: <<Sel:i\d+>> Select [<<Op2>>,<<Op1>>,<<Cnd>>]
287   /// CHECK-DAG:              Return [<<Sel>>]
288   //
289   /// CHECK-START: int TestMinMax.min3(int, int) instruction_simplifier$after_gvn (after)
290   /// CHECK-DAG: <<Min:i\d+>> Min
291   /// CHECK-DAG:              Return [<<Min>>]
292   //
293   /// CHECK-START: int TestMinMax.min3(int, int) instruction_simplifier$after_gvn (after)
294   /// CHECK-NOT:              Select
min3(int a, int b)295   public static int min3(int a, int b) {
296     return a > b ? b : a;
297   }
298 
299   /// CHECK-START: int TestMinMax.min4(int, int) instruction_simplifier$after_gvn (before)
300   /// CHECK-DAG: <<Cnd:z\d+>> LessThan [<<Op1:i\d+>>,<<Op2:i\d+>>]
301   /// CHECK-DAG: <<Sel:i\d+>> Select [<<Op2>>,<<Op1>>,<<Cnd>>]
302   /// CHECK-DAG:              Return [<<Sel>>]
303   //
304   /// CHECK-START: int TestMinMax.min4(int, int) instruction_simplifier$after_gvn (after)
305   /// CHECK-DAG: <<Min:i\d+>> Min
306   /// CHECK-DAG:              Return [<<Min>>]
307   //
308   /// CHECK-START: int TestMinMax.min4(int, int) instruction_simplifier$after_gvn (after)
309   /// CHECK-NOT:              Select
min4(int a, int b)310   public static int min4(int a, int b) {
311     return a >= b ? b : a;
312   }
313 
314   /// CHECK-START: int TestMinMax.min5(short, short) instruction_simplifier$after_gvn (before)
315   /// CHECK-DAG: <<Cnd:z\d+>> LessThan [<<Op1:s\d+>>,<<Op2:s\d+>>]
316   /// CHECK-DAG: <<Sel:i\d+>> Select [<<Op2>>,<<Op1>>,<<Cnd>>]
317   /// CHECK-DAG:              Return [<<Sel>>]
318   //
319   /// CHECK-START: int TestMinMax.min5(short, short) instruction_simplifier$after_gvn (after)
320   /// CHECK-DAG: <<Min:i\d+>> Min
321   /// CHECK-DAG:              Return [<<Min>>]
322   //
323   /// CHECK-START: int TestMinMax.min5(short, short) instruction_simplifier$after_gvn (after)
324   /// CHECK-NOT:              Select
min5(short a, short b)325   public static int min5(short a, short b) {
326     return a >= b ? b : a;
327   }
328 
329   /// CHECK-START: int TestMinMax.min6(byte, byte) instruction_simplifier$after_gvn (before)
330   /// CHECK-DAG: <<Cnd:z\d+>> LessThan [<<Op1:b\d+>>,<<Op2:b\d+>>]
331   /// CHECK-DAG: <<Sel:i\d+>> Select [<<Op2>>,<<Op1>>,<<Cnd>>]
332   /// CHECK-DAG:              Return [<<Sel>>]
333   //
334   /// CHECK-START: int TestMinMax.min6(byte, byte) instruction_simplifier$after_gvn (after)
335   /// CHECK-DAG: <<Min:i\d+>> Min
336   /// CHECK-DAG:              Return [<<Min>>]
337   //
338   /// CHECK-START: int TestMinMax.min6(byte, byte) instruction_simplifier$after_gvn (after)
339   /// CHECK-NOT:              Select
min6(byte a, byte b)340   public static int min6(byte a, byte b) {
341     return a >= b ? b : a;
342   }
343 
344   /// CHECK-START: long TestMinMax.min7(long, long) instruction_simplifier$after_gvn (before)
345   /// CHECK-DAG: <<Cnd:z\d+>> LessThan [<<Op1:j\d+>>,<<Op2:j\d+>>]
346   /// CHECK-DAG: <<Sel:j\d+>> Select [<<Op2>>,<<Op1>>,<<Cnd>>]
347   /// CHECK-DAG:              Return [<<Sel>>]
348   //
349   /// CHECK-START: long TestMinMax.min7(long, long) instruction_simplifier$after_gvn (after)
350   /// CHECK-DAG: <<Min:j\d+>> Min
351   /// CHECK-DAG:              Return [<<Min>>]
352   //
353   /// CHECK-START: long TestMinMax.min7(long, long) instruction_simplifier$after_gvn (after)
354   /// CHECK-NOT:              Select
min7(long a, long b)355   public static long min7(long a, long b) {
356     return a >= b ? b : a;
357   }
358 
359   /// CHECK-START: int TestMinMax.max1(int, int) instruction_simplifier$after_gvn (before)
360   /// CHECK-DAG: <<Cnd:z\d+>> GreaterThanOrEqual [<<Op1:i\d+>>,<<Op2:i\d+>>]
361   /// CHECK-DAG: <<Sel:i\d+>> Select [<<Op2>>,<<Op1>>,<<Cnd>>]
362   /// CHECK-DAG:              Return [<<Sel>>]
363   //
364   /// CHECK-START: int TestMinMax.max1(int, int) instruction_simplifier$after_gvn (after)
365   /// CHECK-DAG: <<Max:i\d+>> Max
366   /// CHECK-DAG:              Return [<<Max>>]
367   //
368   /// CHECK-START: int TestMinMax.max1(int, int) instruction_simplifier$after_gvn (after)
369   /// CHECK-NOT:              Select
max1(int a, int b)370   public static int max1(int a, int b) {
371     return a < b ? b : a;
372   }
373 
374   /// CHECK-START: int TestMinMax.max2(int, int) instruction_simplifier$after_gvn (before)
375   /// CHECK-DAG: <<Cnd:z\d+>> GreaterThan [<<Op1:i\d+>>,<<Op2:i\d+>>]
376   /// CHECK-DAG: <<Sel:i\d+>> Select [<<Op2>>,<<Op1>>,<<Cnd>>]
377   /// CHECK-DAG:              Return [<<Sel>>]
378   //
379   /// CHECK-START: int TestMinMax.max2(int, int) instruction_simplifier$after_gvn (after)
380   /// CHECK-DAG: <<Max:i\d+>> Max
381   /// CHECK-DAG:              Return [<<Max>>]
382   //
383   /// CHECK-START: int TestMinMax.max2(int, int) instruction_simplifier$after_gvn (after)
384   /// CHECK-NOT:              Select
max2(int a, int b)385   public static int max2(int a, int b) {
386     return a <= b ? b : a;
387   }
388 
389   /// CHECK-START: int TestMinMax.max3(int, int) instruction_simplifier$after_gvn (before)
390   /// CHECK-DAG: <<Cnd:z\d+>> LessThanOrEqual [<<Op1:i\d+>>,<<Op2:i\d+>>]
391   /// CHECK-DAG: <<Sel:i\d+>> Select [<<Op1>>,<<Op2>>,<<Cnd>>]
392   /// CHECK-DAG:              Return [<<Sel>>]
393   //
394   /// CHECK-START: int TestMinMax.max3(int, int) instruction_simplifier$after_gvn (after)
395   /// CHECK-DAG: <<Max:i\d+>> Max
396   /// CHECK-DAG:              Return [<<Max>>]
397   //
398   /// CHECK-START: int TestMinMax.max3(int, int) instruction_simplifier$after_gvn (after)
399   /// CHECK-NOT:              Select
max3(int a, int b)400   public static int max3(int a, int b) {
401     return a > b ? a : b;
402   }
403 
404   /// CHECK-START: int TestMinMax.max4(int, int) instruction_simplifier$after_gvn (before)
405   /// CHECK-DAG: <<Cnd:z\d+>> LessThan [<<Op1:i\d+>>,<<Op2:i\d+>>]
406   /// CHECK-DAG: <<Sel:i\d+>> Select [<<Op1>>,<<Op2>>,<<Cnd>>]
407   /// CHECK-DAG:              Return [<<Sel>>]
408   //
409   /// CHECK-START: int TestMinMax.max4(int, int) instruction_simplifier$after_gvn (after)
410   /// CHECK-DAG: <<Max:i\d+>> Max
411   /// CHECK-DAG:              Return [<<Max>>]
412   //
413   /// CHECK-START: int TestMinMax.max4(int, int) instruction_simplifier$after_gvn (after)
414   /// CHECK-NOT:              Select
max4(int a, int b)415   public static int max4(int a, int b) {
416     return a >= b ? a : b;
417   }
418 
419   /// CHECK-START: int TestMinMax.max5(short, short) instruction_simplifier$after_gvn (before)
420   /// CHECK-DAG: <<Cnd:z\d+>> LessThan [<<Op1:s\d+>>,<<Op2:s\d+>>]
421   /// CHECK-DAG: <<Sel:i\d+>> Select [<<Op1>>,<<Op2>>,<<Cnd>>]
422   /// CHECK-DAG:              Return [<<Sel>>]
423   //
424   /// CHECK-START: int TestMinMax.max5(short, short) instruction_simplifier$after_gvn (after)
425   /// CHECK-DAG: <<Max:i\d+>> Max
426   /// CHECK-DAG:              Return [<<Max>>]
427   //
428   /// CHECK-START: int TestMinMax.max5(short, short) instruction_simplifier$after_gvn (after)
429   /// CHECK-NOT:              Select
max5(short a, short b)430   public static int max5(short a, short b) {
431     return a >= b ? a : b;
432   }
433 
434   /// CHECK-START: int TestMinMax.max6(byte, byte) instruction_simplifier$after_gvn (before)
435   /// CHECK-DAG: <<Cnd:z\d+>> LessThan [<<Op1:b\d+>>,<<Op2:b\d+>>]
436   /// CHECK-DAG: <<Sel:i\d+>> Select [<<Op1>>,<<Op2>>,<<Cnd>>]
437   /// CHECK-DAG:              Return [<<Sel>>]
438   //
439   /// CHECK-START: int TestMinMax.max6(byte, byte) instruction_simplifier$after_gvn (after)
440   /// CHECK-DAG: <<Max:i\d+>> Max
441   /// CHECK-DAG:              Return [<<Max>>]
442   //
443   /// CHECK-START: int TestMinMax.max6(byte, byte) instruction_simplifier$after_gvn (after)
444   /// CHECK-NOT:              Select
max6(byte a, byte b)445   public static int max6(byte a, byte b) {
446     return a >= b ? a : b;
447   }
448 
449   /// CHECK-START: long TestMinMax.max7(long, long) instruction_simplifier$after_gvn (before)
450   /// CHECK-DAG: <<Cnd:z\d+>> LessThan [<<Op1:j\d+>>,<<Op2:j\d+>>]
451   /// CHECK-DAG: <<Sel:j\d+>> Select [<<Op1>>,<<Op2>>,<<Cnd>>]
452   /// CHECK-DAG:              Return [<<Sel>>]
453   //
454   /// CHECK-START: long TestMinMax.max7(long, long) instruction_simplifier$after_gvn (after)
455   /// CHECK-DAG: <<Max:j\d+>> Max
456   /// CHECK-DAG:              Return [<<Max>>]
457   //
458   /// CHECK-START: long TestMinMax.max7(long, long) instruction_simplifier$after_gvn (after)
459   /// CHECK-NOT:              Select
max7(long a, long b)460   public static long max7(long a, long b) {
461     return a >= b ? a : b;
462   }
463 
464   //
465   // Complications.
466   //
467 
468   /// CHECK-START: int TestMinMax.min0(int[], int[]) instruction_simplifier$after_gvn (before)
469   /// CHECK-DAG: <<Ar1:i\d+>> ArrayGet [{{l\d+}},{{i\d+}}]
470   /// CHECK-DAG: <<Ar2:i\d+>> ArrayGet [{{l\d+}},{{i\d+}}]
471   /// CHECK-DAG: <<Cnd:z\d+>> GreaterThan [<<Ar1>>,<<Ar2>>]
472   /// CHECK-DAG: <<Sel:i\d+>> Select [<<Ar1>>,<<Ar2>>,<<Cnd>>]
473   /// CHECK-DAG:              Return [<<Sel>>]
474   //
475   /// CHECK-START: int TestMinMax.min0(int[], int[]) instruction_simplifier$after_gvn (after)
476   /// CHECK-DAG: <<Min:i\d+>> Min
477   /// CHECK-DAG:              Return [<<Min>>]
478   //
479   /// CHECK-START: int TestMinMax.min0(int[], int[]) instruction_simplifier$after_gvn (after)
480   /// CHECK-NOT:              Select
min0(int[] a, int[] b)481   public static int min0(int[] a, int[] b) {
482     // Repeat of array references needs finding the common subexpressions
483     // prior to doing the select and min/max recognition.
484     return a[0] <= b[0] ? a[0] : b[0];
485   }
486 
487   /// CHECK-START: int TestMinMax.max0(int[], int[]) instruction_simplifier$after_gvn (before)
488   /// CHECK-DAG: <<Ar1:i\d+>> ArrayGet [{{l\d+}},{{i\d+}}]
489   /// CHECK-DAG: <<Ar2:i\d+>> ArrayGet [{{l\d+}},{{i\d+}}]
490   /// CHECK-DAG: <<Cnd:z\d+>> LessThan [<<Ar1>>,<<Ar2>>]
491   /// CHECK-DAG: <<Sel:i\d+>> Select [<<Ar1>>,<<Ar2>>,<<Cnd>>]
492   /// CHECK-DAG:              Return [<<Sel>>]
493   //
494   /// CHECK-START: int TestMinMax.max0(int[], int[]) instruction_simplifier$after_gvn (after)
495   /// CHECK-DAG: <<Max:i\d+>> Max
496   /// CHECK-DAG:              Return [<<Max>>]
497   //
498   /// CHECK-START: int TestMinMax.max0(int[], int[]) instruction_simplifier$after_gvn (after)
499   /// CHECK-NOT:              Select
max0(int[] a, int[] b)500   public static int max0(int[] a, int[] b) {
501     // Repeat of array references needs finding the common subexpressions
502     // prior to doing the select and min/max recognition.
503     return a[0] >= b[0] ? a[0] : b[0];
504   }
505 
506   /// CHECK-START: int TestMinMax.minmax1(int) instruction_simplifier$after_gvn (before)
507   /// CHECK-DAG: <<Par:i\d+>>  ParameterValue
508   /// CHECK-DAG: <<P100:i\d+>> IntConstant 100
509   /// CHECK-DAG: <<M100:i\d+>> IntConstant -100
510   /// CHECK-DAG: <<Cnd1:z\d+>> LessThanOrEqual [<<Par>>,<<P100>>]
511   /// CHECK-DAG: <<Sel1:i\d+>> Select [<<P100>>,<<Par>>,<<Cnd1>>]
512   /// CHECK-DAG: <<Cnd2:z\d+>> GreaterThanOrEqual [<<Sel1>>,<<M100>>]
513   /// CHECK-DAG: <<Sel2:i\d+>> Select [<<M100>>,<<Sel1>>,<<Cnd2>>]
514   /// CHECK-DAG:               Return [<<Sel2>>]
515   //
516   /// CHECK-START: int TestMinMax.minmax1(int) instruction_simplifier$after_gvn (after)
517   /// CHECK-DAG: <<Par:i\d+>>  ParameterValue
518   /// CHECK-DAG: <<P100:i\d+>> IntConstant 100
519   /// CHECK-DAG: <<M100:i\d+>> IntConstant -100
520   /// CHECK-DAG: <<Min:i\d+>>  Min [<<Par>>,<<P100>>]
521   /// CHECK-DAG: <<Max:i\d+>>  Max [<<Min>>,<<M100>>]
522   /// CHECK-DAG:               Return [<<Max>>]
523   //
524   /// CHECK-START: int TestMinMax.minmax1(int) instruction_simplifier$after_gvn (after)
525   /// CHECK-NOT:               Select
minmax1(int x)526   public static int minmax1(int x) {
527     // Simple if-if gives clean select sequence.
528     if (x > 100) {
529       x = 100;
530     }
531     if (x < -100) {
532       x = -100;
533     }
534     return x;
535   }
536 
537   /// CHECK-START: int TestMinMax.minmax2(int) instruction_simplifier$after_gvn (before)
538   /// CHECK-DAG: <<Par:i\d+>>  ParameterValue
539   /// CHECK-DAG: <<P100:i\d+>> IntConstant 100
540   /// CHECK-DAG: <<M100:i\d+>> IntConstant -100
541   /// CHECK-DAG: <<Cnd1:z\d+>> LessThanOrEqual [<<Par>>,<<P100>>]
542   /// CHECK-DAG: <<Cnd2:z\d+>> GreaterThanOrEqual [<<Par>>,<<M100>>]
543   /// CHECK-DAG: <<Sel1:i\d+>> Select [<<M100>>,<<Par>>,<<Cnd2>>]
544   /// CHECK-DAG: <<Sel2:i\d+>> Select [<<P100>>,<<Sel1>>,<<Cnd1>>]
545   /// CHECK-DAG:               Return [<<Sel2>>]
546   //
547   /// CHECK-START: int TestMinMax.minmax2(int) instruction_simplifier$after_gvn (after)
548   /// CHECK-DAG: <<Par:i\d+>>  ParameterValue
549   /// CHECK-DAG: <<P100:i\d+>> IntConstant 100
550   /// CHECK-DAG: <<M100:i\d+>> IntConstant -100
551   /// CHECK-DAG: <<Max:i\d+>>  Max [<<Par>>,<<M100>>]
552   /// CHECK-DAG: <<Min:i\d+>>  Min [<<Max>>,<<P100>>]
553   /// CHECK-DAG:               Return [<<Min>>]
554   //
555   /// CHECK-START: int TestMinMax.minmax2(int) instruction_simplifier$after_gvn (after)
556   /// CHECK-NOT:               Select
minmax2(int x)557   public static int minmax2(int x) {
558     // Simple if-else requires inspecting bounds of resulting selects.
559     if (x > 100) {
560       x = 100;
561     } else if (x < -100) {
562       x = -100;
563     }
564     return x;
565   }
566 
567   /// CHECK-START: int TestMinMax.minmax3(int) instruction_simplifier$after_gvn (after)
568   /// CHECK-DAG: <<Par:i\d+>>  ParameterValue
569   /// CHECK-DAG: <<P100:i\d+>> IntConstant 100
570   /// CHECK-DAG: <<M100:i\d+>> IntConstant -100
571   /// CHECK-DAG: <<Max:i\d+>>  Max [<<Par>>,<<M100>>]
572   /// CHECK-DAG: <<Min:i\d+>>  Min [<<Max>>,<<P100>>]
573   /// CHECK-DAG:               Return [<<Min>>]
574   //
575   /// CHECK-START: int TestMinMax.minmax3(int) instruction_simplifier$after_gvn (after)
576   /// CHECK-NOT:               Select
minmax3(int x)577   public static int minmax3(int x) {
578     return (x > 100) ? 100 : ((x < -100) ? -100 : x);
579   }
580 
581   /// CHECK-START: int TestMinMax.minmax4(int) instruction_simplifier$after_gvn (after)
582   /// CHECK-DAG: <<Par:i\d+>>  ParameterValue
583   /// CHECK-DAG: <<P100:i\d+>> IntConstant 100
584   /// CHECK-DAG: <<M100:i\d+>> IntConstant -100
585   /// CHECK-DAG: <<Min:i\d+>>  Min [<<Par>>,<<P100>>]
586   /// CHECK-DAG: <<Max:i\d+>>  Max [<<Min>>,<<M100>>]
587   /// CHECK-DAG:               Return [<<Max>>]
588   //
589   /// CHECK-START: int TestMinMax.minmax4(int) instruction_simplifier$after_gvn (after)
590   /// CHECK-NOT:               Select
minmax4(int x)591   public static int minmax4(int x) {
592     return (x < -100) ? -100 : ((x > 100) ? 100 : x);
593   }
594 
595   /// CHECK-START: int TestMinMax.minmaxCSEScalar(int, int) select_generator (after)
596   /// CHECK-DAG: <<Par1:i\d+>> ParameterValue
597   /// CHECK-DAG: <<Par2:i\d+>> ParameterValue
598   /// CHECK-DAG: <<Cnd1:z\d+>> LessThanOrEqual    [<<Par1>>,<<Par2>>]
599   /// CHECK-DAG: <<Sel1:i\d+>> Select             [<<Par1>>,<<Par2>>,<<Cnd1>>]
600   /// CHECK-DAG: <<Cnd2:z\d+>> GreaterThanOrEqual [<<Par1>>,<<Par2>>]
601   /// CHECK-DAG: <<Sel2:i\d+>> Select             [<<Par1>>,<<Par2>>,<<Cnd2>>]
602   /// CHECK-DAG: <<Add1:i\d+>> Add                [<<Sel1>>,<<Sel2>>]
603   /// CHECK-DAG: <<Add2:i\d+>> Add                [<<Sel1>>,<<Add1>>]
604   /// CHECK-DAG: <<Add3:i\d+>> Add                [<<Sel2>>,<<Add2>>]
605   /// CHECK-DAG: <<Add4:i\d+>> Add                [<<Sel1>>,<<Add3>>]
606   /// CHECK-DAG: <<Add5:i\d+>> Add                [<<Sel2>>,<<Add4>>]
607   /// CHECK-DAG:               Return             [<<Add5>>]
608   //
609   /// CHECK-START: int TestMinMax.minmaxCSEScalar(int, int) instruction_simplifier$after_gvn (after)
610   /// CHECK-DAG: <<Par1:i\d+>> ParameterValue
611   /// CHECK-DAG: <<Par2:i\d+>> ParameterValue
612   /// CHECK-DAG: <<Max:i\d+>>  Max    [<<Par1>>,<<Par2>>]
613   /// CHECK-DAG: <<Min:i\d+>>  Min    [<<Par1>>,<<Par2>>]
614   /// CHECK-DAG: <<Add1:i\d+>> Add    [<<Max>>,<<Min>>]
615   /// CHECK-DAG: <<Add2:i\d+>> Add    [<<Max>>,<<Add1>>]
616   /// CHECK-DAG: <<Add3:i\d+>> Add    [<<Min>>,<<Add2>>]
617   /// CHECK-DAG: <<Add4:i\d+>> Add    [<<Max>>,<<Add3>>]
618   /// CHECK-DAG: <<Add5:i\d+>> Add    [<<Min>>,<<Add4>>]
619   /// CHECK-DAG:               Return [<<Add5>>]
minmaxCSEScalar(int x, int y)620   public static int minmaxCSEScalar(int x, int y) {
621     int t1 = (x > y) ? x : y;
622     int t2 = (x < y) ? x : y;
623     int t3 = (x > y) ? x : y;
624     int t4 = (x < y) ? x : y;
625     int t5 = (x > y) ? x : y;
626     int t6 = (x < y) ? x : y;
627     // Make sure min/max is CSEed.
628     return t1 + t2 + t3 + t4 + t5 + t6;
629   }
630 
631   /// CHECK-START: int TestMinMax.minmaxCSEArray(int[], int[]) select_generator (after)
632   /// CHECK-DAG: <<Arr1:i\d+>> ArrayGet
633   /// CHECK-DAG: <<Arr2:i\d+>> ArrayGet
634   /// CHECK-DAG: <<Cnd1:z\d+>> LessThanOrEqual    [<<Arr1>>,<<Arr2>>]
635   /// CHECK-DAG: <<Sel1:i\d+>> Select             [<<Arr1>>,<<Arr2>>,<<Cnd1>>]
636   /// CHECK-DAG: <<Cnd2:z\d+>> GreaterThanOrEqual [<<Arr1>>,<<Arr2>>]
637   /// CHECK-DAG: <<Sel2:i\d+>> Select             [<<Arr1>>,<<Arr2>>,<<Cnd2>>]
638   /// CHECK-DAG: <<Add1:i\d+>> Add                [<<Sel1>>,<<Sel2>>]
639   /// CHECK-DAG: <<Add2:i\d+>> Add                [<<Sel1>>,<<Add1>>]
640   /// CHECK-DAG: <<Add3:i\d+>> Add                [<<Sel2>>,<<Add2>>]
641   /// CHECK-DAG: <<Add4:i\d+>> Add                [<<Sel1>>,<<Add3>>]
642   /// CHECK-DAG: <<Add5:i\d+>> Add                [<<Sel2>>,<<Add4>>]
643   /// CHECK-DAG:               Return             [<<Add5>>]
644   //
645   /// CHECK-START: int TestMinMax.minmaxCSEArray(int[], int[]) instruction_simplifier$after_gvn (after)
646   /// CHECK-DAG: <<Arr1:i\d+>> ArrayGet
647   /// CHECK-DAG: <<Arr2:i\d+>> ArrayGet
648   /// CHECK-DAG: <<Max:i\d+>>  Max    [<<Arr1>>,<<Arr2>>]
649   /// CHECK-DAG: <<Min:i\d+>>  Min    [<<Arr1>>,<<Arr2>>]
650   /// CHECK-DAG: <<Add1:i\d+>> Add    [<<Max>>,<<Min>>]
651   /// CHECK-DAG: <<Add2:i\d+>> Add    [<<Max>>,<<Add1>>]
652   /// CHECK-DAG: <<Add3:i\d+>> Add    [<<Min>>,<<Add2>>]
653   /// CHECK-DAG: <<Add4:i\d+>> Add    [<<Max>>,<<Add3>>]
654   /// CHECK-DAG: <<Add5:i\d+>> Add    [<<Min>>,<<Add4>>]
655   /// CHECK-DAG:               Return [<<Add5>>]
minmaxCSEArray(int[] x, int[] y)656   public static int minmaxCSEArray(int[] x, int[] y) {
657     int t1 = (x[0] > y[0]) ? x[0] : y[0];
658     int t2 = (x[0] < y[0]) ? x[0] : y[0];
659     int t3 = (x[0] > y[0]) ? x[0] : y[0];
660     int t4 = (x[0] < y[0]) ? x[0] : y[0];
661     int t5 = (x[0] > y[0]) ? x[0] : y[0];
662     int t6 = (x[0] < y[0]) ? x[0] : y[0];
663     // Make sure min/max is CSEed.
664     return t1 + t2 + t3 + t4 + t5 + t6;
665   }
666 
667   /// CHECK-START: int TestMinMax.minmaxCSEScalarAndCond(int, int) instruction_simplifier$after_gvn (after)
668   /// CHECK-DAG: <<Par1:i\d+>> ParameterValue
669   /// CHECK-DAG: <<Par2:i\d+>> ParameterValue
670   /// CHECK-DAG: <<Max:i\d+>>  Max    [<<Par1>>,<<Par2>>]
671   /// CHECK-DAG: <<Min:i\d+>>  Min    [<<Par1>>,<<Par2>>]
672   /// CHECK-DAG: <<Add:i\d+>>  Add    [<<Max>>,<<Min>>]
673   /// CHECK-DAG:               Return [<<Add>>]
674   /// CHECK-DAG: <<Add1:i\d+>> Add    [<<Max>>,<<Min>>]
675   /// CHECK-DAG: <<Add2:i\d+>> Add    [<<Max>>,<<Add1>>]
676   /// CHECK-DAG: <<Add3:i\d+>> Add    [<<Min>>,<<Add2>>]
677   /// CHECK-DAG:               Return [<<Add3>>]
minmaxCSEScalarAndCond(int x, int y)678   public static int minmaxCSEScalarAndCond(int x, int y) {
679     int t1 = (x > y) ? x : y;
680     int t2 = (x < y) ? x : y;
681     if (x == y)
682       return t1 + t2;
683     int t3 = (x > y) ? x : y;
684     int t4 = (x < y) ? x : y;
685     // Make sure min/max is CSEed.
686     return t1 + t2 + t3 + t4;
687   }
688 
main()689   public static void main() {
690     // Intrinsics.
691     expectEquals(10, minI(10));
692     expectEquals(20, minI(25));
693     expectEquals(-1, minIntConstantZero(-1));
694     expectEquals(0, minIntConstantZero(1));
695     expectEquals(0, minIntConstantOne(0));
696     expectEquals(1, minIntConstantOne(2));
697     expectEquals(-2, minIntConstantMinusOne(-2));
698     expectEquals(-1, minIntConstantMinusOne(0));
699     expectEquals(10L, minL(10L));
700     expectEquals(20L, minL(25L));
701     expectEquals(-1L, minLongConstantZero(-1L));
702     expectEquals(0L, minLongConstantZero(1L));
703     expectEquals(0L, minLongConstantOne(0L));
704     expectEquals(1L, minLongConstantOne(2L));
705     expectEquals(-2L, minLongConstantMinusOne(-2L));
706     expectEquals(-1L, minLongConstantMinusOne(0L));
707     expectEquals(20, maxI(10));
708     expectEquals(25, maxI(25));
709     expectEquals(0, maxIntConstantZero(-1));
710     expectEquals(1, maxIntConstantZero(1));
711     expectEquals(1, maxIntConstantOne(0));
712     expectEquals(2, maxIntConstantOne(2));
713     expectEquals(-1, maxIntConstantMinusOne(-2));
714     expectEquals(0, maxIntConstantMinusOne(0));
715     expectEquals(8193, maxIntLargeConstant(8192));
716     expectEquals(9000, maxIntLargeConstant(9000));
717     expectEquals(20L, maxL(10L));
718     expectEquals(25L, maxL(25L));
719     expectEquals(0L, maxLongConstantZero(-1L));
720     expectEquals(1L, maxLongConstantZero(1L));
721     expectEquals(1L, maxLongConstantOne(0L));
722     expectEquals(2L, maxLongConstantOne(2L));
723     expectEquals(-1L, maxLongConstantMinusOne(-2L));
724     expectEquals(0L, maxLongConstantMinusOne(0L));
725     expectEquals(8193L, maxLongLargeConstant(8192L));
726     expectEquals(9000L, maxLongLargeConstant(9000L));
727     // Types.
728     expectEquals(10, min1(10, 20));
729     expectEquals(10, min2(10, 20));
730     expectEquals(10, min3(10, 20));
731     expectEquals(10, min4(10, 20));
732     expectEquals(10, min5((short) 10, (short) 20));
733     expectEquals(10, min6((byte) 10, (byte) 20));
734     expectEquals(10L, min7(10L, 20L));
735     expectEquals(20, max1(10, 20));
736     expectEquals(20, max2(10, 20));
737     expectEquals(20, max3(10, 20));
738     expectEquals(20, max4(10, 20));
739     expectEquals(20, max5((short) 10, (short) 20));
740     expectEquals(20, max6((byte) 10, (byte) 20));
741     expectEquals(20L, max7(10L, 20L));
742     // Complications.
743     int[] a = { 10 };
744     int[] b = { 20 };
745     expectEquals(10, min0(a, b));
746     expectEquals(20, max0(a, b));
747     expectEquals(-100, minmax1(-200));
748     expectEquals(10, minmax1(10));
749     expectEquals(100, minmax1(200));
750     expectEquals(-100, minmax2(-200));
751     expectEquals(10, minmax2(10));
752     expectEquals(100, minmax2(200));
753     expectEquals(-100, minmax3(-200));
754     expectEquals(10, minmax3(10));
755     expectEquals(100, minmax3(200));
756     expectEquals(-100, minmax4(-200));
757     expectEquals(10, minmax4(10));
758     expectEquals(100, minmax4(200));
759     expectEquals(90, minmaxCSEScalar(10, 20));
760     expectEquals(90, minmaxCSEArray(a, b));
761     expectEquals(20, minmaxCSEScalarAndCond(10, 10));
762     expectEquals(60, minmaxCSEScalarAndCond(10, 20));
763     System.out.println("TestMinMax passed");
764   }
765 
expectEquals(int expected, int result)766   private static void expectEquals(int expected, int result) {
767     if (expected != result) {
768       throw new Error("Expected: " + expected + ", found: " + result);
769     }
770   }
771 
expectEquals(long expected, long result)772   private static void expectEquals(long expected, long result) {
773     if (expected != result) {
774       throw new Error("Expected: " + expected + ", found: " + result);
775     }
776   }
777 }
778