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 
assertIntEquals(int expected, int result)19   public static void assertIntEquals(int expected, int result) {
20     if (expected != result) {
21       throw new Error("Expected: " + expected + ", found: " + result);
22     }
23   }
24 
25   static boolean doThrow = false;
26 
27   // This function always returns 1.
28   // We use 'throw' to prevent the function from being inlined.
$opt$noinline$function_call(int arg)29   public static int $opt$noinline$function_call(int arg) {
30     if (doThrow) throw new Error();
31     return 1 % arg;
32   }
33 
34   //                               | registers available to | regexp
35   //                               | the register allocator |
36   // ------------------------------|------------------------|-----------------
37   // ARM64 callee-saved registers  | [x20-x29]              | x2[0-9]
38   // ARM callee-saved registers    | [r5-r8,r10,r11]        | r([5-8]|10|11)
39   // X86 callee-saved registers    | [ebp,esi,edi]          | e(bp|si|di)
40   // X86_64 callee-saved registers | [rbx,rbp,r12-15]       | r(bx|bp|1[2-5])
41 
42   /**
43    * Check that a value live across a function call is allocated in a callee
44    * saved register.
45    */
46 
47   /// CHECK-START-ARM:   int Main.$opt$LiveInCall(int) register (after)
48   /// CHECK-DAG:   <<Arg:i\d+>>     ParameterValue
49   /// CHECK-DAG:   <<Const1:i\d+>>  IntConstant 1
50   /// CHECK:       <<t1:i\d+>>      Add [<<Arg>>,<<Const1>>] {{.*->r([5-8]|10|11)}}
51   /// CHECK:       <<t2:i\d+>>      InvokeStaticOrDirect
52   /// CHECK:                        Sub [<<t1>>,<<t2>>]
53   /// CHECK:                        Return
54 
55   /// CHECK-START-ARM64: int Main.$opt$LiveInCall(int) register (after)
56   /// CHECK-DAG:   <<Arg:i\d+>>     ParameterValue
57   /// CHECK-DAG:   <<Const1:i\d+>>  IntConstant 1
58   /// CHECK:       <<t1:i\d+>>      Add [<<Arg>>,<<Const1>>] {{.*->x2[0-9]}}
59   /// CHECK:       <<t2:i\d+>>      InvokeStaticOrDirect
60   /// CHECK:                        Sub [<<t1>>,<<t2>>]
61   /// CHECK:                        Return
62 
63   /// CHECK-START-X86: int Main.$opt$LiveInCall(int) register (after)
64   /// CHECK-DAG:   <<Arg:i\d+>>     ParameterValue
65   /// CHECK-DAG:   <<Const1:i\d+>>  IntConstant 1
66   /// CHECK:       <<t1:i\d+>>      Add [<<Arg>>,<<Const1>>] {{.*->e(bp|si|di)}}
67   /// CHECK:       <<t2:i\d+>>      InvokeStaticOrDirect
68   /// CHECK:                        Sub [<<t1>>,<<t2>>]
69   /// CHECK:                        Return
70 
71   /// CHECK-START-X86_64: int Main.$opt$LiveInCall(int) register (after)
72   /// CHECK-DAG:   <<Arg:i\d+>>     ParameterValue
73   /// CHECK-DAG:   <<Const1:i\d+>>  IntConstant 1
74   /// CHECK:       <<t1:i\d+>>      Add [<<Arg>>,<<Const1>>] {{.*->r(bx|bp|1[2-5])}}
75   /// CHECK:       <<t2:i\d+>>      InvokeStaticOrDirect
76   /// CHECK:                        Sub [<<t1>>,<<t2>>]
77   /// CHECK:                        Return
78 
$opt$LiveInCall(int arg)79   public static int $opt$LiveInCall(int arg) {
80     int t1 = arg + 1;
81     int t2 = $opt$noinline$function_call(arg);
82     return t1 - t2;
83   }
84 
main(String[] args)85   public static void main(String[] args) {
86     int arg = 123;
87     assertIntEquals($opt$LiveInCall(arg), arg);
88   }
89 }
90