1 /* 2 * Copyright (C) 2016 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 public class Main { 18 main(String[] args)19 public static void main(String[] args) { 20 testNoInline(args); 21 System.out.println(staticField); 22 testInline(args); 23 System.out.println(staticField); 24 testNonConstantInputs(args); 25 System.out.println(staticField); 26 testNonConstantEqual(args); 27 System.out.println(staticField); 28 testGreaterCondition(args); 29 System.out.println(staticField); 30 testSwitch(args); 31 System.out.println(staticField); 32 testFP(args); 33 System.out.println(staticField); 34 } 35 36 // Test when a condition is the input of the if. 37 38 /// CHECK-START: void Main.testNoInline(java.lang.String[]) dead_code_elimination$initial (before) 39 /// CHECK: <<Const0:i\d+>> IntConstant 0 40 /// CHECK: If 41 /// CHECK: <<Phi:i\d+>> Phi 42 /// CHECK: <<Equal:z\d+>> Equal [<<Phi>>,<<Const0>>] 43 /// CHECK: If [<<Equal>>] 44 45 /// CHECK-START: void Main.testNoInline(java.lang.String[]) dead_code_elimination$initial (after) 46 /// CHECK: If 47 /// CHECK-NOT: Phi 48 /// CHECK-NOT: Equal 49 /// CHECK-NOT: If testNoInline(String[] args)50 public static void testNoInline(String[] args) { 51 boolean myVar = false; 52 if (args.length == 42) { 53 myVar = true; 54 } else { 55 staticField = 32; 56 myVar = false; 57 } 58 if (myVar) { 59 staticField = 12; 60 } else { 61 staticField = 54; 62 } 63 } 64 65 // Test when the phi is the input of the if. 66 67 /// CHECK-START: void Main.testInline(java.lang.String[]) dead_code_elimination$after_inlining (before) 68 /// CHECK-DAG: <<Const0:i\d+>> IntConstant 0 69 /// CHECK-DAG: If 70 /// CHECK-DAG: <<Phi:i\d+>> Phi 71 /// CHECK-DAG: If [<<Phi>>] 72 73 /// CHECK-START: void Main.testInline(java.lang.String[]) dead_code_elimination$after_inlining (after) 74 /// CHECK: If 75 /// CHECK-NOT: Phi 76 /// CHECK-NOT: If testInline(String[] args)77 public static void testInline(String[] args) { 78 boolean myVar = $inline$doTest(args); 79 if (myVar) { 80 staticField = 12; 81 } else { 82 staticField = 54; 83 } 84 } 85 $inline$doTest(String[] args)86 public static boolean $inline$doTest(String[] args) { 87 boolean myVar; 88 if (args.length == 42) { 89 myVar = true; 90 } else { 91 staticField = 32; 92 myVar = false; 93 } 94 return myVar; 95 } 96 97 // Test when one input is not a constant. We can only optimize the constant input. 98 99 /// CHECK-START: void Main.testNonConstantInputs(java.lang.String[]) dead_code_elimination$initial (before) 100 /// CHECK-DAG: <<Const34:i\d+>> IntConstant 34 101 /// CHECK-DAG: <<Const42:i\d+>> IntConstant 42 102 /// CHECK-DAG: If 103 /// CHECK-DAG: <<StaticFieldGet:i\d+>> StaticFieldGet 104 /// CHECK-DAG: <<Phi:i\d+>> Phi [<<Const34>>,<<StaticFieldGet>>] 105 /// CHECK-DAG: <<NotEqual:z\d+>> NotEqual [<<Phi>>,<<Const42>>] 106 /// CHECK-DAG: If [<<NotEqual>>] 107 108 /// CHECK-START: void Main.testNonConstantInputs(java.lang.String[]) dead_code_elimination$initial (after) 109 /// CHECK-DAG: <<Const42:i\d+>> IntConstant 42 110 /// CHECK-DAG: If 111 /// CHECK-DAG: <<StaticFieldGet:i\d+>> StaticFieldGet 112 /// CHECK-NOT: Phi 113 /// CHECK-DAG: <<NotEqual:z\d+>> NotEqual [<<StaticFieldGet>>,<<Const42>>] 114 /// CHECK-DAG: If [<<NotEqual>>] testNonConstantInputs(String[] args)115 public static void testNonConstantInputs(String[] args) { 116 int a = 42; 117 if (args.length == 42) { 118 a = 34; 119 } else { 120 staticField = 32; 121 a = otherStaticField; 122 } 123 if (a == 42) { 124 staticField = 12; 125 } else { 126 staticField = 54; 127 } 128 } 129 130 // Test with a condition. 131 132 /// CHECK-START: void Main.testGreaterCondition(java.lang.String[]) dead_code_elimination$initial (before) 133 /// CHECK-DAG: <<Const34:i\d+>> IntConstant 34 134 /// CHECK-DAG: <<Const22:i\d+>> IntConstant 22 135 /// CHECK-DAG: <<Const25:i\d+>> IntConstant 25 136 /// CHECK-DAG: If 137 /// CHECK-DAG: <<Phi:i\d+>> Phi [<<Const34>>,<<Const22>>] 138 /// CHECK-DAG: <<GE:z\d+>> GreaterThanOrEqual [<<Phi>>,<<Const25>>] 139 /// CHECK-DAG: If [<<GE>>] 140 141 /// CHECK-START: void Main.testGreaterCondition(java.lang.String[]) dead_code_elimination$initial (after) 142 /// CHECK-DAG: If 143 /// CHECK-NOT: Phi 144 /// CHECK-NOT: GreaterThanOrEqual 145 /// CHECK-NOT: If testGreaterCondition(String[] args)146 public static void testGreaterCondition(String[] args) { 147 int a = 42; 148 if (args.length == 42) { 149 a = 34; 150 } else { 151 staticField = 32; 152 a = 22; 153 } 154 if (a < 25) { 155 staticField = 12; 156 } else { 157 staticField = 54; 158 } 159 } 160 161 // Test when comparing non constants. 162 163 /// CHECK-START: void Main.testNonConstantEqual(java.lang.String[]) dead_code_elimination$initial (before) 164 /// CHECK-DAG: <<Const34:i\d+>> IntConstant 34 165 /// CHECK-DAG: <<Const42:i\d+>> IntConstant 42 166 /// CHECK-DAG: If 167 /// CHECK-DAG: <<StaticFieldGet:i\d+>> StaticFieldGet 168 /// CHECK-DAG: <<Phi:i\d+>> Phi [<<Const34>>,<<StaticFieldGet>>] 169 /// CHECK-DAG: <<NotEqual:z\d+>> NotEqual [<<Phi>>,<<StaticFieldGet>>] 170 /// CHECK-DAG: If [<<NotEqual>>] 171 172 /// CHECK-START: void Main.testNonConstantEqual(java.lang.String[]) dead_code_elimination$initial (after) 173 /// CHECK-DAG: <<Const34:i\d+>> IntConstant 34 174 /// CHECK-DAG: If 175 /// CHECK-DAG: <<StaticFieldGet:i\d+>> StaticFieldGet 176 /// CHECK-NOT: Phi 177 /// CHECK-DAG: <<NotEqual:z\d+>> NotEqual [<<Const34>>,<<StaticFieldGet>>] 178 /// CHECK-DAG: If [<<NotEqual>>] testNonConstantEqual(String[] args)179 public static void testNonConstantEqual(String[] args) { 180 int a = 42; 181 int b = otherStaticField; 182 if (args.length == 42) { 183 a = 34; 184 } else { 185 staticField = 32; 186 a = b; 187 } 188 if (a == b) { 189 staticField = 12; 190 } else { 191 staticField = 54; 192 } 193 } 194 195 // Make sure we don't "simplify" a loop and potentially turn it into 196 // an irreducible loop. The suspend check at the loop header prevents 197 // us from doing the simplification. 198 199 /// CHECK-START: void Main.testLoop(boolean) disassembly (after) 200 /// CHECK-DAG: SuspendCheck 201 /// CHECK: irreducible:false 202 /// CHECK-NOT: irreducible:true testLoop(boolean c)203 public static void testLoop(boolean c) { 204 while (true) { 205 if (c) { 206 if ($noinline$foo()) return; 207 c = false; 208 } else { 209 $noinline$foo(); 210 c = true; 211 } 212 } 213 } 214 $noinline$foo()215 static boolean $noinline$foo() { 216 if (doThrow) throw new Error(""); 217 return true; 218 } 219 220 /// CHECK-START: void Main.testSwitch(java.lang.String[]) dead_code_elimination$initial (before) 221 /// CHECK: If 222 /// CHECK: If 223 /// CHECK: If 224 225 /// CHECK-START: void Main.testSwitch(java.lang.String[]) dead_code_elimination$initial (after) 226 /// CHECK: If 227 /// CHECK: If 228 /// CHECK-NOT: If testSwitch(String[] args)229 public static void testSwitch(String[] args) { 230 boolean cond = false; 231 switch (args.length) { 232 case 42: 233 staticField = 11; 234 cond = true; 235 break; 236 case 43: 237 staticField = 33; 238 cond = true; 239 break; 240 default: 241 cond = false; 242 break; 243 } 244 if (cond) { 245 // Redirect case 42 and 43 here. 246 staticField = 2; 247 } 248 // Redirect default here. 249 } 250 251 /// CHECK-START: void Main.testFP(java.lang.String[]) dead_code_elimination$initial (before) 252 /// CHECK: If 253 /// CHECK: If 254 255 /// CHECK-START: void Main.testFP(java.lang.String[]) dead_code_elimination$initial (after) 256 /// CHECK: If 257 /// CHECK: If testFP(String[] args)258 public static void testFP(String[] args) { 259 float f = 2.2f; 260 float nan = $noinline$getNaN(); 261 if (args.length == 42) { 262 f = 4.3f; 263 } else { 264 staticField = 33; 265 f = nan; 266 } 267 if (f == nan) { 268 staticField = 5; 269 } 270 } 271 272 // No inline variant to avoid having the compiler see it's a NaN. $noinline$getNaN()273 static float $noinline$getNaN() { 274 if (doThrow) throw new Error(""); 275 return Float.NaN; 276 } 277 278 static boolean doThrow; 279 static int staticField; 280 static int otherStaticField; 281 } 282