1 /* 2 * Copyright (C) 2017 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 // Check that we don't generate a select since we don't have a Phi (not even at 19 // the builder stage) since both values are the same. 20 21 /// CHECK-START: int Main.$noinline$testSimpleDiamondSameValue(boolean) builder (after) 22 /// CHECK-NOT: Phi 23 24 /// CHECK-START: int Main.$noinline$testSimpleDiamondSameValue(boolean) select_generator (before) 25 /// CHECK-NOT: Phi 26 27 /// CHECK-START: int Main.$noinline$testSimpleDiamondSameValue(boolean) select_generator (after) 28 /// CHECK-NOT: Phi 29 30 /// CHECK-START: int Main.$noinline$testSimpleDiamondSameValue(boolean) select_generator (after) 31 /// CHECK-NOT: Select $noinline$testSimpleDiamondSameValue(boolean bool_param)32 private static int $noinline$testSimpleDiamondSameValue(boolean bool_param) { 33 int return_value; 34 if (bool_param) { 35 return_value = 10; 36 } else { 37 return_value = 10; 38 } 39 return return_value; 40 } 41 42 // Check that we generate a select for a simple diamond pattern, with different values. 43 44 /// CHECK-START: int Main.$noinline$testSimpleDiamondDifferentValue(boolean) select_generator (before) 45 /// CHECK-DAG: <<Const10:i\d+>> IntConstant 10 46 /// CHECK-DAG: <<Const20:i\d+>> IntConstant 20 47 /// CHECK-DAG: <<Phi:i\d+>> Phi [<<Arg1:i\d+>>,<<Arg2:i\d+>>] 48 /// CHECK-DAG: Return [<<Phi>>] 49 /// CHECK-EVAL: set(["<<Arg1>>","<<Arg2>>"]) == set(["<<Const10>>","<<Const20>>"]) 50 51 /// CHECK-START: int Main.$noinline$testSimpleDiamondDifferentValue(boolean) select_generator (after) 52 /// CHECK-DAG: <<Bool:z\d+>> ParameterValue 53 /// CHECK-DAG: <<Const10:i\d+>> IntConstant 10 54 /// CHECK-DAG: <<Const20:i\d+>> IntConstant 20 55 /// CHECK-DAG: <<Select:i\d+>> Select [<<Const20>>,<<Const10>>,<<Bool>>] 56 /// CHECK-DAG: Return [<<Select>>] $noinline$testSimpleDiamondDifferentValue(boolean bool_param)57 private static int $noinline$testSimpleDiamondDifferentValue(boolean bool_param) { 58 int return_value; 59 if (bool_param) { 60 return_value = 10; 61 } else { 62 return_value = 20; 63 } 64 return return_value; 65 } 66 67 // Check that we don't generate a select since we don't have no Phi (not even at the builder 68 // stage) since all values are the same. 69 70 /// CHECK-START: int Main.$noinline$testDoubleDiamondSameValue(boolean, boolean) builder (after) 71 /// CHECK-NOT: Phi 72 73 /// CHECK-START: int Main.$noinline$testDoubleDiamondSameValue(boolean, boolean) select_generator (before) 74 /// CHECK-NOT: Phi 75 76 /// CHECK-START: int Main.$noinline$testDoubleDiamondSameValue(boolean, boolean) select_generator (after) 77 /// CHECK-NOT: Phi 78 79 /// CHECK-START: int Main.$noinline$testDoubleDiamondSameValue(boolean, boolean) select_generator (after) 80 /// CHECK-NOT: Select $noinline$testDoubleDiamondSameValue(boolean bool_param_1, boolean bool_param_2)81 private static int $noinline$testDoubleDiamondSameValue(boolean bool_param_1, boolean bool_param_2) { 82 int return_value; 83 if (bool_param_1) { 84 return_value = 10; 85 } else { 86 if (bool_param_2) { 87 return_value = 10; 88 } else { 89 return_value = 10; 90 } 91 } 92 return return_value; 93 } 94 95 // Check that we generate a select for a double diamond pattern, with a different value in the outer branch. 96 97 /// CHECK-START: int Main.$noinline$testDoubleDiamondSameValueButNotAllOuter(boolean, boolean) select_generator (before) 98 /// CHECK-DAG: <<Const10:i\d+>> IntConstant 10 99 /// CHECK-DAG: <<Const20:i\d+>> IntConstant 20 100 /// CHECK-DAG: <<Phi:i\d+>> Phi [<<Arg1:i\d+>>,<<Arg2:i\d+>>,<<Arg3:i\d+>>] 101 /// CHECK-DAG: Return [<<Phi>>] 102 /// CHECK-EVAL: set(["<<Arg1>>","<<Arg2>>","<<Arg3>>"]) == set(["<<Const10>>","<<Const20>>","<<Const20>>"]) 103 104 /// CHECK-START: int Main.$noinline$testDoubleDiamondSameValueButNotAllOuter(boolean, boolean) select_generator (after) 105 /// CHECK-DAG: <<Bool1:z\d+>> ParameterValue 106 /// CHECK-DAG: <<Bool2:z\d+>> ParameterValue 107 /// CHECK-DAG: <<Const10:i\d+>> IntConstant 10 108 /// CHECK-DAG: <<Const20:i\d+>> IntConstant 20 109 /// CHECK-DAG: <<Select:i\d+>> Select [<<Const20>>,<<Const20>>,<<Bool2>>] 110 /// CHECK-DAG: <<Select2:i\d+>> Select [<<Select>>,<<Const10>>,<<Bool1>>] 111 /// CHECK-DAG: Return [<<Select2>>] $noinline$testDoubleDiamondSameValueButNotAllOuter(boolean bool_param_1, boolean bool_param_2)112 private static int $noinline$testDoubleDiamondSameValueButNotAllOuter(boolean bool_param_1, boolean bool_param_2) { 113 int return_value; 114 if (bool_param_1) { 115 return_value = 10; 116 } else { 117 if (bool_param_2) { 118 return_value = 20; 119 } else { 120 return_value = 20; 121 } 122 } 123 return return_value; 124 } 125 126 // Check that we generate a select for a double diamond pattern, with a different value in the inner branch. 127 128 /// CHECK-START: int Main.$noinline$testDoubleDiamondSameValueButNotAllInner(boolean, boolean) select_generator (before) 129 /// CHECK-DAG: <<Const10:i\d+>> IntConstant 10 130 /// CHECK-DAG: <<Const20:i\d+>> IntConstant 20 131 /// CHECK-DAG: <<Phi:i\d+>> Phi [<<Arg1:i\d+>>,<<Arg2:i\d+>>,<<Arg3:i\d+>>] 132 /// CHECK-DAG: Return [<<Phi>>] 133 /// CHECK-EVAL: set(["<<Arg1>>","<<Arg2>>","<<Arg3>>"]) == set(["<<Const10>>","<<Const20>>","<<Const20>>"]) 134 135 /// CHECK-START: int Main.$noinline$testDoubleDiamondSameValueButNotAllInner(boolean, boolean) select_generator (after) 136 /// CHECK-DAG: <<Bool1:z\d+>> ParameterValue 137 /// CHECK-DAG: <<Bool2:z\d+>> ParameterValue 138 /// CHECK-DAG: <<Const10:i\d+>> IntConstant 10 139 /// CHECK-DAG: <<Const20:i\d+>> IntConstant 20 140 /// CHECK-DAG: <<Select:i\d+>> Select [<<Const20>>,<<Const10>>,<<Bool2>>] 141 /// CHECK-DAG: <<Select2:i\d+>> Select [<<Select>>,<<Const20>>,<<Bool1>>] 142 /// CHECK-DAG: Return [<<Select2>>] $noinline$testDoubleDiamondSameValueButNotAllInner(boolean bool_param_1, boolean bool_param_2)143 private static int $noinline$testDoubleDiamondSameValueButNotAllInner(boolean bool_param_1, boolean bool_param_2) { 144 int return_value; 145 if (bool_param_1) { 146 return_value = 20; 147 } else { 148 if (bool_param_2) { 149 return_value = 10; 150 } else { 151 return_value = 20; 152 } 153 } 154 return return_value; 155 } 156 157 // Check that we generate a select for a double diamond pattern, with a all different values. 158 159 /// CHECK-START: int Main.$noinline$testDoubleDiamondDifferentValue(boolean, boolean) select_generator (before) 160 /// CHECK-DAG: <<Const10:i\d+>> IntConstant 10 161 /// CHECK-DAG: <<Const20:i\d+>> IntConstant 20 162 /// CHECK-DAG: <<Const30:i\d+>> IntConstant 30 163 /// CHECK-DAG: <<Phi:i\d+>> Phi [<<Arg1:i\d+>>,<<Arg2:i\d+>>,<<Arg3:i\d+>>] 164 /// CHECK-DAG: Return [<<Phi>>] 165 /// CHECK-EVAL: set(["<<Arg1>>","<<Arg2>>","<<Arg3>>"]) == set(["<<Const10>>","<<Const20>>","<<Const30>>"]) 166 167 /// CHECK-START: int Main.$noinline$testDoubleDiamondDifferentValue(boolean, boolean) select_generator (after) 168 /// CHECK-DAG: <<Bool1:z\d+>> ParameterValue 169 /// CHECK-DAG: <<Bool2:z\d+>> ParameterValue 170 /// CHECK-DAG: <<Const10:i\d+>> IntConstant 10 171 /// CHECK-DAG: <<Const20:i\d+>> IntConstant 20 172 /// CHECK-DAG: <<Const30:i\d+>> IntConstant 30 173 /// CHECK-DAG: <<Select:i\d+>> Select [<<Const30>>,<<Const20>>,<<Bool2>>] 174 /// CHECK-DAG: <<Select2:i\d+>> Select [<<Select>>,<<Const10>>,<<Bool1>>] 175 /// CHECK-DAG: Return [<<Select2>>] $noinline$testDoubleDiamondDifferentValue(boolean bool_param_1, boolean bool_param_2)176 private static int $noinline$testDoubleDiamondDifferentValue(boolean bool_param_1, boolean bool_param_2) { 177 int return_value; 178 if (bool_param_1) { 179 return_value = 10; 180 } else { 181 if (bool_param_2) { 182 return_value = 20; 183 } else { 184 return_value = 30; 185 } 186 } 187 return return_value; 188 } 189 assertEquals(int expected, int actual)190 private static void assertEquals(int expected, int actual) { 191 if (expected != actual) { 192 throw new AssertionError("Expected " + expected + " got " + actual); 193 } 194 } 195 196 // Check that we generate a select, which we collapse into a single return. 197 198 /// CHECK-START: int Main.$noinline$testSimpleDiamondSameValueWithReturn(boolean) builder (after) 199 /// CHECK: <<Const10:i\d+>> IntConstant 10 200 /// CHECK: Return [<<Const10>>] 201 /// CHECK: Return [<<Const10>>] 202 203 /// CHECK-START: int Main.$noinline$testSimpleDiamondSameValueWithReturn(boolean) select_generator (after) 204 /// CHECK-DAG: <<Bool:z\d+>> ParameterValue 205 /// CHECK-DAG: <<Const10:i\d+>> IntConstant 10 206 /// CHECK-DAG: <<Select:i\d+>> Select [<<Const10>>,<<Const10>>,<<Bool>>] 207 208 /// CHECK-START: int Main.$noinline$testSimpleDiamondSameValueWithReturn(boolean) instruction_simplifier$after_gvn (after) 209 /// CHECK: <<Const10:i\d+>> IntConstant 10 210 /// CHECK: Return [<<Const10>>] 211 212 /// CHECK-START: int Main.$noinline$testSimpleDiamondSameValueWithReturn(boolean) instruction_simplifier$after_gvn (after) 213 /// CHECK: Return 214 /// CHECK-NOT: Return $noinline$testSimpleDiamondSameValueWithReturn(boolean bool_param)215 private static int $noinline$testSimpleDiamondSameValueWithReturn(boolean bool_param) { 216 if (bool_param) { 217 return 10; 218 } else { 219 return 10; 220 } 221 } 222 223 // Same as testSimpleDiamondDifferentValue, but branches return. 224 225 /// CHECK-START: int Main.$noinline$testSimpleDiamondDifferentValueWithReturn(boolean) select_generator (before) 226 /// CHECK-DAG: <<Const10:i\d+>> IntConstant 10 227 /// CHECK-DAG: <<Const20:i\d+>> IntConstant 20 228 /// CHECK-DAG: Return [<<Const10>>] 229 /// CHECK-DAG: Return [<<Const20>>] 230 231 /// CHECK-START: int Main.$noinline$testSimpleDiamondDifferentValueWithReturn(boolean) select_generator (after) 232 /// CHECK-DAG: <<Bool:z\d+>> ParameterValue 233 /// CHECK-DAG: <<Const10:i\d+>> IntConstant 10 234 /// CHECK-DAG: <<Const20:i\d+>> IntConstant 20 235 /// CHECK-DAG: <<Select:i\d+>> Select [<<Const20>>,<<Const10>>,<<Bool>>] 236 /// CHECK-DAG: Return [<<Select>>] $noinline$testSimpleDiamondDifferentValueWithReturn(boolean bool_param)237 private static int $noinline$testSimpleDiamondDifferentValueWithReturn(boolean bool_param) { 238 if (bool_param) { 239 return 10; 240 } else { 241 return 20; 242 } 243 } 244 245 // Check that we generate a select, which we collapse into a single return. 246 247 /// CHECK-START: int Main.$noinline$testDoubleDiamondSameValueWithReturn(boolean, boolean) builder (after) 248 /// CHECK: <<Const10:i\d+>> IntConstant 10 249 /// CHECK: Return [<<Const10>>] 250 /// CHECK: Return [<<Const10>>] 251 252 /// CHECK-START: int Main.$noinline$testDoubleDiamondSameValueWithReturn(boolean, boolean) select_generator (after) 253 /// CHECK-DAG: <<Bool1:z\d+>> ParameterValue 254 /// CHECK-DAG: <<Bool2:z\d+>> ParameterValue 255 /// CHECK-DAG: <<Const10:i\d+>> IntConstant 10 256 /// CHECK-DAG: <<Select:i\d+>> Select [<<Const10>>,<<Const10>>,<<Bool2>>] 257 /// CHECK-DAG: <<Select2:i\d+>> Select [<<Select>>,<<Const10>>,<<Bool1>>] 258 /// CHECK-DAG: Return [<<Select2>>] 259 260 /// CHECK-START: int Main.$noinline$testDoubleDiamondSameValueWithReturn(boolean, boolean) instruction_simplifier$after_gvn (after) 261 /// CHECK: <<Const10:i\d+>> IntConstant 10 262 /// CHECK: Return [<<Const10>>] 263 264 /// CHECK-START: int Main.$noinline$testDoubleDiamondSameValueWithReturn(boolean, boolean) instruction_simplifier$after_gvn (after) 265 /// CHECK: Return 266 /// CHECK-NOT: Return $noinline$testDoubleDiamondSameValueWithReturn(boolean bool_param_1, boolean bool_param_2)267 private static int $noinline$testDoubleDiamondSameValueWithReturn(boolean bool_param_1, boolean bool_param_2) { 268 if (bool_param_1) { 269 return 10; 270 } else { 271 if (bool_param_2) { 272 return 10; 273 } else { 274 return 10; 275 } 276 } 277 } 278 279 // Same as testDoubleDiamondSameValueButNotAllOuter, but branches return. 280 281 /// CHECK-START: int Main.$noinline$testDoubleDiamondSameValueButNotAllOuterWithReturn(boolean, boolean) select_generator (before) 282 /// CHECK-DAG: <<Const10:i\d+>> IntConstant 10 283 /// CHECK-DAG: <<Const20:i\d+>> IntConstant 20 284 /// CHECK-DAG: Return [<<Const10>>] 285 /// CHECK-DAG: Return [<<Const20>>] 286 /// CHECK-DAG: Return [<<Const20>>] 287 288 // Note that we have 3 returns as D8 only merges when the line positions are equal. 289 /// CHECK-START: int Main.$noinline$testDoubleDiamondSameValueButNotAllOuterWithReturn(boolean, boolean) select_generator (before) 290 /// CHECK: Return 291 /// CHECK: Return 292 /// CHECK: Return 293 294 /// CHECK-START: int Main.$noinline$testDoubleDiamondSameValueButNotAllOuterWithReturn(boolean, boolean) select_generator (after) 295 /// CHECK-DAG: <<Bool1:z\d+>> ParameterValue 296 /// CHECK-DAG: <<Bool2:z\d+>> ParameterValue 297 /// CHECK-DAG: <<Const10:i\d+>> IntConstant 10 298 /// CHECK-DAG: <<Const20:i\d+>> IntConstant 20 299 /// CHECK-DAG: <<Select:i\d+>> Select [<<Const20>>,<<Const20>>,<<Bool2>>] 300 /// CHECK-DAG: <<Select2:i\d+>> Select [<<Select>>,<<Const10>>,<<Bool1>>] 301 /// CHECK-DAG: Return [<<Select2>>] $noinline$testDoubleDiamondSameValueButNotAllOuterWithReturn(boolean bool_param_1, boolean bool_param_2)302 private static int $noinline$testDoubleDiamondSameValueButNotAllOuterWithReturn(boolean bool_param_1, boolean bool_param_2) { 303 if (bool_param_1) { 304 return 10; 305 } else { 306 if (bool_param_2) { 307 return 20; 308 } else { 309 return 20; 310 } 311 } 312 } 313 314 // Same as testDoubleDiamondSameValueButNotAllInner, but branches return. 315 316 /// CHECK-START: int Main.$noinline$testDoubleDiamondSameValueButNotAllInnerWithReturn(boolean, boolean) select_generator (before) 317 /// CHECK-DAG: <<Const10:i\d+>> IntConstant 10 318 /// CHECK-DAG: <<Const20:i\d+>> IntConstant 20 319 /// CHECK-DAG: Return [<<Const10>>] 320 /// CHECK-DAG: Return [<<Const20>>] 321 /// CHECK-DAG: Return [<<Const20>>] 322 323 /// CHECK-START: int Main.$noinline$testDoubleDiamondSameValueButNotAllInnerWithReturn(boolean, boolean) select_generator (after) 324 /// CHECK-DAG: <<Bool1:z\d+>> ParameterValue 325 /// CHECK-DAG: <<Bool2:z\d+>> ParameterValue 326 /// CHECK-DAG: <<Const10:i\d+>> IntConstant 10 327 /// CHECK-DAG: <<Const20:i\d+>> IntConstant 20 328 /// CHECK-DAG: <<Select:i\d+>> Select [<<Const20>>,<<Const10>>,<<Bool2>>] 329 /// CHECK-DAG: <<Select2:i\d+>> Select [<<Select>>,<<Const20>>,<<Bool1>>] 330 /// CHECK-DAG: Return [<<Select2>>] $noinline$testDoubleDiamondSameValueButNotAllInnerWithReturn(boolean bool_param_1, boolean bool_param_2)331 private static int $noinline$testDoubleDiamondSameValueButNotAllInnerWithReturn(boolean bool_param_1, boolean bool_param_2) { 332 if (bool_param_1) { 333 return 20; 334 } else { 335 if (bool_param_2) { 336 return 10; 337 } else { 338 return 20; 339 } 340 } 341 } 342 343 // Same as testDoubleDiamondDifferentValue, but branches return. 344 345 /// CHECK-START: int Main.$noinline$testDoubleDiamondDifferentValueWithReturn(boolean, boolean) select_generator (before) 346 /// CHECK-DAG: <<Const10:i\d+>> IntConstant 10 347 /// CHECK-DAG: <<Const20:i\d+>> IntConstant 20 348 /// CHECK-DAG: <<Const30:i\d+>> IntConstant 30 349 /// CHECK-DAG: Return [<<Const10>>] 350 /// CHECK-DAG: Return [<<Const20>>] 351 /// CHECK-DAG: Return [<<Const30>>] 352 353 /// CHECK-START: int Main.$noinline$testDoubleDiamondDifferentValueWithReturn(boolean, boolean) select_generator (after) 354 /// CHECK-DAG: <<Bool1:z\d+>> ParameterValue 355 /// CHECK-DAG: <<Bool2:z\d+>> ParameterValue 356 /// CHECK-DAG: <<Const10:i\d+>> IntConstant 10 357 /// CHECK-DAG: <<Const20:i\d+>> IntConstant 20 358 /// CHECK-DAG: <<Const30:i\d+>> IntConstant 30 359 /// CHECK-DAG: <<Select:i\d+>> Select [<<Const30>>,<<Const20>>,<<Bool2>>] 360 /// CHECK-DAG: <<Select2:i\d+>> Select [<<Select>>,<<Const10>>,<<Bool1>>] 361 /// CHECK-DAG: Return [<<Select2>>] $noinline$testDoubleDiamondDifferentValueWithReturn(boolean bool_param_1, boolean bool_param_2)362 private static int $noinline$testDoubleDiamondDifferentValueWithReturn(boolean bool_param_1, boolean bool_param_2) { 363 if (bool_param_1) { 364 return 10; 365 } else { 366 if (bool_param_2) { 367 return 20; 368 } else { 369 return 30; 370 } 371 } 372 } 373 main(String[] args)374 public static void main(String[] args) throws Throwable { 375 // With phi 376 assertEquals(10, $noinline$testSimpleDiamondSameValue(false)); 377 assertEquals(20, $noinline$testSimpleDiamondDifferentValue(false)); 378 assertEquals(10, $noinline$testDoubleDiamondSameValue(false, false)); 379 assertEquals(20, $noinline$testDoubleDiamondSameValueButNotAllOuter(false, false)); 380 assertEquals(20, $noinline$testDoubleDiamondSameValueButNotAllInner(false, false)); 381 assertEquals(30, $noinline$testDoubleDiamondDifferentValue(false, false)); 382 383 // With return 384 assertEquals(10, $noinline$testSimpleDiamondSameValueWithReturn(false)); 385 assertEquals(20, $noinline$testSimpleDiamondDifferentValueWithReturn(false)); 386 assertEquals(10, $noinline$testDoubleDiamondSameValueWithReturn(false, false)); 387 assertEquals(20, $noinline$testDoubleDiamondSameValueButNotAllOuterWithReturn(false, false)); 388 assertEquals(20, $noinline$testDoubleDiamondSameValueButNotAllInnerWithReturn(false, false)); 389 assertEquals(30, $noinline$testDoubleDiamondDifferentValueWithReturn(false, false)); 390 } 391 } 392