content: /*
   * Copyright (C) 2015 The Android Open Source Project
   *
   * Licensed under the Apache License, Version 2.0 (the "License");
   * you may not use this file except in compliance with the License.
   * You may obtain a copy of the License at
   *
   *      http://www.apache.org/licenses/LICENSE-2.0
   *
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS IS" BASIS,
   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   * See the License for the specific language governing permissions and
   * limitations under the License.
   */
  
  public class Main {
  
    public static void assertIntEquals(int expected, int result) {
      if (expected != result) {
        throw new Error("Expected: " + expected + ", found: " + result);
      }
    }
  
    static boolean doThrow = false;
  
    // This function always returns 1.
    // We use 'throw' to prevent the function from being inlined.
    public static int $opt$noinline$function_call(int arg) {
      if (doThrow) throw new Error();
      return 1 % arg;
    }
  
    //                               | registers available to | regexp
    //                               | the register allocator |
    // ------------------------------|------------------------|-----------------
    // ARM64 callee-saved registers  | [x20-x29]              | x2[0-9]
    // ARM callee-saved registers    | [r5-r8,r10,r11]        | r([5-8]|10|11)
    // X86 callee-saved registers    | [ebp,esi,edi]          | e(bp|si|di)
    // X86_64 callee-saved registers | [rbx,rbp,r12-15]       | r(bx|bp|1[2-5])
  
    /**
     * Check that a value live across a function call is allocated in a callee
     * saved register.
     */
  
    /// CHECK-START-ARM:   int Main.$opt$LiveInCall(int) register (after)
    /// CHECK-DAG:   <<Arg:i\d+>>     ParameterValue
    /// CHECK-DAG:   <<Const1:i\d+>>  IntConstant 1
    /// CHECK:       <<t1:i\d+>>      Add [<<Arg>>,<<Const1>>] {{.*->r([5-8]|10|11)}}
    /// CHECK:       <<t2:i\d+>>      InvokeStaticOrDirect
    /// CHECK:                        Sub [<<t1>>,<<t2>>]
    /// CHECK:                        Return
  
    /// CHECK-START-ARM64: int Main.$opt$LiveInCall(int) register (after)
    /// CHECK-DAG:   <<Arg:i\d+>>     ParameterValue
    /// CHECK-DAG:   <<Const1:i\d+>>  IntConstant 1
    /// CHECK:       <<t1:i\d+>>      Add [<<Arg>>,<<Const1>>] {{.*->x2[0-9]}}
    /// CHECK:       <<t2:i\d+>>      InvokeStaticOrDirect
    /// CHECK:                        Sub [<<t1>>,<<t2>>]
    /// CHECK:                        Return
  
    /// CHECK-START-X86: int Main.$opt$LiveInCall(int) register (after)
    /// CHECK-DAG:   <<Arg:i\d+>>     ParameterValue
    /// CHECK-DAG:   <<Const1:i\d+>>  IntConstant 1
    /// CHECK:       <<t1:i\d+>>      Add [<<Arg>>,<<Const1>>] {{.*->e(bp|si|di)}}
    /// CHECK:       <<t2:i\d+>>      InvokeStaticOrDirect
    /// CHECK:                        Sub [<<t1>>,<<t2>>]
    /// CHECK:                        Return
  
    /// CHECK-START-X86_64: int Main.$opt$LiveInCall(int) register (after)
    /// CHECK-DAG:   <<Arg:i\d+>>     ParameterValue
    /// CHECK-DAG:   <<Const1:i\d+>>  IntConstant 1
    /// CHECK:       <<t1:i\d+>>      Add [<<Arg>>,<<Const1>>] {{.*->r(bx|bp|1[2-5])}}
    /// CHECK:       <<t2:i\d+>>      InvokeStaticOrDirect
    /// CHECK:                        Sub [<<t1>>,<<t2>>]
    /// CHECK:                        Return
  
    public static int $opt$LiveInCall(int arg) {
      int t1 = arg + 1;
      int t2 = $opt$noinline$function_call(arg);
      return t1 - t2;
    }
  
    public static void main(String[] args) {
      int arg = 123;
      assertIntEquals($opt$LiveInCall(arg), arg);
    }
  }
  