/* * 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; }