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 applyIfOr = {"UseCompactObjectHeaders", "false", "AlignVector", "false"}, 412 applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}) 413 private static void testCMoveFLTforFConstH2(float[] a, float[] b, float[] c) { 414 for (int i = 0; i < a.length; i+=2) { 415 c[i+0] = (a[i+0] < b[i+0]) ? 0.1f : -0.1f; 416 c[i+1] = (a[i+1] < b[i+1]) ? 0.1f : -0.1f; 417 // With AlignVector, we need 8-byte alignment of vector loads/stores. 418 // UseCompactObjectHeaders=false UseCompactObjectHeaders=true 419 // adr = base + 16 + 8*i -> always adr = base + 12 + 8*i -> never 420 // -> vectorize -> no vectorization 421 } 422 } 423 424 @Test 425 @IR(counts = {IRNode.LOAD_VECTOR_F, ">0", 426 IRNode.VECTOR_MASK_CMP_F, ">0", 427 IRNode.VECTOR_BLEND_F, ">0", 428 IRNode.STORE_VECTOR, ">0"}, 429 applyIfOr = {"UseCompactObjectHeaders", "false", "AlignVector", "false"}, 430 applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}) 431 private static void testCMoveFLEforFConstH2(float[] a, float[] b, float[] c) { 432 for (int i = 0; i < a.length; i+=2) { 433 c[i+0] = (a[i+0] <= b[i+0]) ? 0.1f : -0.1f; 434 c[i+1] = (a[i+1] <= b[i+1]) ? 0.1f : -0.1f; 435 // With AlignVector, we need 8-byte alignment of vector loads/stores. 436 // UseCompactObjectHeaders=false UseCompactObjectHeaders=true 437 // adr = base + 16 + 8*i -> always adr = base + 12 + 8*i -> never 438 // -> vectorize -> no vectorization 439 } 440 } 441 442 @Test 443 @IR(counts = {IRNode.LOAD_VECTOR_F, "=0", 444 IRNode.VECTOR_MASK_CMP_F, "=0", 445 IRNode.VECTOR_BLEND_F, "=0", 446 IRNode.STORE_VECTOR, "=0"}, 447 applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}) 448 private static void testCMoveFYYforFConstH2(float[] a, float[] b, float[] c) { 449 for (int i = 0; i < a.length; i+=2) { 450 c[i+0] = (a[i+0] <= b[i+0]) ? 0.1f : -0.1f; 451 c[i+1] = (a[i+1] < b[i+1]) ? 0.1f : -0.1f; 452 } 453 } 454 455 @Test 456 @IR(counts = {IRNode.LOAD_VECTOR_F, "=0", 457 IRNode.VECTOR_MASK_CMP_F, "=0", 458 IRNode.VECTOR_BLEND_F, "=0", 459 IRNode.STORE_VECTOR, "=0"}, 460 applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}) 461 private static void testCMoveFXXforFConstH2(float[] a, float[] b, float[] c) { 462 for (int i = 0; i < a.length; i+=2) { 463 c[i+0] = (a[i+0] < b[i+0]) ? 0.1f : -0.1f; 464 c[i+1] = (a[i+1] <= b[i+1]) ? 0.1f : -0.1f; 465 } 466 } 467 468 @Test 469 @IR(counts = {IRNode.LOAD_VECTOR_D, ">0", 470 IRNode.VECTOR_MASK_CMP_D, ">0", 471 IRNode.VECTOR_BLEND_D, ">0", 472 IRNode.STORE_VECTOR, ">0"}, 473 applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}) 474 private static void testCMoveDGTforDConst(double[] a, double[] b, double[] c) { 475 for (int i = 0; i < a.length; i++) { 476 c[i] = (a[i] > b[i]) ? 0.1 : -0.1; 477 } 478 } 479 480 @Test 481 @IR(counts = {IRNode.LOAD_VECTOR_D, ">0", 482 IRNode.VECTOR_MASK_CMP_D, ">0", 483 IRNode.VECTOR_BLEND_D, ">0", 484 IRNode.STORE_VECTOR, ">0"}, 485 applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}) 486 private static void testCMoveDGEforDConst(double[] a, double[] b, double[] c) { 487 for (int i = 0; i < a.length; i++) { 488 c[i] = (a[i] >= b[i]) ? 0.1 : -0.1; 489 } 490 } 491 492 @Test 493 @IR(counts = {IRNode.LOAD_VECTOR_D, ">0", 494 IRNode.VECTOR_MASK_CMP_D, ">0", 495 IRNode.VECTOR_BLEND_D, ">0", 496 IRNode.STORE_VECTOR, ">0"}, 497 applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}) 498 private static void testCMoveDLTforDConst(double[] a, double[] b, double[] c) { 499 for (int i = 0; i < a.length; i++) { 500 c[i] = (a[i] < b[i]) ? 0.1 : -0.1; 501 } 502 } 503 504 @Test 505 @IR(counts = {IRNode.LOAD_VECTOR_D, ">0", 506 IRNode.VECTOR_MASK_CMP_D, ">0", 507 IRNode.VECTOR_BLEND_D, ">0", 508 IRNode.STORE_VECTOR, ">0"}, 509 applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}) 510 private static void testCMoveDLEforDConst(double[] a, double[] b, double[] c) { 511 for (int i = 0; i < a.length; i++) { 512 c[i] = (a[i] <= b[i]) ? 0.1 : -0.1; 513 } 514 } 515 516 @Test 517 @IR(counts = {IRNode.LOAD_VECTOR_D, ">0", 518 IRNode.VECTOR_MASK_CMP_D, ">0", 519 IRNode.VECTOR_BLEND_D, ">0", 520 IRNode.STORE_VECTOR, ">0"}, 521 applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}) 522 private static void testCMoveDEQforDConst(double[] a, double[] b, double[] c) { 523 for (int i = 0; i < a.length; i++) { 524 c[i] = (a[i] == b[i]) ? 0.1 : -0.1; 525 } 526 } 527 528 @Test 529 @IR(counts = {IRNode.LOAD_VECTOR_D, ">0", 530 IRNode.VECTOR_MASK_CMP_D, ">0", 531 IRNode.VECTOR_BLEND_D, ">0", 532 IRNode.STORE_VECTOR, ">0"}, 533 applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}) 534 private static void testCMoveDNEQforDConst(double[] a, double[] b, double[] c) { 535 for (int i = 0; i < a.length; i++) { 536 c[i] = (a[i] != b[i]) ? 0.1 : -0.1; 537 } 538 } 539 540 @Test 541 @IR(counts = {IRNode.LOAD_VECTOR_D, ">0", 542 IRNode.VECTOR_MASK_CMP_D, ">0", 543 IRNode.VECTOR_BLEND_D, ">0", 544 IRNode.STORE_VECTOR, ">0"}, 545 applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}) 546 private static void testCMoveDLTforDConstH2(double[] a, double[] b, double[] c) { 547 for (int i = 0; i < a.length; i+=2) { 548 c[i+0] = (a[i+0] < b[i+0]) ? 0.1 : -0.1; 549 c[i+1] = (a[i+1] < b[i+1]) ? 0.1 : -0.1; 550 } 551 } 552 553 @Test 554 @IR(counts = {IRNode.LOAD_VECTOR_D, ">0", 555 IRNode.VECTOR_MASK_CMP_D, ">0", 556 IRNode.VECTOR_BLEND_D, ">0", 557 IRNode.STORE_VECTOR, ">0"}, 558 applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}) 559 private static void testCMoveDLEforDConstH2(double[] a, double[] b, double[] c) { 560 for (int i = 0; i < a.length; i+=2) { 561 c[i+0] = (a[i+0] <= b[i+0]) ? 0.1 : -0.1; 562 c[i+1] = (a[i+1] <= b[i+1]) ? 0.1 : -0.1; 563 } 564 } 565 566 @Test 567 @IR(counts = {IRNode.LOAD_VECTOR_D, "=0", 568 IRNode.VECTOR_MASK_CMP_D, "=0", 569 IRNode.VECTOR_BLEND_D, "=0", 570 IRNode.STORE_VECTOR, "=0"}, 571 applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}) 572 private static void testCMoveDYYforDConstH2(double[] a, double[] b, double[] c) { 573 for (int i = 0; i < a.length; i+=2) { 574 c[i+0] = (a[i+0] <= b[i+0]) ? 0.1 : -0.1; 575 c[i+1] = (a[i+1] < b[i+1]) ? 0.1 : -0.1; 576 } 577 } 578 579 @Test 580 @IR(counts = {IRNode.LOAD_VECTOR_D, "=0", 581 IRNode.VECTOR_MASK_CMP_D, "=0", 582 IRNode.VECTOR_BLEND_D, "=0", 583 IRNode.STORE_VECTOR, "=0"}, 584 applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}) 585 private static void testCMoveDXXforDConstH2(double[] a, double[] b, double[] c) { 586 for (int i = 0; i < a.length; i+=2) { 587 c[i+0] = (a[i+0] < b[i+0]) ? 0.1 : -0.1; 588 c[i+1] = (a[i+1] <= b[i+1]) ? 0.1 : -0.1; 589 } 590 } 591 592 // Extension: Compare 2 ILFD values, and pick from 2 ILFD values 593 // Note: 594 // To guarantee that CMove is introduced, I need to perform the loads before the branch. To ensure they 595 // do not float down into the branches, I compute a value, and store it to r2 (same as r, except that the 596 // compilation does not know that). 597 // So far, vectorization only works for CMoveF/D, with same data-width comparison (F/I for F, D/L for D). 598 @Test 599 @IR(failOn = {IRNode.STORE_VECTOR}) 600 private static void testCMoveIGTforI(int[] a, int[] b, int[] c, int[] d, int[] r, int[] r2) { 601 for (int i = 0; i < a.length; i++) { 602 int cc = c[i]; 603 int dd = d[i]; 604 r2[i] = cc + dd; 605 r[i] = (a[i] > b[i]) ? cc : dd; 606 } 607 } 608 609 @Test 610 @IR(failOn = {IRNode.STORE_VECTOR}) 611 private static void testCMoveIGTforL(int[] a, int[] b, long[] c, long[] d, long[] r, long[] r2) { 612 for (int i = 0; i < a.length; i++) { 613 long cc = c[i]; 614 long dd = d[i]; 615 r2[i] = cc + dd; 616 r[i] = (a[i] > b[i]) ? cc : dd; 617 } 618 } 619 620 @Test 621 @IR(counts = {IRNode.LOAD_VECTOR_I, IRNode.VECTOR_SIZE + "min(max_int, max_float)", ">0", 622 IRNode.LOAD_VECTOR_F, IRNode.VECTOR_SIZE + "min(max_int, max_float)", ">0", 623 IRNode.VECTOR_MASK_CMP_I, IRNode.VECTOR_SIZE + "min(max_int, max_float)", ">0", 624 IRNode.VECTOR_BLEND_F, IRNode.VECTOR_SIZE + "min(max_int, max_float)", ">0", 625 IRNode.STORE_VECTOR, ">0"}, 626 applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}) 627 private static void testCMoveIGTforF(int[] a, int[] b, float[] c, float[] d, float[] r, float[] r2) { 628 for (int i = 0; i < a.length; i++) { 629 float cc = c[i]; 630 float dd = d[i]; 631 r2[i] = cc + dd; 632 r[i] = (a[i] > b[i]) ? cc : dd; 633 } 634 } 635 636 @Test 637 @IR(failOn = {IRNode.STORE_VECTOR}) 638 private static void testCMoveIGTforD(int[] a, int[] b, double[] c, double[] d, double[] r, double[] r2) { 639 for (int i = 0; i < a.length; i++) { 640 double cc = c[i]; 641 double dd = d[i]; 642 r2[i] = cc + dd; 643 r[i] = (a[i] > b[i]) ? cc : dd; 644 } 645 } 646 647 @Test 648 @IR(failOn = {IRNode.STORE_VECTOR}) 649 private static void testCMoveLGTforI(long[] a, long[] b, int[] c, int[] d, int[] r, int[] r2) { 650 for (int i = 0; i < a.length; i++) { 651 int cc = c[i]; 652 int dd = d[i]; 653 r2[i] = cc + dd; 654 r[i] = (a[i] > b[i]) ? cc : dd; 655 } 656 } 657 658 @Test 659 @IR(failOn = {IRNode.STORE_VECTOR}) 660 private static void testCMoveLGTforL(long[] a, long[] b, long[] c, long[] d, long[] r, long[] r2) { 661 for (int i = 0; i < a.length; i++) { 662 long cc = c[i]; 663 long dd = d[i]; 664 r2[i] = cc + dd; 665 r[i] = (a[i] > b[i]) ? cc : dd; 666 } 667 } 668 669 @Test 670 @IR(failOn = {IRNode.STORE_VECTOR}) 671 private static void testCMoveLGTforF(long[] a, long[] b, float[] c, float[] d, float[] r, float[] r2) { 672 for (int i = 0; i < a.length; i++) { 673 float cc = c[i]; 674 float dd = d[i]; 675 r2[i] = cc + dd; 676 r[i] = (a[i] > b[i]) ? cc : dd; 677 } 678 } 679 680 @Test 681 @IR(counts = {IRNode.LOAD_VECTOR_L, IRNode.VECTOR_SIZE + "min(max_long, max_double)", ">0", 682 IRNode.LOAD_VECTOR_D, IRNode.VECTOR_SIZE + "min(max_long, max_double)", ">0", 683 IRNode.VECTOR_MASK_CMP_L, IRNode.VECTOR_SIZE + "min(max_long, max_double)", ">0", 684 IRNode.VECTOR_BLEND_D, IRNode.VECTOR_SIZE + "min(max_long, max_double)", ">0", 685 IRNode.STORE_VECTOR, ">0"}, 686 applyIfCPUFeatureOr = {"avx2", "true", "asimd", "true"}) 687 // Requires avx2, else L is restricted to 16 byte, and D has 32. That leads to a vector elements mismatch of 2 to 4. 688 private static void testCMoveLGTforD(long[] a, long[] b, double[] c, double[] d, double[] r, double[] r2) { 689 for (int i = 0; i < a.length; i++) { 690 double cc = c[i]; 691 double dd = d[i]; 692 r2[i] = cc + dd; 693 r[i] = (a[i] > b[i]) ? cc : dd; 694 } 695 } 696 697 @Test 698 @IR(failOn = {IRNode.STORE_VECTOR}) 699 private static void testCMoveFGTforI(float[] a, float[] b, int[] c, int[] d, int[] r, int[] r2) { 700 for (int i = 0; i < a.length; i++) { 701 int cc = c[i]; 702 int dd = d[i]; 703 r2[i] = cc + dd; 704 r[i] = (a[i] > b[i]) ? cc : dd; 705 } 706 } 707 708 @Test 709 @IR(failOn = {IRNode.STORE_VECTOR}) 710 private static void testCMoveFGTforL(float[] a, float[] b, long[] c, long[] d, long[] r, long[] r2) { 711 for (int i = 0; i < a.length; i++) { 712 long cc = c[i]; 713 long dd = d[i]; 714 r2[i] = cc + dd; 715 r[i] = (a[i] > b[i]) ? cc : dd; 716 } 717 } 718 719 @Test 720 @IR(counts = {IRNode.LOAD_VECTOR_F, ">0", 721 IRNode.VECTOR_MASK_CMP_F, ">0", 722 IRNode.VECTOR_BLEND_F, ">0", 723 IRNode.STORE_VECTOR, ">0"}, 724 applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}) 725 private static void testCMoveFGTforF(float[] a, float[] b, float[] c, float[] d, float[] r, float[] r2) { 726 for (int i = 0; i < a.length; i++) { 727 float cc = c[i]; 728 float dd = d[i]; 729 r2[i] = cc + dd; 730 r[i] = (a[i] > b[i]) ? cc : dd; 731 } 732 } 733 734 @Test 735 @IR(failOn = {IRNode.STORE_VECTOR}) 736 private static void testCMoveFGTforD(float[] a, float[] b, double[] c, double[] d, double[] r, double[] r2) { 737 for (int i = 0; i < a.length; i++) { 738 double cc = c[i]; 739 double dd = d[i]; 740 r2[i] = cc + dd; 741 r[i] = (a[i] > b[i]) ? cc : dd; 742 } 743 } 744 745 @Test 746 @IR(failOn = {IRNode.STORE_VECTOR}) 747 private static void testCMoveDGTforI(double[] a, double[] b, int[] c, int[] d, int[] r, int[] r2) { 748 for (int i = 0; i < a.length; i++) { 749 int cc = c[i]; 750 int dd = d[i]; 751 r2[i] = cc + dd; 752 r[i] = (a[i] > b[i]) ? cc : dd; 753 } 754 } 755 756 @Test 757 @IR(failOn = {IRNode.STORE_VECTOR}) 758 private static void testCMoveDGTforL(double[] a, double[] b, long[] c, long[] d, long[] r, long[] r2) { 759 for (int i = 0; i < a.length; i++) { 760 long cc = c[i]; 761 long dd = d[i]; 762 r2[i] = cc + dd; 763 r[i] = (a[i] > b[i]) ? cc : dd; 764 } 765 } 766 767 @Test 768 @IR(failOn = {IRNode.STORE_VECTOR}) 769 private static void testCMoveDGTforF(double[] a, double[] b, float[] c, float[] d, float[] r, float[] r2) { 770 for (int i = 0; i < a.length; i++) { 771 float cc = c[i]; 772 float dd = d[i]; 773 r2[i] = cc + dd; 774 r[i] = (a[i] > b[i]) ? cc : dd; 775 } 776 } 777 778 @Test 779 @IR(counts = {IRNode.LOAD_VECTOR_D, ">0", 780 IRNode.VECTOR_MASK_CMP_D, ">0", 781 IRNode.VECTOR_BLEND_D, ">0", 782 IRNode.STORE_VECTOR, ">0"}, 783 applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}) 784 private static void testCMoveDGTforD(double[] a, double[] b, double[] c, double[] d, double[] r, double[] r2) { 785 for (int i = 0; i < a.length; i++) { 786 double cc = c[i]; 787 double dd = d[i]; 788 r2[i] = cc + dd; 789 r[i] = (a[i] > b[i]) ? cc : dd; 790 } 791 } 792 793 // Use some constants in the comparison 794 @Test 795 @IR(counts = {IRNode.LOAD_VECTOR_F, ">0", 796 IRNode.VECTOR_MASK_CMP_F, ">0", 797 IRNode.VECTOR_BLEND_F, ">0", 798 IRNode.STORE_VECTOR, ">0"}, 799 applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}) 800 private static void testCMoveFGTforFCmpCon1(float a, float[] b, float[] c, float[] d, float[] r, float[] r2) { 801 for (int i = 0; i < b.length; i++) { 802 float cc = c[i]; 803 float dd = d[i]; 804 r2[i] = cc + dd; 805 r[i] = (a > b[i]) ? cc : dd; 806 } 807 } 808 809 @Test 810 @IR(counts = {IRNode.LOAD_VECTOR_F, ">0", 811 IRNode.VECTOR_MASK_CMP_F, ">0", 812 IRNode.VECTOR_BLEND_F, ">0", 813 IRNode.STORE_VECTOR, ">0"}, 814 applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}) 815 private static void testCMoveFGTforFCmpCon2(float[] a, float b, float[] c, float[] d, float[] r, float[] r2) { 816 for (int i = 0; i < a.length; i++) { 817 float cc = c[i]; 818 float dd = d[i]; 819 r2[i] = cc + dd; 820 r[i] = (a[i] > b) ? cc : dd; 821 } 822 } 823 824 // A case that is currently not supported and is not expected to vectorize 825 @Test 826 @IR(failOn = {IRNode.STORE_VECTOR}) 827 private static void testCMoveVDUnsupported() { 828 double[] doublec = new double[SIZE]; 829 int seed = 1001; 830 for (int i = 0; i < doublec.length; i++) { 831 doublec[i] = (i % 2 == 0) ? seed + i : seed - i; 832 } 833 } 834 835 @Warmup(0) 836 @Run(test = {"testCMoveVFGT", "testCMoveVFLT","testCMoveVDLE", "testCMoveVDGE", "testCMoveVFEQ", "testCMoveVDNE", 837 "testCMoveVFGTSwap", "testCMoveVFLTSwap","testCMoveVDLESwap", "testCMoveVDGESwap", 838 "testCMoveFGTforFConst", "testCMoveFGEforFConst", "testCMoveFLTforFConst", 839 "testCMoveFLEforFConst", "testCMoveFEQforFConst", "testCMoveFNEQforFConst", 840 "testCMoveDGTforDConst", "testCMoveDGEforDConst", "testCMoveDLTforDConst", 841 "testCMoveDLEforDConst", "testCMoveDEQforDConst", "testCMoveDNEQforDConst", 842 "testCMoveFLTforFConstH2", "testCMoveFLEforFConstH2", 843 "testCMoveFYYforFConstH2", "testCMoveFXXforFConstH2", 844 "testCMoveDLTforDConstH2", "testCMoveDLEforDConstH2", 845 "testCMoveDYYforDConstH2", "testCMoveDXXforDConstH2"}) 846 private void testCMove_runner() { 847 float[] floata = new float[SIZE]; 848 float[] floatb = new float[SIZE]; 849 float[] floatc = new float[SIZE]; 850 double[] doublea = new double[SIZE]; 851 double[] doubleb = new double[SIZE]; 852 double[] doublec = new double[SIZE]; 853 854 init(floata); 855 init(floatb); 856 init(doublea); 857 init(doubleb); 858 859 testCMoveVFGT(floata, floatb, floatc); 860 testCMoveVDLE(doublea, doubleb, doublec); 861 for (int i = 0; i < SIZE; i++) { 862 Asserts.assertEquals(floatc[i], cmoveFloatGT(floata[i], floatb[i])); 863 Asserts.assertEquals(doublec[i], cmoveDoubleLE(doublea[i], doubleb[i])); 864 } 865 866 testCMoveVFLT(floata, floatb, floatc); 867 testCMoveVDGE(doublea, doubleb, doublec); 868 for (int i = 0; i < SIZE; i++) { 869 Asserts.assertEquals(floatc[i], cmoveFloatLT(floata[i], floatb[i])); 870 Asserts.assertEquals(doublec[i], cmoveDoubleGE(doublea[i], doubleb[i])); 871 } 872 873 // Ensure we frequently have equals 874 for (int i = 0; i < SIZE; i++) { 875 if (i % 3 == 0) { 876 floatb[i] = floata[i]; 877 doubleb[i] = doublea[i]; 878 } 879 } 880 881 testCMoveVFEQ(floata, floatb, floatc); 882 testCMoveVDNE(doublea, doubleb, doublec); 883 for (int i = 0; i < SIZE; i++) { 884 Asserts.assertEquals(floatc[i], cmoveFloatEQ(floata[i], floatb[i])); 885 Asserts.assertEquals(doublec[i], cmoveDoubleNE(doublea[i], doubleb[i])); 886 } 887 888 testCMoveVFGTSwap(floata, floatb, floatc); 889 testCMoveVDLESwap(doublea, doubleb, doublec); 890 for (int i = 0; i < SIZE; i++) { 891 Asserts.assertEquals(floatc[i], cmoveFloatGTSwap(floata[i], floatb[i])); 892 Asserts.assertEquals(doublec[i], cmoveDoubleLESwap(doublea[i], doubleb[i])); 893 } 894 895 testCMoveVFLTSwap(floata, floatb, floatc); 896 testCMoveVDGESwap(doublea, doubleb, doublec); 897 for (int i = 0; i < SIZE; i++) { 898 Asserts.assertEquals(floatc[i], cmoveFloatLTSwap(floata[i], floatb[i])); 899 Asserts.assertEquals(doublec[i], cmoveDoubleGESwap(doublea[i], doubleb[i])); 900 } 901 902 // Extensions: compare 2 values, and pick from 2 consts 903 testCMoveFGTforFConst(floata, floatb, floatc); 904 testCMoveDGTforDConst(doublea, doubleb, doublec); 905 for (int i = 0; i < SIZE; i++) { 906 Asserts.assertEquals(floatc[i], cmoveFGTforFConst(floata[i], floatb[i])); 907 Asserts.assertEquals(doublec[i], cmoveDGTforDConst(doublea[i], doubleb[i])); 908 } 909 910 testCMoveFGEforFConst(floata, floatb, floatc); 911 testCMoveDGEforDConst(doublea, doubleb, doublec); 912 for (int i = 0; i < SIZE; i++) { 913 Asserts.assertEquals(floatc[i], cmoveFGEforFConst(floata[i], floatb[i])); 914 Asserts.assertEquals(doublec[i], cmoveDGEforDConst(doublea[i], doubleb[i])); 915 } 916 917 testCMoveFLTforFConst(floata, floatb, floatc); 918 testCMoveDLTforDConst(doublea, doubleb, doublec); 919 for (int i = 0; i < SIZE; i++) { 920 Asserts.assertEquals(floatc[i], cmoveFLTforFConst(floata[i], floatb[i])); 921 Asserts.assertEquals(doublec[i], cmoveDLTforDConst(doublea[i], doubleb[i])); 922 } 923 924 testCMoveFLEforFConst(floata, floatb, floatc); 925 testCMoveDLEforDConst(doublea, doubleb, doublec); 926 for (int i = 0; i < SIZE; i++) { 927 Asserts.assertEquals(floatc[i], cmoveFLEforFConst(floata[i], floatb[i])); 928 Asserts.assertEquals(doublec[i], cmoveDLEforDConst(doublea[i], doubleb[i])); 929 } 930 931 testCMoveFEQforFConst(floata, floatb, floatc); 932 testCMoveDEQforDConst(doublea, doubleb, doublec); 933 for (int i = 0; i < SIZE; i++) { 934 Asserts.assertEquals(floatc[i], cmoveFEQforFConst(floata[i], floatb[i])); 935 Asserts.assertEquals(doublec[i], cmoveDEQforDConst(doublea[i], doubleb[i])); 936 } 937 938 testCMoveFNEQforFConst(floata, floatb, floatc); 939 testCMoveDNEQforDConst(doublea, doubleb, doublec); 940 for (int i = 0; i < SIZE; i++) { 941 Asserts.assertEquals(floatc[i], cmoveFNEQforFConst(floata[i], floatb[i])); 942 Asserts.assertEquals(doublec[i], cmoveDNEQforDConst(doublea[i], doubleb[i])); 943 } 944 945 // Hand-unrolled (H2) examples: 946 testCMoveFLTforFConstH2(floata, floatb, floatc); 947 testCMoveDLTforDConstH2(doublea, doubleb, doublec); 948 for (int i = 0; i < SIZE; i++) { 949 Asserts.assertEquals(floatc[i], cmoveFLTforFConst(floata[i], floatb[i])); 950 Asserts.assertEquals(doublec[i], cmoveDLTforDConst(doublea[i], doubleb[i])); 951 } 952 953 testCMoveFLEforFConstH2(floata, floatb, floatc); 954 testCMoveDLEforDConstH2(doublea, doubleb, doublec); 955 for (int i = 0; i < SIZE; i++) { 956 Asserts.assertEquals(floatc[i], cmoveFLEforFConst(floata[i], floatb[i])); 957 Asserts.assertEquals(doublec[i], cmoveDLEforDConst(doublea[i], doubleb[i])); 958 } 959 960 testCMoveFYYforFConstH2(floata, floatb, floatc); 961 testCMoveDYYforDConstH2(doublea, doubleb, doublec); 962 for (int i = 0; i < SIZE; i+=2) { 963 Asserts.assertEquals(floatc[i+0], cmoveFLEforFConst(floata[i+0], floatb[i+0])); 964 Asserts.assertEquals(doublec[i+0], cmoveDLEforDConst(doublea[i+0], doubleb[i+0])); 965 Asserts.assertEquals(floatc[i+1], cmoveFLTforFConst(floata[i+1], floatb[i+1])); 966 Asserts.assertEquals(doublec[i+1], cmoveDLTforDConst(doublea[i+1], doubleb[i+1])); 967 } 968 969 testCMoveFXXforFConstH2(floata, floatb, floatc); 970 testCMoveDXXforDConstH2(doublea, doubleb, doublec); 971 for (int i = 0; i < SIZE; i+=2) { 972 Asserts.assertEquals(floatc[i+0], cmoveFLTforFConst(floata[i+0], floatb[i+0])); 973 Asserts.assertEquals(doublec[i+0], cmoveDLTforDConst(doublea[i+0], doubleb[i+0])); 974 Asserts.assertEquals(floatc[i+1], cmoveFLEforFConst(floata[i+1], floatb[i+1])); 975 Asserts.assertEquals(doublec[i+1], cmoveDLEforDConst(doublea[i+1], doubleb[i+1])); 976 } 977 } 978 979 @Warmup(0) 980 @Run(test = {"testCMoveIGTforI", 981 "testCMoveIGTforL", 982 "testCMoveIGTforF", 983 "testCMoveIGTforD", 984 "testCMoveLGTforI", 985 "testCMoveLGTforL", 986 "testCMoveLGTforF", 987 "testCMoveLGTforD", 988 "testCMoveFGTforI", 989 "testCMoveFGTforL", 990 "testCMoveFGTforF", 991 "testCMoveFGTforD", 992 "testCMoveDGTforI", 993 "testCMoveDGTforL", 994 "testCMoveDGTforF", 995 "testCMoveDGTforD", 996 "testCMoveFGTforFCmpCon1", 997 "testCMoveFGTforFCmpCon2"}) 998 private void testCMove_runner_two() { 999 int[] aI = new int[SIZE]; 1000 int[] bI = new int[SIZE]; 1001 int[] cI = new int[SIZE]; 1002 int[] dI = new int[SIZE]; 1003 int[] rI = new int[SIZE]; 1004 long[] aL = new long[SIZE]; 1005 long[] bL = new long[SIZE]; 1006 long[] cL = new long[SIZE]; 1007 long[] dL = new long[SIZE]; 1008 long[] rL = new long[SIZE]; 1009 float[] aF = new float[SIZE]; 1010 float[] bF = new float[SIZE]; 1011 float[] cF = new float[SIZE]; 1012 float[] dF = new float[SIZE]; 1013 float[] rF = new float[SIZE]; 1014 double[] aD = new double[SIZE]; 1015 double[] bD = new double[SIZE]; 1016 double[] cD = new double[SIZE]; 1017 double[] dD = new double[SIZE]; 1018 double[] rD = new double[SIZE]; 1019 1020 init(aI); 1021 init(bI); 1022 init(cI); 1023 init(dI); 1024 init(aL); 1025 init(bL); 1026 init(cL); 1027 init(dL); 1028 init(aF); 1029 init(bF); 1030 init(cF); 1031 init(dF); 1032 init(aD); 1033 init(bD); 1034 init(cD); 1035 init(dD); 1036 1037 testCMoveIGTforI(aI, bI, cI, dI, rI, rI); 1038 for (int i = 0; i < SIZE; i++) { 1039 Asserts.assertEquals(rI[i], cmoveIGTforI(aI[i], bI[i], cI[i], dI[i])); 1040 } 1041 1042 testCMoveIGTforL(aI, bI, cL, dL, rL, rL); 1043 for (int i = 0; i < SIZE; i++) { 1044 Asserts.assertEquals(rL[i], cmoveIGTforL(aI[i], bI[i], cL[i], dL[i])); 1045 } 1046 1047 testCMoveIGTforF(aI, bI, cF, dF, rF, rF); 1048 for (int i = 0; i < SIZE; i++) { 1049 Asserts.assertEquals(rF[i], cmoveIGTforF(aI[i], bI[i], cF[i], dF[i])); 1050 } 1051 1052 testCMoveIGTforD(aI, bI, cD, dD, rD, rD); 1053 for (int i = 0; i < SIZE; i++) { 1054 Asserts.assertEquals(rD[i], cmoveIGTforD(aI[i], bI[i], cD[i], dD[i])); 1055 } 1056 1057 testCMoveLGTforI(aL, bL, cI, dI, rI, rI); 1058 for (int i = 0; i < SIZE; i++) { 1059 Asserts.assertEquals(rI[i], cmoveLGTforI(aL[i], bL[i], cI[i], dI[i])); 1060 } 1061 1062 testCMoveLGTforL(aL, bL, cL, dL, rL, rL); 1063 for (int i = 0; i < SIZE; i++) { 1064 Asserts.assertEquals(rL[i], cmoveLGTforL(aL[i], bL[i], cL[i], dL[i])); 1065 } 1066 1067 testCMoveLGTforF(aL, bL, cF, dF, rF, rF); 1068 for (int i = 0; i < SIZE; i++) { 1069 Asserts.assertEquals(rF[i], cmoveLGTforF(aL[i], bL[i], cF[i], dF[i])); 1070 } 1071 1072 testCMoveLGTforD(aL, bL, cD, dD, rD, rD); 1073 for (int i = 0; i < SIZE; i++) { 1074 Asserts.assertEquals(rD[i], cmoveLGTforD(aL[i], bL[i], cD[i], dD[i])); 1075 } 1076 1077 testCMoveFGTforI(aF, bF, cI, dI, rI, rI); 1078 for (int i = 0; i < SIZE; i++) { 1079 Asserts.assertEquals(rI[i], cmoveFGTforI(aF[i], bF[i], cI[i], dI[i])); 1080 } 1081 1082 testCMoveFGTforL(aF, bF, cL, dL, rL, rL); 1083 for (int i = 0; i < SIZE; i++) { 1084 Asserts.assertEquals(rL[i], cmoveFGTforL(aF[i], bF[i], cL[i], dL[i])); 1085 } 1086 1087 testCMoveFGTforF(aF, bF, cF, dF, rF, rF); 1088 for (int i = 0; i < SIZE; i++) { 1089 Asserts.assertEquals(rF[i], cmoveFGTforF(aF[i], bF[i], cF[i], dF[i])); 1090 } 1091 1092 testCMoveFGTforD(aF, bF, cD, dD, rD, rD); 1093 for (int i = 0; i < SIZE; i++) { 1094 Asserts.assertEquals(rD[i], cmoveFGTforD(aF[i], bF[i], cD[i], dD[i])); 1095 } 1096 1097 testCMoveDGTforI(aD, bD, cI, dI, rI, rI); 1098 for (int i = 0; i < SIZE; i++) { 1099 Asserts.assertEquals(rI[i], cmoveDGTforI(aD[i], bD[i], cI[i], dI[i])); 1100 } 1101 1102 testCMoveDGTforL(aD, bD, cL, dL, rL, rL); 1103 for (int i = 0; i < SIZE; i++) { 1104 Asserts.assertEquals(rL[i], cmoveDGTforL(aD[i], bD[i], cL[i], dL[i])); 1105 } 1106 1107 testCMoveDGTforF(aD, bD, cF, dF, rF, rF); 1108 for (int i = 0; i < SIZE; i++) { 1109 Asserts.assertEquals(rF[i], cmoveDGTforF(aD[i], bD[i], cF[i], dF[i])); 1110 } 1111 1112 testCMoveDGTforD(aD, bD, cD, dD, rD, rD); 1113 for (int i = 0; i < SIZE; i++) { 1114 Asserts.assertEquals(rD[i], cmoveDGTforD(aD[i], bD[i], cD[i], dD[i])); 1115 } 1116 1117 // Use some constants/invariants in the comparison 1118 testCMoveFGTforFCmpCon1(aF[0], bF, cF, dF, rF, rF); 1119 for (int i = 0; i < SIZE; i++) { 1120 Asserts.assertEquals(rF[i], cmoveFGTforF(aF[0], bF[i], cF[i], dF[i])); 1121 } 1122 1123 testCMoveFGTforFCmpCon2(aF, bF[0], cF, dF, rF, rF); 1124 for (int i = 0; i < SIZE; i++) { 1125 Asserts.assertEquals(rF[i], cmoveFGTforF(aF[i], bF[0], cF[i], dF[i])); 1126 } 1127 } 1128 1129 private static void init(int[] a) { 1130 for (int i = 0; i < SIZE; i++) { 1131 a[i] = RANDOM.nextInt(); 1132 } 1133 } 1134 1135 private static void init(long[] a) { 1136 for (int i = 0; i < SIZE; i++) { 1137 a[i] = RANDOM.nextLong(); 1138 } 1139 } 1140 1141 private static void init(float[] a) { 1142 for (int i = 0; i < SIZE; i++) { 1143 a[i] = switch(RANDOM.nextInt() % 20) { 1144 case 0 -> Float.NaN; 1145 case 1 -> 0; 1146 case 2 -> 1; 1147 case 3 -> Float.POSITIVE_INFINITY; 1148 case 4 -> Float.NEGATIVE_INFINITY; 1149 case 5 -> Float.MAX_VALUE; 1150 case 6 -> Float.MIN_VALUE; 1151 case 7, 8, 9 -> RANDOM.nextFloat(); 1152 default -> Float.intBitsToFloat(RANDOM.nextInt()); 1153 }; 1154 } 1155 } 1156 1157 private static void init(double[] a) { 1158 for (int i = 0; i < SIZE; i++) { 1159 a[i] = switch(RANDOM.nextInt() % 20) { 1160 case 0 -> Double.NaN; 1161 case 1 -> 0; 1162 case 2 -> 1; 1163 case 3 -> Double.POSITIVE_INFINITY; 1164 case 4 -> Double.NEGATIVE_INFINITY; 1165 case 5 -> Double.MAX_VALUE; 1166 case 6 -> Double.MIN_VALUE; 1167 case 7, 8, 9 -> RANDOM.nextDouble(); 1168 default -> Double.longBitsToDouble(RANDOM.nextLong()); 1169 }; 1170 } 1171 } 1172 }