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