/*
* 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 {
/// CHECK-START: void Main.loop1(boolean) liveness (after)
/// CHECK-DAG: <<Arg:z\d+>> ParameterValue liveness:<<ArgLiv:\d+>> ranges:{[<<ArgLiv>>,<<ArgUse:\d+>>)} uses:[<<ArgUse>>]
/// CHECK-DAG: If [<<Arg>>] liveness:<<IfLiv:\d+>> loop:none
/// CHECK-DAG: Goto loop:B{{\d+}}
/// CHECK-DAG: Exit
/// CHECK-EVAL: <<IfLiv>> + 1 == <<ArgUse>>
//
// Loop invariant exit check is hoisted from the loop by peeling.
public static void loop1(boolean incoming) {
while (incoming) {}
}
/// CHECK-START: void Main.loop2(boolean) liveness (after)
/// CHECK-DAG: <<Arg:z\d+>> ParameterValue liveness:<<ArgLiv:\d+>> ranges:{[<<ArgLiv>>,<<ArgLoopUse:\d+>>)} uses:[<<ArgUse:\d+>>,<<ArgLoopUse>>]
/// CHECK-DAG: If [<<Arg>>] liveness:<<IfLiv:\d+>> loop:<<Loop1:B\d+>>
/// CHECK-DAG: Goto liveness:<<GotoLiv1:\d+>> loop:<<Loop1>>
/// CHECK-DAG: Goto liveness:<<GotoLiv2:\d+>> loop:<<Loop2:B\d+>>
/// CHECK-EVAL: <<IfLiv>> + 1 == <<ArgUse>>
/// CHECK-EVAL: <<GotoLiv1>> < <<GotoLiv2>>
/// CHECK-EVAL: <<GotoLiv1>> + 2 == <<ArgLoopUse>>
//
// Loop invariant exit check is hoisted from the loop by peeling.
public static void loop2(boolean incoming) {
// Add some code at entry to avoid having the entry block be a pre header.
// This avoids having to create a synthesized block.
System.out.println("Enter");
while (true) {
System.out.println("foo");
while (incoming) {}
}
}
/// CHECK-START: void Main.loop3(boolean) liveness (after)
/// CHECK: <<Arg:z\d+>> ParameterValue liveness:<<ArgLiv:\d+>> ranges:{[<<ArgLiv>>,<<ArgLoopUse:\d+>>)} uses:[<<ArgUse:\d+>>,<<ArgLoopUse>>]
/// CHECK: Goto liveness:<<GotoLiv1:\d+>>
/// CHECK: InvokeVirtual [{{l\d+}},<<Arg>>] method_name:java.io.PrintStream.println liveness:<<InvokeLiv:\d+>>
/// CHECK: Goto liveness:<<GotoLiv2:\d+>>
/// CHECK-EVAL: <<InvokeLiv>> == <<ArgUse>>
/// CHECK-EVAL: <<GotoLiv1>> < <<GotoLiv2>>
/// CHECK-EVAL: <<GotoLiv2>> + 2 == <<ArgLoopUse>>
public static void loop3(boolean incoming) {
// 'incoming' only needs a use at the outer loop's back edge.
while (System.currentTimeMillis() != 42) {
while (Runtime.getRuntime() != null) {}
System.out.println(incoming);
}
}
/// CHECK-START: void Main.loop4(boolean) liveness (after)
/// CHECK: <<Arg:z\d+>> ParameterValue liveness:<<ArgLiv:\d+>> ranges:{[<<ArgLiv>>,<<ArgUse:\d+>>)} uses:[<<ArgUse>>]
/// CHECK: InvokeVirtual [{{l\d+}},<<Arg>>] method_name:java.io.PrintStream.println liveness:<<InvokeLiv:\d+>>
/// CHECK-EVAL: <<InvokeLiv>> == <<ArgUse>>
public static void loop4(boolean incoming) {
// 'incoming' has no loop use, so should not have back edge uses.
System.out.println(incoming);
while (System.currentTimeMillis() != 42) {
while (Runtime.getRuntime() != null) {}
}
}
/// CHECK-START: void Main.loop5(boolean) liveness (after)
/// CHECK: <<Arg:z\d+>> ParameterValue liveness:<<ArgLiv:\d+>> ranges:{[<<ArgLiv>>,<<ArgLoopUse2:\d+>>)} uses:[<<ArgUse:\d+>>,<<ArgLoopUse1:\d+>>,<<ArgLoopUse2>>]
/// CHECK: InvokeVirtual [{{l\d+}},<<Arg>>] method_name:java.io.PrintStream.println liveness:<<InvokeLiv:\d+>>
/// CHECK: Goto liveness:<<GotoLiv1:\d+>>
/// CHECK: Goto liveness:<<GotoLiv2:\d+>>
/// CHECK: Exit
/// CHECK-EVAL: <<InvokeLiv>> == <<ArgUse>>
/// CHECK-EVAL: <<GotoLiv1>> < <<GotoLiv2>>
/// CHECK-EVAL: <<GotoLiv1>> + 2 == <<ArgLoopUse1>>
/// CHECK-EVAL: <<GotoLiv2>> + 2 == <<ArgLoopUse2>>
public static void loop5(boolean incoming) {
// 'incoming' must have a use at both back edges.
for (long i = System.nanoTime(); i < 42; ++i) {
for (long j = System.currentTimeMillis(); j != 42; ++j) {
System.out.println(incoming);
}
}
}
/// CHECK-START: void Main.loop6(boolean) liveness (after)
/// CHECK: <<Arg:z\d+>> ParameterValue liveness:<<ArgLiv:\d+>> ranges:{[<<ArgLiv>>,<<ArgLoopUse:\d+>>)} uses:[<<ArgUse:\d+>>,<<ArgLoopUse>>]
/// CHECK: InvokeVirtual [{{l\d+}},<<Arg>>] method_name:java.io.PrintStream.println liveness:<<InvokeLiv:\d+>>
/// CHECK: Add
/// CHECK: Goto liveness:<<GotoLiv1:\d+>>
/// CHECK: Add
/// CHECK: Goto liveness:<<GotoLiv2:\d+>>
/// CHECK: Exit
/// CHECK-EVAL: <<InvokeLiv>> == <<ArgUse>>
/// CHECK-EVAL: <<GotoLiv1>> < <<GotoLiv2>>
/// CHECK-EVAL: <<GotoLiv2>> + 2 == <<ArgLoopUse>>
public static void loop6(boolean incoming) {
// 'incoming' must have a use only at the first loop's back edge.
for (long i = System.nanoTime(); i < 42; ++i) {
System.out.println(incoming);
for (long j = System.currentTimeMillis(); j != 42; ++j) {
System.out.print(j); // non-empty body
}
}
}
/// CHECK-START: void Main.loop7(boolean) liveness (after)
/// CHECK-DAG: <<Arg:z\d+>> ParameterValue liveness:<<ArgLiv:\d+>> ranges:{[<<ArgLiv>>,<<ArgLoopUse:\d+>>)} uses:[<<ArgUse1:\d+>>,<<ArgUse2:\d+>>,<<ArgLoopUse>>]
/// CHECK-DAG: InvokeVirtual [{{l\d+}},<<Arg>>] method_name:java.io.PrintStream.println liveness:<<InvokeLiv:\d+>>
/// CHECK-DAG: If [<<Arg>>] liveness:<<IfLiv:\d+>> loop:<<Loop1:B\d+>>
/// CHECK-DAG: Goto liveness:<<GotoLiv1:\d+>> loop:<<Loop1>>
/// CHECK-DAG: Goto liveness:<<GotoLiv2:\d+>> loop:<<Loop2:B\d+>>
/// CHECK-DAG: Exit
/// CHECK-EVAL: <<InvokeLiv>> == <<ArgUse1>>
/// CHECK-EVAL: <<IfLiv>> + 1 == <<ArgUse2>>
/// CHECK-EVAL: <<GotoLiv1>> < <<GotoLiv2>>
/// CHECK-EVAL: <<GotoLiv1>> + 2 == <<ArgLoopUse>>
//
// Loop invariant exit check is hoisted from the loop by peeling.
public static void loop7(boolean incoming) {
// 'incoming' must have a use at both back edges.
while (Runtime.getRuntime() != null) {
System.out.println(incoming);
while (incoming) {}
System.nanoTime(); // beat back edge splitting
}
}
/// CHECK-START: void Main.loop8() liveness (after)
/// CHECK-DAG: <<Arg:z\d+>> StaticFieldGet liveness:<<ArgLiv:\d+>> ranges:{[<<ArgLiv>>,<<ArgLoopUse:\d+>>)} uses:[<<ArgUse:\d+>>,<<ArgLoopUse>>]
/// CHECK-DAG: If [<<Arg>>] liveness:<<IfLiv:\d+>> loop:<<Loop1:B\d+>>
/// CHECK-DAG: Goto liveness:<<GotoLiv1:\d+>> loop:<<Loop1>>
/// CHECK-DAG: Goto liveness:<<GotoLiv2:\d+>> loop:<<Loop2:B\d+>>
/// CHECK-DAG: Exit
/// CHECK-EVAL: <<IfLiv>> + 1 == <<ArgUse>>
/// CHECK-EVAL: <<GotoLiv1>> < <<GotoLiv2>>
/// CHECK-EVAL: <<GotoLiv1>> + 2 == <<ArgLoopUse>>
//
// Loop invariant exit check is hoisted from the loop by peeling.
public static void loop8() {
// 'incoming' must have a use at both back edges.
boolean incoming = field;
while (Runtime.getRuntime() != null) {
System.nanoTime(); // beat pre-header creation
while (incoming) {}
System.nanoTime(); // beat back edge splitting
}
}
static boolean $opt$noinline$ensureSideEffects() {
if (doThrow) throw new Error("");
return true;
}
/// CHECK-START: void Main.loop9() liveness (after)
/// CHECK-DAG: <<Arg:z\d+>> StaticFieldGet liveness:<<ArgLiv:\d+>> ranges:{[<<ArgLiv>>,<<ArgUse:\d+>>)} uses:[<<ArgUse>>]
/// CHECK-DAG: If [<<Arg>>] liveness:<<IfLiv:\d+>> loop:<<Loop1:B\d+>>
/// CHECK-DAG: Goto liveness:<<GotoLiv1:\d+>> loop:<<Loop1>>
/// CHECK-DAG: Goto liveness:<<GotoLiv2:\d+>> loop:<<Loop2:B\d+>>
/// CHECK-DAG: Exit
/// CHECK-EVAL: <<IfLiv>> + 1 == <<ArgUse>>
/// CHECK-EVAL: <<GotoLiv1>> < <<GotoLiv2>>
//
// Loop invariant exit check is hoisted from the loop by peeling.
public static void loop9() {
// Add some code at entry to avoid having the entry block be a pre header.
// This avoids having to create a synthesized block.
System.out.println("Enter");
while ($opt$noinline$ensureSideEffects()) {
// 'incoming' must only have a use in the inner loop.
boolean incoming = field;
while (incoming) {}
}
}
public static void main(String[] args) {
}
static boolean field;
static boolean doThrow = false;
}