1 /* 2 * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24 package compiler.c2.irTests; 25 26 import jdk.test.lib.Asserts; 27 import compiler.lib.ir_framework.*; 28 import java.util.Random; 29 import jdk.test.lib.Utils; 30 31 /* 32 * @test 33 * @bug 8324655 8329797 34 * @key randomness 35 * @summary Test that if expressions are properly folded into min/max nodes 36 * @requires os.arch != "riscv64" 37 * @library /test/lib / 38 * @run driver compiler.c2.irTests.TestIfMinMax 39 */ 40 public class TestIfMinMax { 41 private static final Random RANDOM = Utils.getRandomInstance(); 42 43 public static void main(String[] args) { 44 TestFramework.run(); 45 } 46 47 @Test 48 @IR(failOn = { IRNode.IF }, counts = { IRNode.MIN_I, "1" }) 49 public int testMinI1(int a, int b) { 50 return a < b ? a : b; 51 } 52 53 @Test 54 @IR(failOn = { IRNode.IF }, counts = { IRNode.MIN_I, "1" }) 55 public int testMinI2(int a, int b) { 56 return a > b ? b : a; 57 } 58 59 @Test 60 @IR(failOn = { IRNode.IF }, counts = { IRNode.MAX_I, "1" }) 61 public int testMaxI1(int a, int b) { 62 return a > b ? a : b; 63 } 64 65 @Test 66 @IR(failOn = { IRNode.IF }, counts = { IRNode.MAX_I, "1" }) 67 public int testMaxI2(int a, int b) { 68 return a < b ? b : a; 69 } 70 71 @Test 72 @IR(failOn = { IRNode.IF }, counts = { IRNode.MIN_I, "1" }) 73 public int testMinI1E(int a, int b) { 74 return a <= b ? a : b; 75 } 76 77 @Test 78 @IR(failOn = { IRNode.IF }, counts = { IRNode.MIN_I, "1" }) 79 public int testMinI2E(int a, int b) { 80 return a >= b ? b : a; 81 } 82 83 @Test 84 @IR(failOn = { IRNode.IF }, counts = { IRNode.MAX_I, "1" }) 85 public int testMaxI1E(int a, int b) { 86 return a >= b ? a : b; 87 } 88 89 @Test 90 @IR(failOn = { IRNode.IF }, counts = { IRNode.MAX_I, "1" }) 91 public int testMaxI2E(int a, int b) { 92 return a <= b ? b : a; 93 } 94 95 @Test 96 @IR(phase = { CompilePhase.BEFORE_MACRO_EXPANSION }, failOn = { IRNode.IF }, counts = { IRNode.MIN_L, "1" }) 97 public long testMinL1(long a, long b) { 98 return a < b ? a : b; 99 } 100 101 @Test 102 @IR(phase = { CompilePhase.BEFORE_MACRO_EXPANSION }, failOn = { IRNode.IF }, counts = { IRNode.MIN_L, "1" }) 103 public long testMinL2(long a, long b) { 104 return a > b ? b : a; 105 } 106 107 @Test 108 @IR(phase = { CompilePhase.BEFORE_MACRO_EXPANSION }, failOn = { IRNode.IF }, counts = { IRNode.MAX_L, "1" }) 109 public long testMaxL1(long a, long b) { 110 return a > b ? a : b; 111 } 112 113 @Test 114 @IR(phase = { CompilePhase.BEFORE_MACRO_EXPANSION }, failOn = { IRNode.IF }, counts = { IRNode.MAX_L, "1" }) 115 public long testMaxL2(long a, long b) { 116 return a < b ? b : a; 117 } 118 119 @Test 120 @IR(phase = { CompilePhase.BEFORE_MACRO_EXPANSION }, failOn = { IRNode.IF }, counts = { IRNode.MIN_L, "1" }) 121 public long testMinL1E(long a, long b) { 122 return a <= b ? a : b; 123 } 124 125 @Test 126 @IR(phase = { CompilePhase.BEFORE_MACRO_EXPANSION }, failOn = { IRNode.IF }, counts = { IRNode.MIN_L, "1" }) 127 public long testMinL2E(long a, long b) { 128 return a >= b ? b : a; 129 } 130 131 @Test 132 @IR(phase = { CompilePhase.BEFORE_MACRO_EXPANSION }, failOn = { IRNode.IF }, counts = { IRNode.MAX_L, "1" }) 133 public long testMaxL1E(long a, long b) { 134 return a >= b ? a : b; 135 } 136 137 @Test 138 @IR(phase = { CompilePhase.BEFORE_MACRO_EXPANSION }, failOn = { IRNode.IF }, counts = { IRNode.MAX_L, "1" }) 139 public long testMaxL2E(long a, long b) { 140 return a <= b ? b : a; 141 } 142 143 public class Dummy { 144 long l; 145 public Dummy(long l) { this.l = l; } 146 } 147 148 @Setup 149 Object[] setupDummyArray() { 150 Dummy[] arr = new Dummy[512]; 151 for (int i = 0; i < 512; i++) { 152 arr[i] = new Dummy(RANDOM.nextLong()); 153 } 154 return new Object[] { arr }; 155 } 156 157 @Test 158 @Arguments(setup = "setupDummyArray") 159 @IR(failOn = { IRNode.MAX_L }) 160 public long testMaxLAndBarrierInLoop(Dummy[] arr) { 161 long result = 0; 162 for (int i = 0; i < arr.length; ++i) { 163 result += Math.max(arr[i].l, 1); 164 } 165 return result; 166 } 167 168 @Test 169 @Arguments(setup = "setupDummyArray") 170 @IR(failOn = { IRNode.MIN_L }) 171 public long testMinLAndBarrierInLoop(Dummy[] arr) { 172 long result = 0; 173 for (int i = 0; i < arr.length; ++i) { 174 result += Math.min(arr[i].l, 1); 175 } 176 return result; 177 } 178 179 @Setup 180 static Object[] setupIntArrays() { 181 int[] a = new int[512]; 182 int[] b = new int[512]; 183 184 // Fill from 1 to 50 185 for (int i = 0; i < 50; i++) { 186 a[i] = i + 1; 187 b[i] = 1; 188 } 189 190 // Fill from -1 to -50 191 for (int i = 50; i < 100; i++) { 192 a[i] = -(i - 49); 193 b[i] = 1; 194 } 195 196 for (int i = 100; i < 512; i++) { 197 a[i] = RANDOM.nextInt(); 198 b[i] = 1; 199 } 200 201 return new Object[] { a, b }; 202 } 203 204 @Setup 205 static Object[] setupLongArrays() { 206 long[] a = new long[512]; 207 long[] b = new long[512]; 208 209 // Fill from 1 to 50 210 for (int i = 0; i < 50; i++) { 211 a[i] = i + 1; 212 b[i] = 1; 213 } 214 215 // Fill from -1 to -50 216 for (int i = 50; i < 100; i++) { 217 a[i] = -(i - 49); 218 b[i] = 1; 219 } 220 221 for (int i = 100; i < 512; i++) { 222 a[i] = RANDOM.nextLong(); 223 b[i] = 1; 224 } 225 226 return new Object[] { a, b }; 227 } 228 229 @Test 230 @IR(applyIf = { "SuperWordReductions", "true" }, 231 applyIfCPUFeatureOr = { "sse4.1", "true" , "asimd" , "true"}, 232 counts = { IRNode.MAX_REDUCTION_V, "> 0" }) 233 @Arguments(setup = "setupIntArrays") 234 public Object[] testMaxIntReduction(int[] a, int[] b) { 235 int r = 0; 236 for (int i = 0; i < a.length; i++) { 237 int aI = a[i] * b[i]; 238 239 r = aI > r ? aI : r; 240 } 241 242 return new Object[] { a, b, r }; 243 } 244 245 @Check(test = "testMaxIntReduction") 246 public void checkTestMaxIntReduction(Object[] vals) { 247 int[] a = (int[]) vals[0]; 248 int[] b = (int[]) vals[1]; 249 int testRet = (int) vals[2]; 250 251 int r = 0; 252 for (int i = 0; i < a.length; i++) { 253 int aI = a[i] * b[i]; 254 255 r = aI > r ? aI : r; 256 } 257 258 if (r != testRet) { 259 throw new IllegalStateException("Int max reduction test failed: expected " + testRet + " but got " + r); 260 } 261 } 262 263 @Test 264 @IR(applyIf = { "SuperWordReductions", "true" }, 265 applyIfCPUFeatureOr = { "sse4.1", "true" , "asimd" , "true"}, 266 counts = { IRNode.MIN_REDUCTION_V, "> 0" }) 267 @Arguments(setup = "setupIntArrays") 268 public Object[] testMinIntReduction(int[] a, int[] b) { 269 int r = 0; 270 271 for (int i = 0; i < a.length; i++) { 272 int aI = a[i] * b[i]; 273 274 r = aI < r ? aI : r; 275 } 276 277 return new Object[] { a, b, r }; 278 } 279 280 @Check(test = "testMinIntReduction") 281 public void checkTestMinIntReduction(Object[] vals) { 282 int[] a = (int[]) vals[0]; 283 int[] b = (int[]) vals[1]; 284 int testRet = (int) vals[2]; 285 286 int r = 0; 287 for (int i = 0; i < a.length; i++) { 288 int aI = a[i] * b[i]; 289 290 r = aI < r ? aI : r; 291 } 292 293 if (r != testRet) { 294 throw new IllegalStateException("Int min reduction test failed: expected " + testRet + " but got " + r); 295 } 296 } 297 298 @Test 299 @IR(applyIf = { "SuperWordReductions", "true" }, 300 applyIfCPUFeatureOr = { "avx512", "true" }, 301 counts = { IRNode.MAX_REDUCTION_V, "> 0" }) 302 @Arguments(setup = "setupLongArrays") 303 public Object[] testMaxLongReduction(long[] a, long[] b) { 304 long r = 0; 305 306 for (int i = 0; i < a.length; i++) { 307 long aI = a[i] * b[i]; 308 309 r = aI > r ? aI : r; 310 } 311 312 return new Object[] { a, b, r }; 313 } 314 315 @Check(test = "testMaxLongReduction") 316 public void checkTestMaxLongReduction(Object[] vals) { 317 long[] a = (long[]) vals[0]; 318 long[] b = (long[]) vals[1]; 319 long testRet = (long) vals[2]; 320 321 long r = 0; 322 for (int i = 0; i < a.length; i++) { 323 long aI = a[i] * b[i]; 324 325 r = aI > r ? aI : r; 326 } 327 328 if (r != testRet) { 329 throw new IllegalStateException("Long max reduction test failed: expected " + testRet + " but got " + r); 330 } 331 } 332 333 @Test 334 @IR(applyIf = { "SuperWordReductions", "true" }, 335 applyIfCPUFeatureOr = { "avx512", "true" }, 336 counts = { IRNode.MIN_REDUCTION_V, "> 0" }) 337 @Arguments(setup = "setupLongArrays") 338 public Object[] testMinLongReduction(long[] a, long[] b) { 339 long r = 0; 340 341 for (int i = 0; i < a.length; i++) { 342 long aI = a[i] * b[i]; 343 344 r = aI < r ? aI : r; 345 } 346 347 return new Object[] { a, b, r }; 348 } 349 350 @Check(test = "testMinLongReduction") 351 public void checkTestMinLongReduction(Object[] vals) { 352 long[] a = (long[]) vals[0]; 353 long[] b = (long[]) vals[1]; 354 long testRet = (long) vals[2]; 355 356 long r = 0; 357 for (int i = 0; i < a.length; i++) { 358 long aI = a[i] * b[i]; 359 360 r = aI < r ? aI : r; 361 } 362 363 if (r != testRet) { 364 throw new IllegalStateException("Long min reduction test failed: expected " + testRet + " but got " + r); 365 } 366 } 367 368 @Test 369 @IR(applyIfCPUFeatureOr = { "sse4.1", "true" , "asimd" , "true"}, 370 counts = { IRNode.MAX_VI, "> 0" }) 371 @Arguments(setup = "setupIntArrays") 372 public Object[] testMaxIntVector(int[] a, int[] b) { 373 int[] r = new int[a.length]; 374 375 for (int i = 0; i < a.length; i++) { 376 int aI = a[i]; 377 int bI = b[i]; 378 379 r[i] = aI > bI ? aI : bI; 380 } 381 382 return new Object[] { a, b, r }; 383 } 384 385 @Check(test = "testMaxIntVector") 386 public void checkTestMaxIntVector(Object[] vals) { 387 int[] a = (int[]) vals[0]; 388 int[] b = (int[]) vals[1]; 389 int[] testRet = (int[]) vals[2]; 390 391 for (int i = 0; i < a.length; i++) { 392 int aI = a[i]; 393 int bI = b[i]; 394 395 int r = aI > bI ? aI : bI; 396 397 if (r != testRet[i]) { 398 throw new IllegalStateException("Int max vectorization test failed: expected " + testRet + " but got " + r); 399 } 400 } 401 } 402 403 @Test 404 @IR(applyIfCPUFeatureOr = { "sse4.1", "true" , "asimd" , "true"}, 405 counts = { IRNode.MIN_VI, "> 0" }) 406 @Arguments(setup = "setupIntArrays") 407 public Object[] testMinIntVector(int[] a, int[] b) { 408 int[] r = new int[a.length]; 409 410 for (int i = 0; i < a.length; i++) { 411 int aI = a[i]; 412 int bI = b[i]; 413 414 r[i] = aI < bI ? aI : bI; 415 } 416 417 return new Object[] { a, b, r }; 418 } 419 420 @Check(test = "testMinIntVector") 421 public void checkTestMinIntVector(Object[] vals) { 422 int[] a = (int[]) vals[0]; 423 int[] b = (int[]) vals[1]; 424 int[] testRet = (int[]) vals[2]; 425 426 for (int i = 0; i < a.length; i++) { 427 int aI = a[i]; 428 int bI = b[i]; 429 430 int r = aI < bI ? aI : bI; 431 432 if (r != testRet[i]) { 433 throw new IllegalStateException("Int min vectorization test failed: expected " + testRet + " but got " + r); 434 } 435 } 436 } 437 438 @Test 439 @IR(applyIfCPUFeatureOr = { "sse4.1", "true" , "asimd" , "true"}, 440 counts = { IRNode.MAX_VL, "> 0" }) 441 @Arguments(setup = "setupLongArrays") 442 public Object[] testMaxLongVector(long[] a, long[] b) { 443 long[] r = new long[a.length]; 444 445 for (int i = 0; i < a.length; i++) { 446 long aI = a[i]; 447 long bI = b[i]; 448 449 r[i] = aI > bI ? aI : bI; 450 } 451 452 return new Object[] { a, b, r }; 453 } 454 455 @Check(test = "testMaxLongVector") 456 public void checkTestMaxLongVector(Object[] vals) { 457 long[] a = (long[]) vals[0]; 458 long[] b = (long[]) vals[1]; 459 long[] testRet = (long[]) vals[2]; 460 461 for (int i = 0; i < a.length; i++) { 462 long aI = a[i]; 463 long bI = b[i]; 464 465 long r = aI > bI ? aI : bI; 466 467 if (r != testRet[i]) { 468 throw new IllegalStateException("Long max vectorization test failed: expected " + testRet + " but got " + r); 469 } 470 } 471 } 472 473 @Test 474 @IR(applyIfCPUFeatureOr = { "sse4.1", "true" , "asimd" , "true"}, 475 counts = { IRNode.MIN_VL, "> 0" }) 476 @Arguments(setup = "setupLongArrays") 477 public Object[] testMinLongVector(long[] a, long[] b) { 478 long[] r = new long[a.length]; 479 480 for (int i = 0; i < a.length; i++) { 481 long aI = a[i]; 482 long bI = b[i]; 483 484 r[i] = aI < bI ? aI : bI; 485 } 486 487 return new Object[] { a, b, r }; 488 } 489 490 @Check(test = "testMinLongVector") 491 public void checkTestMinLongVector(Object[] vals) { 492 long[] a = (long[]) vals[0]; 493 long[] b = (long[]) vals[1]; 494 long[] testRet = (long[]) vals[2]; 495 496 for (int i = 0; i < a.length; i++) { 497 long aI = a[i]; 498 long bI = b[i]; 499 500 long r = aI < bI ? aI : bI; 501 502 if (r != testRet[i]) { 503 throw new IllegalStateException("Long min vectorization test failed: expected " + testRet + " but got " + r); 504 } 505 } 506 } 507 508 @Run(test = { "testMinI1", "testMinI2", "testMaxI1", "testMaxI2", "testMinI1E", "testMinI2E", "testMaxI1E", "testMaxI2E" }) 509 public void runTestIntegers() { 510 testIntegers(10, 20); 511 testIntegers(20, 10); 512 testIntegers(10, 10); 513 testIntegers(Integer.MAX_VALUE, Integer.MIN_VALUE); 514 testIntegers(Integer.MIN_VALUE, Integer.MAX_VALUE); 515 testIntegers(RANDOM.nextInt(), RANDOM.nextInt()); 516 } 517 518 @DontCompile 519 public void testIntegers(int a, int b) { 520 Asserts.assertEQ(a < b ? a : b, testMinI1(a, b)); 521 Asserts.assertEQ(a > b ? b : a, testMinI2(a, b)); 522 Asserts.assertEQ(a > b ? a : b, testMaxI1(a, b)); 523 Asserts.assertEQ(a < b ? b : a, testMaxI2(a, b)); 524 525 Asserts.assertEQ(a <= b ? a : b, testMinI1E(a, b)); 526 Asserts.assertEQ(a >= b ? b : a, testMinI2E(a, b)); 527 Asserts.assertEQ(a >= b ? a : b, testMaxI1E(a, b)); 528 Asserts.assertEQ(a <= b ? b : a, testMaxI2E(a, b)); 529 } 530 531 @Run(test = { "testMinL1", "testMinL2", "testMaxL1", "testMaxL2", "testMinL1E", "testMinL2E", "testMaxL1E", "testMaxL2E" }) 532 public void runTestLongs() { 533 testLongs(10, 20); 534 testLongs(20, 10); 535 testLongs(10, 10); 536 testLongs(Integer.MAX_VALUE, Integer.MIN_VALUE); 537 testLongs(Integer.MIN_VALUE, Integer.MAX_VALUE); 538 testLongs(Long.MAX_VALUE, Long.MIN_VALUE); 539 testLongs(Long.MIN_VALUE, Long.MAX_VALUE); 540 testLongs(RANDOM.nextLong(), RANDOM.nextLong()); 541 } 542 543 @DontCompile 544 public void testLongs(long a, long b) { 545 Asserts.assertEQ(a < b ? a : b, testMinL1(a, b)); 546 Asserts.assertEQ(a > b ? b : a, testMinL2(a, b)); 547 Asserts.assertEQ(a > b ? a : b, testMaxL1(a, b)); 548 Asserts.assertEQ(a < b ? b : a, testMaxL2(a, b)); 549 550 Asserts.assertEQ(a <= b ? a : b, testMinL1E(a, b)); 551 Asserts.assertEQ(a >= b ? b : a, testMinL2E(a, b)); 552 Asserts.assertEQ(a >= b ? a : b, testMaxL1E(a, b)); 553 Asserts.assertEQ(a <= b ? b : a, testMaxL2E(a, b)); 554 } 555 }