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