1 /* 2 * Copyright (C) 2018 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 * Functional tests for detecting min/max. 19 */ 20 public class Main { 21 22 // 23 // Direct intrinsics. 24 // 25 26 /// CHECK-START: int Main.minI(int) instruction_simplifier (before) 27 /// CHECK-DAG: <<Par:i\d+>> ParameterValue 28 /// CHECK-DAG: <<Con:i\d+>> IntConstant 20 29 /// CHECK-DAG: <<Min:i\d+>> InvokeStaticOrDirect [<<Par>>,<<Con>>] intrinsic:MathMinIntInt 30 /// CHECK-DAG: Return [<<Min>>] 31 // 32 /// CHECK-START: int Main.minI(int) instruction_simplifier (after) 33 /// CHECK-DAG: <<Par:i\d+>> ParameterValue 34 /// CHECK-DAG: <<Con:i\d+>> IntConstant 20 35 /// CHECK-DAG: <<Min:i\d+>> Min [<<Par>>,<<Con>>] 36 /// CHECK-DAG: Return [<<Min>>] 37 // 38 /// CHECK-START: int Main.minI(int) instruction_simplifier (after) 39 /// CHECK-NOT: InvokeStaticOrDirect 40 // 41 /// CHECK-START-ARM64: int Main.minI(int) disassembly (after) 42 /// CHECK-NOT: mov {{w\d+}}, #0x14 43 /// CHECK: cmp {{w\d+}}, #0x14 44 // Check that the constant generation was handled by VIXL. 45 /// CHECK: mov w16, #0x14 46 /// CHECK: csel {{w\d+}}, {{w\d+}}, w16, lt minI(int a)47 public static int minI(int a) { 48 return Math.min(a, 20); 49 } 50 51 /// CHECK-START: long Main.minL(long) instruction_simplifier (before) 52 /// CHECK-DAG: <<Par:j\d+>> ParameterValue 53 /// CHECK-DAG: <<Con:j\d+>> LongConstant 20 54 /// CHECK-DAG: <<Min:j\d+>> InvokeStaticOrDirect [<<Par>>,<<Con>>] intrinsic:MathMinLongLong 55 /// CHECK-DAG: Return [<<Min>>] 56 // 57 /// CHECK-START: long Main.minL(long) instruction_simplifier (after) 58 /// CHECK-DAG: <<Par:j\d+>> ParameterValue 59 /// CHECK-DAG: <<Con:j\d+>> LongConstant 20 60 /// CHECK-DAG: <<Min:j\d+>> Min [<<Par>>,<<Con>>] 61 /// CHECK-DAG: Return [<<Min>>] 62 // 63 /// CHECK-START: long Main.minL(long) instruction_simplifier (after) 64 /// CHECK-NOT: InvokeStaticOrDirect 65 // 66 /// CHECK-START-ARM64: long Main.minL(long) disassembly (after) 67 /// CHECK-NOT: mov {{x\d+}}, #0x14 68 /// CHECK: cmp {{x\d+}}, #0x14 69 // Check that the constant generation was handled by VIXL. 70 /// CHECK: mov x16, #0x14 71 /// CHECK: csel {{x\d+}}, {{x\d+}}, x16, lt minL(long a)72 public static long minL(long a) { 73 return Math.min(a, 20L); 74 } 75 76 /// CHECK-START: int Main.maxI(int) instruction_simplifier (before) 77 /// CHECK-DAG: <<Par:i\d+>> ParameterValue 78 /// CHECK-DAG: <<Con:i\d+>> IntConstant 20 79 /// CHECK-DAG: <<Max:i\d+>> InvokeStaticOrDirect [<<Par>>,<<Con>>] intrinsic:MathMaxIntInt 80 /// CHECK-DAG: Return [<<Max>>] 81 // 82 /// CHECK-START: int Main.maxI(int) instruction_simplifier (after) 83 /// CHECK-DAG: <<Par:i\d+>> ParameterValue 84 /// CHECK-DAG: <<Con:i\d+>> IntConstant 20 85 /// CHECK-DAG: <<Max:i\d+>> Max [<<Par>>,<<Con>>] 86 /// CHECK-DAG: Return [<<Max>>] 87 // 88 /// CHECK-START: int Main.maxI(int) instruction_simplifier (after) 89 /// CHECK-NOT: InvokeStaticOrDirect 90 // 91 /// CHECK-START-ARM64: int Main.maxI(int) disassembly (after) 92 /// CHECK-NOT: mov {{w\d+}}, #0x14 93 /// CHECK: cmp {{w\d+}}, #0x14 94 // Check that the constant generation was handled by VIXL. 95 /// CHECK: mov w16, #0x14 96 /// CHECK: csel {{w\d+}}, {{w\d+}}, w16, gt maxI(int a)97 public static int maxI(int a) { 98 return Math.max(a, 20); 99 } 100 101 /// CHECK-START: long Main.maxL(long) instruction_simplifier (before) 102 /// CHECK-DAG: <<Par:j\d+>> ParameterValue 103 /// CHECK-DAG: <<Con:j\d+>> LongConstant 20 104 /// CHECK-DAG: <<Max:j\d+>> InvokeStaticOrDirect [<<Par>>,<<Con>>] intrinsic:MathMaxLongLong 105 /// CHECK-DAG: Return [<<Max>>] 106 // 107 /// CHECK-START: long Main.maxL(long) instruction_simplifier (after) 108 /// CHECK-DAG: <<Par:j\d+>> ParameterValue 109 /// CHECK-DAG: <<Con:j\d+>> LongConstant 20 110 /// CHECK-DAG: <<Max:j\d+>> Max [<<Par>>,<<Con>>] 111 /// CHECK-DAG: Return [<<Max>>] 112 // 113 /// CHECK-START: long Main.maxL(long) instruction_simplifier (after) 114 /// CHECK-NOT: InvokeStaticOrDirect 115 // 116 /// CHECK-START-ARM64: long Main.maxL(long) disassembly (after) 117 /// CHECK-NOT: mov {{x\d+}}, #0x14 118 /// CHECK: cmp {{x\d+}}, #0x14 119 // Check that the constant generation was handled by VIXL. 120 /// CHECK: mov x16, #0x14 121 /// CHECK: csel {{x\d+}}, {{x\d+}}, x16, gt maxL(long a)122 public static long maxL(long a) { 123 return Math.max(a, 20L); 124 } 125 126 // 127 // Special Cases 128 // 129 130 /// CHECK-START-ARM64: int Main.minIntConstantZero(int) disassembly (after) 131 /// CHECK-NOT: InvokeStaticOrDirect 132 /// CHECK-NOT: mov {{w\d+}}, #0x0 133 /// CHECK: cmp {{w\d+}}, #0x0 (0) 134 /// CHECK: csel {{w\d+}}, {{w\d+}}, wzr, lt 135 /// CHECK: ret minIntConstantZero(int a)136 public static int minIntConstantZero(int a) { 137 return Math.min(a, 0); 138 } 139 140 /// CHECK-START-ARM64: int Main.minIntConstantOne(int) disassembly (after) 141 /// CHECK-NOT: InvokeStaticOrDirect 142 /// CHECK-NOT: mov {{w\d+}}, #0x1 143 /// CHECK: cmp {{w\d+}}, #0x1 (1) 144 /// CHECK: csinc {{w\d+}}, {{w\d+}}, wzr, lt 145 /// CHECK: ret minIntConstantOne(int a)146 public static int minIntConstantOne(int a) { 147 return Math.min(a, 1); 148 } 149 150 /// CHECK-START-ARM64: int Main.minIntConstantMinusOne(int) disassembly (after) 151 /// CHECK-NOT: InvokeStaticOrDirect 152 /// CHECK-NOT: mov {{w\d+}}, #0xffffffff 153 /// CHECK: cmn {{w\d+}}, #0x1 (1) 154 /// CHECK: csinv {{w\d+}}, {{w\d+}}, wzr, lt 155 /// CHECK: ret minIntConstantMinusOne(int a)156 public static int minIntConstantMinusOne(int a) { 157 return Math.min(a, -1); 158 } 159 160 /// CHECK-START-ARM64: long Main.minLongConstantZero(long) disassembly (after) 161 /// CHECK-NOT: InvokeStaticOrDirect 162 /// CHECK-NOT: mov {{x\d+}}, #0x0 163 /// CHECK: cmp {{x\d+}}, #0x0 (0) 164 /// CHECK: csel {{x\d+}}, {{x\d+}}, xzr, lt 165 /// CHECK: ret minLongConstantZero(long a)166 public static long minLongConstantZero(long a) { 167 return Math.min(a, 0L); 168 } 169 170 /// CHECK-START-ARM64: long Main.minLongConstantOne(long) disassembly (after) 171 /// CHECK-NOT: InvokeStaticOrDirect 172 /// CHECK-NOT: mov {{x\d+}}, #0x1 173 /// CHECK: cmp {{x\d+}}, #0x1 (1) 174 /// CHECK: csinc {{x\d+}}, {{x\d+}}, xzr, lt 175 /// CHECK: ret minLongConstantOne(long a)176 public static long minLongConstantOne(long a) { 177 return Math.min(a, 1L); 178 } 179 180 /// CHECK-START-ARM64: long Main.minLongConstantMinusOne(long) disassembly (after) 181 /// CHECK-NOT: InvokeStaticOrDirect 182 /// CHECK-NOT: mov {{x\d+}}, #0xffffffffffffffff 183 /// CHECK: cmn {{x\d+}}, #0x1 (1) 184 /// CHECK: csinv {{x\d+}}, {{x\d+}}, xzr, lt 185 /// CHECK: ret minLongConstantMinusOne(long a)186 public static long minLongConstantMinusOne(long a) { 187 return Math.min(a, -1L); 188 } 189 190 /// CHECK-START-ARM64: int Main.maxIntConstantZero(int) disassembly (after) 191 /// CHECK-NOT: InvokeStaticOrDirect 192 /// CHECK-NOT: mov {{w\d+}}, #0x0 193 /// CHECK: cmp {{w\d+}}, #0x0 (0) 194 /// CHECK: csel {{w\d+}}, {{w\d+}}, wzr, gt 195 /// CHECK: ret maxIntConstantZero(int a)196 public static int maxIntConstantZero(int a) { 197 return Math.max(a, 0); 198 } 199 200 /// CHECK-START-ARM64: int Main.maxIntConstantOne(int) disassembly (after) 201 /// CHECK-NOT: InvokeStaticOrDirect 202 /// CHECK-NOT: mov {{w\d+}}, #0x1 203 /// CHECK: cmp {{w\d+}}, #0x1 (1) 204 /// CHECK: csinc {{w\d+}}, {{w\d+}}, wzr, gt 205 /// CHECK: ret maxIntConstantOne(int a)206 public static int maxIntConstantOne(int a) { 207 return Math.max(a, 1); 208 } 209 210 /// CHECK-START-ARM64: int Main.maxIntConstantMinusOne(int) disassembly (after) 211 /// CHECK-NOT: InvokeStaticOrDirect 212 /// CHECK-NOT: mov {{w\d+}}, #0xffffffff 213 /// CHECK: cmn {{w\d+}}, #0x1 (1) 214 /// CHECK: csinv {{w\d+}}, {{w\d+}}, wzr, gt 215 /// CHECK: ret maxIntConstantMinusOne(int a)216 public static int maxIntConstantMinusOne(int a) { 217 return Math.max(a, -1); 218 } 219 220 /// CHECK-START-ARM64: int Main.maxIntLargeConstant(int) disassembly (after) 221 /// CHECK-NOT: InvokeStaticOrDirect 222 /// CHECK: mov {{w\d+}}, #0x2001 223 /// CHECK: cmp {{w\d+}}, {{w\d+}} 224 // Check that constant generation was not handled by VIXL. 225 /// CHECK-NOT: mov {{w\d+}}, #0x2001 226 /// CHECK: csel {{w\d+}}, {{w\d+}}, {{w\d+}}, gt 227 /// CHECK: ret maxIntLargeConstant(int a)228 public static int maxIntLargeConstant(int a) { 229 return Math.max(a, 8193); 230 } 231 232 /// CHECK-START-ARM64: long Main.maxLongConstantZero(long) disassembly (after) 233 /// CHECK-NOT: InvokeStaticOrDirect 234 /// CHECK-NOT: mov {{x\d+}}, #0x0 235 /// CHECK: cmp {{x\d+}}, #0x0 (0) 236 /// CHECK: csel {{x\d+}}, {{x\d+}}, xzr, gt 237 /// CHECK: ret maxLongConstantZero(long a)238 public static long maxLongConstantZero(long a) { 239 return Math.max(a, 0L); 240 } 241 242 /// CHECK-START-ARM64: long Main.maxLongConstantOne(long) disassembly (after) 243 /// CHECK-NOT: InvokeStaticOrDirect 244 /// CHECK-NOT: mov {{x\d+}}, #0x1 245 /// CHECK: cmp {{x\d+}}, #0x1 (1) 246 /// CHECK: csinc {{x\d+}}, {{x\d+}}, xzr, gt 247 /// CHECK: ret maxLongConstantOne(long a)248 public static long maxLongConstantOne(long a) { 249 return Math.max(a, 1L); 250 } 251 252 /// CHECK-START-ARM64: long Main.maxLongConstantMinusOne(long) disassembly (after) 253 /// CHECK-NOT: InvokeStaticOrDirect 254 /// CHECK-NOT: mov {{x\d+}}, #0xffffffffffffffff 255 /// CHECK: cmn {{x\d+}}, #0x1 (1) 256 /// CHECK: csinv {{x\d+}}, {{x\d+}}, xzr, gt 257 /// CHECK: ret maxLongConstantMinusOne(long a)258 public static long maxLongConstantMinusOne(long a) { 259 return Math.max(a, -1L); 260 } 261 262 /// CHECK-START-ARM64: long Main.maxLongLargeConstant(long) disassembly (after) 263 /// CHECK-NOT: InvokeStaticOrDirect 264 /// CHECK: mov {{x\d+}}, #0x2001 265 /// CHECK: cmp {{x\d+}}, {{x\d+}} 266 // Check that constant generation was not handled by VIXL. 267 /// CHECK-NOT: mov {{x\d+}}, #0x2001 268 /// CHECK: csel {{x\d+}}, {{x\d+}}, {{x\d+}}, gt 269 /// CHECK: ret maxLongLargeConstant(long a)270 public static long maxLongLargeConstant(long a) { 271 return Math.max(a, 8193L); 272 } 273 274 // 275 // Different types. 276 // 277 278 /// CHECK-START: int Main.min1(int, int) instruction_simplifier$after_gvn (before) 279 /// CHECK-DAG: <<Cnd:z\d+>> GreaterThanOrEqual [<<Op1:i\d+>>,<<Op2:i\d+>>] 280 /// CHECK-DAG: <<Sel:i\d+>> Select [<<Op1>>,<<Op2>>,<<Cnd>>] 281 /// CHECK-DAG: Return [<<Sel>>] 282 // 283 /// CHECK-START: int Main.min1(int, int) instruction_simplifier$after_gvn (after) 284 /// CHECK-DAG: <<Min:i\d+>> Min 285 /// CHECK-DAG: Return [<<Min>>] 286 // 287 /// CHECK-START: int Main.min1(int, int) instruction_simplifier$after_gvn (after) 288 /// CHECK-NOT: Select min1(int a, int b)289 public static int min1(int a, int b) { 290 return a < b ? a : b; 291 } 292 293 /// CHECK-START: int Main.min2(int, int) instruction_simplifier$after_gvn (before) 294 /// CHECK-DAG: <<Cnd:z\d+>> GreaterThan [<<Op1:i\d+>>,<<Op2:i\d+>>] 295 /// CHECK-DAG: <<Sel:i\d+>> Select [<<Op1>>,<<Op2>>,<<Cnd>>] 296 /// CHECK-DAG: Return [<<Sel>>] 297 // 298 /// CHECK-START: int Main.min2(int, int) instruction_simplifier$after_gvn (after) 299 /// CHECK-DAG: <<Min:i\d+>> Min 300 /// CHECK-DAG: Return [<<Min>>] 301 // 302 /// CHECK-START: int Main.min2(int, int) instruction_simplifier$after_gvn (after) 303 /// CHECK-NOT: Select min2(int a, int b)304 public static int min2(int a, int b) { 305 return a <= b ? a : b; 306 } 307 308 /// CHECK-START: int Main.min3(int, int) instruction_simplifier$after_gvn (before) 309 /// CHECK-DAG: <<Cnd:z\d+>> LessThanOrEqual [<<Op1:i\d+>>,<<Op2:i\d+>>] 310 /// CHECK-DAG: <<Sel:i\d+>> Select [<<Op2>>,<<Op1>>,<<Cnd>>] 311 /// CHECK-DAG: Return [<<Sel>>] 312 // 313 /// CHECK-START: int Main.min3(int, int) instruction_simplifier$after_gvn (after) 314 /// CHECK-DAG: <<Min:i\d+>> Min 315 /// CHECK-DAG: Return [<<Min>>] 316 // 317 /// CHECK-START: int Main.min3(int, int) instruction_simplifier$after_gvn (after) 318 /// CHECK-NOT: Select min3(int a, int b)319 public static int min3(int a, int b) { 320 return a > b ? b : a; 321 } 322 323 /// CHECK-START: int Main.min4(int, int) instruction_simplifier$after_gvn (before) 324 /// CHECK-DAG: <<Cnd:z\d+>> LessThan [<<Op1:i\d+>>,<<Op2:i\d+>>] 325 /// CHECK-DAG: <<Sel:i\d+>> Select [<<Op2>>,<<Op1>>,<<Cnd>>] 326 /// CHECK-DAG: Return [<<Sel>>] 327 // 328 /// CHECK-START: int Main.min4(int, int) instruction_simplifier$after_gvn (after) 329 /// CHECK-DAG: <<Min:i\d+>> Min 330 /// CHECK-DAG: Return [<<Min>>] 331 // 332 /// CHECK-START: int Main.min4(int, int) instruction_simplifier$after_gvn (after) 333 /// CHECK-NOT: Select min4(int a, int b)334 public static int min4(int a, int b) { 335 return a >= b ? b : a; 336 } 337 338 /// CHECK-START: int Main.min5(short, short) instruction_simplifier$after_gvn (before) 339 /// CHECK-DAG: <<Cnd:z\d+>> LessThan [<<Op1:s\d+>>,<<Op2:s\d+>>] 340 /// CHECK-DAG: <<Sel:i\d+>> Select [<<Op2>>,<<Op1>>,<<Cnd>>] 341 /// CHECK-DAG: Return [<<Sel>>] 342 // 343 /// CHECK-START: int Main.min5(short, short) instruction_simplifier$after_gvn (after) 344 /// CHECK-DAG: <<Min:i\d+>> Min 345 /// CHECK-DAG: Return [<<Min>>] 346 // 347 /// CHECK-START: int Main.min5(short, short) instruction_simplifier$after_gvn (after) 348 /// CHECK-NOT: Select min5(short a, short b)349 public static int min5(short a, short b) { 350 return a >= b ? b : a; 351 } 352 353 /// CHECK-START: int Main.min6(byte, byte) instruction_simplifier$after_gvn (before) 354 /// CHECK-DAG: <<Cnd:z\d+>> LessThan [<<Op1:b\d+>>,<<Op2:b\d+>>] 355 /// CHECK-DAG: <<Sel:i\d+>> Select [<<Op2>>,<<Op1>>,<<Cnd>>] 356 /// CHECK-DAG: Return [<<Sel>>] 357 // 358 /// CHECK-START: int Main.min6(byte, byte) instruction_simplifier$after_gvn (after) 359 /// CHECK-DAG: <<Min:i\d+>> Min 360 /// CHECK-DAG: Return [<<Min>>] 361 // 362 /// CHECK-START: int Main.min6(byte, byte) instruction_simplifier$after_gvn (after) 363 /// CHECK-NOT: Select min6(byte a, byte b)364 public static int min6(byte a, byte b) { 365 return a >= b ? b : a; 366 } 367 368 /// CHECK-START: long Main.min7(long, long) instruction_simplifier$after_gvn (before) 369 /// CHECK-DAG: <<Cnd:z\d+>> LessThan [<<Op1:j\d+>>,<<Op2:j\d+>>] 370 /// CHECK-DAG: <<Sel:j\d+>> Select [<<Op2>>,<<Op1>>,<<Cnd>>] 371 /// CHECK-DAG: Return [<<Sel>>] 372 // 373 /// CHECK-START: long Main.min7(long, long) instruction_simplifier$after_gvn (after) 374 /// CHECK-DAG: <<Min:j\d+>> Min 375 /// CHECK-DAG: Return [<<Min>>] 376 // 377 /// CHECK-START: long Main.min7(long, long) instruction_simplifier$after_gvn (after) 378 /// CHECK-NOT: Select min7(long a, long b)379 public static long min7(long a, long b) { 380 return a >= b ? b : a; 381 } 382 383 /// CHECK-START: int Main.max1(int, int) instruction_simplifier$after_gvn (before) 384 /// CHECK-DAG: <<Cnd:z\d+>> GreaterThanOrEqual [<<Op1:i\d+>>,<<Op2:i\d+>>] 385 /// CHECK-DAG: <<Sel:i\d+>> Select [<<Op2>>,<<Op1>>,<<Cnd>>] 386 /// CHECK-DAG: Return [<<Sel>>] 387 // 388 /// CHECK-START: int Main.max1(int, int) instruction_simplifier$after_gvn (after) 389 /// CHECK-DAG: <<Max:i\d+>> Max 390 /// CHECK-DAG: Return [<<Max>>] 391 // 392 /// CHECK-START: int Main.max1(int, int) instruction_simplifier$after_gvn (after) 393 /// CHECK-NOT: Select max1(int a, int b)394 public static int max1(int a, int b) { 395 return a < b ? b : a; 396 } 397 398 /// CHECK-START: int Main.max2(int, int) instruction_simplifier$after_gvn (before) 399 /// CHECK-DAG: <<Cnd:z\d+>> GreaterThan [<<Op1:i\d+>>,<<Op2:i\d+>>] 400 /// CHECK-DAG: <<Sel:i\d+>> Select [<<Op2>>,<<Op1>>,<<Cnd>>] 401 /// CHECK-DAG: Return [<<Sel>>] 402 // 403 /// CHECK-START: int Main.max2(int, int) instruction_simplifier$after_gvn (after) 404 /// CHECK-DAG: <<Max:i\d+>> Max 405 /// CHECK-DAG: Return [<<Max>>] 406 // 407 /// CHECK-START: int Main.max2(int, int) instruction_simplifier$after_gvn (after) 408 /// CHECK-NOT: Select max2(int a, int b)409 public static int max2(int a, int b) { 410 return a <= b ? b : a; 411 } 412 413 /// CHECK-START: int Main.max3(int, int) instruction_simplifier$after_gvn (before) 414 /// CHECK-DAG: <<Cnd:z\d+>> LessThanOrEqual [<<Op1:i\d+>>,<<Op2:i\d+>>] 415 /// CHECK-DAG: <<Sel:i\d+>> Select [<<Op1>>,<<Op2>>,<<Cnd>>] 416 /// CHECK-DAG: Return [<<Sel>>] 417 // 418 /// CHECK-START: int Main.max3(int, int) instruction_simplifier$after_gvn (after) 419 /// CHECK-DAG: <<Max:i\d+>> Max 420 /// CHECK-DAG: Return [<<Max>>] 421 // 422 /// CHECK-START: int Main.max3(int, int) instruction_simplifier$after_gvn (after) 423 /// CHECK-NOT: Select max3(int a, int b)424 public static int max3(int a, int b) { 425 return a > b ? a : b; 426 } 427 428 /// CHECK-START: int Main.max4(int, int) instruction_simplifier$after_gvn (before) 429 /// CHECK-DAG: <<Cnd:z\d+>> LessThan [<<Op1:i\d+>>,<<Op2:i\d+>>] 430 /// CHECK-DAG: <<Sel:i\d+>> Select [<<Op1>>,<<Op2>>,<<Cnd>>] 431 /// CHECK-DAG: Return [<<Sel>>] 432 // 433 /// CHECK-START: int Main.max4(int, int) instruction_simplifier$after_gvn (after) 434 /// CHECK-DAG: <<Max:i\d+>> Max 435 /// CHECK-DAG: Return [<<Max>>] 436 // 437 /// CHECK-START: int Main.max4(int, int) instruction_simplifier$after_gvn (after) 438 /// CHECK-NOT: Select max4(int a, int b)439 public static int max4(int a, int b) { 440 return a >= b ? a : b; 441 } 442 443 /// CHECK-START: int Main.max5(short, short) instruction_simplifier$after_gvn (before) 444 /// CHECK-DAG: <<Cnd:z\d+>> LessThan [<<Op1:s\d+>>,<<Op2:s\d+>>] 445 /// CHECK-DAG: <<Sel:i\d+>> Select [<<Op1>>,<<Op2>>,<<Cnd>>] 446 /// CHECK-DAG: Return [<<Sel>>] 447 // 448 /// CHECK-START: int Main.max5(short, short) instruction_simplifier$after_gvn (after) 449 /// CHECK-DAG: <<Max:i\d+>> Max 450 /// CHECK-DAG: Return [<<Max>>] 451 // 452 /// CHECK-START: int Main.max5(short, short) instruction_simplifier$after_gvn (after) 453 /// CHECK-NOT: Select max5(short a, short b)454 public static int max5(short a, short b) { 455 return a >= b ? a : b; 456 } 457 458 /// CHECK-START: int Main.max6(byte, byte) instruction_simplifier$after_gvn (before) 459 /// CHECK-DAG: <<Cnd:z\d+>> LessThan [<<Op1:b\d+>>,<<Op2:b\d+>>] 460 /// CHECK-DAG: <<Sel:i\d+>> Select [<<Op1>>,<<Op2>>,<<Cnd>>] 461 /// CHECK-DAG: Return [<<Sel>>] 462 // 463 /// CHECK-START: int Main.max6(byte, byte) instruction_simplifier$after_gvn (after) 464 /// CHECK-DAG: <<Max:i\d+>> Max 465 /// CHECK-DAG: Return [<<Max>>] 466 // 467 /// CHECK-START: int Main.max6(byte, byte) instruction_simplifier$after_gvn (after) 468 /// CHECK-NOT: Select max6(byte a, byte b)469 public static int max6(byte a, byte b) { 470 return a >= b ? a : b; 471 } 472 473 /// CHECK-START: long Main.max7(long, long) instruction_simplifier$after_gvn (before) 474 /// CHECK-DAG: <<Cnd:z\d+>> LessThan [<<Op1:j\d+>>,<<Op2:j\d+>>] 475 /// CHECK-DAG: <<Sel:j\d+>> Select [<<Op1>>,<<Op2>>,<<Cnd>>] 476 /// CHECK-DAG: Return [<<Sel>>] 477 // 478 /// CHECK-START: long Main.max7(long, long) instruction_simplifier$after_gvn (after) 479 /// CHECK-DAG: <<Max:j\d+>> Max 480 /// CHECK-DAG: Return [<<Max>>] 481 // 482 /// CHECK-START: long Main.max7(long, long) instruction_simplifier$after_gvn (after) 483 /// CHECK-NOT: Select max7(long a, long b)484 public static long max7(long a, long b) { 485 return a >= b ? a : b; 486 } 487 488 // 489 // Complications. 490 // 491 492 /// CHECK-START: int Main.min0(int[], int[]) instruction_simplifier$after_gvn (before) 493 /// CHECK-DAG: <<Ar1:i\d+>> ArrayGet [{{l\d+}},{{i\d+}}] 494 /// CHECK-DAG: <<Ar2:i\d+>> ArrayGet [{{l\d+}},{{i\d+}}] 495 /// CHECK-DAG: <<Cnd:z\d+>> GreaterThan [<<Ar1>>,<<Ar2>>] 496 /// CHECK-DAG: <<Sel:i\d+>> Select [<<Ar1>>,<<Ar2>>,<<Cnd>>] 497 /// CHECK-DAG: Return [<<Sel>>] 498 // 499 /// CHECK-START: int Main.min0(int[], int[]) instruction_simplifier$after_gvn (after) 500 /// CHECK-DAG: <<Min:i\d+>> Min 501 /// CHECK-DAG: Return [<<Min>>] 502 // 503 /// CHECK-START: int Main.min0(int[], int[]) instruction_simplifier$after_gvn (after) 504 /// CHECK-NOT: Select min0(int[] a, int[] b)505 public static int min0(int[] a, int[] b) { 506 // Repeat of array references needs finding the common subexpressions 507 // prior to doing the select and min/max recognition. 508 return a[0] <= b[0] ? a[0] : b[0]; 509 } 510 511 /// CHECK-START: int Main.max0(int[], int[]) instruction_simplifier$after_gvn (before) 512 /// CHECK-DAG: <<Ar1:i\d+>> ArrayGet [{{l\d+}},{{i\d+}}] 513 /// CHECK-DAG: <<Ar2:i\d+>> ArrayGet [{{l\d+}},{{i\d+}}] 514 /// CHECK-DAG: <<Cnd:z\d+>> LessThan [<<Ar1>>,<<Ar2>>] 515 /// CHECK-DAG: <<Sel:i\d+>> Select [<<Ar1>>,<<Ar2>>,<<Cnd>>] 516 /// CHECK-DAG: Return [<<Sel>>] 517 // 518 /// CHECK-START: int Main.max0(int[], int[]) instruction_simplifier$after_gvn (after) 519 /// CHECK-DAG: <<Max:i\d+>> Max 520 /// CHECK-DAG: Return [<<Max>>] 521 // 522 /// CHECK-START: int Main.max0(int[], int[]) instruction_simplifier$after_gvn (after) 523 /// CHECK-NOT: Select max0(int[] a, int[] b)524 public static int max0(int[] a, int[] b) { 525 // Repeat of array references needs finding the common subexpressions 526 // prior to doing the select and min/max recognition. 527 return a[0] >= b[0] ? a[0] : b[0]; 528 } 529 530 /// CHECK-START: int Main.minmax1(int) instruction_simplifier$after_gvn (before) 531 /// CHECK-DAG: <<Par:i\d+>> ParameterValue 532 /// CHECK-DAG: <<P100:i\d+>> IntConstant 100 533 /// CHECK-DAG: <<M100:i\d+>> IntConstant -100 534 /// CHECK-DAG: <<Cnd1:z\d+>> LessThanOrEqual [<<Par>>,<<P100>>] 535 /// CHECK-DAG: <<Sel1:i\d+>> Select [<<P100>>,<<Par>>,<<Cnd1>>] 536 /// CHECK-DAG: <<Cnd2:z\d+>> GreaterThanOrEqual [<<Sel1>>,<<M100>>] 537 /// CHECK-DAG: <<Sel2:i\d+>> Select [<<M100>>,<<Sel1>>,<<Cnd2>>] 538 /// CHECK-DAG: Return [<<Sel2>>] 539 // 540 /// CHECK-START: int Main.minmax1(int) instruction_simplifier$after_gvn (after) 541 /// CHECK-DAG: <<Par:i\d+>> ParameterValue 542 /// CHECK-DAG: <<P100:i\d+>> IntConstant 100 543 /// CHECK-DAG: <<M100:i\d+>> IntConstant -100 544 /// CHECK-DAG: <<Min:i\d+>> Min [<<Par>>,<<P100>>] 545 /// CHECK-DAG: <<Max:i\d+>> Max [<<Min>>,<<M100>>] 546 /// CHECK-DAG: Return [<<Max>>] 547 // 548 /// CHECK-START: int Main.minmax1(int) instruction_simplifier$after_gvn (after) 549 /// CHECK-NOT: Select minmax1(int x)550 public static int minmax1(int x) { 551 // Simple if-if gives clean select sequence. 552 if (x > 100) { 553 x = 100; 554 } 555 if (x < -100) { 556 x = -100; 557 } 558 return x; 559 } 560 561 /// CHECK-START: int Main.minmax2(int) instruction_simplifier$after_gvn (before) 562 /// CHECK-DAG: <<Par:i\d+>> ParameterValue 563 /// CHECK-DAG: <<P100:i\d+>> IntConstant 100 564 /// CHECK-DAG: <<M100:i\d+>> IntConstant -100 565 /// CHECK-DAG: <<Cnd1:z\d+>> LessThanOrEqual [<<Par>>,<<P100>>] 566 /// CHECK-DAG: <<Cnd2:z\d+>> GreaterThanOrEqual [<<Par>>,<<M100>>] 567 /// CHECK-DAG: <<Sel1:i\d+>> Select [<<M100>>,<<Par>>,<<Cnd2>>] 568 /// CHECK-DAG: <<Sel2:i\d+>> Select [<<P100>>,<<Sel1>>,<<Cnd1>>] 569 /// CHECK-DAG: Return [<<Sel2>>] 570 // 571 /// CHECK-START: int Main.minmax2(int) instruction_simplifier$after_gvn (after) 572 /// CHECK-DAG: <<Par:i\d+>> ParameterValue 573 /// CHECK-DAG: <<P100:i\d+>> IntConstant 100 574 /// CHECK-DAG: <<M100:i\d+>> IntConstant -100 575 /// CHECK-DAG: <<Max:i\d+>> Max [<<Par>>,<<M100>>] 576 /// CHECK-DAG: <<Min:i\d+>> Min [<<Max>>,<<P100>>] 577 /// CHECK-DAG: Return [<<Min>>] 578 // 579 /// CHECK-START: int Main.minmax2(int) instruction_simplifier$after_gvn (after) 580 /// CHECK-NOT: Select minmax2(int x)581 public static int minmax2(int x) { 582 // Simple if-else requires inspecting bounds of resulting selects. 583 if (x > 100) { 584 x = 100; 585 } else if (x < -100) { 586 x = -100; 587 } 588 return x; 589 } 590 591 /// CHECK-START: int Main.minmax3(int) instruction_simplifier$after_gvn (after) 592 /// CHECK-DAG: <<Par:i\d+>> ParameterValue 593 /// CHECK-DAG: <<P100:i\d+>> IntConstant 100 594 /// CHECK-DAG: <<M100:i\d+>> IntConstant -100 595 /// CHECK-DAG: <<Max:i\d+>> Max [<<Par>>,<<M100>>] 596 /// CHECK-DAG: <<Min:i\d+>> Min [<<Max>>,<<P100>>] 597 /// CHECK-DAG: Return [<<Min>>] 598 // 599 /// CHECK-START: int Main.minmax3(int) instruction_simplifier$after_gvn (after) 600 /// CHECK-NOT: Select minmax3(int x)601 public static int minmax3(int x) { 602 return (x > 100) ? 100 : ((x < -100) ? -100 : x); 603 } 604 605 /// CHECK-START: int Main.minmax4(int) instruction_simplifier$after_gvn (after) 606 /// CHECK-DAG: <<Par:i\d+>> ParameterValue 607 /// CHECK-DAG: <<P100:i\d+>> IntConstant 100 608 /// CHECK-DAG: <<M100:i\d+>> IntConstant -100 609 /// CHECK-DAG: <<Min:i\d+>> Min [<<Par>>,<<P100>>] 610 /// CHECK-DAG: <<Max:i\d+>> Max [<<Min>>,<<M100>>] 611 /// CHECK-DAG: Return [<<Max>>] 612 // 613 /// CHECK-START: int Main.minmax4(int) instruction_simplifier$after_gvn (after) 614 /// CHECK-NOT: Select minmax4(int x)615 public static int minmax4(int x) { 616 return (x < -100) ? -100 : ((x > 100) ? 100 : x); 617 } 618 619 /// CHECK-START: int Main.minmaxCSEScalar(int, int) select_generator (after) 620 /// CHECK-DAG: <<Par1:i\d+>> ParameterValue 621 /// CHECK-DAG: <<Par2:i\d+>> ParameterValue 622 /// CHECK-DAG: <<Cnd1:z\d+>> LessThanOrEqual [<<Par1>>,<<Par2>>] 623 /// CHECK-DAG: <<Sel1:i\d+>> Select [<<Par1>>,<<Par2>>,<<Cnd1>>] 624 /// CHECK-DAG: <<Cnd2:z\d+>> GreaterThanOrEqual [<<Par1>>,<<Par2>>] 625 /// CHECK-DAG: <<Sel2:i\d+>> Select [<<Par1>>,<<Par2>>,<<Cnd2>>] 626 /// CHECK-DAG: <<Add1:i\d+>> Add [<<Sel1>>,<<Sel2>>] 627 /// CHECK-DAG: <<Add2:i\d+>> Add [<<Sel1>>,<<Add1>>] 628 /// CHECK-DAG: <<Add3:i\d+>> Add [<<Sel2>>,<<Add2>>] 629 /// CHECK-DAG: <<Add4:i\d+>> Add [<<Sel1>>,<<Add3>>] 630 /// CHECK-DAG: <<Add5:i\d+>> Add [<<Sel2>>,<<Add4>>] 631 /// CHECK-DAG: Return [<<Add5>>] 632 // 633 /// CHECK-START: int Main.minmaxCSEScalar(int, int) instruction_simplifier$after_gvn (after) 634 /// CHECK-DAG: <<Par1:i\d+>> ParameterValue 635 /// CHECK-DAG: <<Par2:i\d+>> ParameterValue 636 /// CHECK-DAG: <<Max:i\d+>> Max [<<Par1>>,<<Par2>>] 637 /// CHECK-DAG: <<Min:i\d+>> Min [<<Par1>>,<<Par2>>] 638 /// CHECK-DAG: <<Add1:i\d+>> Add [<<Max>>,<<Min>>] 639 /// CHECK-DAG: <<Add2:i\d+>> Add [<<Max>>,<<Add1>>] 640 /// CHECK-DAG: <<Add3:i\d+>> Add [<<Min>>,<<Add2>>] 641 /// CHECK-DAG: <<Add4:i\d+>> Add [<<Max>>,<<Add3>>] 642 /// CHECK-DAG: <<Add5:i\d+>> Add [<<Min>>,<<Add4>>] 643 /// CHECK-DAG: Return [<<Add5>>] minmaxCSEScalar(int x, int y)644 public static int minmaxCSEScalar(int x, int y) { 645 int t1 = (x > y) ? x : y; 646 int t2 = (x < y) ? x : y; 647 int t3 = (x > y) ? x : y; 648 int t4 = (x < y) ? x : y; 649 int t5 = (x > y) ? x : y; 650 int t6 = (x < y) ? x : y; 651 // Make sure min/max is CSEed. 652 return t1 + t2 + t3 + t4 + t5 + t6; 653 } 654 655 /// CHECK-START: int Main.minmaxCSEArray(int[], int[]) select_generator (after) 656 /// CHECK-DAG: <<Arr1:i\d+>> ArrayGet 657 /// CHECK-DAG: <<Arr2:i\d+>> ArrayGet 658 /// CHECK-DAG: <<Cnd1:z\d+>> LessThanOrEqual [<<Arr1>>,<<Arr2>>] 659 /// CHECK-DAG: <<Sel1:i\d+>> Select [<<Arr1>>,<<Arr2>>,<<Cnd1>>] 660 /// CHECK-DAG: <<Cnd2:z\d+>> GreaterThanOrEqual [<<Arr1>>,<<Arr2>>] 661 /// CHECK-DAG: <<Sel2:i\d+>> Select [<<Arr1>>,<<Arr2>>,<<Cnd2>>] 662 /// CHECK-DAG: <<Add1:i\d+>> Add [<<Sel1>>,<<Sel2>>] 663 /// CHECK-DAG: <<Add2:i\d+>> Add [<<Sel1>>,<<Add1>>] 664 /// CHECK-DAG: <<Add3:i\d+>> Add [<<Sel2>>,<<Add2>>] 665 /// CHECK-DAG: <<Add4:i\d+>> Add [<<Sel1>>,<<Add3>>] 666 /// CHECK-DAG: <<Add5:i\d+>> Add [<<Sel2>>,<<Add4>>] 667 /// CHECK-DAG: Return [<<Add5>>] 668 // 669 /// CHECK-START: int Main.minmaxCSEArray(int[], int[]) instruction_simplifier$after_gvn (after) 670 /// CHECK-DAG: <<Arr1:i\d+>> ArrayGet 671 /// CHECK-DAG: <<Arr2:i\d+>> ArrayGet 672 /// CHECK-DAG: <<Max:i\d+>> Max [<<Arr1>>,<<Arr2>>] 673 /// CHECK-DAG: <<Min:i\d+>> Min [<<Arr1>>,<<Arr2>>] 674 /// CHECK-DAG: <<Add1:i\d+>> Add [<<Max>>,<<Min>>] 675 /// CHECK-DAG: <<Add2:i\d+>> Add [<<Max>>,<<Add1>>] 676 /// CHECK-DAG: <<Add3:i\d+>> Add [<<Min>>,<<Add2>>] 677 /// CHECK-DAG: <<Add4:i\d+>> Add [<<Max>>,<<Add3>>] 678 /// CHECK-DAG: <<Add5:i\d+>> Add [<<Min>>,<<Add4>>] 679 /// CHECK-DAG: Return [<<Add5>>] minmaxCSEArray(int[] x, int[] y)680 public static int minmaxCSEArray(int[] x, int[] y) { 681 int t1 = (x[0] > y[0]) ? x[0] : y[0]; 682 int t2 = (x[0] < y[0]) ? x[0] : y[0]; 683 int t3 = (x[0] > y[0]) ? x[0] : y[0]; 684 int t4 = (x[0] < y[0]) ? x[0] : y[0]; 685 int t5 = (x[0] > y[0]) ? x[0] : y[0]; 686 int t6 = (x[0] < y[0]) ? x[0] : y[0]; 687 // Make sure min/max is CSEed. 688 return t1 + t2 + t3 + t4 + t5 + t6; 689 } 690 691 /// CHECK-START: int Main.minmaxCSEScalarAndCond(int, int) instruction_simplifier$after_gvn (after) 692 /// CHECK-DAG: <<Par1:i\d+>> ParameterValue 693 /// CHECK-DAG: <<Par2:i\d+>> ParameterValue 694 /// CHECK-DAG: <<Max:i\d+>> Max [<<Par1>>,<<Par2>>] 695 /// CHECK-DAG: <<Min:i\d+>> Min [<<Par1>>,<<Par2>>] 696 /// CHECK-DAG: <<Add:i\d+>> Add [<<Max>>,<<Min>>] 697 /// CHECK-DAG: Return [<<Add>>] 698 /// CHECK-DAG: <<Add1:i\d+>> Add [<<Max>>,<<Min>>] 699 /// CHECK-DAG: <<Add2:i\d+>> Add [<<Max>>,<<Add1>>] 700 /// CHECK-DAG: <<Add3:i\d+>> Add [<<Min>>,<<Add2>>] 701 /// CHECK-DAG: Return [<<Add3>>] minmaxCSEScalarAndCond(int x, int y)702 public static int minmaxCSEScalarAndCond(int x, int y) { 703 int t1 = (x > y) ? x : y; 704 int t2 = (x < y) ? x : y; 705 if (x == y) 706 return t1 + t2; 707 int t3 = (x > y) ? x : y; 708 int t4 = (x < y) ? x : y; 709 // Make sure min/max is CSEed. 710 return t1 + t2 + t3 + t4; 711 } 712 main(String[] args)713 public static void main(String[] args) { 714 // Intrinsics. 715 expectEquals(10, minI(10)); 716 expectEquals(20, minI(25)); 717 expectEquals(-1, minIntConstantZero(-1)); 718 expectEquals(0, minIntConstantZero(1)); 719 expectEquals(0, minIntConstantOne(0)); 720 expectEquals(1, minIntConstantOne(2)); 721 expectEquals(-2, minIntConstantMinusOne(-2)); 722 expectEquals(-1, minIntConstantMinusOne(0)); 723 expectEquals(10L, minL(10L)); 724 expectEquals(20L, minL(25L)); 725 expectEquals(-1L, minLongConstantZero(-1L)); 726 expectEquals(0L, minLongConstantZero(1L)); 727 expectEquals(0L, minLongConstantOne(0L)); 728 expectEquals(1L, minLongConstantOne(2L)); 729 expectEquals(-2L, minLongConstantMinusOne(-2L)); 730 expectEquals(-1L, minLongConstantMinusOne(0L)); 731 expectEquals(20, maxI(10)); 732 expectEquals(25, maxI(25)); 733 expectEquals(0, maxIntConstantZero(-1)); 734 expectEquals(1, maxIntConstantZero(1)); 735 expectEquals(1, maxIntConstantOne(0)); 736 expectEquals(2, maxIntConstantOne(2)); 737 expectEquals(-1, maxIntConstantMinusOne(-2)); 738 expectEquals(0, maxIntConstantMinusOne(0)); 739 expectEquals(8193, maxIntLargeConstant(8192)); 740 expectEquals(9000, maxIntLargeConstant(9000)); 741 expectEquals(20L, maxL(10L)); 742 expectEquals(25L, maxL(25L)); 743 expectEquals(0L, maxLongConstantZero(-1L)); 744 expectEquals(1L, maxLongConstantZero(1L)); 745 expectEquals(1L, maxLongConstantOne(0L)); 746 expectEquals(2L, maxLongConstantOne(2L)); 747 expectEquals(-1L, maxLongConstantMinusOne(-2L)); 748 expectEquals(0L, maxLongConstantMinusOne(0L)); 749 expectEquals(8193L, maxLongLargeConstant(8192L)); 750 expectEquals(9000L, maxLongLargeConstant(9000L)); 751 // Types. 752 expectEquals(10, min1(10, 20)); 753 expectEquals(10, min2(10, 20)); 754 expectEquals(10, min3(10, 20)); 755 expectEquals(10, min4(10, 20)); 756 expectEquals(10, min5((short) 10, (short) 20)); 757 expectEquals(10, min6((byte) 10, (byte) 20)); 758 expectEquals(10L, min7(10L, 20L)); 759 expectEquals(20, max1(10, 20)); 760 expectEquals(20, max2(10, 20)); 761 expectEquals(20, max3(10, 20)); 762 expectEquals(20, max4(10, 20)); 763 expectEquals(20, max5((short) 10, (short) 20)); 764 expectEquals(20, max6((byte) 10, (byte) 20)); 765 expectEquals(20L, max7(10L, 20L)); 766 // Complications. 767 int[] a = { 10 }; 768 int[] b = { 20 }; 769 expectEquals(10, min0(a, b)); 770 expectEquals(20, max0(a, b)); 771 expectEquals(-100, minmax1(-200)); 772 expectEquals(10, minmax1(10)); 773 expectEquals(100, minmax1(200)); 774 expectEquals(-100, minmax2(-200)); 775 expectEquals(10, minmax2(10)); 776 expectEquals(100, minmax2(200)); 777 expectEquals(-100, minmax3(-200)); 778 expectEquals(10, minmax3(10)); 779 expectEquals(100, minmax3(200)); 780 expectEquals(-100, minmax4(-200)); 781 expectEquals(10, minmax4(10)); 782 expectEquals(100, minmax4(200)); 783 expectEquals(90, minmaxCSEScalar(10, 20)); 784 expectEquals(90, minmaxCSEArray(a, b)); 785 expectEquals(20, minmaxCSEScalarAndCond(10, 10)); 786 expectEquals(60, minmaxCSEScalarAndCond(10, 20)); 787 System.out.println("passed"); 788 } 789 expectEquals(int expected, int result)790 private static void expectEquals(int expected, int result) { 791 if (expected != result) { 792 throw new Error("Expected: " + expected + ", found: " + result); 793 } 794 } 795 expectEquals(long expected, long result)796 private static void expectEquals(long expected, long result) { 797 if (expected != result) { 798 throw new Error("Expected: " + expected + ", found: " + result); 799 } 800 } 801 } 802