1 /* 2 * Copyright (c) 2022, Arm Limited. All rights reserved. 3 * Copyright (c) 2023, 2024, Oracle and/or its affiliates. All rights reserved. 4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 5 * 6 * This code is free software; you can redistribute it and/or modify it 7 * under the terms of the GNU General Public License version 2 only, as 8 * published by the Free Software Foundation. 9 * 10 * This code is distributed in the hope that it will be useful, but WITHOUT 11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 13 * version 2 for more details (a copy is included in the LICENSE file that 14 * accompanied this code). 15 * 16 * You should have received a copy of the GNU General Public License version 17 * 2 along with this work; if not, write to the Free Software Foundation, 18 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 19 * 20 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 21 * or visit www.oracle.com if you need additional information or have any 22 * questions. 23 */ 24 25 package compiler.c2.irTests; 26 27 import compiler.lib.ir_framework.*; 28 import java.util.Random; 29 import jdk.test.lib.Asserts; 30 import jdk.test.lib.Utils; 31 32 /* 33 * @test 34 * @bug 8289422 8306088 8313720 35 * @key randomness 36 * @summary Auto-vectorization enhancement to support vector conditional move. 37 * @library /test/lib / 38 * @run driver compiler.c2.irTests.TestVectorConditionalMove 39 */ 40 41 public class TestVectorConditionalMove { 42 final private static int SIZE = 1024; 43 private static final Random RANDOM = Utils.getRandomInstance(); 44 45 public static void main(String[] args) { 46 // Cross-product: +-AlignVector and +-UseCompactObjectHeaders 47 TestFramework.runWithFlags("-XX:+UseCMoveUnconditionally", "-XX:+UseVectorCmov", 48 "-XX:+UnlockExperimentalVMOptions", "-XX:-UseCompactObjectHeaders", "-XX:-AlignVector"); 49 TestFramework.runWithFlags("-XX:+UseCMoveUnconditionally", "-XX:+UseVectorCmov", 50 "-XX:+UnlockExperimentalVMOptions", "-XX:-UseCompactObjectHeaders", "-XX:+AlignVector"); 51 TestFramework.runWithFlags("-XX:+UseCMoveUnconditionally", "-XX:+UseVectorCmov", 52 "-XX:+UnlockExperimentalVMOptions", "-XX:+UseCompactObjectHeaders", "-XX:-AlignVector"); 53 TestFramework.runWithFlags("-XX:+UseCMoveUnconditionally", "-XX:+UseVectorCmov", 54 "-XX:+UnlockExperimentalVMOptions", "-XX:+UseCompactObjectHeaders", "-XX:+AlignVector"); 55 } 56 57 // Compare 2 values, and pick one of them 58 private float cmoveFloatGT(float a, float b) { 59 return (a > b) ? a : b; 60 } 61 62 private float cmoveFloatGTSwap(float a, float b) { 63 return (b > a) ? a : b; 64 } 65 66 private float cmoveFloatLT(float a, float b) { 67 return (a < b) ? a : b; 68 } 69 70 private float cmoveFloatLTSwap(float a, float b) { 71 return (b < a) ? a : b; 72 } 73 74 private float cmoveFloatEQ(float a, float b) { 75 return (a == b) ? a : b; 76 } 77 78 private double cmoveDoubleLE(double a, double b) { 79 return (a <= b) ? a : b; 80 } 81 82 private double cmoveDoubleLESwap(double a, double b) { 83 return (b <= a) ? a : b; 84 } 85 86 private double cmoveDoubleGE(double a, double b) { 87 return (a >= b) ? a : b; 88 } 89 90 private double cmoveDoubleGESwap(double a, double b) { 91 return (b >= a) ? a : b; 92 } 93 94 private double cmoveDoubleNE(double a, double b) { 95 return (a != b) ? a : b; 96 } 97 98 // Extensions: compare 2 values, and pick from 2 consts 99 private float cmoveFGTforFConst(float a, float b) { 100 return (a > b) ? 0.1f : -0.1f; 101 } 102 103 private float cmoveFGEforFConst(float a, float b) { 104 return (a >= b) ? 0.1f : -0.1f; 105 } 106 107 private float cmoveFLTforFConst(float a, float b) { 108 return (a < b) ? 0.1f : -0.1f; 109 } 110 111 private float cmoveFLEforFConst(float a, float b) { 112 return (a <= b) ? 0.1f : -0.1f; 113 } 114 115 private float cmoveFEQforFConst(float a, float b) { 116 return (a == b) ? 0.1f : -0.1f; 117 } 118 119 private float cmoveFNEQforFConst(float a, float b) { 120 return (a != b) ? 0.1f : -0.1f; 121 } 122 123 private double cmoveDGTforDConst(double a, double b) { 124 return (a > b) ? 0.1 : -0.1; 125 } 126 127 private double cmoveDGEforDConst(double a, double b) { 128 return (a >= b) ? 0.1 : -0.1; 129 } 130 131 private double cmoveDLTforDConst(double a, double b) { 132 return (a < b) ? 0.1 : -0.1; 133 } 134 135 private double cmoveDLEforDConst(double a, double b) { 136 return (a <= b) ? 0.1 : -0.1; 137 } 138 139 private double cmoveDEQforDConst(double a, double b) { 140 return (a == b) ? 0.1 : -0.1; 141 } 142 143 private double cmoveDNEQforDConst(double a, double b) { 144 return (a != b) ? 0.1 : -0.1; 145 } 146 147 // Extension: Compare 2 ILFD values, and pick from 2 ILFD values 148 private int cmoveIGTforI(int a, int b, int c, int d) { 149 return (a > b) ? c : d; 150 } 151 152 private long cmoveIGTforL(int a, int b, long c, long d) { 153 return (a > b) ? c : d; 154 } 155 156 private float cmoveIGTforF(int a, int b, float c, float d) { 157 return (a > b) ? c : d; 158 } 159 160 private double cmoveIGTforD(int a, int b, double c, double d) { 161 return (a > b) ? c : d; 162 } 163 164 private int cmoveLGTforI(long a, long b, int c, int d) { 165 return (a > b) ? c : d; 166 } 167 168 private long cmoveLGTforL(long a, long b, long c, long d) { 169 return (a > b) ? c : d; 170 } 171 172 private float cmoveLGTforF(long a, long b, float c, float d) { 173 return (a > b) ? c : d; 174 } 175 176 private double cmoveLGTforD(long a, long b, double c, double d) { 177 return (a > b) ? c : d; 178 } 179 180 private int cmoveFGTforI(float a, float b, int c, int d) { 181 return (a > b) ? c : d; 182 } 183 184 private long cmoveFGTforL(float a, float b, long c, long d) { 185 return (a > b) ? c : d; 186 } 187 188 private float cmoveFGTforF(float a, float b, float c, float d) { 189 return (a > b) ? c : d; 190 } 191 192 private double cmoveFGTforD(float a, float b, double c, double d) { 193 return (a > b) ? c : d; 194 } 195 196 private int cmoveDGTforI(double a, double b, int c, int d) { 197 return (a > b) ? c : d; 198 } 199 200 private long cmoveDGTforL(double a, double b, long c, long d) { 201 return (a > b) ? c : d; 202 } 203 204 private float cmoveDGTforF(double a, double b, float c, float d) { 205 return (a > b) ? c : d; 206 } 207 208 private double cmoveDGTforD(double a, double b, double c, double d) { 209 return (a > b) ? c : d; 210 } 211 212 // Compare 2 values, and pick one of them 213 @Test 214 @IR(counts = {IRNode.LOAD_VECTOR_F, ">0", 215 IRNode.VECTOR_MASK_CMP_F, ">0", 216 IRNode.VECTOR_BLEND_F, ">0", 217 IRNode.STORE_VECTOR, ">0"}, 218 applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}) 219 private static void testCMoveVFGT(float[] a, float[] b, float[] c) { 220 for (int i = 0; i < a.length; i++) { 221 c[i] = (a[i] > b[i]) ? a[i] : b[i]; 222 } 223 } 224 225 @Test 226 @IR(counts = {IRNode.LOAD_VECTOR_F, ">0", 227 IRNode.VECTOR_MASK_CMP_F, ">0", 228 IRNode.VECTOR_BLEND_F, ">0", 229 IRNode.STORE_VECTOR, ">0"}, 230 applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}) 231 private static void testCMoveVFGTSwap(float[] a, float[] b, float[] c) { 232 for (int i = 0; i < a.length; i++) { 233 c[i] = (b[i] > a[i]) ? a[i] : b[i]; 234 } 235 } 236 237 @Test 238 @IR(counts = {IRNode.LOAD_VECTOR_F, ">0", 239 IRNode.VECTOR_MASK_CMP_F, ">0", 240 IRNode.VECTOR_BLEND_F, ">0", 241 IRNode.STORE_VECTOR, ">0"}, 242 applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}) 243 private static void testCMoveVFLT(float[] a, float[] b, float[] c) { 244 for (int i = 0; i < a.length; i++) { 245 c[i] = (a[i] < b[i]) ? a[i] : b[i]; 246 } 247 } 248 249 @Test 250 @IR(counts = {IRNode.LOAD_VECTOR_F, ">0", 251 IRNode.VECTOR_MASK_CMP_F, ">0", 252 IRNode.VECTOR_BLEND_F, ">0", 253 IRNode.STORE_VECTOR, ">0"}, 254 applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}) 255 private static void testCMoveVFLTSwap(float[] a, float[] b, float[] c) { 256 for (int i = 0; i < a.length; i++) { 257 c[i] = (b[i] < a[i]) ? a[i] : b[i]; 258 } 259 } 260 261 @Test 262 @IR(counts = {IRNode.LOAD_VECTOR_F, ">0", 263 IRNode.VECTOR_MASK_CMP_F, ">0", 264 IRNode.VECTOR_BLEND_F, ">0", 265 IRNode.STORE_VECTOR, ">0"}, 266 applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}) 267 private static void testCMoveVFEQ(float[] a, float[] b, float[] c) { 268 for (int i = 0; i < a.length; i++) { 269 c[i] = (a[i] == b[i]) ? a[i] : b[i]; 270 } 271 } 272 273 @Test 274 @IR(counts = {IRNode.LOAD_VECTOR_D, ">0", 275 IRNode.VECTOR_MASK_CMP_D, ">0", 276 IRNode.VECTOR_BLEND_D, ">0", 277 IRNode.STORE_VECTOR, ">0"}, 278 applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}) 279 private static void testCMoveVDLE(double[] a, double[] b, double[] c) { 280 for (int i = 0; i < a.length; i++) { 281 c[i] = (a[i] <= b[i]) ? a[i] : b[i]; 282 } 283 } 284 285 @Test 286 @IR(counts = {IRNode.LOAD_VECTOR_D, ">0", 287 IRNode.VECTOR_MASK_CMP_D, ">0", 288 IRNode.VECTOR_BLEND_D, ">0", 289 IRNode.STORE_VECTOR, ">0"}, 290 applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}) 291 private static void testCMoveVDLESwap(double[] a, double[] b, double[] c) { 292 for (int i = 0; i < a.length; i++) { 293 c[i] = (b[i] <= a[i]) ? a[i] : b[i]; 294 } 295 } 296 297 @Test 298 @IR(counts = {IRNode.LOAD_VECTOR_D, ">0", 299 IRNode.VECTOR_MASK_CMP_D, ">0", 300 IRNode.VECTOR_BLEND_D, ">0", 301 IRNode.STORE_VECTOR, ">0"}, 302 applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}) 303 private static void testCMoveVDGE(double[] a, double[] b, double[] c) { 304 for (int i = 0; i < a.length; i++) { 305 c[i] = (a[i] >= b[i]) ? a[i] : b[i]; 306 } 307 } 308 309 @Test 310 @IR(counts = {IRNode.LOAD_VECTOR_D, ">0", 311 IRNode.VECTOR_MASK_CMP_D, ">0", 312 IRNode.VECTOR_BLEND_D, ">0", 313 IRNode.STORE_VECTOR, ">0"}, 314 applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}) 315 private static void testCMoveVDGESwap(double[] a, double[] b, double[] c) { 316 for (int i = 0; i < a.length; i++) { 317 c[i] = (b[i] >= a[i]) ? a[i] : b[i]; 318 } 319 } 320 321 @Test 322 @IR(counts = {IRNode.LOAD_VECTOR_D, ">0", 323 IRNode.VECTOR_MASK_CMP_D, ">0", 324 IRNode.VECTOR_BLEND_D, ">0", 325 IRNode.STORE_VECTOR, ">0"}, 326 applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}) 327 private static void testCMoveVDNE(double[] a, double[] b, double[] c) { 328 for (int i = 0; i < a.length; i++) { 329 c[i] = (a[i] != b[i]) ? a[i] : b[i]; 330 } 331 } 332 333 // Extensions: compare 2 values, and pick from 2 consts 334 @Test 335 @IR(counts = {IRNode.LOAD_VECTOR_F, ">0", 336 IRNode.VECTOR_MASK_CMP_F, ">0", 337 IRNode.VECTOR_BLEND_F, ">0", 338 IRNode.STORE_VECTOR, ">0"}, 339 applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}) 340 private static void testCMoveFGTforFConst(float[] a, float[] b, float[] c) { 341 for (int i = 0; i < a.length; i++) { 342 c[i] = (a[i] > b[i]) ? 0.1f : -0.1f; 343 } 344 } 345 346 @Test 347 @IR(counts = {IRNode.LOAD_VECTOR_F, ">0", 348 IRNode.VECTOR_MASK_CMP_F, ">0", 349 IRNode.VECTOR_BLEND_F, ">0", 350 IRNode.STORE_VECTOR, ">0"}, 351 applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}) 352 private static void testCMoveFGEforFConst(float[] a, float[] b, float[] c) { 353 for (int i = 0; i < a.length; i++) { 354 c[i] = (a[i] >= b[i]) ? 0.1f : -0.1f; 355 } 356 } 357 358 @Test 359 @IR(counts = {IRNode.LOAD_VECTOR_F, ">0", 360 IRNode.VECTOR_MASK_CMP_F, ">0", 361 IRNode.VECTOR_BLEND_F, ">0", 362 IRNode.STORE_VECTOR, ">0"}, 363 applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}) 364 private static void testCMoveFLTforFConst(float[] a, float[] b, float[] c) { 365 for (int i = 0; i < a.length; i++) { 366 c[i] = (a[i] < b[i]) ? 0.1f : -0.1f; 367 } 368 } 369 370 @Test 371 @IR(counts = {IRNode.LOAD_VECTOR_F, ">0", 372 IRNode.VECTOR_MASK_CMP_F, ">0", 373 IRNode.VECTOR_BLEND_F, ">0", 374 IRNode.STORE_VECTOR, ">0"}, 375 applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}) 376 private static void testCMoveFLEforFConst(float[] a, float[] b, float[] c) { 377 for (int i = 0; i < a.length; i++) { 378 c[i] = (a[i] <= b[i]) ? 0.1f : -0.1f; 379 } 380 } 381 382 @Test 383 @IR(counts = {IRNode.LOAD_VECTOR_F, ">0", 384 IRNode.VECTOR_MASK_CMP_F, ">0", 385 IRNode.VECTOR_BLEND_F, ">0", 386 IRNode.STORE_VECTOR, ">0"}, 387 applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}) 388 private static void testCMoveFEQforFConst(float[] a, float[] b, float[] c) { 389 for (int i = 0; i < a.length; i++) { 390 c[i] = (a[i] == b[i]) ? 0.1f : -0.1f; 391 } 392 } 393 394 @Test 395 @IR(counts = {IRNode.LOAD_VECTOR_F, ">0", 396 IRNode.VECTOR_MASK_CMP_F, ">0", 397 IRNode.VECTOR_BLEND_F, ">0", 398 IRNode.STORE_VECTOR, ">0"}, 399 applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}) 400 private static void testCMoveFNEQforFConst(float[] a, float[] b, float[] c) { 401 for (int i = 0; i < a.length; i++) { 402 c[i] = (a[i] != b[i]) ? 0.1f : -0.1f; 403 } 404 } 405 406 @Test 407 @IR(counts = {IRNode.LOAD_VECTOR_F, ">0", 408 IRNode.VECTOR_MASK_CMP_F, ">0", 409 IRNode.VECTOR_BLEND_F, ">0", 410 IRNode.STORE_VECTOR, ">0"}, 411 applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}) 412 private static void testCMoveFLTforFConstH2(float[] a, float[] b, float[] c) { 413 for (int i = 0; i < a.length; i+=2) { 414 c[i+0] = (a[i+0] < b[i+0]) ? 0.1f : -0.1f; 415 c[i+1] = (a[i+1] < b[i+1]) ? 0.1f : -0.1f; 416 } 417 } 418 419 @Test 420 @IR(counts = {IRNode.LOAD_VECTOR_F, ">0", 421 IRNode.VECTOR_MASK_CMP_F, ">0", 422 IRNode.VECTOR_BLEND_F, ">0", 423 IRNode.STORE_VECTOR, ">0"}, 424 applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}) 425 private static void testCMoveFLEforFConstH2(float[] a, float[] b, float[] c) { 426 for (int i = 0; i < a.length; i+=2) { 427 c[i+0] = (a[i+0] <= b[i+0]) ? 0.1f : -0.1f; 428 c[i+1] = (a[i+1] <= b[i+1]) ? 0.1f : -0.1f; 429 } 430 } 431 432 @Test 433 @IR(counts = {IRNode.LOAD_VECTOR_F, "=0", 434 IRNode.VECTOR_MASK_CMP_F, "=0", 435 IRNode.VECTOR_BLEND_F, "=0", 436 IRNode.STORE_VECTOR, "=0"}, 437 applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}) 438 private static void testCMoveFYYforFConstH2(float[] a, float[] b, float[] c) { 439 for (int i = 0; i < a.length; i+=2) { 440 c[i+0] = (a[i+0] <= b[i+0]) ? 0.1f : -0.1f; 441 c[i+1] = (a[i+1] < b[i+1]) ? 0.1f : -0.1f; 442 } 443 } 444 445 @Test 446 @IR(counts = {IRNode.LOAD_VECTOR_F, "=0", 447 IRNode.VECTOR_MASK_CMP_F, "=0", 448 IRNode.VECTOR_BLEND_F, "=0", 449 IRNode.STORE_VECTOR, "=0"}, 450 applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}) 451 private static void testCMoveFXXforFConstH2(float[] a, float[] b, float[] c) { 452 for (int i = 0; i < a.length; i+=2) { 453 c[i+0] = (a[i+0] < b[i+0]) ? 0.1f : -0.1f; 454 c[i+1] = (a[i+1] <= b[i+1]) ? 0.1f : -0.1f; 455 } 456 } 457 458 @Test 459 @IR(counts = {IRNode.LOAD_VECTOR_D, ">0", 460 IRNode.VECTOR_MASK_CMP_D, ">0", 461 IRNode.VECTOR_BLEND_D, ">0", 462 IRNode.STORE_VECTOR, ">0"}, 463 applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}) 464 private static void testCMoveDGTforDConst(double[] a, double[] b, double[] c) { 465 for (int i = 0; i < a.length; i++) { 466 c[i] = (a[i] > b[i]) ? 0.1 : -0.1; 467 } 468 } 469 470 @Test 471 @IR(counts = {IRNode.LOAD_VECTOR_D, ">0", 472 IRNode.VECTOR_MASK_CMP_D, ">0", 473 IRNode.VECTOR_BLEND_D, ">0", 474 IRNode.STORE_VECTOR, ">0"}, 475 applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}) 476 private static void testCMoveDGEforDConst(double[] a, double[] b, double[] c) { 477 for (int i = 0; i < a.length; i++) { 478 c[i] = (a[i] >= b[i]) ? 0.1 : -0.1; 479 } 480 } 481 482 @Test 483 @IR(counts = {IRNode.LOAD_VECTOR_D, ">0", 484 IRNode.VECTOR_MASK_CMP_D, ">0", 485 IRNode.VECTOR_BLEND_D, ">0", 486 IRNode.STORE_VECTOR, ">0"}, 487 applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}) 488 private static void testCMoveDLTforDConst(double[] a, double[] b, double[] c) { 489 for (int i = 0; i < a.length; i++) { 490 c[i] = (a[i] < b[i]) ? 0.1 : -0.1; 491 } 492 } 493 494 @Test 495 @IR(counts = {IRNode.LOAD_VECTOR_D, ">0", 496 IRNode.VECTOR_MASK_CMP_D, ">0", 497 IRNode.VECTOR_BLEND_D, ">0", 498 IRNode.STORE_VECTOR, ">0"}, 499 applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}) 500 private static void testCMoveDLEforDConst(double[] a, double[] b, double[] c) { 501 for (int i = 0; i < a.length; i++) { 502 c[i] = (a[i] <= b[i]) ? 0.1 : -0.1; 503 } 504 } 505 506 @Test 507 @IR(counts = {IRNode.LOAD_VECTOR_D, ">0", 508 IRNode.VECTOR_MASK_CMP_D, ">0", 509 IRNode.VECTOR_BLEND_D, ">0", 510 IRNode.STORE_VECTOR, ">0"}, 511 applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}) 512 private static void testCMoveDEQforDConst(double[] a, double[] b, double[] c) { 513 for (int i = 0; i < a.length; i++) { 514 c[i] = (a[i] == b[i]) ? 0.1 : -0.1; 515 } 516 } 517 518 @Test 519 @IR(counts = {IRNode.LOAD_VECTOR_D, ">0", 520 IRNode.VECTOR_MASK_CMP_D, ">0", 521 IRNode.VECTOR_BLEND_D, ">0", 522 IRNode.STORE_VECTOR, ">0"}, 523 applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}) 524 private static void testCMoveDNEQforDConst(double[] a, double[] b, double[] c) { 525 for (int i = 0; i < a.length; i++) { 526 c[i] = (a[i] != b[i]) ? 0.1 : -0.1; 527 } 528 } 529 530 @Test 531 @IR(counts = {IRNode.LOAD_VECTOR_D, ">0", 532 IRNode.VECTOR_MASK_CMP_D, ">0", 533 IRNode.VECTOR_BLEND_D, ">0", 534 IRNode.STORE_VECTOR, ">0"}, 535 applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}) 536 private static void testCMoveDLTforDConstH2(double[] a, double[] b, double[] c) { 537 for (int i = 0; i < a.length; i+=2) { 538 c[i+0] = (a[i+0] < b[i+0]) ? 0.1 : -0.1; 539 c[i+1] = (a[i+1] < b[i+1]) ? 0.1 : -0.1; 540 } 541 } 542 543 @Test 544 @IR(counts = {IRNode.LOAD_VECTOR_D, ">0", 545 IRNode.VECTOR_MASK_CMP_D, ">0", 546 IRNode.VECTOR_BLEND_D, ">0", 547 IRNode.STORE_VECTOR, ">0"}, 548 applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}) 549 private static void testCMoveDLEforDConstH2(double[] a, double[] b, double[] c) { 550 for (int i = 0; i < a.length; i+=2) { 551 c[i+0] = (a[i+0] <= b[i+0]) ? 0.1 : -0.1; 552 c[i+1] = (a[i+1] <= b[i+1]) ? 0.1 : -0.1; 553 } 554 } 555 556 @Test 557 @IR(counts = {IRNode.LOAD_VECTOR_D, "=0", 558 IRNode.VECTOR_MASK_CMP_D, "=0", 559 IRNode.VECTOR_BLEND_D, "=0", 560 IRNode.STORE_VECTOR, "=0"}, 561 applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}) 562 private static void testCMoveDYYforDConstH2(double[] a, double[] b, double[] c) { 563 for (int i = 0; i < a.length; i+=2) { 564 c[i+0] = (a[i+0] <= b[i+0]) ? 0.1 : -0.1; 565 c[i+1] = (a[i+1] < b[i+1]) ? 0.1 : -0.1; 566 } 567 } 568 569 @Test 570 @IR(counts = {IRNode.LOAD_VECTOR_D, "=0", 571 IRNode.VECTOR_MASK_CMP_D, "=0", 572 IRNode.VECTOR_BLEND_D, "=0", 573 IRNode.STORE_VECTOR, "=0"}, 574 applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}) 575 private static void testCMoveDXXforDConstH2(double[] a, double[] b, double[] c) { 576 for (int i = 0; i < a.length; i+=2) { 577 c[i+0] = (a[i+0] < b[i+0]) ? 0.1 : -0.1; 578 c[i+1] = (a[i+1] <= b[i+1]) ? 0.1 : -0.1; 579 } 580 } 581 582 // Extension: Compare 2 ILFD values, and pick from 2 ILFD values 583 // Note: 584 // To guarantee that CMove is introduced, I need to perform the loads before the branch. To ensure they 585 // do not float down into the branches, I compute a value, and store it to r2 (same as r, except that the 586 // compilation does not know that). 587 // So far, vectorization only works for CMoveF/D, with same data-width comparison (F/I for F, D/L for D). 588 @Test 589 @IR(failOn = {IRNode.STORE_VECTOR}) 590 private static void testCMoveIGTforI(int[] a, int[] b, int[] c, int[] d, int[] r, int[] r2) { 591 for (int i = 0; i < a.length; i++) { 592 int cc = c[i]; 593 int dd = d[i]; 594 r2[i] = cc + dd; 595 r[i] = (a[i] > b[i]) ? cc : dd; 596 } 597 } 598 599 @Test 600 @IR(failOn = {IRNode.STORE_VECTOR}) 601 private static void testCMoveIGTforL(int[] a, int[] b, long[] c, long[] d, long[] r, long[] r2) { 602 for (int i = 0; i < a.length; i++) { 603 long cc = c[i]; 604 long dd = d[i]; 605 r2[i] = cc + dd; 606 r[i] = (a[i] > b[i]) ? cc : dd; 607 } 608 } 609 610 @Test 611 @IR(counts = {IRNode.LOAD_VECTOR_I, IRNode.VECTOR_SIZE + "min(max_int, max_float)", ">0", 612 IRNode.LOAD_VECTOR_F, IRNode.VECTOR_SIZE + "min(max_int, max_float)", ">0", 613 IRNode.VECTOR_MASK_CMP_I, IRNode.VECTOR_SIZE + "min(max_int, max_float)", ">0", 614 IRNode.VECTOR_BLEND_F, IRNode.VECTOR_SIZE + "min(max_int, max_float)", ">0", 615 IRNode.STORE_VECTOR, ">0"}, 616 applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}) 617 private static void testCMoveIGTforF(int[] a, int[] b, float[] c, float[] d, float[] r, float[] r2) { 618 for (int i = 0; i < a.length; i++) { 619 float cc = c[i]; 620 float dd = d[i]; 621 r2[i] = cc + dd; 622 r[i] = (a[i] > b[i]) ? cc : dd; 623 } 624 } 625 626 @Test 627 @IR(failOn = {IRNode.STORE_VECTOR}) 628 private static void testCMoveIGTforD(int[] a, int[] b, double[] c, double[] d, double[] r, double[] r2) { 629 for (int i = 0; i < a.length; i++) { 630 double cc = c[i]; 631 double dd = d[i]; 632 r2[i] = cc + dd; 633 r[i] = (a[i] > b[i]) ? cc : dd; 634 } 635 } 636 637 @Test 638 @IR(failOn = {IRNode.STORE_VECTOR}) 639 private static void testCMoveLGTforI(long[] a, long[] b, int[] c, int[] d, int[] r, int[] r2) { 640 for (int i = 0; i < a.length; i++) { 641 int cc = c[i]; 642 int dd = d[i]; 643 r2[i] = cc + dd; 644 r[i] = (a[i] > b[i]) ? cc : dd; 645 } 646 } 647 648 @Test 649 @IR(failOn = {IRNode.STORE_VECTOR}) 650 private static void testCMoveLGTforL(long[] a, long[] b, long[] c, long[] d, long[] r, long[] r2) { 651 for (int i = 0; i < a.length; i++) { 652 long cc = c[i]; 653 long dd = d[i]; 654 r2[i] = cc + dd; 655 r[i] = (a[i] > b[i]) ? cc : dd; 656 } 657 } 658 659 @Test 660 @IR(failOn = {IRNode.STORE_VECTOR}) 661 private static void testCMoveLGTforF(long[] a, long[] b, float[] c, float[] d, float[] r, float[] r2) { 662 for (int i = 0; i < a.length; i++) { 663 float cc = c[i]; 664 float dd = d[i]; 665 r2[i] = cc + dd; 666 r[i] = (a[i] > b[i]) ? cc : dd; 667 } 668 } 669 670 @Test 671 @IR(counts = {IRNode.LOAD_VECTOR_L, IRNode.VECTOR_SIZE + "min(max_long, max_double)", ">0", 672 IRNode.LOAD_VECTOR_D, IRNode.VECTOR_SIZE + "min(max_long, max_double)", ">0", 673 IRNode.VECTOR_MASK_CMP_L, IRNode.VECTOR_SIZE + "min(max_long, max_double)", ">0", 674 IRNode.VECTOR_BLEND_D, IRNode.VECTOR_SIZE + "min(max_long, max_double)", ">0", 675 IRNode.STORE_VECTOR, ">0"}, 676 applyIfCPUFeatureOr = {"avx2", "true", "asimd", "true"}) 677 // Requires avx2, else L is restricted to 16 byte, and D has 32. That leads to a vector elements mismatch of 2 to 4. 678 private static void testCMoveLGTforD(long[] a, long[] b, double[] c, double[] d, double[] r, double[] r2) { 679 for (int i = 0; i < a.length; i++) { 680 double cc = c[i]; 681 double dd = d[i]; 682 r2[i] = cc + dd; 683 r[i] = (a[i] > b[i]) ? cc : dd; 684 } 685 } 686 687 @Test 688 @IR(failOn = {IRNode.STORE_VECTOR}) 689 private static void testCMoveFGTforI(float[] a, float[] b, int[] c, int[] d, int[] r, int[] r2) { 690 for (int i = 0; i < a.length; i++) { 691 int cc = c[i]; 692 int dd = d[i]; 693 r2[i] = cc + dd; 694 r[i] = (a[i] > b[i]) ? cc : dd; 695 } 696 } 697 698 @Test 699 @IR(failOn = {IRNode.STORE_VECTOR}) 700 private static void testCMoveFGTforL(float[] a, float[] b, long[] c, long[] d, long[] r, long[] r2) { 701 for (int i = 0; i < a.length; i++) { 702 long cc = c[i]; 703 long dd = d[i]; 704 r2[i] = cc + dd; 705 r[i] = (a[i] > b[i]) ? cc : dd; 706 } 707 } 708 709 @Test 710 @IR(counts = {IRNode.LOAD_VECTOR_F, ">0", 711 IRNode.VECTOR_MASK_CMP_F, ">0", 712 IRNode.VECTOR_BLEND_F, ">0", 713 IRNode.STORE_VECTOR, ">0"}, 714 applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}) 715 private static void testCMoveFGTforF(float[] a, float[] b, float[] c, float[] d, float[] r, float[] r2) { 716 for (int i = 0; i < a.length; i++) { 717 float cc = c[i]; 718 float dd = d[i]; 719 r2[i] = cc + dd; 720 r[i] = (a[i] > b[i]) ? cc : dd; 721 } 722 } 723 724 @Test 725 @IR(failOn = {IRNode.STORE_VECTOR}) 726 private static void testCMoveFGTforD(float[] a, float[] b, double[] c, double[] d, double[] r, double[] r2) { 727 for (int i = 0; i < a.length; i++) { 728 double cc = c[i]; 729 double dd = d[i]; 730 r2[i] = cc + dd; 731 r[i] = (a[i] > b[i]) ? cc : dd; 732 } 733 } 734 735 @Test 736 @IR(failOn = {IRNode.STORE_VECTOR}) 737 private static void testCMoveDGTforI(double[] a, double[] b, int[] c, int[] d, int[] r, int[] r2) { 738 for (int i = 0; i < a.length; i++) { 739 int cc = c[i]; 740 int dd = d[i]; 741 r2[i] = cc + dd; 742 r[i] = (a[i] > b[i]) ? cc : dd; 743 } 744 } 745 746 @Test 747 @IR(failOn = {IRNode.STORE_VECTOR}) 748 private static void testCMoveDGTforL(double[] a, double[] b, long[] c, long[] d, long[] r, long[] r2) { 749 for (int i = 0; i < a.length; i++) { 750 long cc = c[i]; 751 long dd = d[i]; 752 r2[i] = cc + dd; 753 r[i] = (a[i] > b[i]) ? cc : dd; 754 } 755 } 756 757 @Test 758 @IR(failOn = {IRNode.STORE_VECTOR}) 759 private static void testCMoveDGTforF(double[] a, double[] b, float[] c, float[] d, float[] r, float[] r2) { 760 for (int i = 0; i < a.length; i++) { 761 float cc = c[i]; 762 float dd = d[i]; 763 r2[i] = cc + dd; 764 r[i] = (a[i] > b[i]) ? cc : dd; 765 } 766 } 767 768 @Test 769 @IR(counts = {IRNode.LOAD_VECTOR_D, ">0", 770 IRNode.VECTOR_MASK_CMP_D, ">0", 771 IRNode.VECTOR_BLEND_D, ">0", 772 IRNode.STORE_VECTOR, ">0"}, 773 applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}) 774 private static void testCMoveDGTforD(double[] a, double[] b, double[] c, double[] d, double[] r, double[] r2) { 775 for (int i = 0; i < a.length; i++) { 776 double cc = c[i]; 777 double dd = d[i]; 778 r2[i] = cc + dd; 779 r[i] = (a[i] > b[i]) ? cc : dd; 780 } 781 } 782 783 // Use some constants in the comparison 784 @Test 785 @IR(counts = {IRNode.LOAD_VECTOR_F, ">0", 786 IRNode.VECTOR_MASK_CMP_F, ">0", 787 IRNode.VECTOR_BLEND_F, ">0", 788 IRNode.STORE_VECTOR, ">0"}, 789 applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}) 790 private static void testCMoveFGTforFCmpCon1(float a, float[] b, float[] c, float[] d, float[] r, float[] r2) { 791 for (int i = 0; i < b.length; i++) { 792 float cc = c[i]; 793 float dd = d[i]; 794 r2[i] = cc + dd; 795 r[i] = (a > b[i]) ? cc : dd; 796 } 797 } 798 799 @Test 800 @IR(counts = {IRNode.LOAD_VECTOR_F, ">0", 801 IRNode.VECTOR_MASK_CMP_F, ">0", 802 IRNode.VECTOR_BLEND_F, ">0", 803 IRNode.STORE_VECTOR, ">0"}, 804 applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}) 805 private static void testCMoveFGTforFCmpCon2(float[] a, float b, float[] c, float[] d, float[] r, float[] r2) { 806 for (int i = 0; i < a.length; i++) { 807 float cc = c[i]; 808 float dd = d[i]; 809 r2[i] = cc + dd; 810 r[i] = (a[i] > b) ? cc : dd; 811 } 812 } 813 814 // A case that is currently not supported and is not expected to vectorize 815 @Test 816 @IR(failOn = {IRNode.STORE_VECTOR}) 817 private static void testCMoveVDUnsupported() { 818 double[] doublec = new double[SIZE]; 819 int seed = 1001; 820 for (int i = 0; i < doublec.length; i++) { 821 doublec[i] = (i % 2 == 0) ? seed + i : seed - i; 822 } 823 } 824 825 @Warmup(0) 826 @Run(test = {"testCMoveVFGT", "testCMoveVFLT","testCMoveVDLE", "testCMoveVDGE", "testCMoveVFEQ", "testCMoveVDNE", 827 "testCMoveVFGTSwap", "testCMoveVFLTSwap","testCMoveVDLESwap", "testCMoveVDGESwap", 828 "testCMoveFGTforFConst", "testCMoveFGEforFConst", "testCMoveFLTforFConst", 829 "testCMoveFLEforFConst", "testCMoveFEQforFConst", "testCMoveFNEQforFConst", 830 "testCMoveDGTforDConst", "testCMoveDGEforDConst", "testCMoveDLTforDConst", 831 "testCMoveDLEforDConst", "testCMoveDEQforDConst", "testCMoveDNEQforDConst", 832 "testCMoveFLTforFConstH2", "testCMoveFLEforFConstH2", 833 "testCMoveFYYforFConstH2", "testCMoveFXXforFConstH2", 834 "testCMoveDLTforDConstH2", "testCMoveDLEforDConstH2", 835 "testCMoveDYYforDConstH2", "testCMoveDXXforDConstH2"}) 836 private void testCMove_runner() { 837 float[] floata = new float[SIZE]; 838 float[] floatb = new float[SIZE]; 839 float[] floatc = new float[SIZE]; 840 double[] doublea = new double[SIZE]; 841 double[] doubleb = new double[SIZE]; 842 double[] doublec = new double[SIZE]; 843 844 init(floata); 845 init(floatb); 846 init(doublea); 847 init(doubleb); 848 849 testCMoveVFGT(floata, floatb, floatc); 850 testCMoveVDLE(doublea, doubleb, doublec); 851 for (int i = 0; i < SIZE; i++) { 852 Asserts.assertEquals(floatc[i], cmoveFloatGT(floata[i], floatb[i])); 853 Asserts.assertEquals(doublec[i], cmoveDoubleLE(doublea[i], doubleb[i])); 854 } 855 856 testCMoveVFLT(floata, floatb, floatc); 857 testCMoveVDGE(doublea, doubleb, doublec); 858 for (int i = 0; i < SIZE; i++) { 859 Asserts.assertEquals(floatc[i], cmoveFloatLT(floata[i], floatb[i])); 860 Asserts.assertEquals(doublec[i], cmoveDoubleGE(doublea[i], doubleb[i])); 861 } 862 863 // Ensure we frequently have equals 864 for (int i = 0; i < SIZE; i++) { 865 if (i % 3 == 0) { 866 floatb[i] = floata[i]; 867 doubleb[i] = doublea[i]; 868 } 869 } 870 871 testCMoveVFEQ(floata, floatb, floatc); 872 testCMoveVDNE(doublea, doubleb, doublec); 873 for (int i = 0; i < SIZE; i++) { 874 Asserts.assertEquals(floatc[i], cmoveFloatEQ(floata[i], floatb[i])); 875 Asserts.assertEquals(doublec[i], cmoveDoubleNE(doublea[i], doubleb[i])); 876 } 877 878 testCMoveVFGTSwap(floata, floatb, floatc); 879 testCMoveVDLESwap(doublea, doubleb, doublec); 880 for (int i = 0; i < SIZE; i++) { 881 Asserts.assertEquals(floatc[i], cmoveFloatGTSwap(floata[i], floatb[i])); 882 Asserts.assertEquals(doublec[i], cmoveDoubleLESwap(doublea[i], doubleb[i])); 883 } 884 885 testCMoveVFLTSwap(floata, floatb, floatc); 886 testCMoveVDGESwap(doublea, doubleb, doublec); 887 for (int i = 0; i < SIZE; i++) { 888 Asserts.assertEquals(floatc[i], cmoveFloatLTSwap(floata[i], floatb[i])); 889 Asserts.assertEquals(doublec[i], cmoveDoubleGESwap(doublea[i], doubleb[i])); 890 } 891 892 // Extensions: compare 2 values, and pick from 2 consts 893 testCMoveFGTforFConst(floata, floatb, floatc); 894 testCMoveDGTforDConst(doublea, doubleb, doublec); 895 for (int i = 0; i < SIZE; i++) { 896 Asserts.assertEquals(floatc[i], cmoveFGTforFConst(floata[i], floatb[i])); 897 Asserts.assertEquals(doublec[i], cmoveDGTforDConst(doublea[i], doubleb[i])); 898 } 899 900 testCMoveFGEforFConst(floata, floatb, floatc); 901 testCMoveDGEforDConst(doublea, doubleb, doublec); 902 for (int i = 0; i < SIZE; i++) { 903 Asserts.assertEquals(floatc[i], cmoveFGEforFConst(floata[i], floatb[i])); 904 Asserts.assertEquals(doublec[i], cmoveDGEforDConst(doublea[i], doubleb[i])); 905 } 906 907 testCMoveFLTforFConst(floata, floatb, floatc); 908 testCMoveDLTforDConst(doublea, doubleb, doublec); 909 for (int i = 0; i < SIZE; i++) { 910 Asserts.assertEquals(floatc[i], cmoveFLTforFConst(floata[i], floatb[i])); 911 Asserts.assertEquals(doublec[i], cmoveDLTforDConst(doublea[i], doubleb[i])); 912 } 913 914 testCMoveFLEforFConst(floata, floatb, floatc); 915 testCMoveDLEforDConst(doublea, doubleb, doublec); 916 for (int i = 0; i < SIZE; i++) { 917 Asserts.assertEquals(floatc[i], cmoveFLEforFConst(floata[i], floatb[i])); 918 Asserts.assertEquals(doublec[i], cmoveDLEforDConst(doublea[i], doubleb[i])); 919 } 920 921 testCMoveFEQforFConst(floata, floatb, floatc); 922 testCMoveDEQforDConst(doublea, doubleb, doublec); 923 for (int i = 0; i < SIZE; i++) { 924 Asserts.assertEquals(floatc[i], cmoveFEQforFConst(floata[i], floatb[i])); 925 Asserts.assertEquals(doublec[i], cmoveDEQforDConst(doublea[i], doubleb[i])); 926 } 927 928 testCMoveFNEQforFConst(floata, floatb, floatc); 929 testCMoveDNEQforDConst(doublea, doubleb, doublec); 930 for (int i = 0; i < SIZE; i++) { 931 Asserts.assertEquals(floatc[i], cmoveFNEQforFConst(floata[i], floatb[i])); 932 Asserts.assertEquals(doublec[i], cmoveDNEQforDConst(doublea[i], doubleb[i])); 933 } 934 935 // Hand-unrolled (H2) examples: 936 testCMoveFLTforFConstH2(floata, floatb, floatc); 937 testCMoveDLTforDConstH2(doublea, doubleb, doublec); 938 for (int i = 0; i < SIZE; i++) { 939 Asserts.assertEquals(floatc[i], cmoveFLTforFConst(floata[i], floatb[i])); 940 Asserts.assertEquals(doublec[i], cmoveDLTforDConst(doublea[i], doubleb[i])); 941 } 942 943 testCMoveFLEforFConstH2(floata, floatb, floatc); 944 testCMoveDLEforDConstH2(doublea, doubleb, doublec); 945 for (int i = 0; i < SIZE; i++) { 946 Asserts.assertEquals(floatc[i], cmoveFLEforFConst(floata[i], floatb[i])); 947 Asserts.assertEquals(doublec[i], cmoveDLEforDConst(doublea[i], doubleb[i])); 948 } 949 950 testCMoveFYYforFConstH2(floata, floatb, floatc); 951 testCMoveDYYforDConstH2(doublea, doubleb, doublec); 952 for (int i = 0; i < SIZE; i+=2) { 953 Asserts.assertEquals(floatc[i+0], cmoveFLEforFConst(floata[i+0], floatb[i+0])); 954 Asserts.assertEquals(doublec[i+0], cmoveDLEforDConst(doublea[i+0], doubleb[i+0])); 955 Asserts.assertEquals(floatc[i+1], cmoveFLTforFConst(floata[i+1], floatb[i+1])); 956 Asserts.assertEquals(doublec[i+1], cmoveDLTforDConst(doublea[i+1], doubleb[i+1])); 957 } 958 959 testCMoveFXXforFConstH2(floata, floatb, floatc); 960 testCMoveDXXforDConstH2(doublea, doubleb, doublec); 961 for (int i = 0; i < SIZE; i+=2) { 962 Asserts.assertEquals(floatc[i+0], cmoveFLTforFConst(floata[i+0], floatb[i+0])); 963 Asserts.assertEquals(doublec[i+0], cmoveDLTforDConst(doublea[i+0], doubleb[i+0])); 964 Asserts.assertEquals(floatc[i+1], cmoveFLEforFConst(floata[i+1], floatb[i+1])); 965 Asserts.assertEquals(doublec[i+1], cmoveDLEforDConst(doublea[i+1], doubleb[i+1])); 966 } 967 } 968 969 @Warmup(0) 970 @Run(test = {"testCMoveIGTforI", 971 "testCMoveIGTforL", 972 "testCMoveIGTforF", 973 "testCMoveIGTforD", 974 "testCMoveLGTforI", 975 "testCMoveLGTforL", 976 "testCMoveLGTforF", 977 "testCMoveLGTforD", 978 "testCMoveFGTforI", 979 "testCMoveFGTforL", 980 "testCMoveFGTforF", 981 "testCMoveFGTforD", 982 "testCMoveDGTforI", 983 "testCMoveDGTforL", 984 "testCMoveDGTforF", 985 "testCMoveDGTforD", 986 "testCMoveFGTforFCmpCon1", 987 "testCMoveFGTforFCmpCon2"}) 988 private void testCMove_runner_two() { 989 int[] aI = new int[SIZE]; 990 int[] bI = new int[SIZE]; 991 int[] cI = new int[SIZE]; 992 int[] dI = new int[SIZE]; 993 int[] rI = new int[SIZE]; 994 long[] aL = new long[SIZE]; 995 long[] bL = new long[SIZE]; 996 long[] cL = new long[SIZE]; 997 long[] dL = new long[SIZE]; 998 long[] rL = new long[SIZE]; 999 float[] aF = new float[SIZE]; 1000 float[] bF = new float[SIZE]; 1001 float[] cF = new float[SIZE]; 1002 float[] dF = new float[SIZE]; 1003 float[] rF = new float[SIZE]; 1004 double[] aD = new double[SIZE]; 1005 double[] bD = new double[SIZE]; 1006 double[] cD = new double[SIZE]; 1007 double[] dD = new double[SIZE]; 1008 double[] rD = new double[SIZE]; 1009 1010 init(aI); 1011 init(bI); 1012 init(cI); 1013 init(dI); 1014 init(aL); 1015 init(bL); 1016 init(cL); 1017 init(dL); 1018 init(aF); 1019 init(bF); 1020 init(cF); 1021 init(dF); 1022 init(aD); 1023 init(bD); 1024 init(cD); 1025 init(dD); 1026 1027 testCMoveIGTforI(aI, bI, cI, dI, rI, rI); 1028 for (int i = 0; i < SIZE; i++) { 1029 Asserts.assertEquals(rI[i], cmoveIGTforI(aI[i], bI[i], cI[i], dI[i])); 1030 } 1031 1032 testCMoveIGTforL(aI, bI, cL, dL, rL, rL); 1033 for (int i = 0; i < SIZE; i++) { 1034 Asserts.assertEquals(rL[i], cmoveIGTforL(aI[i], bI[i], cL[i], dL[i])); 1035 } 1036 1037 testCMoveIGTforF(aI, bI, cF, dF, rF, rF); 1038 for (int i = 0; i < SIZE; i++) { 1039 Asserts.assertEquals(rF[i], cmoveIGTforF(aI[i], bI[i], cF[i], dF[i])); 1040 } 1041 1042 testCMoveIGTforD(aI, bI, cD, dD, rD, rD); 1043 for (int i = 0; i < SIZE; i++) { 1044 Asserts.assertEquals(rD[i], cmoveIGTforD(aI[i], bI[i], cD[i], dD[i])); 1045 } 1046 1047 testCMoveLGTforI(aL, bL, cI, dI, rI, rI); 1048 for (int i = 0; i < SIZE; i++) { 1049 Asserts.assertEquals(rI[i], cmoveLGTforI(aL[i], bL[i], cI[i], dI[i])); 1050 } 1051 1052 testCMoveLGTforL(aL, bL, cL, dL, rL, rL); 1053 for (int i = 0; i < SIZE; i++) { 1054 Asserts.assertEquals(rL[i], cmoveLGTforL(aL[i], bL[i], cL[i], dL[i])); 1055 } 1056 1057 testCMoveLGTforF(aL, bL, cF, dF, rF, rF); 1058 for (int i = 0; i < SIZE; i++) { 1059 Asserts.assertEquals(rF[i], cmoveLGTforF(aL[i], bL[i], cF[i], dF[i])); 1060 } 1061 1062 testCMoveLGTforD(aL, bL, cD, dD, rD, rD); 1063 for (int i = 0; i < SIZE; i++) { 1064 Asserts.assertEquals(rD[i], cmoveLGTforD(aL[i], bL[i], cD[i], dD[i])); 1065 } 1066 1067 testCMoveFGTforI(aF, bF, cI, dI, rI, rI); 1068 for (int i = 0; i < SIZE; i++) { 1069 Asserts.assertEquals(rI[i], cmoveFGTforI(aF[i], bF[i], cI[i], dI[i])); 1070 } 1071 1072 testCMoveFGTforL(aF, bF, cL, dL, rL, rL); 1073 for (int i = 0; i < SIZE; i++) { 1074 Asserts.assertEquals(rL[i], cmoveFGTforL(aF[i], bF[i], cL[i], dL[i])); 1075 } 1076 1077 testCMoveFGTforF(aF, bF, cF, dF, rF, rF); 1078 for (int i = 0; i < SIZE; i++) { 1079 Asserts.assertEquals(rF[i], cmoveFGTforF(aF[i], bF[i], cF[i], dF[i])); 1080 } 1081 1082 testCMoveFGTforD(aF, bF, cD, dD, rD, rD); 1083 for (int i = 0; i < SIZE; i++) { 1084 Asserts.assertEquals(rD[i], cmoveFGTforD(aF[i], bF[i], cD[i], dD[i])); 1085 } 1086 1087 testCMoveDGTforI(aD, bD, cI, dI, rI, rI); 1088 for (int i = 0; i < SIZE; i++) { 1089 Asserts.assertEquals(rI[i], cmoveDGTforI(aD[i], bD[i], cI[i], dI[i])); 1090 } 1091 1092 testCMoveDGTforL(aD, bD, cL, dL, rL, rL); 1093 for (int i = 0; i < SIZE; i++) { 1094 Asserts.assertEquals(rL[i], cmoveDGTforL(aD[i], bD[i], cL[i], dL[i])); 1095 } 1096 1097 testCMoveDGTforF(aD, bD, cF, dF, rF, rF); 1098 for (int i = 0; i < SIZE; i++) { 1099 Asserts.assertEquals(rF[i], cmoveDGTforF(aD[i], bD[i], cF[i], dF[i])); 1100 } 1101 1102 testCMoveDGTforD(aD, bD, cD, dD, rD, rD); 1103 for (int i = 0; i < SIZE; i++) { 1104 Asserts.assertEquals(rD[i], cmoveDGTforD(aD[i], bD[i], cD[i], dD[i])); 1105 } 1106 1107 // Use some constants/invariants in the comparison 1108 testCMoveFGTforFCmpCon1(aF[0], bF, cF, dF, rF, rF); 1109 for (int i = 0; i < SIZE; i++) { 1110 Asserts.assertEquals(rF[i], cmoveFGTforF(aF[0], bF[i], cF[i], dF[i])); 1111 } 1112 1113 testCMoveFGTforFCmpCon2(aF, bF[0], cF, dF, rF, rF); 1114 for (int i = 0; i < SIZE; i++) { 1115 Asserts.assertEquals(rF[i], cmoveFGTforF(aF[i], bF[0], cF[i], dF[i])); 1116 } 1117 } 1118 1119 private static void init(int[] a) { 1120 for (int i = 0; i < SIZE; i++) { 1121 a[i] = RANDOM.nextInt(); 1122 } 1123 } 1124 1125 private static void init(long[] a) { 1126 for (int i = 0; i < SIZE; i++) { 1127 a[i] = RANDOM.nextLong(); 1128 } 1129 } 1130 1131 private static void init(float[] a) { 1132 for (int i = 0; i < SIZE; i++) { 1133 a[i] = switch(RANDOM.nextInt() % 20) { 1134 case 0 -> Float.NaN; 1135 case 1 -> 0; 1136 case 2 -> 1; 1137 case 3 -> Float.POSITIVE_INFINITY; 1138 case 4 -> Float.NEGATIVE_INFINITY; 1139 case 5 -> Float.MAX_VALUE; 1140 case 6 -> Float.MIN_VALUE; 1141 case 7, 8, 9 -> RANDOM.nextFloat(); 1142 default -> Float.intBitsToFloat(RANDOM.nextInt()); 1143 }; 1144 } 1145 } 1146 1147 private static void init(double[] a) { 1148 for (int i = 0; i < SIZE; i++) { 1149 a[i] = switch(RANDOM.nextInt() % 20) { 1150 case 0 -> Double.NaN; 1151 case 1 -> 0; 1152 case 2 -> 1; 1153 case 3 -> Double.POSITIVE_INFINITY; 1154 case 4 -> Double.NEGATIVE_INFINITY; 1155 case 5 -> Double.MAX_VALUE; 1156 case 6 -> Double.MIN_VALUE; 1157 case 7, 8, 9 -> RANDOM.nextDouble(); 1158 default -> Double.longBitsToDouble(RANDOM.nextLong()); 1159 }; 1160 } 1161 } 1162 }