mirror of
https://github.com/openjdk/jdk.git
synced 2026-04-21 04:10:33 +00:00
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:
parent
50358d1ca4
commit
bcc33d5ef3
@ -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) {
|
||||
|
||||
@ -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));
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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) \
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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 %{
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -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[] {
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -146,6 +146,7 @@ public class TestFramework {
|
||||
"UseRVV",
|
||||
"UseZbb",
|
||||
"UseZfh",
|
||||
"UseZicond",
|
||||
"UseZvbb"
|
||||
)
|
||||
);
|
||||
|
||||
@ -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 {
|
||||
|
||||
101
test/micro/org/openjdk/bench/java/lang/ClassComparison.java
Normal file
101
test/micro/org/openjdk/bench/java/lang/ClassComparison.java
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
153
test/micro/org/openjdk/bench/java/lang/IntegerComparison.java
Normal file
153
test/micro/org/openjdk/bench/java/lang/IntegerComparison.java
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
152
test/micro/org/openjdk/bench/java/lang/LongComparison.java
Normal file
152
test/micro/org/openjdk/bench/java/lang/LongComparison.java
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
101
test/micro/org/openjdk/bench/java/lang/PointerComparison.java
Normal file
101
test/micro/org/openjdk/bench/java/lang/PointerComparison.java
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user