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