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:-UseCompactObjectHeaders", "-XX:-AlignVector");
49 TestFramework.runWithFlags("-XX:+UseCMoveUnconditionally", "-XX:+UseVectorCmov",
50 "-XX:-UseCompactObjectHeaders", "-XX:+AlignVector");
51 TestFramework.runWithFlags("-XX:+UseCMoveUnconditionally", "-XX:+UseVectorCmov",
52 "-XX:+UseCompactObjectHeaders", "-XX:-AlignVector");
53 TestFramework.runWithFlags("-XX:+UseCMoveUnconditionally", "-XX:+UseVectorCmov",
54 "-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 }