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 18 public class Main { 19 20 /// CHECK-START: void Main.loop1(boolean) liveness (after) 21 /// CHECK-DAG: <<Arg:z\d+>> ParameterValue liveness:<<ArgLiv:\d+>> ranges:{[<<ArgLiv>>,<<ArgUse:\d+>>)} uses:[<<ArgUse>>] 22 /// CHECK-DAG: If [<<Arg>>] liveness:<<IfLiv:\d+>> loop:none 23 /// CHECK-DAG: Goto loop:B{{\d+}} 24 /// CHECK-DAG: Exit 25 /// CHECK-EVAL: <<IfLiv>> + 1 == <<ArgUse>> 26 // 27 // Loop invariant exit check is hoisted from the loop by peeling. 28 loop1(boolean incoming)29 public static void loop1(boolean incoming) { 30 while (incoming) {} 31 } 32 33 /// CHECK-START: void Main.loop2(boolean) liveness (after) 34 /// CHECK-DAG: <<Arg:z\d+>> ParameterValue liveness:<<ArgLiv:\d+>> ranges:{[<<ArgLiv>>,<<ArgLoopUse:\d+>>)} uses:[<<ArgUse:\d+>>,<<ArgLoopUse>>] 35 /// CHECK-DAG: If [<<Arg>>] liveness:<<IfLiv:\d+>> loop:<<Loop1:B\d+>> 36 /// CHECK-DAG: Goto liveness:<<GotoLiv1:\d+>> loop:<<Loop1>> 37 /// CHECK-DAG: Goto liveness:<<GotoLiv2:\d+>> loop:<<Loop2:B\d+>> 38 /// CHECK-EVAL: <<IfLiv>> + 1 == <<ArgUse>> 39 /// CHECK-EVAL: <<GotoLiv1>> < <<GotoLiv2>> 40 /// CHECK-EVAL: <<GotoLiv1>> + 2 == <<ArgLoopUse>> 41 // 42 // Loop invariant exit check is hoisted from the loop by peeling. 43 loop2(boolean incoming)44 public static void loop2(boolean incoming) { 45 // Add some code at entry to avoid having the entry block be a pre header. 46 // This avoids having to create a synthesized block. 47 System.out.println("Enter"); 48 while (true) { 49 System.out.println("foo"); 50 while (incoming) {} 51 } 52 } 53 54 /// CHECK-START: void Main.loop3(boolean) liveness (after) 55 /// CHECK: <<Arg:z\d+>> ParameterValue liveness:<<ArgLiv:\d+>> ranges:{[<<ArgLiv>>,<<ArgLoopUse:\d+>>)} uses:[<<ArgUse:\d+>>,<<ArgLoopUse>>] 56 /// CHECK: Goto liveness:<<GotoLiv1:\d+>> 57 /// CHECK: InvokeVirtual [{{l\d+}},<<Arg>>] method_name:java.io.PrintStream.println liveness:<<InvokeLiv:\d+>> 58 /// CHECK: Goto liveness:<<GotoLiv2:\d+>> 59 /// CHECK-EVAL: <<InvokeLiv>> == <<ArgUse>> 60 /// CHECK-EVAL: <<GotoLiv1>> < <<GotoLiv2>> 61 /// CHECK-EVAL: <<GotoLiv2>> + 2 == <<ArgLoopUse>> 62 loop3(boolean incoming)63 public static void loop3(boolean incoming) { 64 // 'incoming' only needs a use at the outer loop's back edge. 65 while (System.currentTimeMillis() != 42) { 66 while (Runtime.getRuntime() != null) {} 67 System.out.println(incoming); 68 } 69 } 70 71 /// CHECK-START: void Main.loop4(boolean) liveness (after) 72 /// CHECK: <<Arg:z\d+>> ParameterValue liveness:<<ArgLiv:\d+>> ranges:{[<<ArgLiv>>,<<ArgUse:\d+>>)} uses:[<<ArgUse>>] 73 /// CHECK: InvokeVirtual [{{l\d+}},<<Arg>>] method_name:java.io.PrintStream.println liveness:<<InvokeLiv:\d+>> 74 /// CHECK-EVAL: <<InvokeLiv>> == <<ArgUse>> 75 loop4(boolean incoming)76 public static void loop4(boolean incoming) { 77 // 'incoming' has no loop use, so should not have back edge uses. 78 System.out.println(incoming); 79 while (System.currentTimeMillis() != 42) { 80 while (Runtime.getRuntime() != null) {} 81 } 82 } 83 84 /// CHECK-START: void Main.loop5(boolean) liveness (after) 85 /// CHECK: <<Arg:z\d+>> ParameterValue liveness:<<ArgLiv:\d+>> ranges:{[<<ArgLiv>>,<<ArgLoopUse2:\d+>>)} uses:[<<ArgUse:\d+>>,<<ArgLoopUse1:\d+>>,<<ArgLoopUse2>>] 86 /// CHECK: InvokeVirtual [{{l\d+}},<<Arg>>] method_name:java.io.PrintStream.println liveness:<<InvokeLiv:\d+>> 87 /// CHECK: Goto liveness:<<GotoLiv1:\d+>> 88 /// CHECK: Goto liveness:<<GotoLiv2:\d+>> 89 /// CHECK: Exit 90 /// CHECK-EVAL: <<InvokeLiv>> == <<ArgUse>> 91 /// CHECK-EVAL: <<GotoLiv1>> < <<GotoLiv2>> 92 /// CHECK-EVAL: <<GotoLiv1>> + 2 == <<ArgLoopUse1>> 93 /// CHECK-EVAL: <<GotoLiv2>> + 2 == <<ArgLoopUse2>> 94 loop5(boolean incoming)95 public static void loop5(boolean incoming) { 96 // 'incoming' must have a use at both back edges. 97 for (long i = System.nanoTime(); i < 42; ++i) { 98 for (long j = System.currentTimeMillis(); j != 42; ++j) { 99 System.out.println(incoming); 100 } 101 } 102 } 103 104 /// CHECK-START: void Main.loop6(boolean) liveness (after) 105 /// CHECK: <<Arg:z\d+>> ParameterValue liveness:<<ArgLiv:\d+>> ranges:{[<<ArgLiv>>,<<ArgLoopUse:\d+>>)} uses:[<<ArgUse:\d+>>,<<ArgLoopUse>>] 106 /// CHECK: InvokeVirtual [{{l\d+}},<<Arg>>] method_name:java.io.PrintStream.println liveness:<<InvokeLiv:\d+>> 107 /// CHECK: Add 108 /// CHECK: Goto liveness:<<GotoLiv1:\d+>> 109 /// CHECK: Add 110 /// CHECK: Goto liveness:<<GotoLiv2:\d+>> 111 /// CHECK: Exit 112 /// CHECK-EVAL: <<InvokeLiv>> == <<ArgUse>> 113 /// CHECK-EVAL: <<GotoLiv1>> < <<GotoLiv2>> 114 /// CHECK-EVAL: <<GotoLiv2>> + 2 == <<ArgLoopUse>> 115 loop6(boolean incoming)116 public static void loop6(boolean incoming) { 117 // 'incoming' must have a use only at the first loop's back edge. 118 for (long i = System.nanoTime(); i < 42; ++i) { 119 System.out.println(incoming); 120 for (long j = System.currentTimeMillis(); j != 42; ++j) { 121 System.out.print(j); // non-empty body 122 } 123 } 124 } 125 126 /// CHECK-START: void Main.loop7(boolean) liveness (after) 127 /// CHECK-DAG: <<Arg:z\d+>> ParameterValue liveness:<<ArgLiv:\d+>> ranges:{[<<ArgLiv>>,<<ArgLoopUse:\d+>>)} uses:[<<ArgUse1:\d+>>,<<ArgUse2:\d+>>,<<ArgLoopUse>>] 128 /// CHECK-DAG: InvokeVirtual [{{l\d+}},<<Arg>>] method_name:java.io.PrintStream.println liveness:<<InvokeLiv:\d+>> 129 /// CHECK-DAG: If [<<Arg>>] liveness:<<IfLiv:\d+>> loop:<<Loop1:B\d+>> 130 /// CHECK-DAG: Goto liveness:<<GotoLiv1:\d+>> loop:<<Loop1>> 131 /// CHECK-DAG: Goto liveness:<<GotoLiv2:\d+>> loop:<<Loop2:B\d+>> 132 /// CHECK-DAG: Exit 133 /// CHECK-EVAL: <<InvokeLiv>> == <<ArgUse1>> 134 /// CHECK-EVAL: <<IfLiv>> + 1 == <<ArgUse2>> 135 /// CHECK-EVAL: <<GotoLiv1>> < <<GotoLiv2>> 136 /// CHECK-EVAL: <<GotoLiv1>> + 2 == <<ArgLoopUse>> 137 // 138 // Loop invariant exit check is hoisted from the loop by peeling. 139 loop7(boolean incoming)140 public static void loop7(boolean incoming) { 141 // 'incoming' must have a use at both back edges. 142 while (Runtime.getRuntime() != null) { 143 System.out.println(incoming); 144 while (incoming) {} 145 System.nanoTime(); // beat back edge splitting 146 } 147 } 148 149 /// CHECK-START: void Main.loop8() liveness (after) 150 /// CHECK-DAG: <<Arg:z\d+>> StaticFieldGet liveness:<<ArgLiv:\d+>> ranges:{[<<ArgLiv>>,<<ArgLoopUse:\d+>>)} uses:[<<ArgUse:\d+>>,<<ArgLoopUse>>] 151 /// CHECK-DAG: If [<<Arg>>] liveness:<<IfLiv:\d+>> loop:<<Loop1:B\d+>> 152 /// CHECK-DAG: Goto liveness:<<GotoLiv1:\d+>> loop:<<Loop1>> 153 /// CHECK-DAG: Goto liveness:<<GotoLiv2:\d+>> loop:<<Loop2:B\d+>> 154 /// CHECK-DAG: Exit 155 /// CHECK-EVAL: <<IfLiv>> + 1 == <<ArgUse>> 156 /// CHECK-EVAL: <<GotoLiv1>> < <<GotoLiv2>> 157 /// CHECK-EVAL: <<GotoLiv1>> + 2 == <<ArgLoopUse>> 158 // 159 // Loop invariant exit check is hoisted from the loop by peeling. 160 loop8()161 public static void loop8() { 162 // 'incoming' must have a use at both back edges. 163 boolean incoming = field; 164 while (Runtime.getRuntime() != null) { 165 System.nanoTime(); // beat pre-header creation 166 while (incoming) {} 167 System.nanoTime(); // beat back edge splitting 168 } 169 } 170 171 $opt$noinline$ensureSideEffects()172 static boolean $opt$noinline$ensureSideEffects() { 173 if (doThrow) throw new Error(""); 174 return true; 175 } 176 177 /// CHECK-START: void Main.loop9() liveness (after) 178 /// CHECK-DAG: <<Arg:z\d+>> StaticFieldGet liveness:<<ArgLiv:\d+>> ranges:{[<<ArgLiv>>,<<ArgUse:\d+>>)} uses:[<<ArgUse>>] 179 /// CHECK-DAG: If [<<Arg>>] liveness:<<IfLiv:\d+>> loop:<<Loop1:B\d+>> 180 /// CHECK-DAG: Goto liveness:<<GotoLiv1:\d+>> loop:<<Loop1>> 181 /// CHECK-DAG: Goto liveness:<<GotoLiv2:\d+>> loop:<<Loop2:B\d+>> 182 /// CHECK-DAG: Exit 183 /// CHECK-EVAL: <<IfLiv>> + 1 == <<ArgUse>> 184 /// CHECK-EVAL: <<GotoLiv1>> < <<GotoLiv2>> 185 // 186 // Loop invariant exit check is hoisted from the loop by peeling. 187 loop9()188 public static void loop9() { 189 // Add some code at entry to avoid having the entry block be a pre header. 190 // This avoids having to create a synthesized block. 191 System.out.println("Enter"); 192 while ($opt$noinline$ensureSideEffects()) { 193 // 'incoming' must only have a use in the inner loop. 194 boolean incoming = field; 195 while (incoming) {} 196 } 197 } 198 main(String[] args)199 public static void main(String[] args) { 200 } 201 202 static boolean field; 203 static boolean doThrow = false; 204 } 205