8352504: RISC-V: implement and enable CMoveI/L

8346786: RISC-V: Reconsider ConditionalMoveLimit when adding conditional move

Reviewed-by: fyang, fjiang
This commit is contained in:
Hamlin Li 2025-04-22 08:32:03 +00:00
parent 50358d1ca4
commit bcc33d5ef3
20 changed files with 940 additions and 49 deletions

View File

@ -2156,6 +2156,36 @@ void C2_MacroAssembler::enc_cmove(int cmpFlag, Register op1, Register op2, Regis
}
}
void C2_MacroAssembler::enc_cmove_cmp_fp(int cmpFlag, FloatRegister op1, FloatRegister op2, Register dst, Register src, bool is_single) {
int op_select = cmpFlag & (~unsigned_branch_mask);
switch (op_select) {
case BoolTest::eq:
cmov_cmp_fp_eq(op1, op2, dst, src, is_single);
break;
case BoolTest::ne:
cmov_cmp_fp_ne(op1, op2, dst, src, is_single);
break;
case BoolTest::le:
cmov_cmp_fp_le(op1, op2, dst, src, is_single);
break;
case BoolTest::ge:
assert(false, "Should go to BoolTest::le case");
ShouldNotReachHere();
break;
case BoolTest::lt:
cmov_cmp_fp_lt(op1, op2, dst, src, is_single);
break;
case BoolTest::gt:
assert(false, "Should go to BoolTest::lt case");
ShouldNotReachHere();
break;
default:
assert(false, "unsupported compare condition");
ShouldNotReachHere();
}
}
// Set dst to NaN if any NaN input.
void C2_MacroAssembler::minmax_fp(FloatRegister dst, FloatRegister src1, FloatRegister src2,
FLOAT_TYPE ft, bool is_min) {

View File

@ -129,6 +129,10 @@
Register op1, Register op2,
Register dst, Register src);
void enc_cmove_cmp_fp(int cmpFlag,
FloatRegister op1, FloatRegister op2,
Register dst, Register src, bool is_single);
void spill(Register r, bool is64, int offset) {
is64 ? sd(r, Address(sp, offset))
: sw(r, Address(sp, offset));

View File

@ -43,7 +43,7 @@ define_pd_global(bool, TieredCompilation, COMPILER1_PRESENT(true) NOT
define_pd_global(intx, CompileThreshold, 10000);
define_pd_global(intx, OnStackReplacePercentage, 140);
define_pd_global(intx, ConditionalMoveLimit, 0);
define_pd_global(intx, ConditionalMoveLimit, 3);
define_pd_global(intx, FreqInlineSize, 325);
define_pd_global(intx, MinJumpTableSize, 10);
define_pd_global(intx, InteriorEntryAlignment, 16);

View File

@ -1267,6 +1267,130 @@ void MacroAssembler::cmov_gtu(Register cmp1, Register cmp2, Register dst, Regist
bind(no_set);
}
// ----------- cmove, compare float -----------
// Move src to dst only if cmp1 == cmp2,
// otherwise leave dst unchanged, including the case where one of them is NaN.
// Clarification:
// java code : cmp1 != cmp2 ? dst : src
// transformed to : CMove dst, (cmp1 eq cmp2), dst, src
void MacroAssembler::cmov_cmp_fp_eq(FloatRegister cmp1, FloatRegister cmp2, Register dst, Register src, bool is_single) {
if (UseZicond) {
if (is_single) {
feq_s(t0, cmp1, cmp2);
} else {
feq_d(t0, cmp1, cmp2);
}
czero_nez(dst, dst, t0);
czero_eqz(t0 , src, t0);
orr(dst, dst, t0);
return;
}
Label no_set;
if (is_single) {
// jump if cmp1 != cmp2, including the case of NaN
// not jump (i.e. move src to dst) if cmp1 == cmp2
float_bne(cmp1, cmp2, no_set);
} else {
double_bne(cmp1, cmp2, no_set);
}
mv(dst, src);
bind(no_set);
}
// Keep dst unchanged only if cmp1 == cmp2,
// otherwise move src to dst, including the case where one of them is NaN.
// Clarification:
// java code : cmp1 == cmp2 ? dst : src
// transformed to : CMove dst, (cmp1 ne cmp2), dst, src
void MacroAssembler::cmov_cmp_fp_ne(FloatRegister cmp1, FloatRegister cmp2, Register dst, Register src, bool is_single) {
if (UseZicond) {
if (is_single) {
feq_s(t0, cmp1, cmp2);
} else {
feq_d(t0, cmp1, cmp2);
}
czero_eqz(dst, dst, t0);
czero_nez(t0 , src, t0);
orr(dst, dst, t0);
return;
}
Label no_set;
if (is_single) {
// jump if cmp1 == cmp2
// not jump (i.e. move src to dst) if cmp1 != cmp2, including the case of NaN
float_beq(cmp1, cmp2, no_set);
} else {
double_beq(cmp1, cmp2, no_set);
}
mv(dst, src);
bind(no_set);
}
// When cmp1 <= cmp2 or any of them is NaN then dst = src, otherwise, dst = dst
// Clarification
// scenario 1:
// java code : cmp2 < cmp1 ? dst : src
// transformed to : CMove dst, (cmp1 le cmp2), dst, src
// scenario 2:
// java code : cmp1 > cmp2 ? dst : src
// transformed to : CMove dst, (cmp1 le cmp2), dst, src
void MacroAssembler::cmov_cmp_fp_le(FloatRegister cmp1, FloatRegister cmp2, Register dst, Register src, bool is_single) {
if (UseZicond) {
if (is_single) {
flt_s(t0, cmp2, cmp1);
} else {
flt_d(t0, cmp2, cmp1);
}
czero_eqz(dst, dst, t0);
czero_nez(t0 , src, t0);
orr(dst, dst, t0);
return;
}
Label no_set;
if (is_single) {
// jump if cmp1 > cmp2
// not jump (i.e. move src to dst) if cmp1 <= cmp2 or either is NaN
float_bgt(cmp1, cmp2, no_set);
} else {
double_bgt(cmp1, cmp2, no_set);
}
mv(dst, src);
bind(no_set);
}
// When cmp1 < cmp2 or any of them is NaN then dst = src, otherwise, dst = dst
// Clarification
// scenario 1:
// java code : cmp2 <= cmp1 ? dst : src
// transformed to : CMove dst, (cmp1 lt cmp2), dst, src
// scenario 2:
// java code : cmp1 >= cmp2 ? dst : src
// transformed to : CMove dst, (cmp1 lt cmp2), dst, src
void MacroAssembler::cmov_cmp_fp_lt(FloatRegister cmp1, FloatRegister cmp2, Register dst, Register src, bool is_single) {
if (UseZicond) {
if (is_single) {
fle_s(t0, cmp2, cmp1);
} else {
fle_d(t0, cmp2, cmp1);
}
czero_eqz(dst, dst, t0);
czero_nez(t0 , src, t0);
orr(dst, dst, t0);
return;
}
Label no_set;
if (is_single) {
// jump if cmp1 >= cmp2
// not jump (i.e. move src to dst) if cmp1 < cmp2 or either is NaN
float_bge(cmp1, cmp2, no_set);
} else {
double_bge(cmp1, cmp2, no_set);
}
mv(dst, src);
bind(no_set);
}
// Float compare branch instructions
#define INSN(NAME, FLOATCMP, BRANCH) \

View File

@ -657,6 +657,11 @@ class MacroAssembler: public Assembler {
void cmov_gt(Register cmp1, Register cmp2, Register dst, Register src);
void cmov_gtu(Register cmp1, Register cmp2, Register dst, Register src);
void cmov_cmp_fp_eq(FloatRegister cmp1, FloatRegister cmp2, Register dst, Register src, bool is_single);
void cmov_cmp_fp_ne(FloatRegister cmp1, FloatRegister cmp2, Register dst, Register src, bool is_single);
void cmov_cmp_fp_le(FloatRegister cmp1, FloatRegister cmp2, Register dst, Register src, bool is_single);
void cmov_cmp_fp_lt(FloatRegister cmp1, FloatRegister cmp2, Register dst, Register src, bool is_single);
public:
// We try to follow risc-v asm menomics.
// But as we don't layout a reachable GOT,

View File

@ -1933,6 +1933,12 @@ bool Matcher::match_rule_supported(int opcode) {
case Op_SubHF:
case Op_SqrtHF:
return UseZfh;
case Op_CMoveF:
case Op_CMoveD:
case Op_CMoveP:
case Op_CMoveN:
return false;
}
return true; // Per default match rules are supported.
@ -9938,12 +9944,15 @@ instruct far_cmpP_narrowOop_imm0_branch(cmpOpEqNe cmp, iRegN op1, immP0 zero, la
// ============================================================================
// Conditional Move Instructions
// --------- CMoveI ---------
instruct cmovI_cmpI(iRegINoSp dst, iRegI src, iRegI op1, iRegI op2, cmpOp cop) %{
match(Set dst (CMoveI (Binary cop (CmpI op1 op2)) (Binary dst src)));
ins_cost(ALU_COST + BRANCH_COST);
format %{
"CMove $dst, ($op1 $cop $op2), $dst, $src\t#@cmovI_cmpI\n\t"
"CMoveI $dst, ($op1 $cop $op2), $dst, $src\t#@cmovI_cmpI\n\t"
%}
ins_encode %{
@ -9960,7 +9969,7 @@ instruct cmovI_cmpU(iRegINoSp dst, iRegI src, iRegI op1, iRegI op2, cmpOpU cop)
ins_cost(ALU_COST + BRANCH_COST);
format %{
"CMove $dst, ($op1 $cop $op2), $dst, $src\t#@cmovI_cmpU\n\t"
"CMoveI $dst, ($op1 $cop $op2), $dst, $src\t#@cmovI_cmpU\n\t"
%}
ins_encode %{
@ -9977,7 +9986,7 @@ instruct cmovI_cmpL(iRegINoSp dst, iRegI src, iRegL op1, iRegL op2, cmpOp cop) %
ins_cost(ALU_COST + BRANCH_COST);
format %{
"CMove $dst, ($op1 $cop $op2), $dst, $src\t#@cmovI_cmpL\n\t"
"CMoveI $dst, ($op1 $cop $op2), $dst, $src\t#@cmovI_cmpL\n\t"
%}
ins_encode %{
@ -9994,7 +10003,7 @@ instruct cmovI_cmpUL(iRegINoSp dst, iRegI src, iRegL op1, iRegL op2, cmpOpU cop)
ins_cost(ALU_COST + BRANCH_COST);
format %{
"CMove $dst, ($op1 $cop $op2), $dst, $src\t#@cmovI_cmpUL\n\t"
"CMoveI $dst, ($op1 $cop $op2), $dst, $src\t#@cmovI_cmpUL\n\t"
%}
ins_encode %{
@ -10006,12 +10015,46 @@ instruct cmovI_cmpUL(iRegINoSp dst, iRegI src, iRegL op1, iRegL op2, cmpOpU cop)
ins_pipe(pipe_class_compare);
%}
instruct cmovI_cmpF(iRegINoSp dst, iRegI src, fRegF op1, fRegF op2, cmpOp cop) %{
match(Set dst (CMoveI (Binary cop (CmpF op1 op2)) (Binary dst src)));
ins_cost(ALU_COST + BRANCH_COST);
format %{
"CMoveI $dst, ($op1 $cop $op2), $dst, $src\t#@cmovI_cmpF\n\t"
%}
ins_encode %{
__ enc_cmove_cmp_fp($cop$$cmpcode,
as_FloatRegister($op1$$reg), as_FloatRegister($op2$$reg),
as_Register($dst$$reg), as_Register($src$$reg), true /* is_single */);
%}
ins_pipe(pipe_class_compare);
%}
instruct cmovI_cmpD(iRegINoSp dst, iRegI src, fRegD op1, fRegD op2, cmpOp cop) %{
match(Set dst (CMoveI (Binary cop (CmpD op1 op2)) (Binary dst src)));
ins_cost(ALU_COST + BRANCH_COST);
format %{
"CMoveI $dst, ($op1 $cop $op2), $dst, $src\t#@cmovI_cmpD\n\t"
%}
ins_encode %{
__ enc_cmove_cmp_fp($cop$$cmpcode | C2_MacroAssembler::double_branch_mask,
as_FloatRegister($op1$$reg), as_FloatRegister($op2$$reg),
as_Register($dst$$reg), as_Register($src$$reg), false /* is_single */);
%}
ins_pipe(pipe_class_compare);
%}
instruct cmovI_cmpN(iRegINoSp dst, iRegI src, iRegN op1, iRegN op2, cmpOpU cop) %{
match(Set dst (CMoveI (Binary cop (CmpN op1 op2)) (Binary dst src)));
ins_cost(ALU_COST + BRANCH_COST);
format %{
"CMove $dst, ($op1 $cop $op2), $dst, $src\t#@cmovI_cmpN\n\t"
"CMoveI $dst, ($op1 $cop $op2), $dst, $src\t#@cmovI_cmpN\n\t"
%}
ins_encode %{
@ -10028,7 +10071,7 @@ instruct cmovI_cmpP(iRegINoSp dst, iRegI src, iRegP op1, iRegP op2, cmpOpU cop)
ins_cost(ALU_COST + BRANCH_COST);
format %{
"CMove $dst, ($op1 $cop $op2), $dst, $src\t#@cmovI_cmpP\n\t"
"CMoveI $dst, ($op1 $cop $op2), $dst, $src\t#@cmovI_cmpP\n\t"
%}
ins_encode %{
@ -10040,12 +10083,14 @@ instruct cmovI_cmpP(iRegINoSp dst, iRegI src, iRegP op1, iRegP op2, cmpOpU cop)
ins_pipe(pipe_class_compare);
%}
// --------- CMoveL ---------
instruct cmovL_cmpL(iRegLNoSp dst, iRegL src, iRegL op1, iRegL op2, cmpOp cop) %{
match(Set dst (CMoveL (Binary cop (CmpL op1 op2)) (Binary dst src)));
ins_cost(ALU_COST + BRANCH_COST);
format %{
"CMove $dst, ($op1 $cop $op2), $dst, $src\t#@cmovL_cmpL\n\t"
"CMoveL $dst, ($op1 $cop $op2), $dst, $src\t#@cmovL_cmpL\n\t"
%}
ins_encode %{
@ -10062,7 +10107,7 @@ instruct cmovL_cmpUL(iRegLNoSp dst, iRegL src, iRegL op1, iRegL op2, cmpOpU cop)
ins_cost(ALU_COST + BRANCH_COST);
format %{
"CMove $dst, ($op1 $cop $op2), $dst, $src\t#@cmovL_cmpUL\n\t"
"CMoveL $dst, ($op1 $cop $op2), $dst, $src\t#@cmovL_cmpUL\n\t"
%}
ins_encode %{
@ -10079,7 +10124,7 @@ instruct cmovL_cmpI(iRegLNoSp dst, iRegL src, iRegI op1, iRegI op2, cmpOp cop) %
ins_cost(ALU_COST + BRANCH_COST);
format %{
"CMove $dst, ($op1 $cop $op2), $dst, $src\t#@cmovL_cmpI\n\t"
"CMoveL $dst, ($op1 $cop $op2), $dst, $src\t#@cmovL_cmpI\n\t"
%}
ins_encode %{
@ -10096,7 +10141,7 @@ instruct cmovL_cmpU(iRegLNoSp dst, iRegL src, iRegI op1, iRegI op2, cmpOpU cop)
ins_cost(ALU_COST + BRANCH_COST);
format %{
"CMove $dst, ($op1 $cop $op2), $dst, $src\t#@cmovL_cmpU\n\t"
"CMoveL $dst, ($op1 $cop $op2), $dst, $src\t#@cmovL_cmpU\n\t"
%}
ins_encode %{
@ -10108,12 +10153,46 @@ instruct cmovL_cmpU(iRegLNoSp dst, iRegL src, iRegI op1, iRegI op2, cmpOpU cop)
ins_pipe(pipe_class_compare);
%}
instruct cmovL_cmpF(iRegLNoSp dst, iRegL src, fRegF op1, fRegF op2, cmpOp cop) %{
match(Set dst (CMoveL (Binary cop (CmpF op1 op2)) (Binary dst src)));
ins_cost(ALU_COST + BRANCH_COST);
format %{
"CMoveL $dst, ($op1 $cop $op2), $dst, $src\t#@cmovL_cmpF\n\t"
%}
ins_encode %{
__ enc_cmove_cmp_fp($cop$$cmpcode,
as_FloatRegister($op1$$reg), as_FloatRegister($op2$$reg),
as_Register($dst$$reg), as_Register($src$$reg), true /* is_single */);
%}
ins_pipe(pipe_class_compare);
%}
instruct cmovL_cmpD(iRegLNoSp dst, iRegL src, fRegD op1, fRegD op2, cmpOp cop) %{
match(Set dst (CMoveL (Binary cop (CmpD op1 op2)) (Binary dst src)));
ins_cost(ALU_COST + BRANCH_COST);
format %{
"CMoveL $dst, ($op1 $cop $op2), $dst, $src\t#@cmovL_cmpD\n\t"
%}
ins_encode %{
__ enc_cmove_cmp_fp($cop$$cmpcode | C2_MacroAssembler::double_branch_mask,
as_FloatRegister($op1$$reg), as_FloatRegister($op2$$reg),
as_Register($dst$$reg), as_Register($src$$reg), false /* is_single */);
%}
ins_pipe(pipe_class_compare);
%}
instruct cmovL_cmpN(iRegLNoSp dst, iRegL src, iRegN op1, iRegN op2, cmpOpU cop) %{
match(Set dst (CMoveL (Binary cop (CmpN op1 op2)) (Binary dst src)));
ins_cost(ALU_COST + BRANCH_COST);
format %{
"CMove $dst, ($op1 $cop $op2), $dst, $src\t#@cmovL_cmpN\n\t"
"CMoveL $dst, ($op1 $cop $op2), $dst, $src\t#@cmovL_cmpN\n\t"
%}
ins_encode %{
@ -10130,7 +10209,7 @@ instruct cmovL_cmpP(iRegLNoSp dst, iRegL src, iRegP op1, iRegP op2, cmpOpU cop)
ins_cost(ALU_COST + BRANCH_COST);
format %{
"CMove $dst, ($op1 $cop $op2), $dst, $src\t#@cmovL_cmpP\n\t"
"CMoveL $dst, ($op1 $cop $op2), $dst, $src\t#@cmovL_cmpP\n\t"
%}
ins_encode %{

View File

@ -248,14 +248,6 @@ void VM_Version::common_initialize() {
#ifdef COMPILER2
void VM_Version::c2_initialize() {
if (UseCMoveUnconditionally) {
FLAG_SET_DEFAULT(UseCMoveUnconditionally, false);
}
if (ConditionalMoveLimit > 0) {
FLAG_SET_DEFAULT(ConditionalMoveLimit, 0);
}
if (!UseRVV) {
FLAG_SET_DEFAULT(MaxVectorSize, 0);
} else {

View File

@ -233,10 +233,13 @@ void RiscvHwprobe::add_features_from_query_result() {
if (is_set(RISCV_HWPROBE_KEY_IMA_EXT_0, RISCV_HWPROBE_EXT_ZACAS)) {
VM_Version::ext_Zacas.enable_feature();
}
#endif
// Currently tests shows that cmove using Zicond instructions will bring
// performance regression, but to get a test coverage all the time, will
// still prefer to enabling it in debug version.
if (is_set(RISCV_HWPROBE_KEY_IMA_EXT_0, RISCV_HWPROBE_EXT_ZICOND)) {
VM_Version::ext_Zicond.enable_feature();
}
#endif
if (is_valid(RISCV_HWPROBE_KEY_CPUPERF_0)) {
VM_Version::unaligned_access.enable_feature(
query[RISCV_HWPROBE_KEY_CPUPERF_0].value & RISCV_HWPROBE_MISALIGNED_MASK);

View File

@ -121,10 +121,8 @@ public class ModINodeIdealizationTests {
}
@Test
@IR(applyIfPlatform = {"riscv64", "false"},
failOn = {IRNode.MOD_I})
@IR(applyIfPlatform = {"riscv64", "false"},
counts = {IRNode.AND_I, ">=1", IRNode.RSHIFT, ">=1", IRNode.CMP_I, "2"})
@IR(failOn = {IRNode.MOD_I})
@IR(counts = {IRNode.AND_I, ">=1", IRNode.RSHIFT, ">=1", IRNode.CMP_I, "2"})
// Special optimization for the case 2^k-1 for bigger k
public int powerOf2Minus1(int x) {
return x % 127;

View File

@ -105,10 +105,8 @@ public class ModLNodeIdealizationTests {
}
@Test
@IR(applyIfPlatform = {"riscv64", "false"},
failOn = {IRNode.MOD_L})
@IR(applyIfPlatform = {"riscv64", "false"},
counts = {IRNode.AND_L, ">=1", IRNode.RSHIFT, ">=1", IRNode.CMP_L, "2"})
@IR(failOn = {IRNode.MOD_L})
@IR(counts = {IRNode.AND_L, ">=1", IRNode.RSHIFT, ">=1", IRNode.CMP_L, "2"})
// Special optimization for the case 2^k-1 for bigger k
public long powerOf2Minus1(long x) {
return x % ((1L << 33) - 1);

View File

@ -42,6 +42,14 @@ public class TestConv2BExpansion {
TestFramework.run();
}
// These IR checks do not apply on riscv64, as riscv64 supports Conv2B, e.g. for `return x == 0`,
// the graph looks like:
// Return (XorI (Conv2B ConI(#int: 1)))
// On other platforms, e.g. x86_64 which does not supports Conv2B, the graph looks like:
// Return (CMoveI (Bool (CompI (Param1 ConI(#int: 0))) ConI(#int: 1) ConI(#int: 0)))
// On riscv64, current graph is more efficient than `CMoveI`, as it
// 1. generates less code
// 2. even when zicond is not supported, it does not introduce branches.
@Test
@IR(counts = {IRNode.CMOVE_I, "1"}, failOn = {IRNode.XOR})
public boolean testIntEquals0(int x) {

View File

@ -31,7 +31,6 @@ import jdk.test.lib.Asserts;
* @summary Test that code generation for fp comparison works as intended
* @library /test/lib /
* @run driver compiler.c2.irTests.TestFPComparison
* @requires os.arch != "riscv64"
*/
public class TestFPComparison {
static final double[] DOUBLES = new double[] {

View File

@ -33,7 +33,6 @@ import jdk.test.lib.Utils;
* @bug 8324655 8329797 8331090
* @key randomness
* @summary Test that if expressions are properly folded into min/max nodes
* @requires os.arch != "riscv64"
* @library /test/lib /
* @run driver compiler.c2.irTests.TestIfMinMax
*/
@ -228,7 +227,7 @@ public class TestIfMinMax {
@Test
@IR(applyIf = { "SuperWordReductions", "true" },
applyIfCPUFeatureOr = { "sse4.1", "true" , "asimd" , "true"},
applyIfCPUFeatureOr = { "sse4.1", "true" , "asimd" , "true", "rvv", "true"},
counts = { IRNode.MAX_REDUCTION_V, "> 0" })
@Arguments(setup = "setupIntArrays")
public Object[] testMaxIntReduction(int[] a, int[] b) {
@ -262,7 +261,7 @@ public class TestIfMinMax {
@Test
@IR(applyIf = { "SuperWordReductions", "true" },
applyIfCPUFeatureOr = { "sse4.1", "true" , "asimd" , "true"},
applyIfCPUFeatureOr = { "sse4.1", "true" , "asimd" , "true", "rvv", "true"},
counts = { IRNode.MIN_REDUCTION_V, "> 0" })
@Arguments(setup = "setupIntArrays")
public Object[] testMinIntReduction(int[] a, int[] b) {
@ -297,7 +296,7 @@ public class TestIfMinMax {
@Test
@IR(applyIf = { "SuperWordReductions", "true" },
applyIfCPUFeatureOr = { "avx512", "true" },
applyIfCPUFeatureOr = { "avx512", "true", "rvv", "true" },
counts = { IRNode.MAX_REDUCTION_V, "> 0" })
@Arguments(setup = "setupLongArrays")
public Object[] testMaxLongReduction(long[] a, long[] b) {
@ -332,7 +331,7 @@ public class TestIfMinMax {
@Test
@IR(applyIf = { "SuperWordReductions", "true" },
applyIfCPUFeatureOr = { "avx512", "true" },
applyIfCPUFeatureOr = { "avx512", "true", "rvv", "true" },
counts = { IRNode.MIN_REDUCTION_V, "> 0" })
@Arguments(setup = "setupLongArrays")
public Object[] testMinLongReduction(long[] a, long[] b) {
@ -366,7 +365,7 @@ public class TestIfMinMax {
}
@Test
@IR(applyIfCPUFeatureOr = { "sse4.1", "true" , "asimd" , "true"},
@IR(applyIfCPUFeatureOr = { "sse4.1", "true" , "asimd" , "true", "rvv", "true"},
counts = { IRNode.MAX_VI, "> 0" })
@Arguments(setup = "setupIntArrays")
public Object[] testMaxIntVector(int[] a, int[] b) {
@ -401,7 +400,7 @@ public class TestIfMinMax {
}
@Test
@IR(applyIfCPUFeatureOr = { "sse4.1", "true" , "asimd" , "true"},
@IR(applyIfCPUFeatureOr = { "sse4.1", "true" , "asimd" , "true", "rvv", "true"},
counts = { IRNode.MIN_VI, "> 0" })
@Arguments(setup = "setupIntArrays")
public Object[] testMinIntVector(int[] a, int[] b) {
@ -436,7 +435,7 @@ public class TestIfMinMax {
}
@Test
@IR(applyIfCPUFeatureOr = { "sse4.1", "true" , "asimd" , "true"},
@IR(applyIfCPUFeatureOr = { "sse4.1", "true" , "asimd" , "true", "rvv", "true"},
counts = { IRNode.MAX_VL, "> 0" })
@Arguments(setup = "setupLongArrays")
public Object[] testMaxLongVector(long[] a, long[] b) {
@ -471,7 +470,7 @@ public class TestIfMinMax {
}
@Test
@IR(applyIfCPUFeatureOr = { "sse4.1", "true" , "asimd" , "true"},
@IR(applyIfCPUFeatureOr = { "sse4.1", "true" , "asimd" , "true", "rvv", "true"},
counts = { IRNode.MIN_VL, "> 0" })
@Arguments(setup = "setupLongArrays")
public Object[] testMinLongVector(long[] a, long[] b) {

View File

@ -146,6 +146,7 @@ public class TestFramework {
"UseRVV",
"UseZbb",
"UseZfh",
"UseZicond",
"UseZvbb"
)
);

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2022, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -35,6 +35,7 @@ import jdk.incubator.vector.VectorMask;
* @library /test/lib /
* @requires (os.simpleArch == "x64" & vm.cpu.features ~= ".*sse4.*" & (vm.opt.UseSSE == "null" | vm.opt.UseSSE > 3))
* | os.arch == "aarch64"
* | (os.arch == "riscv64" & vm.cpu.features ~= ".*rvv.*")
* @run driver compiler.vectorapi.TestVectorTest
*/
public class TestVectorTest {

View File

@ -0,0 +1,101 @@
/*
* Copyright (c) 2025, Rivos Inc. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package org.openjdk.bench.java.lang;
import org.openjdk.jmh.annotations.*;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.random.RandomGenerator;
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
@State(Scope.Thread)
@Warmup(iterations = 5, time = 1)
@Measurement(iterations = 5, time = 1)
@Fork(3)
public class ClassComparison {
static final int INVOCATIONS = 1024;
Class[] c1;
Class[] c2;
int[] res;
long[] resLong;
Object[] resObject;
Object ro1;
Object ro2;
Object[] resClass;
Class rc1;
Class rc2;
@Setup
public void setup() {
var random = RandomGenerator.getDefault();
c1 = new Class[INVOCATIONS];
c2 = new Class[INVOCATIONS];
res = new int[INVOCATIONS];
resLong = new long[INVOCATIONS];
resObject = new Object[INVOCATIONS];
ro1 = new Object();
ro2 = new Object();
resClass = new Class[INVOCATIONS];
rc1 = Float.class;
rc2 = Double.class;
for (int i = 0; i < INVOCATIONS; i++) {
c1[i] = random.nextBoolean() ? Float.class : Double.class;
}
List<Class> list = Arrays.asList(c1);
Collections.shuffle(list);
list.toArray(c2);
}
@Benchmark
public void equalClass() {
for (int i = 0; i < INVOCATIONS; i++) {
res[i] = (c1[i] == c2[i]) ? 1 : 2;
}
}
@Benchmark
public void notEqualClass() {
for (int i = 0; i < INVOCATIONS; i++) {
res[i] = (c1[i] != c2[i]) ? 1 : 2;
}
}
public void equalClassResLong() {
for (int i = 0; i < INVOCATIONS; i++) {
resLong[i] = (c1[i] == c2[i]) ? Long.MAX_VALUE : Long.MIN_VALUE;
}
}
@Benchmark
public void notEqualClassResLong() {
for (int i = 0; i < INVOCATIONS; i++) {
resLong[i] = (c1[i] != c2[i]) ? Long.MAX_VALUE : Long.MIN_VALUE;
}
}
}

View File

@ -23,6 +23,7 @@
package org.openjdk.bench.java.lang;
import org.openjdk.jmh.annotations.*;
import org.openjdk.jmh.infra.Blackhole;
import java.util.concurrent.TimeUnit;
import java.util.random.RandomGenerator;
@ -41,6 +42,13 @@ public class FPComparison {
float[] f2;
double[] d2;
int[] res;
long[] resLong;
Object[] resObject;
Object ro1;
Object ro2;
Class[] resClass;
Class rc1;
Class rc2;
@Setup
public void setup() {
@ -50,6 +58,13 @@ public class FPComparison {
f2 = new float[INVOCATIONS];
d2 = new double[INVOCATIONS];
res = new int[INVOCATIONS];
resLong = new long[INVOCATIONS];
resObject = new Object[INVOCATIONS];
ro1 = new Object();
ro2 = new Object();
resClass = new Class[INVOCATIONS];
rc1 = Float.class;
rc2 = Double.class;
for (int i = 0; i < INVOCATIONS; i++) {
int type = random.nextInt(5);
if (type == 1) {
@ -79,56 +94,184 @@ public class FPComparison {
@Benchmark
public void isNanFloat() {
for (int i = 0; i < INVOCATIONS; i++) {
res[i] = Float.isNaN(f1[i]) ? 1 : 0;
res[i] = Float.isNaN(f1[i]) ? 1 : 2;
}
}
@Benchmark
public void isNanDouble() {
for (int i = 0; i < INVOCATIONS; i++) {
res[i] = Double.isNaN(d1[i]) ? 1 : 0;
res[i] = Double.isNaN(d1[i]) ? 1 : 2;
}
}
@Benchmark
public void isInfiniteFloat() {
for (int i = 0; i < INVOCATIONS; i++) {
res[i] = Float.isInfinite(f1[i]) ? 1 : 0;
res[i] = Float.isInfinite(f1[i]) ? 1 : 2;
}
}
@Benchmark
public void isInfiniteDouble() {
for (int i = 0; i < INVOCATIONS; i++) {
res[i] = Double.isInfinite(d1[i]) ? 1 : 0;
res[i] = Double.isInfinite(d1[i]) ? 1 : 2;
}
}
@Benchmark
public void isFiniteFloat() {
for (int i = 0; i < INVOCATIONS; i++) {
res[i] = Float.isFinite(f1[i]) ? 1 : 0;
res[i] = Float.isFinite(f1[i]) ? 1 : 2;
}
}
@Benchmark
public void isFiniteDouble() {
for (int i = 0; i < INVOCATIONS; i++) {
res[i] = Double.isFinite(d1[i]) ? 1 : 0;
res[i] = Double.isFinite(d1[i]) ? 1 : 2;
}
}
@Benchmark
public void equalFloat() {
for (int i = 0; i < INVOCATIONS; i++) {
res[i] = (f1[i] == f2[i]) ? 1 : 0;
res[i] = (f1[i] == f2[i]) ? 1 : 2;
}
}
@Benchmark
public void equalDouble() {
for (int i = 0; i < INVOCATIONS; i++) {
res[i] = (d1[i] == d2[i]) ? 1 : 0;
res[i] = (d1[i] == d2[i]) ? 1 : 2;
}
}
@Benchmark
public void lessFloat() {
for (int i = 0; i < INVOCATIONS; i++) {
res[i] = (f1[i] < f2[i]) ? 1 : 2;
}
}
@Benchmark
public void lessDouble() {
for (int i = 0; i < INVOCATIONS; i++) {
res[i] = (d1[i] < d2[i]) ? 1 : 2;
}
}
@Benchmark
public void lessEqualFloat() {
for (int i = 0; i < INVOCATIONS; i++) {
res[i] = (f1[i] <= f2[i]) ? 1 : 2;
}
}
@Benchmark
public void lessEqualDouble() {
for (int i = 0; i < INVOCATIONS; i++) {
res[i] = (d1[i] <= d2[i]) ? 1 : 2;
}
}
@Benchmark
public void greaterFloat() {
for (int i = 0; i < INVOCATIONS; i++) {
res[i] = (f1[i] > f2[i]) ? 1 : 2;
}
}
@Benchmark
public void greaterDouble() {
for (int i = 0; i < INVOCATIONS; i++) {
res[i] = (d1[i] > d2[i]) ? 1 : 2;
}
}
@Benchmark
public void greaterEqualFloat() {
for (int i = 0; i < INVOCATIONS; i++) {
res[i] = (f1[i] >= f2[i]) ? 1 : 2;
}
}
@Benchmark
public void greaterEqualDouble() {
for (int i = 0; i < INVOCATIONS; i++) {
res[i] = (d1[i] >= d2[i]) ? 1 : 2;
}
}
// --------- result: long ---------
@Benchmark
public void equalFloatResLong() {
for (int i = 0; i < INVOCATIONS; i++) {
resLong[i] = (f1[i] == f2[i]) ? Long.MAX_VALUE : Long.MIN_VALUE;
}
}
@Benchmark
public void equalDoubleResLong() {
for (int i = 0; i < INVOCATIONS; i++) {
resLong[i] = (d1[i] == d2[i]) ? Long.MAX_VALUE : Long.MIN_VALUE;
}
}
@Benchmark
public void lessFloatResLong() {
for (int i = 0; i < INVOCATIONS; i++) {
resLong[i] = (f1[i] < f2[i]) ? Long.MAX_VALUE : Long.MIN_VALUE;
}
}
@Benchmark
public void lessDoubleResLong() {
for (int i = 0; i < INVOCATIONS; i++) {
resLong[i] = (d1[i] < d2[i]) ? Long.MAX_VALUE : Long.MIN_VALUE;
}
}
@Benchmark
public void lessEqualFloatResLong() {
for (int i = 0; i < INVOCATIONS; i++) {
resLong[i] = (f1[i] <= f2[i]) ? Long.MAX_VALUE : Long.MIN_VALUE;
}
}
@Benchmark
public void lessEqualDoubleResLong() {
for (int i = 0; i < INVOCATIONS; i++) {
resLong[i] = (d1[i] <= d2[i]) ? Long.MAX_VALUE : Long.MIN_VALUE;
}
}
@Benchmark
public void greaterFloatResLong() {
for (int i = 0; i < INVOCATIONS; i++) {
resLong[i] = (f1[i] > f2[i]) ? Long.MAX_VALUE : Long.MIN_VALUE;
}
}
@Benchmark
public void greaterDoubleResLong() {
for (int i = 0; i < INVOCATIONS; i++) {
resLong[i] = (d1[i] > d2[i]) ? Long.MAX_VALUE : Long.MIN_VALUE;
}
}
@Benchmark
public void greaterEqualFloatResLong() {
for (int i = 0; i < INVOCATIONS; i++) {
resLong[i] = (f1[i] >= f2[i]) ? Long.MAX_VALUE : Long.MIN_VALUE;
}
}
@Benchmark
public void greaterEqualDoubleResLong() {
for (int i = 0; i < INVOCATIONS; i++) {
resLong[i] = (d1[i] >= d2[i]) ? Long.MAX_VALUE : Long.MIN_VALUE;
}
}
}

View File

@ -0,0 +1,153 @@
/*
* Copyright (c) 2025, Rivos Inc. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package org.openjdk.bench.java.lang;
import org.openjdk.jmh.annotations.*;
import org.openjdk.jmh.infra.Blackhole;
import java.util.concurrent.TimeUnit;
import java.util.random.RandomGenerator;
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
@State(Scope.Thread)
@Warmup(iterations = 5, time = 1)
@Measurement(iterations = 5, time = 1)
@Fork(3)
public class IntegerComparison {
static final int INVOCATIONS = 1024;
int[] i1;
int[] i2;
int[] res;
long[] resLong;
Object[] resObject;
Object ro1;
Object ro2;
Object[] resClass;
Class rc1;
Class rc2;
@Setup
public void setup() {
var random = RandomGenerator.getDefault();
i1 = new int[INVOCATIONS];
i2 = new int[INVOCATIONS];
res = new int[INVOCATIONS];
resLong = new long[INVOCATIONS];
resObject = new Object[INVOCATIONS];
ro1 = new Object();
ro2 = new Object();
resClass = new Class[INVOCATIONS];
rc1 = Float.class;
rc2 = Double.class;
for (int i = 0; i < INVOCATIONS; i++) {
i1[i] = random.nextInt(INVOCATIONS);
i2[i] = random.nextInt(INVOCATIONS);
}
}
@Benchmark
public void equalInteger() {
for (int i = 0; i < INVOCATIONS; i++) {
res[i] = (i1[i] == i2[i]) ? 1 : 2;
}
}
@Benchmark
public void notEqualInteger() {
for (int i = 0; i < INVOCATIONS; i++) {
res[i] = (i1[i] != i2[i]) ? 1 : 2;
}
}
@Benchmark
public void lessInteger() {
for (int i = 0; i < INVOCATIONS; i++) {
res[i] = (i1[i] < i2[i]) ? 1 : 2;
}
}
@Benchmark
public void lessEqualInteger() {
for (int i = 0; i < INVOCATIONS; i++) {
res[i] = (i1[i] <= i2[i]) ? 1 : 2;
}
}
@Benchmark
public void greaterInteger() {
for (int i = 0; i < INVOCATIONS; i++) {
res[i] = (i1[i] > i2[i]) ? 1 : 2;
}
}
@Benchmark
public void greaterEqualInteger() {
for (int i = 0; i < INVOCATIONS; i++) {
res[i] = (i1[i] >= i2[i]) ? 1 : 2;
}
}
// --------- result: long ---------
public void equalIntegerResLong() {
for (int i = 0; i < INVOCATIONS; i++) {
resLong[i] = (i1[i] == i2[i]) ? Long.MAX_VALUE : Long.MIN_VALUE;
}
}
@Benchmark
public void notEqualIntegerResLong() {
for (int i = 0; i < INVOCATIONS; i++) {
resLong[i] = (i1[i] != i2[i]) ? Long.MAX_VALUE : Long.MIN_VALUE;
}
}
public void lessIntegerResLong() {
for (int i = 0; i < INVOCATIONS; i++) {
resLong[i] = (i1[i] < i2[i]) ? Long.MAX_VALUE : Long.MIN_VALUE;
}
}
@Benchmark
public void lessEqualIntegerResLong() {
for (int i = 0; i < INVOCATIONS; i++) {
resLong[i] = (i1[i] <= i2[i]) ? Long.MAX_VALUE : Long.MIN_VALUE;
}
}
public void greaterIntegerResLong() {
for (int i = 0; i < INVOCATIONS; i++) {
resLong[i] = (i1[i] > i2[i]) ? Long.MAX_VALUE : Long.MIN_VALUE;
}
}
@Benchmark
public void greaterEqualIntegerResLong() {
for (int i = 0; i < INVOCATIONS; i++) {
resLong[i] = (i1[i] >= i2[i]) ? Long.MAX_VALUE : Long.MIN_VALUE;
}
}
}

View File

@ -0,0 +1,152 @@
/*
* Copyright (c) 2025, Rivos Inc. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package org.openjdk.bench.java.lang;
import org.openjdk.jmh.annotations.*;
import java.util.concurrent.TimeUnit;
import java.util.random.RandomGenerator;
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
@State(Scope.Thread)
@Warmup(iterations = 5, time = 1)
@Measurement(iterations = 5, time = 1)
@Fork(3)
public class LongComparison {
static final int INVOCATIONS = 1024;
long[] l1;
long[] l2;
int[] res;
long[] resLong;
Object[] resObject;
Object ro1;
Object ro2;
Object[] resClass;
Class rc1;
Class rc2;
@Setup
public void setup() {
var random = RandomGenerator.getDefault();
l1 = new long[INVOCATIONS];
l2 = new long[INVOCATIONS];
res = new int[INVOCATIONS];
resLong = new long[INVOCATIONS];
resObject = new Object[INVOCATIONS];
ro1 = new Object();
ro2 = new Object();
resClass = new Class[INVOCATIONS];
rc1 = Float.class;
rc2 = Double.class;
for (int i = 0; i < INVOCATIONS; i++) {
l1[i] = random.nextLong(INVOCATIONS);
l2[i] = random.nextLong(INVOCATIONS);
}
}
@Benchmark
public void equalLong() {
for (int i = 0; i < INVOCATIONS; i++) {
res[i] = (l1[i] == l2[i]) ? 1 : 2;
}
}
@Benchmark
public void notEqualLong() {
for (int i = 0; i < INVOCATIONS; i++) {
res[i] = (l1[i] != l2[i]) ? 1 : 2;
}
}
@Benchmark
public void lessLong() {
for (int i = 0; i < INVOCATIONS; i++) {
res[i] = (l1[i] < l2[i]) ? 1 : 2;
}
}
@Benchmark
public void lessEqualLong() {
for (int i = 0; i < INVOCATIONS; i++) {
res[i] = (l1[i] <= l2[i]) ? 1 : 2;
}
}
@Benchmark
public void greaterLong() {
for (int i = 0; i < INVOCATIONS; i++) {
res[i] = (l1[i] > l2[i]) ? 1 : 2;
}
}
@Benchmark
public void greaterEqualLong() {
for (int i = 0; i < INVOCATIONS; i++) {
res[i] = (l1[i] >= l2[i]) ? 1 : 2;
}
}
// --------- result: long ---------
public void equalLongResLong() {
for (int i = 0; i < INVOCATIONS; i++) {
resLong[i] = (l1[i] == l2[i]) ? Long.MAX_VALUE : Long.MIN_VALUE;
}
}
@Benchmark
public void notEqualLongResLong() {
for (int i = 0; i < INVOCATIONS; i++) {
resLong[i] = (l1[i] != l2[i]) ? Long.MAX_VALUE : Long.MIN_VALUE;
}
}
public void lessLongResLong() {
for (int i = 0; i < INVOCATIONS; i++) {
resLong[i] = (l1[i] < l2[i]) ? Long.MAX_VALUE : Long.MIN_VALUE;
}
}
@Benchmark
public void lessEqualLongResLong() {
for (int i = 0; i < INVOCATIONS; i++) {
resLong[i] = (l1[i] <= l2[i]) ? Long.MAX_VALUE : Long.MIN_VALUE;
}
}
public void greaterLongResLong() {
for (int i = 0; i < INVOCATIONS; i++) {
resLong[i] = (l1[i] > l2[i]) ? Long.MAX_VALUE : Long.MIN_VALUE;
}
}
@Benchmark
public void greaterEqualLongResLong() {
for (int i = 0; i < INVOCATIONS; i++) {
resLong[i] = (l1[i] >= l2[i]) ? Long.MAX_VALUE : Long.MIN_VALUE;
}
}
}

View File

@ -0,0 +1,101 @@
/*
* Copyright (c) 2025, Rivos Inc. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package org.openjdk.bench.java.lang;
import org.openjdk.jmh.annotations.*;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.random.RandomGenerator;
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
@State(Scope.Thread)
@Warmup(iterations = 5, time = 1)
@Measurement(iterations = 5, time = 1)
@Fork(3)
public class PointerComparison {
static final int INVOCATIONS = 1024;
Object[] o1;
Object[] o2;
int[] res;
long[] resLong;
Object[] resObject;
Object ro1;
Object ro2;
Object[] resClass;
Class rc1;
Class rc2;
@Setup
public void setup() {
var random = RandomGenerator.getDefault();
o1 = new Object[INVOCATIONS];
o2 = new Object[INVOCATIONS];
res = new int[INVOCATIONS];
resLong = new long[INVOCATIONS];
resObject = new Object[INVOCATIONS];
ro1 = new Object();
ro2 = new Object();
resClass = new Class[INVOCATIONS];
rc1 = Float.class;
rc2 = Double.class;
for (int i = 0; i < INVOCATIONS; i++) {
o1[i] = new Object();
}
List<Object> list = Arrays.asList(o1);
Collections.shuffle(list);
list.toArray(o2);
}
@Benchmark
public void equalObject() {
for (int i = 0; i < INVOCATIONS; i++) {
res[i] = (o1[i] == o2[i]) ? 1 : 2;
}
}
@Benchmark
public void notEqualObject() {
for (int i = 0; i < INVOCATIONS; i++) {
res[i] = (o1[i] != o2[i]) ? 1 : 2;
}
}
public void equalObjectResLong() {
for (int i = 0; i < INVOCATIONS; i++) {
resLong[i] = (o1[i] == o2[i]) ? Long.MAX_VALUE : Long.MIN_VALUE;
}
}
@Benchmark
public void notEqualObjectResLong() {
for (int i = 0; i < INVOCATIONS; i++) {
resLong[i] = (o1[i] != o2[i]) ? Long.MAX_VALUE : Long.MIN_VALUE;
}
}
}