• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2015 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 public class Main {
18 
19   // A dummy value to defeat inlining of these routines.
20   static boolean doThrow = false;
21 
assertByteEquals(byte expected, byte result)22   public static void assertByteEquals(byte expected, byte result) {
23     if (expected != result) {
24       throw new Error("Expected: " + expected + ", found: " + result);
25     }
26   }
27 
assertCharEquals(char expected, char result)28   public static void assertCharEquals(char expected, char result) {
29     if (expected != result) {
30       throw new Error("Expected: " + expected + ", found: " + result);
31     }
32   }
33 
assertShortEquals(short expected, short result)34   public static void assertShortEquals(short expected, short result) {
35     if (expected != result) {
36       throw new Error("Expected: " + expected + ", found: " + result);
37     }
38   }
39 
assertIntEquals(int expected, int result)40   public static void assertIntEquals(int expected, int result) {
41     if (expected != result) {
42       throw new Error("Expected: " + expected + ", found: " + result);
43     }
44   }
45 
assertLongEquals(long expected, long result)46   public static void assertLongEquals(long expected, long result) {
47     if (expected != result) {
48       throw new Error("Expected: " + expected + ", found: " + result);
49     }
50   }
51 
52   // Non-inlinable type-casting helpers.
$noinline$byteToChar(byte v)53   static  char $noinline$byteToChar   (byte v) { if (doThrow) throw new Error(); return  (char)v; }
$noinline$byteToShort(byte v)54   static short $noinline$byteToShort  (byte v) { if (doThrow) throw new Error(); return (short)v; }
$noinline$byteToInt(byte v)55   static   int $noinline$byteToInt    (byte v) { if (doThrow) throw new Error(); return   (int)v; }
$noinline$byteToLong(byte v)56   static  long $noinline$byteToLong   (byte v) { if (doThrow) throw new Error(); return  (long)v; }
$noinline$charToByte(char v)57   static  byte $noinline$charToByte   (char v) { if (doThrow) throw new Error(); return  (byte)v; }
$noinline$charToShort(char v)58   static short $noinline$charToShort  (char v) { if (doThrow) throw new Error(); return (short)v; }
$noinline$charToInt(char v)59   static   int $noinline$charToInt    (char v) { if (doThrow) throw new Error(); return   (int)v; }
$noinline$charToLong(char v)60   static  long $noinline$charToLong   (char v) { if (doThrow) throw new Error(); return  (long)v; }
$noinline$shortToByte(short v)61   static  byte $noinline$shortToByte (short v) { if (doThrow) throw new Error(); return  (byte)v; }
$noinline$shortToChar(short v)62   static  char $noinline$shortToChar (short v) { if (doThrow) throw new Error(); return  (char)v; }
$noinline$shortToInt(short v)63   static   int $noinline$shortToInt  (short v) { if (doThrow) throw new Error(); return   (int)v; }
$noinline$shortToLong(short v)64   static  long $noinline$shortToLong (short v) { if (doThrow) throw new Error(); return  (long)v; }
$noinline$intToByte(int v)65   static  byte $noinline$intToByte     (int v) { if (doThrow) throw new Error(); return  (byte)v; }
$noinline$intToChar(int v)66   static  char $noinline$intToChar     (int v) { if (doThrow) throw new Error(); return  (char)v; }
$noinline$intToShort(int v)67   static short $noinline$intToShort    (int v) { if (doThrow) throw new Error(); return (short)v; }
$noinline$intToLong(int v)68   static  long $noinline$intToLong     (int v) { if (doThrow) throw new Error(); return  (long)v; }
$noinline$longToByte(long v)69   static  byte $noinline$longToByte   (long v) { if (doThrow) throw new Error(); return  (byte)v; }
$noinline$longToChar(long v)70   static  char $noinline$longToChar   (long v) { if (doThrow) throw new Error(); return  (char)v; }
$noinline$longToShort(long v)71   static short $noinline$longToShort  (long v) { if (doThrow) throw new Error(); return (short)v; }
$noinline$longToInt(long v)72   static   int $noinline$longToInt    (long v) { if (doThrow) throw new Error(); return   (int)v; }
73 
74   /**
75    * Basic test merging a bitfield move operation (here a type conversion) into
76    * the shifter operand.
77    */
78 
79   /// CHECK-START-ARM64: long Main.$opt$noinline$translate(long, byte) instruction_simplifier_arm64 (before)
80   /// CHECK-DAG:   <<l:j\d+>>           ParameterValue
81   /// CHECK-DAG:   <<b:b\d+>>           ParameterValue
82   /// CHECK:       <<tmp:j\d+>>         TypeConversion [<<b>>]
83   /// CHECK:                            Sub [<<l>>,<<tmp>>]
84 
85   /// CHECK-START-ARM64: long Main.$opt$noinline$translate(long, byte) instruction_simplifier_arm64 (after)
86   /// CHECK-DAG:   <<l:j\d+>>           ParameterValue
87   /// CHECK-DAG:   <<b:b\d+>>           ParameterValue
88   /// CHECK:                            Arm64DataProcWithShifterOp [<<l>>,<<b>>] kind:Sub+SXTB
89 
90   /// CHECK-START-ARM64: long Main.$opt$noinline$translate(long, byte) instruction_simplifier_arm64 (after)
91   /// CHECK-NOT:                        TypeConversion
92   /// CHECK-NOT:                        Sub
93 
94   /// CHECK-START-ARM64: long Main.$opt$noinline$translate(long, byte) disassembly (after)
95   /// CHECK:                            sub x{{\d+}}, x{{\d+}}, w{{\d+}}, sxtb
96 
$opt$noinline$translate(long l, byte b)97   public static long $opt$noinline$translate(long l, byte b) {
98     if (doThrow) throw new Error();
99     long tmp = (long)b;
100     return l - tmp;
101   }
102 
103 
104   /**
105    * Test that we do not merge into the shifter operand when the left and right
106    * inputs are the the IR.
107    */
108 
109   /// CHECK-START-ARM64: int Main.$opt$noinline$sameInput(int) instruction_simplifier_arm64 (before)
110   /// CHECK:       <<a:i\d+>>           ParameterValue
111   /// CHECK:       <<Const2:i\d+>>      IntConstant 2
112   /// CHECK:       <<tmp:i\d+>>         Shl [<<a>>,<<Const2>>]
113   /// CHECK:                            Add [<<tmp>>,<<tmp>>]
114 
115   /// CHECK-START-ARM64: int Main.$opt$noinline$sameInput(int) instruction_simplifier_arm64 (after)
116   /// CHECK-DAG:   <<a:i\d+>>           ParameterValue
117   /// CHECK-DAG:   <<Const2:i\d+>>      IntConstant 2
118   /// CHECK:       <<Shl:i\d+>>         Shl [<<a>>,<<Const2>>]
119   /// CHECK:                            Add [<<Shl>>,<<Shl>>]
120 
121   /// CHECK-START-ARM64: int Main.$opt$noinline$sameInput(int) instruction_simplifier_arm64 (after)
122   /// CHECK-NOT:                        Arm64DataProcWithShifterOp
123 
$opt$noinline$sameInput(int a)124   public static int $opt$noinline$sameInput(int a) {
125     if (doThrow) throw new Error();
126     int tmp = a << 2;
127     return tmp + tmp;
128   }
129 
130   /**
131    * Check that we perform the merge for multiple uses.
132    */
133 
134   /// CHECK-START-ARM64: int Main.$opt$noinline$multipleUses(int) instruction_simplifier_arm64 (before)
135   /// CHECK:       <<arg:i\d+>>         ParameterValue
136   /// CHECK:       <<Const23:i\d+>>     IntConstant 23
137   /// CHECK:       <<tmp:i\d+>>         Shl [<<arg>>,<<Const23>>]
138   /// CHECK:                            Add [<<tmp>>,{{i\d+}}]
139   /// CHECK:                            Add [<<tmp>>,{{i\d+}}]
140   /// CHECK:                            Add [<<tmp>>,{{i\d+}}]
141   /// CHECK:                            Add [<<tmp>>,{{i\d+}}]
142   /// CHECK:                            Add [<<tmp>>,{{i\d+}}]
143 
144   /// CHECK-START-ARM64: int Main.$opt$noinline$multipleUses(int) instruction_simplifier_arm64 (after)
145   /// CHECK:       <<arg:i\d+>>         ParameterValue
146   /// CHECK:                            Arm64DataProcWithShifterOp [{{i\d+}},<<arg>>] kind:Add+LSL shift:23
147   /// CHECK:                            Arm64DataProcWithShifterOp [{{i\d+}},<<arg>>] kind:Add+LSL shift:23
148   /// CHECK:                            Arm64DataProcWithShifterOp [{{i\d+}},<<arg>>] kind:Add+LSL shift:23
149   /// CHECK:                            Arm64DataProcWithShifterOp [{{i\d+}},<<arg>>] kind:Add+LSL shift:23
150   /// CHECK:                            Arm64DataProcWithShifterOp [{{i\d+}},<<arg>>] kind:Add+LSL shift:23
151 
152   /// CHECK-START-ARM64: int Main.$opt$noinline$multipleUses(int) instruction_simplifier_arm64 (after)
153   /// CHECK-NOT:                        Shl
154   /// CHECK-NOT:                        Add
155 
$opt$noinline$multipleUses(int arg)156   public static int $opt$noinline$multipleUses(int arg) {
157     if (doThrow) throw new Error();
158     int tmp = arg << 23;
159     switch (arg) {
160       case 1:  return (arg | 1) + tmp;
161       case 2:  return (arg | 2) + tmp;
162       case 3:  return (arg | 3) + tmp;
163       case 4:  return (arg | 4) + tmp;
164       case (1 << 20):  return (arg | 5) + tmp;
165       default: return 0;
166     }
167   }
168 
169   /**
170    * Logical instructions cannot take 'extend' operations into the shift
171    * operand, so test that only the shifts are merged.
172    */
173 
174   /// CHECK-START-ARM64: void Main.$opt$noinline$testAnd(long, long) instruction_simplifier_arm64 (after)
175   /// CHECK:                            Arm64DataProcWithShifterOp
176   /// CHECK-NOT:                        Arm64DataProcWithShifterOp
177 
178   /// CHECK-START-ARM64: void Main.$opt$noinline$testAnd(long, long) disassembly (after)
179   /// CHECK:                            and lsl
180   /// CHECK:                            sxtb
181   /// CHECK:                            and
182 
$opt$noinline$testAnd(long a, long b)183   static void $opt$noinline$testAnd(long a, long b) {
184     if (doThrow) throw new Error();
185     assertLongEquals((a & $noinline$LongShl(b, 5)) | (a & $noinline$longToByte(b)),
186                      (a & (b << 5)) | (a & (byte)b));
187   }
188 
189   /// CHECK-START-ARM64: void Main.$opt$noinline$testOr(int, int) instruction_simplifier_arm64 (after)
190   /// CHECK:                            Arm64DataProcWithShifterOp
191   /// CHECK-NOT:                        Arm64DataProcWithShifterOp
192 
193   /// CHECK-START-ARM64: void Main.$opt$noinline$testOr(int, int) disassembly (after)
194   /// CHECK:                            orr asr
195   /// CHECK:                            uxth
196   /// CHECK:                            orr
197 
$opt$noinline$testOr(int a, int b)198   static void $opt$noinline$testOr(int a, int b) {
199     if (doThrow) throw new Error();
200     assertIntEquals((a | $noinline$IntShr(b, 6)) | (a | $noinline$intToChar(b)),
201                     (a | (b >> 6)) | (a | (char)b));
202   }
203 
204   /// CHECK-START-ARM64: void Main.$opt$noinline$testXor(long, long) instruction_simplifier_arm64 (after)
205   /// CHECK:                            Arm64DataProcWithShifterOp
206   /// CHECK-NOT:                        Arm64DataProcWithShifterOp
207 
208   /// CHECK-START-ARM64: void Main.$opt$noinline$testXor(long, long) disassembly (after)
209   /// CHECK:                            eor lsr
210   /// CHECK:                            sxtw
211   /// CHECK:                            eor
212 
$opt$noinline$testXor(long a, long b)213   static void $opt$noinline$testXor(long a, long b) {
214     if (doThrow) throw new Error();
215     assertLongEquals((a ^ $noinline$LongUshr(b, 7)) | (a ^ $noinline$longToInt(b)),
216                      (a ^ (b >>> 7)) | (a ^ (int)b));
217   }
218 
219   /// CHECK-START-ARM64: void Main.$opt$noinline$testNeg(int) instruction_simplifier_arm64 (after)
220   /// CHECK:                            Arm64DataProcWithShifterOp
221   /// CHECK-NOT:                        Arm64DataProcWithShifterOp
222 
223   /// CHECK-START-ARM64: void Main.$opt$noinline$testNeg(int) disassembly (after)
224   /// CHECK:                            neg lsl
225   /// CHECK:                            sxth
226   /// CHECK:                            neg
227 
$opt$noinline$testNeg(int a)228   static void $opt$noinline$testNeg(int a) {
229     if (doThrow) throw new Error();
230     assertIntEquals(-$noinline$IntShl(a, 8) | -$noinline$intToShort(a),
231                     (-(a << 8)) | (-(short)a));
232   }
233 
234   /**
235    * The functions below are used to compare the result of optimized operations
236    * to non-optimized operations.
237    * On the left-hand side we use a non-inlined function call to ensure the
238    * optimization does not occur. The checker tests ensure that the optimization
239    * does occur on the right-hand.
240    */
241 
242   /// CHECK-START-ARM64: void Main.$opt$validateExtendByteInt1(int, byte) instruction_simplifier_arm64 (after)
243   /// CHECK:                            Arm64DataProcWithShifterOp
244   /// CHECK-NOT:                        Arm64DataProcWithShifterOp
245 
246   /// CHECK-START-ARM64: void Main.$opt$validateExtendByteInt1(int, byte) instruction_simplifier_arm64 (after)
247   /// CHECK-NOT:                        TypeConversion
248 
$opt$validateExtendByteInt1(int a, byte b)249   public static void $opt$validateExtendByteInt1(int a, byte b) {
250     assertIntEquals(a + $noinline$byteToChar (b), a +  (char)b);
251     // Conversions byte->short and short->int are implicit; nothing to merge.
252     assertIntEquals(a + $noinline$byteToShort(b), a + (short)b);
253   }
254 
255   /// CHECK-START-ARM64: void Main.$opt$validateExtendByteInt2(int, byte) instruction_simplifier_arm64 (after)
256   /// CHECK-NOT:                        Arm64DataProcWithShifterOp
257   /// CHECK-NOT:                        Arm64DataProcWithShifterOp
258 
$opt$validateExtendByteInt2(int a, byte b)259   public static void $opt$validateExtendByteInt2(int a, byte b) {
260     // The conversion to `int` has been optimized away, so there is nothing to merge.
261     assertIntEquals (a + $noinline$byteToInt (b), a +  (int)b);
262     // There is an environment use for `(long)b`, preventing the merge.
263     assertLongEquals(a + $noinline$byteToLong(b), a + (long)b);
264   }
265 
266   /// CHECK-START-ARM64: void Main.$opt$validateExtendByteLong(long, byte) instruction_simplifier_arm64 (after)
267   /// CHECK:                            Arm64DataProcWithShifterOp
268   /// CHECK:                            Arm64DataProcWithShifterOp
269   /// CHECK:                            Arm64DataProcWithShifterOp
270   /// CHECK:                            Arm64DataProcWithShifterOp
271   /// CHECK:                            Arm64DataProcWithShifterOp
272   /// CHECK-NOT:                        Arm64DataProcWithShifterOp
273 
274   /// CHECK-START-ARM64: void Main.$opt$validateExtendByteLong(long, byte) instruction_simplifier_arm64 (after)
275   /// CHECK:                            TypeConversion
276   /// CHECK-NOT:                        TypeConversion
277 
$opt$validateExtendByteLong(long a, byte b)278   public static void $opt$validateExtendByteLong(long a, byte b) {
279     // In each of the following tests, there will be a merge on the LHS.
280 
281     // The first test has an explicit byte->char conversion on RHS,
282     // followed by a conversion that is merged with the Add.
283     assertLongEquals(a + $noinline$byteToChar (b), a +  (char)b);
284     // Since conversions byte->short and byte->int are implicit, the RHS
285     // for the two tests below is the same and one is eliminated by GVN.
286     // The other is then merged to a shifter operand instruction.
287     assertLongEquals(a + $noinline$byteToShort(b), a + (short)b);
288     assertLongEquals(a + $noinline$byteToInt  (b), a +  (int)b);
289   }
290 
$opt$validateExtendByte(long a, byte b)291   public static void $opt$validateExtendByte(long a, byte b) {
292     $opt$validateExtendByteInt1((int)a, b);
293     $opt$validateExtendByteInt2((int)a, b);
294     $opt$validateExtendByteLong(a, b);
295   }
296 
297   /// CHECK-START-ARM64: void Main.$opt$validateExtendCharInt1(int, char) instruction_simplifier_arm64 (after)
298   /// CHECK:                            Arm64DataProcWithShifterOp
299   /// CHECK:                            Arm64DataProcWithShifterOp
300 
301   /// CHECK-START-ARM64: void Main.$opt$validateExtendCharInt1(int, char) instruction_simplifier_arm64 (after)
302   /// CHECK-NOT:                        TypeConversion
303 
$opt$validateExtendCharInt1(int a, char b)304   public static void $opt$validateExtendCharInt1(int a, char b) {
305     assertIntEquals(a + $noinline$charToByte (b), a +  (byte)b);
306     assertIntEquals(a + $noinline$charToShort(b), a + (short)b);
307   }
308 
309   /// CHECK-START-ARM64: void Main.$opt$validateExtendCharInt2(int, char) instruction_simplifier_arm64 (after)
310   /// CHECK-NOT:                        Arm64DataProcWithShifterOp
311   /// CHECK-NOT:                        Arm64DataProcWithShifterOp
312 
$opt$validateExtendCharInt2(int a, char b)313   public static void $opt$validateExtendCharInt2(int a, char b) {
314     // The conversion to `int` has been optimized away, so there is nothing to merge.
315     assertIntEquals (a + $noinline$charToInt (b), a +  (int)b);
316     // There is an environment use for `(long)b`, preventing the merge.
317     assertLongEquals(a + $noinline$charToLong(b), a + (long)b);
318   }
319 
320   /// CHECK-START-ARM64: void Main.$opt$validateExtendCharLong(long, char) instruction_simplifier_arm64 (after)
321   /// CHECK:                            Arm64DataProcWithShifterOp
322   /// CHECK:                            Arm64DataProcWithShifterOp
323   /// CHECK:                            Arm64DataProcWithShifterOp
324   /// CHECK:                            Arm64DataProcWithShifterOp
325 
326   /// CHECK-START-ARM64: void Main.$opt$validateExtendCharLong(long, char) instruction_simplifier_arm64 (after)
327   /// CHECK:                            TypeConversion
328   /// CHECK:                            TypeConversion
329   /// CHECK-NOT:                        TypeConversion
330 
$opt$validateExtendCharLong(long a, char b)331   public static void $opt$validateExtendCharLong(long a, char b) {
332     // The first two tests have a type conversion.
333     assertLongEquals(a + $noinline$charToByte (b), a +  (byte)b);
334     assertLongEquals(a + $noinline$charToShort(b), a + (short)b);
335     // This test does not because the conversion to `int` is optimized away.
336     assertLongEquals(a + $noinline$charToInt  (b), a +   (int)b);
337   }
338 
$opt$validateExtendChar(long a, char b)339   public static void $opt$validateExtendChar(long a, char b) {
340     $opt$validateExtendCharInt1((int)a, b);
341     $opt$validateExtendCharInt2((int)a, b);
342     $opt$validateExtendCharLong(a, b);
343   }
344 
345   /// CHECK-START-ARM64: void Main.$opt$validateExtendShortInt1(int, short) instruction_simplifier_arm64 (after)
346   /// CHECK:                            Arm64DataProcWithShifterOp
347   /// CHECK:                            Arm64DataProcWithShifterOp
348 
349   /// CHECK-START-ARM64: void Main.$opt$validateExtendShortInt1(int, short) instruction_simplifier_arm64 (after)
350   /// CHECK-NOT:                        TypeConversion
351 
$opt$validateExtendShortInt1(int a, short b)352   public static void $opt$validateExtendShortInt1(int a, short b) {
353     assertIntEquals(a + $noinline$shortToByte (b), a + (byte)b);
354     assertIntEquals(a + $noinline$shortToChar (b), a + (char)b);
355   }
356 
357   /// CHECK-START-ARM64: void Main.$opt$validateExtendShortInt2(int, short) instruction_simplifier_arm64 (after)
358   /// CHECK-NOT:                        Arm64DataProcWithShifterOp
359   /// CHECK-NOT:                        Arm64DataProcWithShifterOp
360 
$opt$validateExtendShortInt2(int a, short b)361   public static void $opt$validateExtendShortInt2(int a, short b) {
362     // The conversion to `int` has been optimized away, so there is nothing to merge.
363     assertIntEquals (a + $noinline$shortToInt  (b), a +  (int)b);
364     // There is an environment use for `(long)b`, preventing the merge.
365     assertLongEquals(a + $noinline$shortToLong (b), a + (long)b);
366   }
367 
368   /// CHECK-START-ARM64: void Main.$opt$validateExtendShortLong(long, short) instruction_simplifier_arm64 (after)
369   /// CHECK:                            Arm64DataProcWithShifterOp
370   /// CHECK:                            Arm64DataProcWithShifterOp
371   /// CHECK:                            Arm64DataProcWithShifterOp
372 
373   /// CHECK-START-ARM64: void Main.$opt$validateExtendShortLong(long, short) instruction_simplifier_arm64 (after)
374   /// CHECK:                            TypeConversion
375   /// CHECK:                            TypeConversion
376   /// CHECK-NOT:                        TypeConversion
377 
$opt$validateExtendShortLong(long a, short b)378   public static void $opt$validateExtendShortLong(long a, short b) {
379     // The first two tests have a type conversion.
380     assertLongEquals(a + $noinline$shortToByte(b), a + (byte)b);
381     assertLongEquals(a + $noinline$shortToChar(b), a + (char)b);
382     // This test does not because the conversion to `int` is optimized away.
383     assertLongEquals(a + $noinline$shortToInt (b), a +  (int)b);
384   }
385 
$opt$validateExtendShort(long a, short b)386   public static void $opt$validateExtendShort(long a, short b) {
387     $opt$validateExtendShortInt1((int)a, b);
388     $opt$validateExtendShortInt2((int)a, b);
389     $opt$validateExtendShortLong(a, b);
390   }
391 
392   /// CHECK-START-ARM64: void Main.$opt$validateExtendInt(long, int) instruction_simplifier_arm64 (after)
393   /// CHECK:                            Arm64DataProcWithShifterOp
394   /// CHECK:                            Arm64DataProcWithShifterOp
395   /// CHECK:                            Arm64DataProcWithShifterOp
396   /// CHECK:                            Arm64DataProcWithShifterOp
397 
398   /// CHECK-START-ARM64: void Main.$opt$validateExtendInt(long, int) instruction_simplifier_arm64 (after)
399   /// CHECK:                            TypeConversion
400   /// CHECK:                            TypeConversion
401   /// CHECK:                            TypeConversion
402   /// CHECK-NOT:                        TypeConversion
403 
$opt$validateExtendInt(long a, int b)404   public static void $opt$validateExtendInt(long a, int b) {
405     // All tests have a conversion to `long`. The first three tests also have a
406     // conversion from `int` to the specified type. For each test the conversion
407     // to `long` is merged into the shifter operand.
408     assertLongEquals(a + $noinline$intToByte (b), a +  (byte)b);
409     assertLongEquals(a + $noinline$intToChar (b), a +  (char)b);
410     assertLongEquals(a + $noinline$intToShort(b), a + (short)b);
411     assertLongEquals(a + $noinline$intToLong (b), a +  (long)b);
412   }
413 
414   /// CHECK-START-ARM64: void Main.$opt$validateExtendLong(long, long) instruction_simplifier_arm64 (after)
415   /// CHECK:                            Arm64DataProcWithShifterOp
416   /// CHECK:                            Arm64DataProcWithShifterOp
417   /// CHECK:                            Arm64DataProcWithShifterOp
418   /// CHECK:                            Arm64DataProcWithShifterOp
419 
420   /// CHECK-START-ARM64: void Main.$opt$validateExtendLong(long, long) instruction_simplifier_arm64 (after)
421   /// CHECK:                            TypeConversion
422   /// CHECK:                            TypeConversion
423   /// CHECK:                            TypeConversion
424   /// CHECK:                            TypeConversion
425   /// CHECK-NOT:                        TypeConversion
426 
$opt$validateExtendLong(long a, long b)427   public static void $opt$validateExtendLong(long a, long b) {
428     // Each test has two conversions, from `long` and then back to `long`. The
429     // conversions to `long` are merged.
430     assertLongEquals(a + $noinline$longToByte (b), a +  (byte)b);
431     assertLongEquals(a + $noinline$longToChar (b), a +  (char)b);
432     assertLongEquals(a + $noinline$longToShort(b), a + (short)b);
433     assertLongEquals(a + $noinline$longToInt  (b), a +   (int)b);
434   }
435 
436 
$noinline$IntShl(int b, int c)437   static int $noinline$IntShl(int b, int c) {
438     if (doThrow) throw new Error();
439     return b << c;
440   }
$noinline$IntShr(int b, int c)441   static int $noinline$IntShr(int b, int c) {
442     if (doThrow) throw new Error();
443     return b >> c;
444   }
$noinline$IntUshr(int b, int c)445   static int $noinline$IntUshr(int b, int c) {
446     if (doThrow) throw new Error();
447     return b >>> c;
448   }
449 
450 
451   // Each test line below should see one merge.
452   /// CHECK-START-ARM64: void Main.$opt$validateShiftInt(int, int) instruction_simplifier_arm64 (after)
453   /// CHECK:                            Arm64DataProcWithShifterOp
454   /// CHECK:                            Arm64DataProcWithShifterOp
455   /// CHECK:                            Arm64DataProcWithShifterOp
456   /// CHECK:                            Arm64DataProcWithShifterOp
457   /// CHECK:                            Arm64DataProcWithShifterOp
458   /// CHECK:                            Arm64DataProcWithShifterOp
459   /// CHECK:                            Arm64DataProcWithShifterOp
460   /// CHECK:                            Arm64DataProcWithShifterOp
461   /// CHECK:                            Arm64DataProcWithShifterOp
462   /// CHECK:                            Arm64DataProcWithShifterOp
463   /// CHECK:                            Arm64DataProcWithShifterOp
464   /// CHECK:                            Arm64DataProcWithShifterOp
465   /// CHECK:                            Arm64DataProcWithShifterOp
466   /// CHECK:                            Arm64DataProcWithShifterOp
467   /// CHECK:                            Arm64DataProcWithShifterOp
468   /// CHECK:                            Arm64DataProcWithShifterOp
469   /// CHECK:                            Arm64DataProcWithShifterOp
470   /// CHECK:                            Arm64DataProcWithShifterOp
471   /// CHECK:                            Arm64DataProcWithShifterOp
472   /// CHECK:                            Arm64DataProcWithShifterOp
473   /// CHECK:                            Arm64DataProcWithShifterOp
474   /// CHECK:                            Arm64DataProcWithShifterOp
475   /// CHECK:                            Arm64DataProcWithShifterOp
476   /// CHECK:                            Arm64DataProcWithShifterOp
477   /// CHECK:                            Arm64DataProcWithShifterOp
478   /// CHECK:                            Arm64DataProcWithShifterOp
479   /// CHECK:                            Arm64DataProcWithShifterOp
480   /// CHECK:                            Arm64DataProcWithShifterOp
481   /// CHECK:                            Arm64DataProcWithShifterOp
482   /// CHECK:                            Arm64DataProcWithShifterOp
483   /// CHECK:                            Arm64DataProcWithShifterOp
484   /// CHECK:                            Arm64DataProcWithShifterOp
485   /// CHECK:                            Arm64DataProcWithShifterOp
486   // Note: `b << 32`, `b >> 32` and `b >>> 32` are optimized away by generic simplifier.
487 
488   /// CHECK-START-ARM64: void Main.$opt$validateShiftInt(int, int) instruction_simplifier_arm64 (after)
489   /// CHECK-NOT:                        Shl
490   /// CHECK-NOT:                        Shr
491   /// CHECK-NOT:                        UShr
492 
$opt$validateShiftInt(int a, int b)493   public static void $opt$validateShiftInt(int a, int b) {
494     assertIntEquals(a + $noinline$IntShl(b, 1),   a + (b <<  1));
495     assertIntEquals(a + $noinline$IntShl(b, 6),   a + (b <<  6));
496     assertIntEquals(a + $noinline$IntShl(b, 7),   a + (b <<  7));
497     assertIntEquals(a + $noinline$IntShl(b, 8),   a + (b <<  8));
498     assertIntEquals(a + $noinline$IntShl(b, 14),  a + (b << 14));
499     assertIntEquals(a + $noinline$IntShl(b, 15),  a + (b << 15));
500     assertIntEquals(a + $noinline$IntShl(b, 16),  a + (b << 16));
501     assertIntEquals(a + $noinline$IntShl(b, 30),  a + (b << 30));
502     assertIntEquals(a + $noinline$IntShl(b, 31),  a + (b << 31));
503     assertIntEquals(a + $noinline$IntShl(b, 32),  a + (b << $opt$inline$IntConstant32()));
504     assertIntEquals(a + $noinline$IntShl(b, 62),  a + (b << $opt$inline$IntConstant62()));
505     assertIntEquals(a + $noinline$IntShl(b, 63),  a + (b << $opt$inline$IntConstant63()));
506 
507     assertIntEquals(a - $noinline$IntShr(b, 1),   a - (b >>  1));
508     assertIntEquals(a - $noinline$IntShr(b, 6),   a - (b >>  6));
509     assertIntEquals(a - $noinline$IntShr(b, 7),   a - (b >>  7));
510     assertIntEquals(a - $noinline$IntShr(b, 8),   a - (b >>  8));
511     assertIntEquals(a - $noinline$IntShr(b, 14),  a - (b >> 14));
512     assertIntEquals(a - $noinline$IntShr(b, 15),  a - (b >> 15));
513     assertIntEquals(a - $noinline$IntShr(b, 16),  a - (b >> 16));
514     assertIntEquals(a - $noinline$IntShr(b, 30),  a - (b >> 30));
515     assertIntEquals(a - $noinline$IntShr(b, 31),  a - (b >> 31));
516     assertIntEquals(a - $noinline$IntShr(b, 32),  a - (b >> $opt$inline$IntConstant32()));
517     assertIntEquals(a - $noinline$IntShr(b, 62),  a - (b >> $opt$inline$IntConstant62()));
518     assertIntEquals(a - $noinline$IntShr(b, 63),  a - (b >> $opt$inline$IntConstant63()));
519 
520     assertIntEquals(a ^ $noinline$IntUshr(b, 1),   a ^ (b >>>  1));
521     assertIntEquals(a ^ $noinline$IntUshr(b, 6),   a ^ (b >>>  6));
522     assertIntEquals(a ^ $noinline$IntUshr(b, 7),   a ^ (b >>>  7));
523     assertIntEquals(a ^ $noinline$IntUshr(b, 8),   a ^ (b >>>  8));
524     assertIntEquals(a ^ $noinline$IntUshr(b, 14),  a ^ (b >>> 14));
525     assertIntEquals(a ^ $noinline$IntUshr(b, 15),  a ^ (b >>> 15));
526     assertIntEquals(a ^ $noinline$IntUshr(b, 16),  a ^ (b >>> 16));
527     assertIntEquals(a ^ $noinline$IntUshr(b, 30),  a ^ (b >>> 30));
528     assertIntEquals(a ^ $noinline$IntUshr(b, 31),  a ^ (b >>> 31));
529     assertIntEquals(a ^ $noinline$IntUshr(b, 32),  a ^ (b >>> $opt$inline$IntConstant32()));
530     assertIntEquals(a ^ $noinline$IntUshr(b, 62),  a ^ (b >>> $opt$inline$IntConstant62()));
531     assertIntEquals(a ^ $noinline$IntUshr(b, 63),  a ^ (b >>> $opt$inline$IntConstant63()));
532   }
533 
534   // Hiding constants outside the range [0, 32) used for int shifts from Jack.
535   // (Jack extracts only the low 5 bits.)
$opt$inline$IntConstant32()536   public static int $opt$inline$IntConstant32() { return 32; }
$opt$inline$IntConstant62()537   public static int $opt$inline$IntConstant62() { return 62; }
$opt$inline$IntConstant63()538   public static int $opt$inline$IntConstant63() { return 63; }
539 
540 
$noinline$LongShl(long b, long c)541   static long $noinline$LongShl(long b, long c) {
542     if (doThrow) throw new Error();
543     return b << c;
544   }
$noinline$LongShr(long b, long c)545   static long $noinline$LongShr(long b, long c) {
546     if (doThrow) throw new Error();
547     return b >> c;
548   }
$noinline$LongUshr(long b, long c)549   static long $noinline$LongUshr(long b, long c) {
550     if (doThrow) throw new Error();
551     return b >>> c;
552   }
553 
554   // Each test line below should see one merge.
555   /// CHECK-START-ARM64: void Main.$opt$validateShiftLong(long, long) instruction_simplifier_arm64 (after)
556   /// CHECK:                            Arm64DataProcWithShifterOp
557   /// CHECK:                            Arm64DataProcWithShifterOp
558   /// CHECK:                            Arm64DataProcWithShifterOp
559   /// CHECK:                            Arm64DataProcWithShifterOp
560   /// CHECK:                            Arm64DataProcWithShifterOp
561   /// CHECK:                            Arm64DataProcWithShifterOp
562   /// CHECK:                            Arm64DataProcWithShifterOp
563   /// CHECK:                            Arm64DataProcWithShifterOp
564   /// CHECK:                            Arm64DataProcWithShifterOp
565   /// CHECK:                            Arm64DataProcWithShifterOp
566   /// CHECK:                            Arm64DataProcWithShifterOp
567   /// CHECK:                            Arm64DataProcWithShifterOp
568   /// CHECK:                            Arm64DataProcWithShifterOp
569   /// CHECK:                            Arm64DataProcWithShifterOp
570   /// CHECK:                            Arm64DataProcWithShifterOp
571   /// CHECK:                            Arm64DataProcWithShifterOp
572   /// CHECK:                            Arm64DataProcWithShifterOp
573   /// CHECK:                            Arm64DataProcWithShifterOp
574   /// CHECK:                            Arm64DataProcWithShifterOp
575   /// CHECK:                            Arm64DataProcWithShifterOp
576   /// CHECK:                            Arm64DataProcWithShifterOp
577   /// CHECK:                            Arm64DataProcWithShifterOp
578   /// CHECK:                            Arm64DataProcWithShifterOp
579   /// CHECK:                            Arm64DataProcWithShifterOp
580   /// CHECK:                            Arm64DataProcWithShifterOp
581   /// CHECK:                            Arm64DataProcWithShifterOp
582   /// CHECK:                            Arm64DataProcWithShifterOp
583   /// CHECK:                            Arm64DataProcWithShifterOp
584   /// CHECK:                            Arm64DataProcWithShifterOp
585   /// CHECK:                            Arm64DataProcWithShifterOp
586   /// CHECK:                            Arm64DataProcWithShifterOp
587   /// CHECK:                            Arm64DataProcWithShifterOp
588   /// CHECK:                            Arm64DataProcWithShifterOp
589   /// CHECK:                            Arm64DataProcWithShifterOp
590   /// CHECK:                            Arm64DataProcWithShifterOp
591   /// CHECK:                            Arm64DataProcWithShifterOp
592 
593   /// CHECK-START-ARM64: void Main.$opt$validateShiftLong(long, long) instruction_simplifier_arm64 (after)
594   /// CHECK-NOT:                        Shl
595   /// CHECK-NOT:                        Shr
596   /// CHECK-NOT:                        UShr
597 
$opt$validateShiftLong(long a, long b)598   public static void $opt$validateShiftLong(long a, long b) {
599     assertLongEquals(a + $noinline$LongShl(b, 1),   a + (b <<  1));
600     assertLongEquals(a + $noinline$LongShl(b, 6),   a + (b <<  6));
601     assertLongEquals(a + $noinline$LongShl(b, 7),   a + (b <<  7));
602     assertLongEquals(a + $noinline$LongShl(b, 8),   a + (b <<  8));
603     assertLongEquals(a + $noinline$LongShl(b, 14),  a + (b << 14));
604     assertLongEquals(a + $noinline$LongShl(b, 15),  a + (b << 15));
605     assertLongEquals(a + $noinline$LongShl(b, 16),  a + (b << 16));
606     assertLongEquals(a + $noinline$LongShl(b, 30),  a + (b << 30));
607     assertLongEquals(a + $noinline$LongShl(b, 31),  a + (b << 31));
608     assertLongEquals(a + $noinline$LongShl(b, 32),  a + (b << 32));
609     assertLongEquals(a + $noinline$LongShl(b, 62),  a + (b << 62));
610     assertLongEquals(a + $noinline$LongShl(b, 63),  a + (b << 63));
611 
612     assertLongEquals(a - $noinline$LongShr(b, 1),   a - (b >>  1));
613     assertLongEquals(a - $noinline$LongShr(b, 6),   a - (b >>  6));
614     assertLongEquals(a - $noinline$LongShr(b, 7),   a - (b >>  7));
615     assertLongEquals(a - $noinline$LongShr(b, 8),   a - (b >>  8));
616     assertLongEquals(a - $noinline$LongShr(b, 14),  a - (b >> 14));
617     assertLongEquals(a - $noinline$LongShr(b, 15),  a - (b >> 15));
618     assertLongEquals(a - $noinline$LongShr(b, 16),  a - (b >> 16));
619     assertLongEquals(a - $noinline$LongShr(b, 30),  a - (b >> 30));
620     assertLongEquals(a - $noinline$LongShr(b, 31),  a - (b >> 31));
621     assertLongEquals(a - $noinline$LongShr(b, 32),  a - (b >> 32));
622     assertLongEquals(a - $noinline$LongShr(b, 62),  a - (b >> 62));
623     assertLongEquals(a - $noinline$LongShr(b, 63),  a - (b >> 63));
624 
625     assertLongEquals(a ^ $noinline$LongUshr(b, 1),   a ^ (b >>>  1));
626     assertLongEquals(a ^ $noinline$LongUshr(b, 6),   a ^ (b >>>  6));
627     assertLongEquals(a ^ $noinline$LongUshr(b, 7),   a ^ (b >>>  7));
628     assertLongEquals(a ^ $noinline$LongUshr(b, 8),   a ^ (b >>>  8));
629     assertLongEquals(a ^ $noinline$LongUshr(b, 14),  a ^ (b >>> 14));
630     assertLongEquals(a ^ $noinline$LongUshr(b, 15),  a ^ (b >>> 15));
631     assertLongEquals(a ^ $noinline$LongUshr(b, 16),  a ^ (b >>> 16));
632     assertLongEquals(a ^ $noinline$LongUshr(b, 30),  a ^ (b >>> 30));
633     assertLongEquals(a ^ $noinline$LongUshr(b, 31),  a ^ (b >>> 31));
634     assertLongEquals(a ^ $noinline$LongUshr(b, 32),  a ^ (b >>> 32));
635     assertLongEquals(a ^ $noinline$LongUshr(b, 62),  a ^ (b >>> 62));
636     assertLongEquals(a ^ $noinline$LongUshr(b, 63),  a ^ (b >>> 63));
637   }
638 
639 
main(String[] args)640   public static void main(String[] args) {
641     assertLongEquals(10000L - 3L, $opt$noinline$translate(10000L, (byte)3));
642     assertLongEquals(-10000L - -3L, $opt$noinline$translate(-10000L, (byte)-3));
643 
644     assertIntEquals(4096, $opt$noinline$sameInput(512));
645     assertIntEquals(-8192, $opt$noinline$sameInput(-1024));
646 
647     assertIntEquals(((1 << 23) | 1), $opt$noinline$multipleUses(1));
648     assertIntEquals(((1 << 20) | 5), $opt$noinline$multipleUses(1 << 20));
649 
650     long inputs[] = {
651       -((1L <<  7) - 1L), -((1L <<  7)), -((1L <<  7) + 1L),
652       -((1L << 15) - 1L), -((1L << 15)), -((1L << 15) + 1L),
653       -((1L << 16) - 1L), -((1L << 16)), -((1L << 16) + 1L),
654       -((1L << 31) - 1L), -((1L << 31)), -((1L << 31) + 1L),
655       -((1L << 32) - 1L), -((1L << 32)), -((1L << 32) + 1L),
656       -((1L << 63) - 1L), -((1L << 63)), -((1L << 63) + 1L),
657       -42L, -314L, -2718281828L, -0x123456789L, -0x987654321L,
658       -1L, -20L, -300L, -4000L, -50000L, -600000L, -7000000L, -80000000L,
659       0L,
660       1L, 20L, 300L, 4000L, 50000L, 600000L, 7000000L, 80000000L,
661       42L,  314L,  2718281828L,  0x123456789L,  0x987654321L,
662       (1L <<  7) - 1L, (1L <<  7), (1L <<  7) + 1L,
663       (1L <<  8) - 1L, (1L <<  8), (1L <<  8) + 1L,
664       (1L << 15) - 1L, (1L << 15), (1L << 15) + 1L,
665       (1L << 16) - 1L, (1L << 16), (1L << 16) + 1L,
666       (1L << 31) - 1L, (1L << 31), (1L << 31) + 1L,
667       (1L << 32) - 1L, (1L << 32), (1L << 32) + 1L,
668       (1L << 63) - 1L, (1L << 63), (1L << 63) + 1L,
669       Long.MIN_VALUE, Long.MAX_VALUE
670     };
671     for (int i = 0; i < inputs.length; i++) {
672       $opt$noinline$testNeg((int)inputs[i]);
673       for (int j = 0; j < inputs.length; j++) {
674         $opt$noinline$testAnd(inputs[i], inputs[j]);
675         $opt$noinline$testOr((int)inputs[i], (int)inputs[j]);
676         $opt$noinline$testXor(inputs[i], inputs[j]);
677 
678         $opt$validateExtendByte(inputs[i], (byte)inputs[j]);
679         $opt$validateExtendChar(inputs[i], (char)inputs[j]);
680         $opt$validateExtendShort(inputs[i], (short)inputs[j]);
681         $opt$validateExtendInt(inputs[i], (int)inputs[j]);
682         $opt$validateExtendLong(inputs[i], inputs[j]);
683 
684         $opt$validateShiftInt((int)inputs[i], (int)inputs[j]);
685         $opt$validateShiftLong(inputs[i], inputs[j]);
686       }
687     }
688 
689   }
690 }
691