8248830
: C2: Optimize Rotate API on x86
Improved existing scalar rotate operations, added support for vector rotate operations using new AVX512 instructions. Reviewed-by: vlivanov, kvn
This commit is contained in:
parent
084e15bca3
commit
3ed56830b4
@ -4311,6 +4311,58 @@ void Assembler::roll(Register dst, int imm8) {
|
||||
}
|
||||
}
|
||||
|
||||
void Assembler::roll(Register dst) {
|
||||
int encode = prefix_and_encode(dst->encoding());
|
||||
emit_int16((unsigned char)0xD3, (0xC0 | encode));
|
||||
}
|
||||
|
||||
void Assembler::rorl(Register dst, int imm8) {
|
||||
assert(isShiftCount(imm8 >> 1), "illegal shift count");
|
||||
int encode = prefix_and_encode(dst->encoding());
|
||||
if (imm8 == 1) {
|
||||
emit_int16((unsigned char)0xD1, (0xC8 | encode));
|
||||
} else {
|
||||
emit_int24((unsigned char)0xC1, (0xc8 | encode), imm8);
|
||||
}
|
||||
}
|
||||
|
||||
void Assembler::rorl(Register dst) {
|
||||
int encode = prefix_and_encode(dst->encoding());
|
||||
emit_int16((unsigned char)0xD3, (0xC8 | encode));
|
||||
}
|
||||
|
||||
#ifdef _LP64
|
||||
void Assembler::rorq(Register dst) {
|
||||
int encode = prefixq_and_encode(dst->encoding());
|
||||
emit_int16((unsigned char)0xD3, (0xC8 | encode));
|
||||
}
|
||||
|
||||
void Assembler::rorq(Register dst, int imm8) {
|
||||
assert(isShiftCount(imm8 >> 1), "illegal shift count");
|
||||
int encode = prefixq_and_encode(dst->encoding());
|
||||
if (imm8 == 1) {
|
||||
emit_int16((unsigned char)0xD1, (0xC8 | encode));
|
||||
} else {
|
||||
emit_int24((unsigned char)0xC1, (0xc8 | encode), imm8);
|
||||
}
|
||||
}
|
||||
|
||||
void Assembler::rolq(Register dst) {
|
||||
int encode = prefixq_and_encode(dst->encoding());
|
||||
emit_int16((unsigned char)0xD3, (0xC0 | encode));
|
||||
}
|
||||
|
||||
void Assembler::rolq(Register dst, int imm8) {
|
||||
assert(isShiftCount(imm8 >> 1), "illegal shift count");
|
||||
int encode = prefixq_and_encode(dst->encoding());
|
||||
if (imm8 == 1) {
|
||||
emit_int16((unsigned char)0xD1, (0xC0 | encode));
|
||||
} else {
|
||||
emit_int24((unsigned char)0xC1, (0xc0 | encode), imm8);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void Assembler::sahf() {
|
||||
#ifdef _LP64
|
||||
// Not supported in 64bit mode
|
||||
@ -6226,6 +6278,78 @@ void Assembler::evpxorq(XMMRegister dst, XMMRegister nds, Address src, int vecto
|
||||
emit_operand(dst, src);
|
||||
}
|
||||
|
||||
void Assembler::evprold(XMMRegister dst, XMMRegister src, int shift, int vector_len) {
|
||||
assert(VM_Version::supports_evex(), "requires EVEX support");
|
||||
assert(vector_len == Assembler::AVX_512bit || VM_Version::supports_avx512vl(), "requires VL support");
|
||||
InstructionAttr attributes(vector_len, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ true);
|
||||
attributes.set_is_evex_instruction();
|
||||
int encode = vex_prefix_and_encode(xmm1->encoding(), dst->encoding(), src->encoding(), VEX_SIMD_66, VEX_OPCODE_0F, &attributes);
|
||||
emit_int24(0x72, (0xC0 | encode), shift & 0xFF);
|
||||
}
|
||||
|
||||
void Assembler::evprolq(XMMRegister dst, XMMRegister src, int shift, int vector_len) {
|
||||
assert(VM_Version::supports_evex(), "requires EVEX support");
|
||||
assert(vector_len == Assembler::AVX_512bit || VM_Version::supports_avx512vl(), "requires VL support");
|
||||
InstructionAttr attributes(vector_len, /* vex_w */ true, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ true);
|
||||
attributes.set_is_evex_instruction();
|
||||
int encode = vex_prefix_and_encode(xmm1->encoding(), dst->encoding(), src->encoding(), VEX_SIMD_66, VEX_OPCODE_0F, &attributes);
|
||||
emit_int24(0x72, (0xC0 | encode), shift & 0xFF);
|
||||
}
|
||||
|
||||
void Assembler::evprord(XMMRegister dst, XMMRegister src, int shift, int vector_len) {
|
||||
assert(VM_Version::supports_evex(), "requires EVEX support");
|
||||
assert(vector_len == Assembler::AVX_512bit || VM_Version::supports_avx512vl(), "requires VL support");
|
||||
InstructionAttr attributes(vector_len, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ true);
|
||||
attributes.set_is_evex_instruction();
|
||||
int encode = vex_prefix_and_encode(xmm0->encoding(), dst->encoding(), src->encoding(), VEX_SIMD_66, VEX_OPCODE_0F, &attributes);
|
||||
emit_int24(0x72, (0xC0 | encode), shift & 0xFF);
|
||||
}
|
||||
|
||||
void Assembler::evprorq(XMMRegister dst, XMMRegister src, int shift, int vector_len) {
|
||||
assert(VM_Version::supports_evex(), "requires EVEX support");
|
||||
assert(vector_len == Assembler::AVX_512bit || VM_Version::supports_avx512vl(), "requires VL support");
|
||||
InstructionAttr attributes(vector_len, /* vex_w */ true, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ true);
|
||||
attributes.set_is_evex_instruction();
|
||||
int encode = vex_prefix_and_encode(xmm0->encoding(), dst->encoding(), src->encoding(), VEX_SIMD_66, VEX_OPCODE_0F, &attributes);
|
||||
emit_int24(0x72, (0xC0 | encode), shift & 0xFF);
|
||||
}
|
||||
|
||||
void Assembler::evprolvd(XMMRegister dst, XMMRegister src, XMMRegister shift, int vector_len) {
|
||||
assert(VM_Version::supports_evex(), "requires EVEX support");
|
||||
assert(vector_len == Assembler::AVX_512bit || VM_Version::supports_avx512vl(), "requires VL support");
|
||||
InstructionAttr attributes(vector_len, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ true);
|
||||
attributes.set_is_evex_instruction();
|
||||
int encode = vex_prefix_and_encode(dst->encoding(), src->encoding(), shift->encoding(), VEX_SIMD_66, VEX_OPCODE_0F_38, &attributes);
|
||||
emit_int16(0x15, (unsigned char)(0xC0 | encode));
|
||||
}
|
||||
|
||||
void Assembler::evprolvq(XMMRegister dst, XMMRegister src, XMMRegister shift, int vector_len) {
|
||||
assert(VM_Version::supports_evex(), "requires EVEX support");
|
||||
assert(vector_len == Assembler::AVX_512bit || VM_Version::supports_avx512vl(), "requires VL support");
|
||||
InstructionAttr attributes(vector_len, /* vex_w */ true, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ true);
|
||||
attributes.set_is_evex_instruction();
|
||||
int encode = vex_prefix_and_encode(dst->encoding(), src->encoding(), shift->encoding(), VEX_SIMD_66, VEX_OPCODE_0F_38, &attributes);
|
||||
emit_int16(0x15, (unsigned char)(0xC0 | encode));
|
||||
}
|
||||
|
||||
void Assembler::evprorvd(XMMRegister dst, XMMRegister src, XMMRegister shift, int vector_len) {
|
||||
assert(VM_Version::supports_evex(), "requires EVEX support");
|
||||
assert(vector_len == Assembler::AVX_512bit || VM_Version::supports_avx512vl(), "requires VL support");
|
||||
InstructionAttr attributes(vector_len, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ true);
|
||||
attributes.set_is_evex_instruction();
|
||||
int encode = vex_prefix_and_encode(dst->encoding(), src->encoding(), shift->encoding(), VEX_SIMD_66, VEX_OPCODE_0F_38, &attributes);
|
||||
emit_int16(0x14, (unsigned char)(0xC0 | encode));
|
||||
}
|
||||
|
||||
void Assembler::evprorvq(XMMRegister dst, XMMRegister src, XMMRegister shift, int vector_len) {
|
||||
assert(VM_Version::supports_evex(), "requires EVEX support");
|
||||
assert(vector_len == Assembler::AVX_512bit || VM_Version::supports_avx512vl(), "requires VL support");
|
||||
InstructionAttr attributes(vector_len, /* vex_w */ true, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ true);
|
||||
attributes.set_is_evex_instruction();
|
||||
int encode = vex_prefix_and_encode(dst->encoding(), src->encoding(), shift->encoding(), VEX_SIMD_66, VEX_OPCODE_0F_38, &attributes);
|
||||
emit_int16(0x14, (unsigned char)(0xC0 | encode));
|
||||
}
|
||||
|
||||
void Assembler::vpternlogd(XMMRegister dst, int imm8, XMMRegister src2, XMMRegister src3, int vector_len) {
|
||||
assert(VM_Version::supports_evex(), "requires EVEX support");
|
||||
assert(vector_len == Assembler::AVX_512bit || VM_Version::supports_avx512vl(), "requires VL support");
|
||||
@ -8905,15 +9029,6 @@ void Assembler::rcrq(Register dst, int imm8) {
|
||||
}
|
||||
}
|
||||
|
||||
void Assembler::rorq(Register dst, int imm8) {
|
||||
assert(isShiftCount(imm8 >> 1), "illegal shift count");
|
||||
int encode = prefixq_and_encode(dst->encoding());
|
||||
if (imm8 == 1) {
|
||||
emit_int16((unsigned char)0xD1, (0xC8 | encode));
|
||||
} else {
|
||||
emit_int24((unsigned char)0xC1, (0xc8 | encode), imm8);
|
||||
}
|
||||
}
|
||||
|
||||
void Assembler::rorxq(Register dst, Register src, int imm8) {
|
||||
assert(VM_Version::supports_bmi2(), "bit manipulation instructions not supported");
|
||||
|
@ -1827,9 +1827,18 @@ private:
|
||||
|
||||
void ret(int imm16);
|
||||
|
||||
void roll(Register dst);
|
||||
|
||||
void roll(Register dst, int imm8);
|
||||
|
||||
void rorl(Register dst);
|
||||
|
||||
void rorl(Register dst, int imm8);
|
||||
|
||||
#ifdef _LP64
|
||||
void rolq(Register dst);
|
||||
void rolq(Register dst, int imm8);
|
||||
void rorq(Register dst);
|
||||
void rorq(Register dst, int imm8);
|
||||
void rorxq(Register dst, Register src, int imm8);
|
||||
void rorxd(Register dst, Register src, int imm8);
|
||||
@ -2205,6 +2214,16 @@ private:
|
||||
void vpternlogd(XMMRegister dst, int imm8, XMMRegister src2, Address src3, int vector_len);
|
||||
void vpternlogq(XMMRegister dst, int imm8, XMMRegister src2, XMMRegister src3, int vector_len);
|
||||
|
||||
// Vector Rotate Left/Right instruction.
|
||||
void evprolvd(XMMRegister dst, XMMRegister src, XMMRegister shift, int vector_len);
|
||||
void evprolvq(XMMRegister dst, XMMRegister src, XMMRegister shift, int vector_len);
|
||||
void evprorvd(XMMRegister dst, XMMRegister src, XMMRegister shift, int vector_len);
|
||||
void evprorvq(XMMRegister dst, XMMRegister src, XMMRegister shift, int vector_len);
|
||||
void evprold(XMMRegister dst, XMMRegister src, int shift, int vector_len);
|
||||
void evprolq(XMMRegister dst, XMMRegister src, int shift, int vector_len);
|
||||
void evprord(XMMRegister dst, XMMRegister src, int shift, int vector_len);
|
||||
void evprorq(XMMRegister dst, XMMRegister src, int shift, int vector_len);
|
||||
|
||||
// vinserti forms
|
||||
void vinserti128(XMMRegister dst, XMMRegister nds, XMMRegister src, uint8_t imm8);
|
||||
void vinserti128(XMMRegister dst, XMMRegister nds, Address src, uint8_t imm8);
|
||||
|
@ -870,6 +870,57 @@ void C2_MacroAssembler::vextendbw(bool sign, XMMRegister dst, XMMRegister src, i
|
||||
}
|
||||
}
|
||||
|
||||
void C2_MacroAssembler::vprotate_imm(int opcode, BasicType etype, XMMRegister dst, XMMRegister src,
|
||||
int shift, int vector_len) {
|
||||
if (opcode == Op_RotateLeftV) {
|
||||
if (etype == T_INT) {
|
||||
evprold(dst, src, shift, vector_len);
|
||||
} else {
|
||||
assert(etype == T_LONG, "expected type T_LONG");
|
||||
evprolq(dst, src, shift, vector_len);
|
||||
}
|
||||
} else {
|
||||
assert(opcode == Op_RotateRightV, "opcode should be Op_RotateRightV");
|
||||
if (etype == T_INT) {
|
||||
evprord(dst, src, shift, vector_len);
|
||||
} else {
|
||||
assert(etype == T_LONG, "expected type T_LONG");
|
||||
evprorq(dst, src, shift, vector_len);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void C2_MacroAssembler::vprotate_var(int opcode, BasicType etype, XMMRegister dst, XMMRegister src,
|
||||
XMMRegister shift, int vector_len) {
|
||||
if (opcode == Op_RotateLeftV) {
|
||||
if (etype == T_INT) {
|
||||
evprolvd(dst, src, shift, vector_len);
|
||||
} else {
|
||||
assert(etype == T_LONG, "expected type T_LONG");
|
||||
evprolvq(dst, src, shift, vector_len);
|
||||
}
|
||||
} else {
|
||||
assert(opcode == Op_RotateRightV, "opcode should be Op_RotateRightV");
|
||||
if (etype == T_INT) {
|
||||
evprorvd(dst, src, shift, vector_len);
|
||||
} else {
|
||||
assert(etype == T_LONG, "expected type T_LONG");
|
||||
evprorvq(dst, src, shift, vector_len);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void C2_MacroAssembler::vshiftd_imm(int opcode, XMMRegister dst, int shift) {
|
||||
if (opcode == Op_RShiftVI) {
|
||||
psrad(dst, shift);
|
||||
} else if (opcode == Op_LShiftVI) {
|
||||
pslld(dst, shift);
|
||||
} else {
|
||||
assert((opcode == Op_URShiftVI),"opcode should be Op_URShiftVI");
|
||||
psrld(dst, shift);
|
||||
}
|
||||
}
|
||||
|
||||
void C2_MacroAssembler::vshiftd(int opcode, XMMRegister dst, XMMRegister src) {
|
||||
if (opcode == Op_RShiftVI) {
|
||||
psrad(dst, src);
|
||||
@ -881,6 +932,17 @@ void C2_MacroAssembler::vshiftd(int opcode, XMMRegister dst, XMMRegister src) {
|
||||
}
|
||||
}
|
||||
|
||||
void C2_MacroAssembler::vshiftd_imm(int opcode, XMMRegister dst, XMMRegister nds, int shift, int vector_len) {
|
||||
if (opcode == Op_RShiftVI) {
|
||||
vpsrad(dst, nds, shift, vector_len);
|
||||
} else if (opcode == Op_LShiftVI) {
|
||||
vpslld(dst, nds, shift, vector_len);
|
||||
} else {
|
||||
assert((opcode == Op_URShiftVI),"opcode should be Op_URShiftVI");
|
||||
vpsrld(dst, nds, shift, vector_len);
|
||||
}
|
||||
}
|
||||
|
||||
void C2_MacroAssembler::vshiftd(int opcode, XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len) {
|
||||
if (opcode == Op_RShiftVI) {
|
||||
vpsrad(dst, nds, src, vector_len);
|
||||
@ -925,6 +987,17 @@ void C2_MacroAssembler::vshiftq(int opcode, XMMRegister dst, XMMRegister src) {
|
||||
}
|
||||
}
|
||||
|
||||
void C2_MacroAssembler::vshiftq_imm(int opcode, XMMRegister dst, int shift) {
|
||||
if (opcode == Op_RShiftVL) {
|
||||
psrlq(dst, shift); // using srl to implement sra on pre-avs512 systems
|
||||
} else if (opcode == Op_LShiftVL) {
|
||||
psllq(dst, shift);
|
||||
} else {
|
||||
assert((opcode == Op_URShiftVL),"opcode should be Op_URShiftVL");
|
||||
psrlq(dst, shift);
|
||||
}
|
||||
}
|
||||
|
||||
void C2_MacroAssembler::vshiftq(int opcode, XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len) {
|
||||
if (opcode == Op_RShiftVL) {
|
||||
evpsraq(dst, nds, src, vector_len);
|
||||
@ -936,6 +1009,17 @@ void C2_MacroAssembler::vshiftq(int opcode, XMMRegister dst, XMMRegister nds, XM
|
||||
}
|
||||
}
|
||||
|
||||
void C2_MacroAssembler::vshiftq_imm(int opcode, XMMRegister dst, XMMRegister nds, int shift, int vector_len) {
|
||||
if (opcode == Op_RShiftVL) {
|
||||
evpsraq(dst, nds, shift, vector_len);
|
||||
} else if (opcode == Op_LShiftVL) {
|
||||
vpsllq(dst, nds, shift, vector_len);
|
||||
} else {
|
||||
assert((opcode == Op_URShiftVL),"opcode should be Op_URShiftVL");
|
||||
vpsrlq(dst, nds, shift, vector_len);
|
||||
}
|
||||
}
|
||||
|
||||
// Reductions for vectors of ints, longs, floats, and doubles.
|
||||
|
||||
void C2_MacroAssembler::reduce_operation_128(int opcode, XMMRegister dst, XMMRegister src) {
|
||||
|
@ -74,11 +74,18 @@ public:
|
||||
void vextendbw(bool sign, XMMRegister dst, XMMRegister src, int vector_len);
|
||||
void vextendbw(bool sign, XMMRegister dst, XMMRegister src);
|
||||
void vshiftd(int opcode, XMMRegister dst, XMMRegister src);
|
||||
void vshiftd_imm(int opcode, XMMRegister dst, int shift);
|
||||
void vshiftd(int opcode, XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len);
|
||||
void vshiftd_imm(int opcode, XMMRegister dst, XMMRegister nds, int shift, int vector_len);
|
||||
void vshiftw(int opcode, XMMRegister dst, XMMRegister src);
|
||||
void vshiftw(int opcode, XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len);
|
||||
void vshiftq(int opcode, XMMRegister dst, XMMRegister src);
|
||||
void vshiftq_imm(int opcode, XMMRegister dst, int shift);
|
||||
void vshiftq(int opcode, XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len);
|
||||
void vshiftq_imm(int opcode, XMMRegister dst, XMMRegister nds, int shift, int vector_len);
|
||||
|
||||
void vprotate_imm(int opcode, BasicType etype, XMMRegister dst, XMMRegister src, int shift, int vector_len);
|
||||
void vprotate_var(int opcode, BasicType etype, XMMRegister dst, XMMRegister src, XMMRegister shift, int vector_len);
|
||||
|
||||
// Reductions for vectors of ints, longs, floats, and doubles.
|
||||
|
||||
|
@ -1469,6 +1469,8 @@ const bool Matcher::match_rule_supported_vector(int opcode, int vlen, BasicType
|
||||
return false; // implementation limitation (only vcmov8F_reg is present)
|
||||
}
|
||||
break;
|
||||
case Op_RotateRightV:
|
||||
case Op_RotateLeftV:
|
||||
case Op_MacroLogicV:
|
||||
if (!VM_Version::supports_evex() ||
|
||||
((size_in_bits != 512) && !VM_Version::supports_avx512vl())) {
|
||||
@ -4955,6 +4957,33 @@ instruct vshiftI(vec dst, vec src, vec shift) %{
|
||||
ins_pipe( pipe_slow );
|
||||
%}
|
||||
|
||||
// Integers vector left constant shift
|
||||
instruct vshiftI_imm(vec dst, vec src, immI8 shift) %{
|
||||
match(Set dst (LShiftVI src (LShiftCntV shift)));
|
||||
match(Set dst (RShiftVI src (RShiftCntV shift)));
|
||||
match(Set dst (URShiftVI src (RShiftCntV shift)));
|
||||
effect(TEMP dst, USE src);
|
||||
format %{ "vshiftd_imm $dst,$src,$shift\t! shift packedI" %}
|
||||
ins_encode %{
|
||||
int opcode = this->ideal_Opcode();
|
||||
if (UseAVX > 0) {
|
||||
int vector_len = vector_length_encoding(this);
|
||||
__ vshiftd_imm(opcode, $dst$$XMMRegister, $src$$XMMRegister, $shift$$constant, vector_len);
|
||||
} else {
|
||||
int vlen = vector_length(this);
|
||||
if (vlen == 2) {
|
||||
__ movdbl($dst$$XMMRegister, $src$$XMMRegister);
|
||||
__ vshiftd_imm(opcode, $dst$$XMMRegister, $shift$$constant);
|
||||
} else {
|
||||
assert(vlen == 4, "sanity");
|
||||
__ movdqu($dst$$XMMRegister, $src$$XMMRegister);
|
||||
__ vshiftd_imm(opcode, $dst$$XMMRegister, $shift$$constant);
|
||||
}
|
||||
}
|
||||
%}
|
||||
ins_pipe( pipe_slow );
|
||||
%}
|
||||
|
||||
// Longs vector shift
|
||||
instruct vshiftL(vec dst, vec src, vec shift) %{
|
||||
match(Set dst (LShiftVL src shift));
|
||||
@ -4975,6 +5004,26 @@ instruct vshiftL(vec dst, vec src, vec shift) %{
|
||||
ins_pipe( pipe_slow );
|
||||
%}
|
||||
|
||||
// Longs vector constant shift
|
||||
instruct vshiftL_imm(vec dst, vec src, immI8 shift) %{
|
||||
match(Set dst (LShiftVL src (LShiftCntV shift)));
|
||||
match(Set dst (URShiftVL src (RShiftCntV shift)));
|
||||
effect(TEMP dst, USE src, USE shift);
|
||||
format %{ "vshiftq_imm $dst,$src,$shift\t! shift packedL" %}
|
||||
ins_encode %{
|
||||
int opcode = this->ideal_Opcode();
|
||||
if (UseAVX > 0) {
|
||||
int vector_len = vector_length_encoding(this);
|
||||
__ vshiftq_imm(opcode, $dst$$XMMRegister, $src$$XMMRegister, $shift$$constant, vector_len);
|
||||
} else {
|
||||
assert(vector_length(this) == 2, "");
|
||||
__ movdqu($dst$$XMMRegister, $src$$XMMRegister);
|
||||
__ vshiftq_imm(opcode, $dst$$XMMRegister, $shift$$constant);
|
||||
}
|
||||
%}
|
||||
ins_pipe( pipe_slow );
|
||||
%}
|
||||
|
||||
// -------------------ArithmeticRightShift -----------------------------------
|
||||
// Long vector arithmetic right shift
|
||||
instruct vshiftL_arith_reg(vec dst, vec src, vec shift, vec tmp, rRegI scratch) %{
|
||||
@ -5359,3 +5408,31 @@ instruct vpternlog_mem(vec dst, vec src2, memory src3, immU8 func) %{
|
||||
%}
|
||||
ins_pipe( pipe_slow );
|
||||
%}
|
||||
|
||||
// --------------------------------- Rotation Operations ----------------------------------
|
||||
instruct vprotate_immI8(vec dst, vec src, immI8 shift) %{
|
||||
match(Set dst (RotateLeftV src shift));
|
||||
match(Set dst (RotateRightV src shift));
|
||||
format %{ "vprotate_imm8 $dst,$src,$shift\t! vector rotate" %}
|
||||
ins_encode %{
|
||||
int opcode = this->ideal_Opcode();
|
||||
int vector_len = vector_length_encoding(this);
|
||||
BasicType etype = this->bottom_type()->is_vect()->element_basic_type();
|
||||
__ vprotate_imm(opcode, etype, $dst$$XMMRegister, $src$$XMMRegister, $shift$$constant, vector_len);
|
||||
%}
|
||||
ins_pipe( pipe_slow );
|
||||
%}
|
||||
|
||||
instruct vprorate(vec dst, vec src, vec shift) %{
|
||||
match(Set dst (RotateLeftV src shift));
|
||||
match(Set dst (RotateRightV src shift));
|
||||
format %{ "vprotate $dst,$src,$shift\t! vector rotate" %}
|
||||
ins_encode %{
|
||||
int opcode = this->ideal_Opcode();
|
||||
int vector_len = vector_length_encoding(this);
|
||||
BasicType etype = this->bottom_type()->is_vect()->element_basic_type();
|
||||
__ vprotate_var(opcode, etype, $dst$$XMMRegister, $src$$XMMRegister, $shift$$XMMRegister, vector_len);
|
||||
%}
|
||||
ins_pipe( pipe_slow );
|
||||
%}
|
||||
|
||||
|
@ -3339,19 +3339,6 @@ operand rdi_RegI()
|
||||
interface(REG_INTER);
|
||||
%}
|
||||
|
||||
operand no_rcx_RegI()
|
||||
%{
|
||||
constraint(ALLOC_IN_RC(int_no_rcx_reg));
|
||||
match(RegI);
|
||||
match(rax_RegI);
|
||||
match(rbx_RegI);
|
||||
match(rdx_RegI);
|
||||
match(rdi_RegI);
|
||||
|
||||
format %{ %}
|
||||
interface(REG_INTER);
|
||||
%}
|
||||
|
||||
operand no_rax_rdx_RegI()
|
||||
%{
|
||||
constraint(ALLOC_IN_RC(int_no_rax_rdx_reg));
|
||||
@ -3561,16 +3548,6 @@ operand no_rax_RegL()
|
||||
interface(REG_INTER);
|
||||
%}
|
||||
|
||||
operand no_rcx_RegL()
|
||||
%{
|
||||
constraint(ALLOC_IN_RC(long_no_rcx_reg));
|
||||
match(RegL);
|
||||
match(rRegL);
|
||||
|
||||
format %{ %}
|
||||
interface(REG_INTER);
|
||||
%}
|
||||
|
||||
operand rax_RegL()
|
||||
%{
|
||||
constraint(ALLOC_IN_RC(long_rax_reg));
|
||||
@ -8969,294 +8946,137 @@ instruct i2s(rRegI dst, rRegI src, immI_16 sixteen)
|
||||
|
||||
// ROL/ROR instructions
|
||||
|
||||
// ROL expand
|
||||
instruct rolI_rReg_imm1(rRegI dst, rFlagsReg cr) %{
|
||||
effect(KILL cr, USE_DEF dst);
|
||||
|
||||
format %{ "roll $dst" %}
|
||||
opcode(0xD1, 0x0); /* Opcode D1 /0 */
|
||||
ins_encode(REX_reg(dst), OpcP, reg_opc(dst));
|
||||
ins_pipe(ialu_reg);
|
||||
%}
|
||||
|
||||
instruct rolI_rReg_imm8(rRegI dst, immI8 shift, rFlagsReg cr) %{
|
||||
effect(USE_DEF dst, USE shift, KILL cr);
|
||||
|
||||
// Rotate left by constant.
|
||||
instruct rolI_imm(rRegI dst, immI8 shift, rFlagsReg cr)
|
||||
%{
|
||||
predicate(n->bottom_type()->basic_type() == T_INT);
|
||||
match(Set dst (RotateLeft dst shift));
|
||||
effect(KILL cr);
|
||||
format %{ "roll $dst, $shift" %}
|
||||
opcode(0xC1, 0x0); /* Opcode C1 /0 ib */
|
||||
ins_encode( reg_opc_imm(dst, shift) );
|
||||
ins_encode %{
|
||||
__ roll($dst$$Register, $shift$$constant);
|
||||
%}
|
||||
ins_pipe(ialu_reg);
|
||||
%}
|
||||
|
||||
instruct rolI_rReg_CL(no_rcx_RegI dst, rcx_RegI shift, rFlagsReg cr)
|
||||
// Rotate Left by variable
|
||||
instruct rolI_rReg_Var(rRegI dst, rcx_RegI shift, rFlagsReg cr)
|
||||
%{
|
||||
effect(USE_DEF dst, USE shift, KILL cr);
|
||||
|
||||
predicate(n->bottom_type()->basic_type() == T_INT);
|
||||
match(Set dst (RotateLeft dst shift));
|
||||
effect(KILL cr);
|
||||
format %{ "roll $dst, $shift" %}
|
||||
opcode(0xD3, 0x0); /* Opcode D3 /0 */
|
||||
ins_encode(REX_reg(dst), OpcP, reg_opc(dst));
|
||||
ins_encode %{
|
||||
__ roll($dst$$Register);
|
||||
%}
|
||||
ins_pipe(ialu_reg_reg);
|
||||
%}
|
||||
// end of ROL expand
|
||||
|
||||
// Rotate Left by one
|
||||
instruct rolI_rReg_i1(rRegI dst, immI1 lshift, immI_M1 rshift, rFlagsReg cr)
|
||||
// Rotate Right by constant.
|
||||
instruct rorI_immI8_legacy(rRegI dst, immI8 shift, rFlagsReg cr)
|
||||
%{
|
||||
match(Set dst (OrI (LShiftI dst lshift) (URShiftI dst rshift)));
|
||||
|
||||
expand %{
|
||||
rolI_rReg_imm1(dst, cr);
|
||||
%}
|
||||
%}
|
||||
|
||||
// Rotate Left by 8-bit immediate
|
||||
instruct rolI_rReg_i8(rRegI dst, immI8 lshift, immI8 rshift, rFlagsReg cr)
|
||||
%{
|
||||
predicate(0 == ((n->in(1)->in(2)->get_int() + n->in(2)->in(2)->get_int()) & 0x1f));
|
||||
match(Set dst (OrI (LShiftI dst lshift) (URShiftI dst rshift)));
|
||||
|
||||
expand %{
|
||||
rolI_rReg_imm8(dst, lshift, cr);
|
||||
%}
|
||||
%}
|
||||
|
||||
// Rotate Left by variable
|
||||
instruct rolI_rReg_Var_C0(no_rcx_RegI dst, rcx_RegI shift, immI0 zero, rFlagsReg cr)
|
||||
%{
|
||||
match(Set dst (OrI (LShiftI dst shift) (URShiftI dst (SubI zero shift))));
|
||||
|
||||
expand %{
|
||||
rolI_rReg_CL(dst, shift, cr);
|
||||
%}
|
||||
%}
|
||||
|
||||
// Rotate Left by variable
|
||||
instruct rolI_rReg_Var_C32(no_rcx_RegI dst, rcx_RegI shift, immI_32 c32, rFlagsReg cr)
|
||||
%{
|
||||
match(Set dst (OrI (LShiftI dst shift) (URShiftI dst (SubI c32 shift))));
|
||||
|
||||
expand %{
|
||||
rolI_rReg_CL(dst, shift, cr);
|
||||
%}
|
||||
%}
|
||||
|
||||
// ROR expand
|
||||
instruct rorI_rReg_imm1(rRegI dst, rFlagsReg cr)
|
||||
%{
|
||||
effect(USE_DEF dst, KILL cr);
|
||||
|
||||
format %{ "rorl $dst" %}
|
||||
opcode(0xD1, 0x1); /* D1 /1 */
|
||||
ins_encode(REX_reg(dst), OpcP, reg_opc(dst));
|
||||
ins_pipe(ialu_reg);
|
||||
%}
|
||||
|
||||
instruct rorI_rReg_imm8(rRegI dst, immI8 shift, rFlagsReg cr)
|
||||
%{
|
||||
effect(USE_DEF dst, USE shift, KILL cr);
|
||||
|
||||
predicate(!VM_Version::supports_bmi2() && n->bottom_type()->basic_type() == T_INT);
|
||||
match(Set dst (RotateRight dst shift));
|
||||
effect(KILL cr);
|
||||
format %{ "rorl $dst, $shift" %}
|
||||
opcode(0xC1, 0x1); /* C1 /1 ib */
|
||||
ins_encode(reg_opc_imm(dst, shift));
|
||||
ins_encode %{
|
||||
__ rorl($dst$$Register, $shift$$constant);
|
||||
%}
|
||||
ins_pipe(ialu_reg);
|
||||
%}
|
||||
|
||||
instruct rorI_rReg_CL(no_rcx_RegI dst, rcx_RegI shift, rFlagsReg cr)
|
||||
// Rotate Right by constant.
|
||||
instruct rorI_immI8(rRegI dst, immI8 shift)
|
||||
%{
|
||||
effect(USE_DEF dst, USE shift, KILL cr);
|
||||
predicate(VM_Version::supports_bmi2() && n->bottom_type()->basic_type() == T_INT);
|
||||
match(Set dst (RotateRight dst shift));
|
||||
format %{ "rorxd $dst, $shift" %}
|
||||
ins_encode %{
|
||||
__ rorxd($dst$$Register, $dst$$Register, $shift$$constant);
|
||||
%}
|
||||
ins_pipe(ialu_reg_reg);
|
||||
%}
|
||||
|
||||
// Rotate Right by variable
|
||||
instruct rorI_rReg_Var(rRegI dst, rcx_RegI shift, rFlagsReg cr)
|
||||
%{
|
||||
predicate(n->bottom_type()->basic_type() == T_INT);
|
||||
match(Set dst (RotateRight dst shift));
|
||||
effect(KILL cr);
|
||||
format %{ "rorl $dst, $shift" %}
|
||||
opcode(0xD3, 0x1); /* D3 /1 */
|
||||
ins_encode(REX_reg(dst), OpcP, reg_opc(dst));
|
||||
ins_encode %{
|
||||
__ rorl($dst$$Register);
|
||||
%}
|
||||
ins_pipe(ialu_reg_reg);
|
||||
%}
|
||||
// end of ROR expand
|
||||
|
||||
// Rotate Right by one
|
||||
instruct rorI_rReg_i1(rRegI dst, immI1 rshift, immI_M1 lshift, rFlagsReg cr)
|
||||
|
||||
// Rotate Left by constant.
|
||||
instruct rolL_immI8(rRegL dst, immI8 shift, rFlagsReg cr)
|
||||
%{
|
||||
match(Set dst (OrI (URShiftI dst rshift) (LShiftI dst lshift)));
|
||||
|
||||
expand %{
|
||||
rorI_rReg_imm1(dst, cr);
|
||||
%}
|
||||
%}
|
||||
|
||||
// Rotate Right by 8-bit immediate
|
||||
instruct rorI_rReg_i8(rRegI dst, immI8 rshift, immI8 lshift, rFlagsReg cr)
|
||||
%{
|
||||
predicate(0 == ((n->in(1)->in(2)->get_int() + n->in(2)->in(2)->get_int()) & 0x1f));
|
||||
match(Set dst (OrI (URShiftI dst rshift) (LShiftI dst lshift)));
|
||||
|
||||
expand %{
|
||||
rorI_rReg_imm8(dst, rshift, cr);
|
||||
%}
|
||||
%}
|
||||
|
||||
// Rotate Right by variable
|
||||
instruct rorI_rReg_Var_C0(no_rcx_RegI dst, rcx_RegI shift, immI0 zero, rFlagsReg cr)
|
||||
%{
|
||||
match(Set dst (OrI (URShiftI dst shift) (LShiftI dst (SubI zero shift))));
|
||||
|
||||
expand %{
|
||||
rorI_rReg_CL(dst, shift, cr);
|
||||
%}
|
||||
%}
|
||||
|
||||
// Rotate Right by variable
|
||||
instruct rorI_rReg_Var_C32(no_rcx_RegI dst, rcx_RegI shift, immI_32 c32, rFlagsReg cr)
|
||||
%{
|
||||
match(Set dst (OrI (URShiftI dst shift) (LShiftI dst (SubI c32 shift))));
|
||||
|
||||
expand %{
|
||||
rorI_rReg_CL(dst, shift, cr);
|
||||
%}
|
||||
%}
|
||||
|
||||
// for long rotate
|
||||
// ROL expand
|
||||
instruct rolL_rReg_imm1(rRegL dst, rFlagsReg cr) %{
|
||||
effect(USE_DEF dst, KILL cr);
|
||||
|
||||
format %{ "rolq $dst" %}
|
||||
opcode(0xD1, 0x0); /* Opcode D1 /0 */
|
||||
ins_encode(REX_reg_wide(dst), OpcP, reg_opc(dst));
|
||||
ins_pipe(ialu_reg);
|
||||
%}
|
||||
|
||||
instruct rolL_rReg_imm8(rRegL dst, immI8 shift, rFlagsReg cr) %{
|
||||
effect(USE_DEF dst, USE shift, KILL cr);
|
||||
|
||||
predicate(n->bottom_type()->basic_type() == T_LONG);
|
||||
match(Set dst (RotateLeft dst shift));
|
||||
effect(KILL cr);
|
||||
format %{ "rolq $dst, $shift" %}
|
||||
opcode(0xC1, 0x0); /* Opcode C1 /0 ib */
|
||||
ins_encode( reg_opc_imm_wide(dst, shift) );
|
||||
ins_encode %{
|
||||
__ rolq($dst$$Register, $shift$$constant);
|
||||
%}
|
||||
ins_pipe(ialu_reg);
|
||||
%}
|
||||
|
||||
instruct rolL_rReg_CL(no_rcx_RegL dst, rcx_RegI shift, rFlagsReg cr)
|
||||
%{
|
||||
effect(USE_DEF dst, USE shift, KILL cr);
|
||||
|
||||
format %{ "rolq $dst, $shift" %}
|
||||
opcode(0xD3, 0x0); /* Opcode D3 /0 */
|
||||
ins_encode(REX_reg_wide(dst), OpcP, reg_opc(dst));
|
||||
ins_pipe(ialu_reg_reg);
|
||||
%}
|
||||
// end of ROL expand
|
||||
|
||||
// Rotate Left by one
|
||||
instruct rolL_rReg_i1(rRegL dst, immI1 lshift, immI_M1 rshift, rFlagsReg cr)
|
||||
%{
|
||||
match(Set dst (OrL (LShiftL dst lshift) (URShiftL dst rshift)));
|
||||
|
||||
expand %{
|
||||
rolL_rReg_imm1(dst, cr);
|
||||
%}
|
||||
%}
|
||||
|
||||
// Rotate Left by 8-bit immediate
|
||||
instruct rolL_rReg_i8(rRegL dst, immI8 lshift, immI8 rshift, rFlagsReg cr)
|
||||
%{
|
||||
predicate(0 == ((n->in(1)->in(2)->get_int() + n->in(2)->in(2)->get_int()) & 0x3f));
|
||||
match(Set dst (OrL (LShiftL dst lshift) (URShiftL dst rshift)));
|
||||
|
||||
expand %{
|
||||
rolL_rReg_imm8(dst, lshift, cr);
|
||||
%}
|
||||
%}
|
||||
|
||||
// Rotate Left by variable
|
||||
instruct rolL_rReg_Var_C0(no_rcx_RegL dst, rcx_RegI shift, immI0 zero, rFlagsReg cr)
|
||||
instruct rolL_rReg_Var(rRegL dst, rcx_RegI shift, rFlagsReg cr)
|
||||
%{
|
||||
match(Set dst (OrL (LShiftL dst shift) (URShiftL dst (SubI zero shift))));
|
||||
|
||||
expand %{
|
||||
rolL_rReg_CL(dst, shift, cr);
|
||||
predicate(n->bottom_type()->basic_type() == T_LONG);
|
||||
match(Set dst (RotateLeft dst shift));
|
||||
effect(KILL cr);
|
||||
format %{ "rolq $dst, $shift" %}
|
||||
ins_encode %{
|
||||
__ rolq($dst$$Register);
|
||||
%}
|
||||
%}
|
||||
|
||||
// Rotate Left by variable
|
||||
instruct rolL_rReg_Var_C64(no_rcx_RegL dst, rcx_RegI shift, immI_64 c64, rFlagsReg cr)
|
||||
%{
|
||||
match(Set dst (OrL (LShiftL dst shift) (URShiftL dst (SubI c64 shift))));
|
||||
|
||||
expand %{
|
||||
rolL_rReg_CL(dst, shift, cr);
|
||||
%}
|
||||
%}
|
||||
|
||||
// ROR expand
|
||||
instruct rorL_rReg_imm1(rRegL dst, rFlagsReg cr)
|
||||
%{
|
||||
effect(USE_DEF dst, KILL cr);
|
||||
|
||||
format %{ "rorq $dst" %}
|
||||
opcode(0xD1, 0x1); /* D1 /1 */
|
||||
ins_encode(REX_reg_wide(dst), OpcP, reg_opc(dst));
|
||||
ins_pipe(ialu_reg);
|
||||
%}
|
||||
|
||||
instruct rorL_rReg_imm8(rRegL dst, immI8 shift, rFlagsReg cr)
|
||||
%{
|
||||
effect(USE_DEF dst, USE shift, KILL cr);
|
||||
|
||||
format %{ "rorq $dst, $shift" %}
|
||||
opcode(0xC1, 0x1); /* C1 /1 ib */
|
||||
ins_encode(reg_opc_imm_wide(dst, shift));
|
||||
ins_pipe(ialu_reg);
|
||||
%}
|
||||
|
||||
instruct rorL_rReg_CL(no_rcx_RegL dst, rcx_RegI shift, rFlagsReg cr)
|
||||
%{
|
||||
effect(USE_DEF dst, USE shift, KILL cr);
|
||||
|
||||
format %{ "rorq $dst, $shift" %}
|
||||
opcode(0xD3, 0x1); /* D3 /1 */
|
||||
ins_encode(REX_reg_wide(dst), OpcP, reg_opc(dst));
|
||||
ins_pipe(ialu_reg_reg);
|
||||
%}
|
||||
// end of ROR expand
|
||||
|
||||
// Rotate Right by one
|
||||
instruct rorL_rReg_i1(rRegL dst, immI1 rshift, immI_M1 lshift, rFlagsReg cr)
|
||||
|
||||
// Rotate Right by constant.
|
||||
instruct rorL_immI8_legacy(rRegL dst, immI8 shift, rFlagsReg cr)
|
||||
%{
|
||||
match(Set dst (OrL (URShiftL dst rshift) (LShiftL dst lshift)));
|
||||
|
||||
expand %{
|
||||
rorL_rReg_imm1(dst, cr);
|
||||
predicate(!VM_Version::supports_bmi2() && n->bottom_type()->basic_type() == T_LONG);
|
||||
match(Set dst (RotateRight dst shift));
|
||||
effect(KILL cr);
|
||||
format %{ "rorq $dst, $shift" %}
|
||||
ins_encode %{
|
||||
__ rorq($dst$$Register, $shift$$constant);
|
||||
%}
|
||||
ins_pipe(ialu_reg);
|
||||
%}
|
||||
|
||||
// Rotate Right by 8-bit immediate
|
||||
instruct rorL_rReg_i8(rRegL dst, immI8 rshift, immI8 lshift, rFlagsReg cr)
|
||||
%{
|
||||
predicate(0 == ((n->in(1)->in(2)->get_int() + n->in(2)->in(2)->get_int()) & 0x3f));
|
||||
match(Set dst (OrL (URShiftL dst rshift) (LShiftL dst lshift)));
|
||||
|
||||
expand %{
|
||||
rorL_rReg_imm8(dst, rshift, cr);
|
||||
// Rotate Right by constant
|
||||
instruct rorL_immI8(rRegL dst, immI8 shift)
|
||||
%{
|
||||
predicate(VM_Version::supports_bmi2() && n->bottom_type()->basic_type() == T_LONG);
|
||||
match(Set dst (RotateRight dst shift));
|
||||
format %{ "rorxq $dst, $shift" %}
|
||||
ins_encode %{
|
||||
__ rorxq($dst$$Register, $dst$$Register, $shift$$constant);
|
||||
%}
|
||||
ins_pipe(ialu_reg_reg);
|
||||
%}
|
||||
|
||||
// Rotate Right by variable
|
||||
instruct rorL_rReg_Var_C0(no_rcx_RegL dst, rcx_RegI shift, immI0 zero, rFlagsReg cr)
|
||||
instruct rorL_rReg_Var(rRegL dst, rcx_RegI shift, rFlagsReg cr)
|
||||
%{
|
||||
match(Set dst (OrL (URShiftL dst shift) (LShiftL dst (SubI zero shift))));
|
||||
|
||||
expand %{
|
||||
rorL_rReg_CL(dst, shift, cr);
|
||||
predicate(n->bottom_type()->basic_type() == T_LONG);
|
||||
match(Set dst (RotateRight dst shift));
|
||||
effect(KILL cr);
|
||||
format %{ "rorq $dst, $shift" %}
|
||||
ins_encode %{
|
||||
__ rorq($dst$$Register);
|
||||
%}
|
||||
ins_pipe(ialu_reg_reg);
|
||||
%}
|
||||
|
||||
// Rotate Right by variable
|
||||
instruct rorL_rReg_Var_C64(no_rcx_RegL dst, rcx_RegI shift, immI_64 c64, rFlagsReg cr)
|
||||
%{
|
||||
match(Set dst (OrL (URShiftL dst shift) (LShiftL dst (SubI c64 shift))));
|
||||
|
||||
expand %{
|
||||
rorL_rReg_CL(dst, shift, cr);
|
||||
%}
|
||||
%}
|
||||
|
||||
// Logical Instructions
|
||||
|
||||
|
@ -773,6 +773,8 @@ bool InstructForm::captures_bottom_type(FormDict &globals) const {
|
||||
!strcmp(_matrule->_rChild->_opType,"CheckCastPP") ||
|
||||
!strcmp(_matrule->_rChild->_opType,"GetAndSetP") ||
|
||||
!strcmp(_matrule->_rChild->_opType,"GetAndSetN") ||
|
||||
!strcmp(_matrule->_rChild->_opType,"RotateLeft") ||
|
||||
!strcmp(_matrule->_rChild->_opType,"RotateRight") ||
|
||||
#if INCLUDE_SHENANDOAHGC
|
||||
!strcmp(_matrule->_rChild->_opType,"ShenandoahCompareAndExchangeP") ||
|
||||
!strcmp(_matrule->_rChild->_opType,"ShenandoahCompareAndExchangeN") ||
|
||||
@ -4164,7 +4166,7 @@ bool MatchRule::is_vector() const {
|
||||
"RShiftVB","RShiftVS","RShiftVI","RShiftVL",
|
||||
"URShiftVB","URShiftVS","URShiftVI","URShiftVL",
|
||||
"ReplicateB","ReplicateS","ReplicateI","ReplicateL","ReplicateF","ReplicateD",
|
||||
"RoundDoubleModeV","LoadVector","StoreVector",
|
||||
"RoundDoubleModeV","RotateLeftV" , "RotateRightV", "LoadVector","StoreVector",
|
||||
"FmaVD", "FmaVF","PopCountVI",
|
||||
// Next are not supported currently.
|
||||
"PackB","PackS","PackI","PackL","PackF","PackD","Pack2L","Pack2D",
|
||||
|
@ -743,6 +743,46 @@ Node* OrINode::Identity(PhaseGVN* phase) {
|
||||
return AddNode::Identity(phase);
|
||||
}
|
||||
|
||||
Node *OrINode::Ideal(PhaseGVN *phase, bool can_reshape) {
|
||||
int lopcode = in(1)->Opcode();
|
||||
int ropcode = in(2)->Opcode();
|
||||
if (Matcher::match_rule_supported(Op_RotateLeft) &&
|
||||
lopcode == Op_LShiftI && ropcode == Op_URShiftI && in(1)->in(1) == in(2)->in(1)) {
|
||||
Node *lshift = in(1)->in(2);
|
||||
Node *rshift = in(2)->in(2);
|
||||
// val << norm_con_shift | val >> (32 - norm_con_shift) => rotate_left val , norm_con_shift
|
||||
if (lshift->is_Con() && rshift->is_Con() &&
|
||||
((lshift->get_int() & 0x1F) == (32 - (rshift->get_int() & 0x1F)))) {
|
||||
return new RotateLeftNode(in(1)->in(1),
|
||||
phase->intcon(lshift->get_int() & 0x1F), TypeInt::INT);
|
||||
}
|
||||
// val << var_shift | val >> (0/32 - var_shift) => rotate_left val , var_shift
|
||||
if (rshift->Opcode() == Op_SubI && rshift->in(2) == lshift &&
|
||||
rshift->in(1)->is_Con() &&
|
||||
(rshift->in(1)->get_int() == 0 || rshift->in(1)->get_int() == 32)) {
|
||||
return new RotateLeftNode(in(1)->in(1), lshift, TypeInt::INT);
|
||||
}
|
||||
}
|
||||
if (Matcher::match_rule_supported(Op_RotateRight) &&
|
||||
lopcode == Op_URShiftI && ropcode == Op_LShiftI && in(1)->in(1) == in(2)->in(1)) {
|
||||
Node *rshift = in(1)->in(2);
|
||||
Node *lshift = in(2)->in(2);
|
||||
// val >> norm_con_shift | val << (32 - norm_con_shift) => rotate_right val , norm_con_shift
|
||||
if (rshift->is_Con() && lshift->is_Con() &&
|
||||
((rshift->get_int() & 0x1F) == (32 - (lshift->get_int() & 0x1F)))) {
|
||||
return new RotateRightNode(in(1)->in(1),
|
||||
phase->intcon(rshift->get_int() & 0x1F), TypeInt::INT);
|
||||
}
|
||||
// val >> var_shift | val << (0/32 - var_shift) => rotate_right val , var_shift
|
||||
if (lshift->Opcode() == Op_SubI && lshift->in(2) == rshift &&
|
||||
lshift->in(1)->is_Con() &&
|
||||
(lshift->in(1)->get_int() == 0 || lshift->in(1)->get_int() == 32)) {
|
||||
return new RotateRightNode(in(1)->in(1), rshift, TypeInt::INT);
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//------------------------------add_ring---------------------------------------
|
||||
// Supplied function returns the sum of the inputs IN THE CURRENT RING. For
|
||||
// the logical operations the ring's ADD is really a logical OR function.
|
||||
@ -784,6 +824,46 @@ Node* OrLNode::Identity(PhaseGVN* phase) {
|
||||
return AddNode::Identity(phase);
|
||||
}
|
||||
|
||||
Node *OrLNode::Ideal(PhaseGVN *phase, bool can_reshape) {
|
||||
int lopcode = in(1)->Opcode();
|
||||
int ropcode = in(2)->Opcode();
|
||||
if (Matcher::match_rule_supported(Op_RotateLeft) &&
|
||||
lopcode == Op_LShiftL && ropcode == Op_URShiftL && in(1)->in(1) == in(2)->in(1)) {
|
||||
Node *lshift = in(1)->in(2);
|
||||
Node *rshift = in(2)->in(2);
|
||||
// val << norm_con_shift | val >> (64 - norm_con_shift) => rotate_left val , norm_con_shift
|
||||
if (lshift->is_Con() && rshift->is_Con() &&
|
||||
((lshift->get_int() & 0x3F) == (64 - (rshift->get_int() & 0x3F)))) {
|
||||
return new RotateLeftNode(in(1)->in(1),
|
||||
phase->intcon(lshift->get_int() & 0x3F), TypeLong::LONG);
|
||||
}
|
||||
// val << var_shift | val >> (0/64 - var_shift) => rotate_left val , var_shift
|
||||
if (rshift->Opcode() == Op_SubI && rshift->in(2) == lshift &&
|
||||
rshift->in(1)->is_Con() &&
|
||||
(rshift->in(1)->get_int() == 0 || rshift->in(1)->get_int() == 64)) {
|
||||
return new RotateLeftNode(in(1)->in(1), lshift, TypeLong::LONG);
|
||||
}
|
||||
}
|
||||
if (Matcher::match_rule_supported(Op_RotateRight) &&
|
||||
lopcode == Op_URShiftL && ropcode == Op_LShiftL && in(1)->in(1) == in(2)->in(1)) {
|
||||
Node *rshift = in(1)->in(2);
|
||||
Node *lshift = in(2)->in(2);
|
||||
// val >> norm_con_shift | val << (64 - norm_con_shift) => rotate_right val , norm_con_shift
|
||||
if (rshift->is_Con() && lshift->is_Con() &&
|
||||
((rshift->get_int() & 0x3F) == (64 - (lshift->get_int() & 0x3F)))) {
|
||||
return new RotateRightNode(in(1)->in(1),
|
||||
phase->intcon(rshift->get_int() & 0x3F), TypeLong::LONG);
|
||||
}
|
||||
// val >> var_shift | val << (0/64 - var_shift) => rotate_right val , var_shift
|
||||
if (lshift->Opcode() == Op_SubI && lshift->in(2) == rshift &&
|
||||
lshift->in(1)->is_Con() &&
|
||||
(lshift->in(1)->get_int() == 0 || lshift->in(1)->get_int() == 64)) {
|
||||
return new RotateRightNode(in(1)->in(1), rshift, TypeLong::LONG);
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//------------------------------add_ring---------------------------------------
|
||||
const Type *OrLNode::add_ring( const Type *t0, const Type *t1 ) const {
|
||||
const TypeLong *r0 = t0->is_long(); // Handy access
|
||||
|
@ -172,6 +172,7 @@ public:
|
||||
virtual const Type *bottom_type() const { return TypeInt::INT; }
|
||||
virtual Node* Identity(PhaseGVN* phase);
|
||||
virtual uint ideal_reg() const { return Op_RegI; }
|
||||
virtual Node *Ideal(PhaseGVN *phase, bool can_reshape);
|
||||
};
|
||||
|
||||
//------------------------------OrLNode----------------------------------------
|
||||
@ -186,6 +187,7 @@ public:
|
||||
virtual const Type *bottom_type() const { return TypeLong::LONG; }
|
||||
virtual Node* Identity(PhaseGVN* phase);
|
||||
virtual uint ideal_reg() const { return Op_RegL; }
|
||||
virtual Node *Ideal(PhaseGVN *phase, bool can_reshape);
|
||||
};
|
||||
|
||||
//------------------------------XorINode---------------------------------------
|
||||
|
@ -268,6 +268,10 @@ macro(RoundDouble)
|
||||
macro(RoundDoubleMode)
|
||||
macro(RoundDoubleModeV)
|
||||
macro(RoundFloat)
|
||||
macro(RotateLeft)
|
||||
macro(RotateLeftV)
|
||||
macro(RotateRight)
|
||||
macro(RotateRightV)
|
||||
macro(SafePoint)
|
||||
macro(SafePointScalarObject)
|
||||
#if INCLUDE_SHENANDOAHGC
|
||||
|
@ -1433,3 +1433,99 @@ const Type* FmaFNode::Value(PhaseGVN* phase) const {
|
||||
uint MulAddS2INode::hash() const {
|
||||
return (uintptr_t)in(1) + (uintptr_t)in(2) + (uintptr_t)in(3) + (uintptr_t)in(4) + Opcode();
|
||||
}
|
||||
|
||||
//------------------------------Rotate Operations ------------------------------
|
||||
|
||||
const Type* RotateLeftNode::Value(PhaseGVN* phase) const {
|
||||
const Type* t1 = phase->type(in(1));
|
||||
const Type* t2 = phase->type(in(2));
|
||||
// Either input is TOP ==> the result is TOP
|
||||
if (t1 == Type::TOP || t2 == Type::TOP) {
|
||||
return Type::TOP;
|
||||
}
|
||||
|
||||
if (t1->isa_int()) {
|
||||
const TypeInt* r1 = t1->is_int();
|
||||
const TypeInt* r2 = t2->is_int();
|
||||
|
||||
// Left input is ZERO ==> the result is ZERO.
|
||||
if (r1 == TypeInt::ZERO) {
|
||||
return TypeInt::ZERO;
|
||||
}
|
||||
// Shift by zero does nothing
|
||||
if (r2 == TypeInt::ZERO) {
|
||||
return r1;
|
||||
}
|
||||
|
||||
if (r1->is_con() && r2->is_con()) {
|
||||
int shift = r2->get_con() & (BitsPerJavaInteger - 1); // semantics of Java shifts
|
||||
return TypeInt::make((r1->get_con() << shift) | (r1->get_con() >> (32 - shift)));
|
||||
}
|
||||
return TypeInt::INT;
|
||||
} else {
|
||||
assert(t1->isa_long(), "Type must be a long");
|
||||
const TypeLong* r1 = t1->is_long();
|
||||
const TypeInt* r2 = t2->is_int();
|
||||
|
||||
// Left input is ZERO ==> the result is ZERO.
|
||||
if (r1 == TypeLong::ZERO) {
|
||||
return TypeLong::ZERO;
|
||||
}
|
||||
// Shift by zero does nothing
|
||||
if (r2 == TypeInt::ZERO) {
|
||||
return r1;
|
||||
}
|
||||
|
||||
if (r1->is_con() && r2->is_con()) {
|
||||
int shift = r2->get_con() & (BitsPerJavaLong - 1); // semantics of Java shifts
|
||||
return TypeLong::make((r1->get_con() << shift) | (r1->get_con() >> (64 - shift)));
|
||||
}
|
||||
return TypeLong::LONG;
|
||||
}
|
||||
}
|
||||
|
||||
const Type* RotateRightNode::Value(PhaseGVN* phase) const {
|
||||
const Type* t1 = phase->type(in(1));
|
||||
const Type* t2 = phase->type(in(2));
|
||||
// Either input is TOP ==> the result is TOP
|
||||
if (t1 == Type::TOP || t2 == Type::TOP) {
|
||||
return Type::TOP;
|
||||
}
|
||||
|
||||
if (t1->isa_int()) {
|
||||
const TypeInt* r1 = t1->is_int();
|
||||
const TypeInt* r2 = t2->is_int();
|
||||
|
||||
// Left input is ZERO ==> the result is ZERO.
|
||||
if (r1 == TypeInt::ZERO) {
|
||||
return TypeInt::ZERO;
|
||||
}
|
||||
// Shift by zero does nothing
|
||||
if (r2 == TypeInt::ZERO) {
|
||||
return r1;
|
||||
}
|
||||
if (r1->is_con() && r2->is_con()) {
|
||||
int shift = r2->get_con() & (BitsPerJavaInteger - 1); // semantics of Java shifts
|
||||
return TypeInt::make((r1->get_con() >> shift) | (r1->get_con() << (32 - shift)));
|
||||
}
|
||||
return TypeInt::INT;
|
||||
|
||||
} else {
|
||||
assert(t1->isa_long(), "Type must be a long");
|
||||
const TypeLong* r1 = t1->is_long();
|
||||
const TypeInt* r2 = t2->is_int();
|
||||
// Left input is ZERO ==> the result is ZERO.
|
||||
if (r1 == TypeLong::ZERO) {
|
||||
return TypeLong::ZERO;
|
||||
}
|
||||
// Shift by zero does nothing
|
||||
if (r2 == TypeInt::ZERO) {
|
||||
return r1;
|
||||
}
|
||||
if (r1->is_con() && r2->is_con()) {
|
||||
int shift = r2->get_con() & (BitsPerJavaLong - 1); // semantics of Java shifts
|
||||
return TypeLong::make((r1->get_con() >> shift) | (r1->get_con() << (64 - shift)));
|
||||
}
|
||||
return TypeLong::LONG;
|
||||
}
|
||||
}
|
||||
|
@ -211,6 +211,29 @@ public:
|
||||
virtual uint ideal_reg() const { return Op_RegL; }
|
||||
};
|
||||
|
||||
|
||||
//------------------------ RotateLeftNode ----------------------------------
|
||||
class RotateLeftNode : public TypeNode {
|
||||
public:
|
||||
RotateLeftNode(Node* in1, Node* in2, const Type* type) : TypeNode(type, 3) {
|
||||
init_req(1, in1);
|
||||
init_req(2, in2);
|
||||
}
|
||||
virtual int Opcode() const;
|
||||
virtual const Type* Value(PhaseGVN* phase) const;
|
||||
};
|
||||
|
||||
//----------------------- RotateRightNode ----------------------------------
|
||||
class RotateRightNode : public TypeNode {
|
||||
public:
|
||||
RotateRightNode(Node* in1, Node* in2, const Type* type) : TypeNode(type, 3) {
|
||||
init_req(1, in1);
|
||||
init_req(2, in2);
|
||||
}
|
||||
virtual int Opcode() const;
|
||||
virtual const Type* Value(PhaseGVN* phase) const;
|
||||
};
|
||||
|
||||
//------------------------------RShiftINode------------------------------------
|
||||
// Signed shift right
|
||||
class RShiftINode : public Node {
|
||||
|
@ -2464,6 +2464,16 @@ void SuperWord::output() {
|
||||
const TypePtr* atyp = n->adr_type();
|
||||
vn = StoreVectorNode::make(opc, ctl, mem, adr, atyp, val, vlen);
|
||||
vlen_in_bytes = vn->as_StoreVector()->memory_size();
|
||||
} else if (VectorNode::is_scalar_rotate(n)) {
|
||||
Node* in1 = low_adr->in(1);
|
||||
Node* in2 = p->at(0)->in(2);
|
||||
assert(in2->bottom_type()->isa_int(), "Shift must always be an int value");
|
||||
// If rotation count is non-constant or greater than 8bit value create a vector.
|
||||
if (!in2->is_Con() || -0x80 > in2->get_int() || in2->get_int() >= 0x80) {
|
||||
in2 = vector_opd(p, 2);
|
||||
}
|
||||
vn = VectorNode::make(opc, in1, in2, vlen, velt_basic_type(n));
|
||||
vlen_in_bytes = vn->as_Vector()->length_in_bytes();
|
||||
} else if (VectorNode::is_roundopD(n)) {
|
||||
Node* in1 = vector_opd(p, 1);
|
||||
Node* in2 = low_adr->in(2);
|
||||
@ -2758,8 +2768,22 @@ Node* SuperWord::vector_opd(Node_List* p, int opd_idx) {
|
||||
// Convert scalar input to vector with the same number of elements as
|
||||
// p0's vector. Use p0's type because size of operand's container in
|
||||
// vector should match p0's size regardless operand's size.
|
||||
const Type* p0_t = velt_type(p0);
|
||||
VectorNode* vn = VectorNode::scalar2vector(opd, vlen, p0_t);
|
||||
const Type* p0_t = NULL;
|
||||
VectorNode* vn = NULL;
|
||||
if (opd_idx == 2 && VectorNode::is_scalar_rotate(p0)) {
|
||||
Node* conv = opd;
|
||||
p0_t = TypeInt::INT;
|
||||
if (p0->bottom_type()->isa_long()) {
|
||||
p0_t = TypeLong::LONG;
|
||||
conv = new ConvI2LNode(opd);
|
||||
_igvn.register_new_node_with_optimizer(conv);
|
||||
_phase->set_ctrl(conv, _phase->get_ctrl(opd));
|
||||
}
|
||||
vn = VectorNode::scalar2vector(conv, vlen, p0_t);
|
||||
} else {
|
||||
p0_t = velt_type(p0);
|
||||
vn = VectorNode::scalar2vector(opd, vlen, p0_t);
|
||||
}
|
||||
|
||||
_igvn.register_new_node_with_optimizer(vn);
|
||||
_phase->set_ctrl(vn, _phase->get_ctrl(opd));
|
||||
|
@ -24,8 +24,11 @@
|
||||
#include "precompiled.hpp"
|
||||
#include "memory/allocation.inline.hpp"
|
||||
#include "opto/connode.hpp"
|
||||
#include "opto/mulnode.hpp"
|
||||
#include "opto/subnode.hpp"
|
||||
#include "opto/vectornode.hpp"
|
||||
#include "utilities/powerOfTwo.hpp"
|
||||
#include "utilities/globalDefinitions.hpp"
|
||||
|
||||
//------------------------------VectorNode--------------------------------------
|
||||
|
||||
@ -132,6 +135,12 @@ int VectorNode::opcode(int sopc, BasicType bt) {
|
||||
case Op_RoundDoubleMode:
|
||||
assert(bt == T_DOUBLE, "must be");
|
||||
return Op_RoundDoubleModeV;
|
||||
case Op_RotateLeft:
|
||||
assert(bt == T_LONG || bt == T_INT, "must be");
|
||||
return Op_RotateLeftV;
|
||||
case Op_RotateRight:
|
||||
assert(bt == T_LONG || bt == T_INT, "must be");
|
||||
return Op_RotateRightV;
|
||||
case Op_SqrtF:
|
||||
assert(bt == T_FLOAT, "must be");
|
||||
return Op_SqrtVF;
|
||||
@ -239,6 +248,12 @@ bool VectorNode::implemented(int opc, uint vlen, BasicType bt) {
|
||||
(vlen > 1) && is_power_of_2(vlen) &&
|
||||
Matcher::vector_size_supported(bt, vlen)) {
|
||||
int vopc = VectorNode::opcode(opc, bt);
|
||||
// For rotate operation we will do a lazy de-generation into
|
||||
// OrV/LShiftV/URShiftV pattern if the target does not support
|
||||
// vector rotation instruction.
|
||||
if (vopc == Op_RotateLeftV || vopc == Op_RotateRightV) {
|
||||
return is_vector_rotate_supported(vopc, vlen, bt);
|
||||
}
|
||||
return vopc > 0 && Matcher::match_rule_supported_vector(vopc, vlen, bt);
|
||||
}
|
||||
return false;
|
||||
@ -263,13 +278,45 @@ bool VectorNode::is_muladds2i(Node* n) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool VectorNode::is_roundopD(Node *n) {
|
||||
bool VectorNode::is_roundopD(Node* n) {
|
||||
if (n->Opcode() == Op_RoundDoubleMode) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool VectorNode::is_scalar_rotate(Node* n) {
|
||||
if (n->Opcode() == Op_RotateLeft || n->Opcode() == Op_RotateRight) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool VectorNode::is_vector_rotate_supported(int vopc, uint vlen, BasicType bt) {
|
||||
assert(vopc == Op_RotateLeftV || vopc == Op_RotateRightV, "wrong opcode");
|
||||
|
||||
// If target defines vector rotation patterns then no
|
||||
// need for degeneration.
|
||||
if (Matcher::match_rule_supported_vector(vopc, vlen, bt)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Validate existence of nodes created in case of rotate degeneration.
|
||||
switch (bt) {
|
||||
case T_INT:
|
||||
return Matcher::match_rule_supported_vector(Op_OrV, vlen, bt) &&
|
||||
Matcher::match_rule_supported_vector(Op_LShiftVI, vlen, bt) &&
|
||||
Matcher::match_rule_supported_vector(Op_URShiftVI, vlen, bt);
|
||||
case T_LONG:
|
||||
return Matcher::match_rule_supported_vector(Op_OrV, vlen, bt) &&
|
||||
Matcher::match_rule_supported_vector(Op_LShiftVL, vlen, bt) &&
|
||||
Matcher::match_rule_supported_vector(Op_URShiftVL, vlen, bt);
|
||||
default:
|
||||
assert(false, "not supported: %s", type2name(bt));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool VectorNode::is_shift(Node* n) {
|
||||
switch (n->Opcode()) {
|
||||
case Op_LShiftI:
|
||||
@ -395,6 +442,8 @@ VectorNode* VectorNode::make(int opc, Node* n1, Node* n2, uint vlen, BasicType b
|
||||
case Op_SqrtVD: return new SqrtVDNode(n1, vt);
|
||||
|
||||
case Op_PopCountVI: return new PopCountVINode(n1, vt);
|
||||
case Op_RotateLeftV: return new RotateLeftVNode(n1, n2, vt);
|
||||
case Op_RotateRightV: return new RotateRightVNode(n1, n2, vt);
|
||||
|
||||
case Op_LShiftVB: return new LShiftVBNode(n1, n2, vt);
|
||||
case Op_LShiftVS: return new LShiftVSNode(n1, n2, vt);
|
||||
@ -784,3 +833,161 @@ MacroLogicVNode* MacroLogicVNode::make(PhaseGVN& gvn, Node* in1, Node* in2, Node
|
||||
return new MacroLogicVNode(in1, in2, in3, fn, vt);
|
||||
}
|
||||
|
||||
Node* VectorNode::degenerate_vector_rotate(Node* src, Node* cnt, bool is_rotate_left,
|
||||
int vlen, BasicType bt, PhaseGVN* phase) {
|
||||
int shiftLOpc;
|
||||
int shiftROpc;
|
||||
Node* shiftLCnt = NULL;
|
||||
Node* shiftRCnt = NULL;
|
||||
const TypeVect* vt = TypeVect::make(bt, vlen);
|
||||
|
||||
// Compute shift values for right rotation and
|
||||
// later swap them in case of left rotation.
|
||||
if (cnt->is_Con()) {
|
||||
// Constant shift case.
|
||||
if (bt == T_INT) {
|
||||
int shift = cnt->get_int() & 31;
|
||||
shiftRCnt = phase->intcon(shift);
|
||||
shiftLCnt = phase->intcon(32 - shift);
|
||||
shiftLOpc = Op_LShiftI;
|
||||
shiftROpc = Op_URShiftI;
|
||||
} else {
|
||||
int shift = cnt->get_int() & 63;
|
||||
shiftRCnt = phase->intcon(shift);
|
||||
shiftLCnt = phase->intcon(64 - shift);
|
||||
shiftLOpc = Op_LShiftL;
|
||||
shiftROpc = Op_URShiftL;
|
||||
}
|
||||
} else {
|
||||
// Variable shift case.
|
||||
assert(VectorNode::is_invariant_vector(cnt), "Broadcast expected");
|
||||
cnt = cnt->in(1);
|
||||
if (bt == T_INT) {
|
||||
shiftRCnt = phase->transform(new AndINode(cnt, phase->intcon(31)));
|
||||
shiftLCnt = phase->transform(new SubINode(phase->intcon(32), shiftRCnt));
|
||||
shiftLOpc = Op_LShiftI;
|
||||
shiftROpc = Op_URShiftI;
|
||||
} else {
|
||||
assert(cnt->Opcode() == Op_ConvI2L, "ConvI2L expected");
|
||||
cnt = cnt->in(1);
|
||||
shiftRCnt = phase->transform(new AndINode(cnt, phase->intcon(63)));
|
||||
shiftLCnt = phase->transform(new SubINode(phase->intcon(64), shiftRCnt));
|
||||
shiftLOpc = Op_LShiftL;
|
||||
shiftROpc = Op_URShiftL;
|
||||
}
|
||||
}
|
||||
|
||||
// Swap the computed left and right shift counts.
|
||||
if (is_rotate_left) {
|
||||
swap(shiftRCnt,shiftLCnt);
|
||||
}
|
||||
|
||||
shiftLCnt = phase->transform(new LShiftCntVNode(shiftLCnt, vt));
|
||||
shiftRCnt = phase->transform(new RShiftCntVNode(shiftRCnt, vt));
|
||||
|
||||
return new OrVNode(phase->transform(VectorNode::make(shiftLOpc, src, shiftLCnt, vlen, bt)),
|
||||
phase->transform(VectorNode::make(shiftROpc, src, shiftRCnt, vlen, bt)),
|
||||
vt);
|
||||
}
|
||||
|
||||
Node* RotateLeftVNode::Ideal(PhaseGVN* phase, bool can_reshape) {
|
||||
int vlen = length();
|
||||
BasicType bt = vect_type()->element_basic_type();
|
||||
if (!Matcher::match_rule_supported_vector(Op_RotateLeftV, vlen, bt)) {
|
||||
return VectorNode::degenerate_vector_rotate(in(1), in(2), true, vlen, bt, phase);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Node* RotateRightVNode::Ideal(PhaseGVN* phase, bool can_reshape) {
|
||||
int vlen = length();
|
||||
BasicType bt = vect_type()->element_basic_type();
|
||||
if (!Matcher::match_rule_supported_vector(Op_RotateRightV, vlen, bt)) {
|
||||
return VectorNode::degenerate_vector_rotate(in(1), in(2), false, vlen, bt, phase);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Node* OrVNode::Ideal(PhaseGVN* phase, bool can_reshape) {
|
||||
int lopcode = in(1)->Opcode();
|
||||
int ropcode = in(2)->Opcode();
|
||||
const TypeVect* vt = bottom_type()->is_vect();
|
||||
int vec_len = vt->length();
|
||||
BasicType bt = vt->element_basic_type();
|
||||
|
||||
// Vector Rotate operations inferencing, this will be useful when vector
|
||||
// operations are created via non-SLP route i.e. (VectorAPI).
|
||||
if (Matcher::match_rule_supported_vector(Op_RotateLeftV, vec_len, bt) &&
|
||||
((ropcode == Op_LShiftVI && lopcode == Op_URShiftVI) ||
|
||||
(ropcode == Op_LShiftVL && lopcode == Op_URShiftVL)) &&
|
||||
in(1)->in(1) == in(2)->in(1)) {
|
||||
assert(Op_RShiftCntV == in(1)->in(2)->Opcode(), "LShiftCntV operand expected");
|
||||
assert(Op_LShiftCntV == in(2)->in(2)->Opcode(), "RShiftCntV operand expected");
|
||||
Node* lshift = in(1)->in(2)->in(1);
|
||||
Node* rshift = in(2)->in(2)->in(1);
|
||||
int mod_val = bt == T_LONG ? 64 : 32;
|
||||
int shift_mask = bt == T_LONG ? 0x3F : 0x1F;
|
||||
// val >> norm_con_shift | val << (32 - norm_con_shift) => rotate_right val ,
|
||||
// norm_con_shift
|
||||
if (lshift->is_Con() && rshift->is_Con() &&
|
||||
((lshift->get_int() & shift_mask) ==
|
||||
(mod_val - (rshift->get_int() & shift_mask)))) {
|
||||
return new RotateRightVNode(
|
||||
in(1)->in(1), phase->intcon(lshift->get_int() & shift_mask), vt);
|
||||
}
|
||||
if (lshift->Opcode() == Op_AndI && rshift->Opcode() == Op_AndI &&
|
||||
lshift->in(2)->is_Con() && rshift->in(2)->is_Con() &&
|
||||
lshift->in(2)->get_int() == (mod_val - 1) &&
|
||||
rshift->in(2)->get_int() == (mod_val - 1)) {
|
||||
lshift = lshift->in(1);
|
||||
rshift = rshift->in(1);
|
||||
// val << var_shift | val >> (0/32 - var_shift) => rotate_left val ,
|
||||
// var_shift
|
||||
if (lshift->Opcode() == Op_SubI && lshift->in(2) == rshift &&
|
||||
lshift->in(1)->is_Con() &&
|
||||
(lshift->in(1)->get_int() == 0 ||
|
||||
lshift->in(1)->get_int() == mod_val)) {
|
||||
Node* rotate_cnt = phase->transform(new ReplicateINode(rshift, vt));
|
||||
return new RotateLeftVNode(in(1)->in(1), rotate_cnt, vt);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (Matcher::match_rule_supported_vector(Op_RotateRightV, vec_len, bt) &&
|
||||
((ropcode == Op_URShiftVI && lopcode == Op_LShiftVI) ||
|
||||
(ropcode == Op_URShiftVL && lopcode == Op_LShiftVL)) &&
|
||||
in(1)->in(1) == in(2)->in(1)) {
|
||||
assert(Op_LShiftCntV == in(1)->in(2)->Opcode(), "RShiftCntV operand expected");
|
||||
assert(Op_RShiftCntV == in(2)->in(2)->Opcode(), "LShiftCntV operand expected");
|
||||
Node* rshift = in(1)->in(2)->in(1);
|
||||
Node* lshift = in(2)->in(2)->in(1);
|
||||
int mod_val = bt == T_LONG ? 64 : 32;
|
||||
int shift_mask = bt == T_LONG ? 0x3F : 0x1F;
|
||||
// val << norm_con_shift | val >> (32 - norm_con_shift) => rotate_left val
|
||||
// , norm_con_shift
|
||||
if (rshift->is_Con() && lshift->is_Con() &&
|
||||
((rshift->get_int() & shift_mask) ==
|
||||
(mod_val - (lshift->get_int() & shift_mask)))) {
|
||||
return new RotateLeftVNode(
|
||||
in(1)->in(1), phase->intcon(rshift->get_int() & shift_mask), vt);
|
||||
}
|
||||
if (lshift->Opcode() == Op_AndI && rshift->Opcode() == Op_AndI &&
|
||||
lshift->in(2)->is_Con() && rshift->in(2)->is_Con() &&
|
||||
rshift->in(2)->get_int() == (mod_val - 1) &&
|
||||
lshift->in(2)->get_int() == (mod_val - 1)) {
|
||||
rshift = rshift->in(1);
|
||||
lshift = lshift->in(1);
|
||||
// val >> var_shift | val << (0/32 - var_shift) => rotate_right val ,
|
||||
// var_shift
|
||||
if (rshift->Opcode() == Op_SubI && rshift->in(2) == lshift &&
|
||||
rshift->in(1)->is_Con() &&
|
||||
(rshift->in(1)->get_int() == 0 ||
|
||||
rshift->in(1)->get_int() == mod_val)) {
|
||||
Node* rotate_cnt = phase->transform(new ReplicateINode(lshift, vt));
|
||||
return new RotateRightVNode(in(1)->in(1), rotate_cnt, vt);
|
||||
}
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -78,10 +78,14 @@ class VectorNode : public TypeNode {
|
||||
static bool is_type_transition_short_to_int(Node* n);
|
||||
static bool is_type_transition_to_int(Node* n);
|
||||
static bool is_muladds2i(Node* n);
|
||||
static bool is_roundopD(Node * n);
|
||||
static bool is_roundopD(Node* n);
|
||||
static bool is_scalar_rotate(Node* n);
|
||||
static bool is_vector_rotate_supported(int vopc, uint vlen, BasicType bt);
|
||||
static bool is_invariant_vector(Node* n);
|
||||
static bool is_all_ones_vector(Node* n);
|
||||
static bool is_vector_bitwise_not_pattern(Node* n);
|
||||
static Node* degenerate_vector_rotate(Node* n1, Node* n2, bool is_rotate_left, int vlen,
|
||||
BasicType bt, PhaseGVN* phase);
|
||||
|
||||
// [Start, end) half-open range defining which operands are vectors
|
||||
static void vector_operands(Node* n, uint* start, uint* end);
|
||||
@ -620,6 +624,7 @@ class OrVNode : public VectorNode {
|
||||
public:
|
||||
OrVNode(Node* in1, Node* in2, const TypeVect* vt) : VectorNode(in1,in2,vt) {}
|
||||
virtual int Opcode() const;
|
||||
Node* Ideal(PhaseGVN* phase, bool can_reshape);
|
||||
};
|
||||
|
||||
//------------------------------XorVNode---------------------------------------
|
||||
@ -1003,4 +1008,22 @@ public:
|
||||
static MacroLogicVNode* make(PhaseGVN& igvn, Node* in1, Node* in2, Node* in3, uint truth_table, const TypeVect* vt);
|
||||
};
|
||||
|
||||
class RotateRightVNode : public VectorNode {
|
||||
public:
|
||||
RotateRightVNode(Node* in1, Node* in2, const TypeVect* vt)
|
||||
: VectorNode(in1, in2, vt) {}
|
||||
|
||||
virtual int Opcode() const;
|
||||
Node* Ideal(PhaseGVN* phase, bool can_reshape);
|
||||
};
|
||||
|
||||
class RotateLeftVNode : public VectorNode {
|
||||
public:
|
||||
RotateLeftVNode(Node* in1, Node* in2, const TypeVect* vt)
|
||||
: VectorNode(in1, in2, vt) {}
|
||||
|
||||
virtual int Opcode() const;
|
||||
Node* Ideal(PhaseGVN* phase, bool can_reshape);
|
||||
};
|
||||
|
||||
#endif // SHARE_OPTO_VECTORNODE_HPP
|
||||
|
@ -30,6 +30,7 @@
|
||||
* @run main/othervm/timeout=400 -Xbatch -Xmx128m -XX:MaxVectorSize=8 compiler.c2.cr6340864.TestIntVect
|
||||
* @run main/othervm/timeout=400 -Xbatch -Xmx128m -XX:MaxVectorSize=16 compiler.c2.cr6340864.TestIntVect
|
||||
* @run main/othervm/timeout=400 -Xbatch -Xmx128m -XX:MaxVectorSize=32 compiler.c2.cr6340864.TestIntVect
|
||||
* @run main/othervm/timeout=400 -Xbatch -Xmx128m -XX:+IgnoreUnrecognizedVMOptions -XX:UseAVX=3 compiler.c2.cr6340864.TestIntVect
|
||||
*/
|
||||
|
||||
package compiler.c2.cr6340864;
|
||||
@ -41,6 +42,8 @@ public class TestIntVect {
|
||||
private static final int BIT_MASK = 0xEC80F731;
|
||||
private static final int VALUE = 15;
|
||||
private static final int SHIFT = 32;
|
||||
private static final int SHIFT_LT_IMM8 = -128;
|
||||
private static final int SHIFT_GT_IMM8 = 128;
|
||||
|
||||
public static void main(String args[]) {
|
||||
System.out.println("Testing Integer vectors");
|
||||
@ -148,6 +151,13 @@ public class TestIntVect {
|
||||
test_srac_and(a0, a1);
|
||||
test_srav_and(a0, a1, BIT_MASK);
|
||||
|
||||
test1_ror(a0, a1);
|
||||
test1_rol(a0, a1);
|
||||
test2_ror(a0, a1);
|
||||
test2_rol(a0, a1);
|
||||
test3_ror(a0, a1, SHIFT);
|
||||
test3_rol(a0, a1, SHIFT);
|
||||
|
||||
test_pack2(p2, a1);
|
||||
test_unpack2(a0, p2);
|
||||
test_pack2_swap(p2, a1);
|
||||
@ -375,6 +385,30 @@ public class TestIntVect {
|
||||
for (int i=0; i<ARRLEN; i++) {
|
||||
errn += verify("test_srav_o: ", i, a0[i], (int)((int)(ADD_INIT+i)>>SHIFT));
|
||||
}
|
||||
test1_ror(a0, a1);
|
||||
for (int i=0; i<ARRLEN; i++) {
|
||||
errn += verify("test1_ror: ", i, a0[i], (int)(((int)(ADD_INIT+i)>>>SHIFT_GT_IMM8) | (int)(ADD_INIT+i)<<-SHIFT_GT_IMM8));
|
||||
}
|
||||
test1_rol(a0, a1);
|
||||
for (int i=0; i<ARRLEN; i++) {
|
||||
errn += verify("test1_rol: ", i, a0[i], (int)(((int)(ADD_INIT+i)<<SHIFT_GT_IMM8) | (int)(ADD_INIT+i)>>>-SHIFT_GT_IMM8));
|
||||
}
|
||||
test2_ror(a0, a1);
|
||||
for (int i=0; i<ARRLEN; i++) {
|
||||
errn += verify("test2_ror: ", i, a0[i], (int)(((int)(ADD_INIT+i)>>>SHIFT_LT_IMM8) | (int)(ADD_INIT+i)<<-SHIFT_LT_IMM8));
|
||||
}
|
||||
test2_rol(a0, a1);
|
||||
for (int i=0; i<ARRLEN; i++) {
|
||||
errn += verify("test2_rol: ", i, a0[i], (int)(((int)(ADD_INIT+i)<<SHIFT_LT_IMM8) | (int)(ADD_INIT+i)>>>-SHIFT_LT_IMM8));
|
||||
}
|
||||
test3_rol(a0, a1, SHIFT);
|
||||
for (int i=0; i<ARRLEN; i++) {
|
||||
errn += verify("test3_rol: ", i, a0[i], (int)(((int)(ADD_INIT+i)<<SHIFT) | (int)(ADD_INIT+i)>>>-SHIFT));
|
||||
}
|
||||
test3_ror(a0, a1, SHIFT);
|
||||
for (int i=0; i<ARRLEN; i++) {
|
||||
errn += verify("test3_ror: ", i, a0[i], (int)(((int)(ADD_INIT+i)>>>SHIFT) | (int)(ADD_INIT+i)<<-SHIFT));
|
||||
}
|
||||
|
||||
test_sllc_on(a0, a1);
|
||||
for (int i=0; i<ARRLEN; i++) {
|
||||
@ -902,6 +936,49 @@ public class TestIntVect {
|
||||
}
|
||||
end = System.currentTimeMillis();
|
||||
System.out.println("test_srlc_and: " + (end - start));
|
||||
|
||||
start = System.currentTimeMillis();
|
||||
for (int i=0; i<ITERS; i++) {
|
||||
test1_rol(a0, a1);
|
||||
}
|
||||
end = System.currentTimeMillis();
|
||||
System.out.println("test1_rol: " + (end - start));
|
||||
|
||||
start = System.currentTimeMillis();
|
||||
for (int i=0; i<ITERS; i++) {
|
||||
test1_ror(a0, a1);
|
||||
}
|
||||
end = System.currentTimeMillis();
|
||||
System.out.println("test1_ror: " + (end - start));
|
||||
|
||||
start = System.currentTimeMillis();
|
||||
for (int i=0; i<ITERS; i++) {
|
||||
test2_rol(a0, a1);
|
||||
}
|
||||
end = System.currentTimeMillis();
|
||||
System.out.println("test2_rol: " + (end - start));
|
||||
|
||||
start = System.currentTimeMillis();
|
||||
for (int i=0; i<ITERS; i++) {
|
||||
test2_ror(a0, a1);
|
||||
}
|
||||
end = System.currentTimeMillis();
|
||||
System.out.println("test2_ror: " + (end - start));
|
||||
|
||||
start = System.currentTimeMillis();
|
||||
for (int i=0; i<ITERS; i++) {
|
||||
test3_rol(a0, a1, SHIFT);
|
||||
}
|
||||
end = System.currentTimeMillis();
|
||||
System.out.println("test3_rol: " + (end - start));
|
||||
|
||||
start = System.currentTimeMillis();
|
||||
for (int i=0; i<ITERS; i++) {
|
||||
test3_ror(a0, a1, SHIFT);
|
||||
}
|
||||
end = System.currentTimeMillis();
|
||||
System.out.println("test3_ror: " + (end - start));
|
||||
|
||||
start = System.currentTimeMillis();
|
||||
for (int i=0; i<ITERS; i++) {
|
||||
test_srlv_and(a0, a1, BIT_MASK);
|
||||
@ -922,6 +999,7 @@ public class TestIntVect {
|
||||
end = System.currentTimeMillis();
|
||||
System.out.println("test_srav_and: " + (end - start));
|
||||
|
||||
|
||||
start = System.currentTimeMillis();
|
||||
for (int i=0; i<ITERS; i++) {
|
||||
test_pack2(p2, a1);
|
||||
@ -1097,7 +1175,36 @@ public class TestIntVect {
|
||||
a0[i] = (int)(~a1[i]);
|
||||
}
|
||||
}
|
||||
|
||||
static void test1_rol(int[] a0, int[] a1) {
|
||||
for (int i = 0; i < a0.length; i+=1) {
|
||||
a0[i] = (int)(Integer.rotateLeft(a1[i], SHIFT_GT_IMM8));
|
||||
}
|
||||
}
|
||||
static void test1_ror(int[] a0, int[] a1) {
|
||||
for (int i = 0; i < a0.length; i+=1) {
|
||||
a0[i] = (int)(Integer.rotateRight(a1[i], SHIFT_GT_IMM8));
|
||||
}
|
||||
}
|
||||
static void test2_rol(int[] a0, int[] a1) {
|
||||
for (int i = 0; i < a0.length; i+=1) {
|
||||
a0[i] = (int)(Integer.rotateLeft(a1[i], SHIFT_LT_IMM8));
|
||||
}
|
||||
}
|
||||
static void test2_ror(int[] a0, int[] a1) {
|
||||
for (int i = 0; i < a0.length; i+=1) {
|
||||
a0[i] = (int)(Integer.rotateRight(a1[i], SHIFT_LT_IMM8));
|
||||
}
|
||||
}
|
||||
static void test3_rol(int[] a0, int[] a1, int shift) {
|
||||
for (int i = 0; i < a0.length; i+=1) {
|
||||
a0[i] = (int)(Integer.rotateLeft(a1[i], shift));
|
||||
}
|
||||
}
|
||||
static void test3_ror(int[] a0, int[] a1, int shift) {
|
||||
for (int i = 0; i < a0.length; i+=1) {
|
||||
a0[i] = (int)(Integer.rotateRight(a1[i], shift));
|
||||
}
|
||||
}
|
||||
static void test_sllc(int[] a0, int[] a1) {
|
||||
for (int i = 0; i < a0.length; i+=1) {
|
||||
a0[i] = (int)(a1[i]<<VALUE);
|
||||
|
@ -30,6 +30,7 @@
|
||||
* @run main/othervm/timeout=400 -Xbatch -Xmx128m -XX:MaxVectorSize=8 compiler.c2.cr6340864.TestLongVect
|
||||
* @run main/othervm/timeout=400 -Xbatch -Xmx128m -XX:MaxVectorSize=16 compiler.c2.cr6340864.TestLongVect
|
||||
* @run main/othervm/timeout=400 -Xbatch -Xmx128m -XX:MaxVectorSize=32 compiler.c2.cr6340864.TestLongVect
|
||||
* @run main/othervm/timeout=400 -Xbatch -Xmx128m -XX:+IgnoreUnrecognizedVMOptions -XX:UseAVX=3 compiler.c2.cr6340864.TestLongVect
|
||||
*/
|
||||
|
||||
package compiler.c2.cr6340864;
|
||||
@ -41,6 +42,8 @@ public class TestLongVect {
|
||||
private static final long BIT_MASK = 0xEC80F731EC80F731L;
|
||||
private static final int VALUE = 31;
|
||||
private static final int SHIFT = 64;
|
||||
private static final int SHIFT_LT_IMM8 = -128;
|
||||
private static final int SHIFT_GT_IMM8 = 128;
|
||||
|
||||
public static void main(String args[]) {
|
||||
System.out.println("Testing Long vectors");
|
||||
@ -142,6 +145,13 @@ public class TestLongVect {
|
||||
test_srlv_and(a0, a1, BIT_MASK);
|
||||
test_srac_and(a0, a1);
|
||||
test_srav_and(a0, a1, BIT_MASK);
|
||||
|
||||
test1_ror(a0, a1);
|
||||
test1_rol(a0, a1);
|
||||
test2_ror(a0, a1);
|
||||
test2_rol(a0, a1);
|
||||
test3_ror(a0, a1, SHIFT);
|
||||
test3_rol(a0, a1, SHIFT);
|
||||
}
|
||||
// Test and verify results
|
||||
System.out.println("Verification");
|
||||
@ -432,6 +442,30 @@ public class TestLongVect {
|
||||
errn += verify("test_srav_and: ", i, a0[i], (long)(((long)(ADD_INIT+i) & BIT_MASK)>>VALUE));
|
||||
}
|
||||
|
||||
test1_ror(a0, a1);
|
||||
for (int i=0; i<ARRLEN; i++) {
|
||||
errn += verify("test1_ror: ", i, a0[i], (long)(((long)(ADD_INIT+i)>>>SHIFT_GT_IMM8) | (long)(ADD_INIT+i)<<-SHIFT_GT_IMM8));
|
||||
}
|
||||
test1_rol(a0, a1);
|
||||
for (int i=0; i<ARRLEN; i++) {
|
||||
errn += verify("test1_rol: ", i, a0[i], (long)(((long)(ADD_INIT+i)<<SHIFT_GT_IMM8) | (long)(ADD_INIT+i)>>>-SHIFT_GT_IMM8));
|
||||
}
|
||||
test2_ror(a0, a1);
|
||||
for (int i=0; i<ARRLEN; i++) {
|
||||
errn += verify("test2_ror: ", i, a0[i], (long)(((long)(ADD_INIT+i)>>>SHIFT_LT_IMM8) | (long)(ADD_INIT+i)<<-SHIFT_LT_IMM8));
|
||||
}
|
||||
test2_rol(a0, a1);
|
||||
for (int i=0; i<ARRLEN; i++) {
|
||||
errn += verify("test2_rol: ", i, a0[i], (long)(((long)(ADD_INIT+i)<<SHIFT_LT_IMM8) | (long)(ADD_INIT+i)>>>-SHIFT_LT_IMM8));
|
||||
}
|
||||
test3_rol(a0, a1, SHIFT);
|
||||
for (int i=0; i<ARRLEN; i++) {
|
||||
errn += verify("test3_rol: ", i, a0[i], (long)(((long)(ADD_INIT+i)<<SHIFT) | (long)(ADD_INIT+i)>>>-SHIFT));
|
||||
}
|
||||
test3_ror(a0, a1, SHIFT);
|
||||
for (int i=0; i<ARRLEN; i++) {
|
||||
errn += verify("test3_ror: ", i, a0[i], (long)(((long)(ADD_INIT+i)>>>SHIFT) | (long)(ADD_INIT+i)<<-SHIFT));
|
||||
}
|
||||
}
|
||||
|
||||
if (errn > 0)
|
||||
@ -852,6 +886,48 @@ public class TestLongVect {
|
||||
end = System.currentTimeMillis();
|
||||
System.out.println("test_srav_and: " + (end - start));
|
||||
|
||||
start = System.currentTimeMillis();
|
||||
for (int i=0; i<ITERS; i++) {
|
||||
test1_rol(a0, a1);
|
||||
}
|
||||
end = System.currentTimeMillis();
|
||||
System.out.println("test1_rol: " + (end - start));
|
||||
|
||||
start = System.currentTimeMillis();
|
||||
for (int i=0; i<ITERS; i++) {
|
||||
test1_ror(a0, a1);
|
||||
}
|
||||
end = System.currentTimeMillis();
|
||||
System.out.println("test1_ror: " + (end - start));
|
||||
|
||||
start = System.currentTimeMillis();
|
||||
for (int i=0; i<ITERS; i++) {
|
||||
test2_rol(a0, a1);
|
||||
}
|
||||
end = System.currentTimeMillis();
|
||||
System.out.println("test2_rol: " + (end - start));
|
||||
|
||||
start = System.currentTimeMillis();
|
||||
for (int i=0; i<ITERS; i++) {
|
||||
test2_ror(a0, a1);
|
||||
}
|
||||
end = System.currentTimeMillis();
|
||||
System.out.println("test2_ror: " + (end - start));
|
||||
|
||||
start = System.currentTimeMillis();
|
||||
for (int i=0; i<ITERS; i++) {
|
||||
test3_rol(a0, a1, SHIFT);
|
||||
}
|
||||
end = System.currentTimeMillis();
|
||||
System.out.println("test3_rol: " + (end - start));
|
||||
|
||||
start = System.currentTimeMillis();
|
||||
for (int i=0; i<ITERS; i++) {
|
||||
test3_ror(a0, a1, SHIFT);
|
||||
}
|
||||
end = System.currentTimeMillis();
|
||||
System.out.println("test3_ror: " + (end - start));
|
||||
|
||||
return errn;
|
||||
}
|
||||
|
||||
@ -1122,6 +1198,36 @@ public class TestLongVect {
|
||||
a0[i] = (long)((a1[i] & b)>>VALUE);
|
||||
}
|
||||
}
|
||||
static void test1_rol(long[] a0, long[] a1) {
|
||||
for (int i = 0; i < a0.length; i+=1) {
|
||||
a0[i] = (long)(Long.rotateLeft(a1[i], SHIFT_GT_IMM8));
|
||||
}
|
||||
}
|
||||
static void test1_ror(long[] a0, long[] a1) {
|
||||
for (int i = 0; i < a0.length; i+=1) {
|
||||
a0[i] = (long)(Long.rotateRight(a1[i], SHIFT_GT_IMM8));
|
||||
}
|
||||
}
|
||||
static void test2_rol(long[] a0, long[] a1) {
|
||||
for (int i = 0; i < a0.length; i+=1) {
|
||||
a0[i] = (long)(Long.rotateLeft(a1[i], SHIFT_LT_IMM8));
|
||||
}
|
||||
}
|
||||
static void test2_ror(long[] a0, long[] a1) {
|
||||
for (int i = 0; i < a0.length; i+=1) {
|
||||
a0[i] = (long)(Long.rotateRight(a1[i], SHIFT_LT_IMM8));
|
||||
}
|
||||
}
|
||||
static void test3_rol(long[] a0, long[] a1, int shift) {
|
||||
for (int i = 0; i < a0.length; i+=1) {
|
||||
a0[i] = (long)(Long.rotateLeft(a1[i], shift));
|
||||
}
|
||||
}
|
||||
static void test3_ror(long[] a0, long[] a1, int shift) {
|
||||
for (int i = 0; i < a0.length; i+=1) {
|
||||
a0[i] = (long)(Long.rotateRight(a1[i], shift));
|
||||
}
|
||||
}
|
||||
|
||||
static int verify(String text, int i, long elem, long val) {
|
||||
if (elem != val) {
|
||||
|
309
test/hotspot/jtreg/compiler/intrinsics/TestRotate.java
Normal file
309
test/hotspot/jtreg/compiler/intrinsics/TestRotate.java
Normal file
@ -0,0 +1,309 @@
|
||||
/*
|
||||
* Copyright (c) 2019, 2020, 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
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @bug 8248830
|
||||
* @summary Support for scalar rotates ([Integer/Long].rotate[Left/Right]).
|
||||
* @library /test/lib
|
||||
* @requires vm.compiler2.enabled
|
||||
*
|
||||
* @run main/othervm/timeout=600 -XX:-TieredCompilation -XX:CompileThreshold=1000 -Xbatch
|
||||
* compiler.intrinsics.TestRotate
|
||||
*
|
||||
*/
|
||||
|
||||
package compiler.intrinsics;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Random;
|
||||
import jdk.test.lib.Utils;
|
||||
|
||||
public class TestRotate {
|
||||
static int ITERS = 500000;
|
||||
static int SIZE = 32;
|
||||
static Random rand;
|
||||
|
||||
static final int [] ref_rol_int = {1073741824,2147483647,-1847483168,-762700135,617181014,1499775590,770793873,-921711375,1843194553,618929189,543569581,-1524383055,-1358287055,-2015951670,1688073778,687346128,2069534693,-649937276,-1986172760,-1935023546,1291562794,-1493576900,1682263699,807071113,888440312,1299098553,1799312476,745578744,762073952,-1048231621,479680827,403988906};
|
||||
|
||||
static final int [] ref_ror_int = {1,2147483647,-1847483168,1244166759,1284961634,1704135065,770793873,-53535600,-1217156379,118049081,1667944966,1766387884,-960747332,849475009,2106366247,-532201309,-111225179,-1590275921,1733962274,-1851577736,1055640211,1872573386,356142481,1649149627,1025605133,1537928787,1799312476,-131305312,190518488,82773525,1321674198,-2126112095};
|
||||
|
||||
static final long [] ref_rol_long = {4611686018427387904L,9223372036854775807L,-3965526468698771170L,-4285866096636113521L,7635506276746300070L,5413117018148508287L,1868037460083876000L,-3244573585138770353L,7136025216317516898L,-4913621043675642569L,-6391133452542036978L,3902621950534797292L,-4632945906580257763L,4947809816008258399L,5235987658397734862L,2619582334080606650L,1815014778597694835L,-2451797983190531776L,-12499474356882106L,-8308822678069541478L,8441313153103433409L,3994820770127321462L,3403550366464210270L,-5787882067214947834L,-3689654055874130041L,-589861354719079036L,6641098980367723810L,763129181839551415L,4389436227302949880L,-8023110070632385182L,-8486732357167672789L,7236425339463197932L};
|
||||
|
||||
static final long [] ref_ror_long = {1L,9223372036854775807L,-3965526468698771170L,1303279687165097535L,-6959108088026060186L,681250795361731838L,3705372465420868140L,-8117671657526198993L,-335604442896202624L,-3176041913244586253L,-2152781018329716108L,975655487633699323L,8574521504761035792L,-5473888690750018935L,1581768605333334728L,7674419410656225425L,6685114322387540375L,5780227587575757360L,-799966358840454721L,8284086884492323912L,5288463661042741341L,912426852973757747L,-11970671133582816L,-344117270115783853L,-2106591766031512621L,-857638554601955011L,6641098980367723810L,-5257223391402178581L,1097359056825737470L,-4640791861453503840L,8696676574724001348L,-6526192196514797544L};
|
||||
|
||||
static final int [] ref_int_rol_shift_1 = {1,-2,600000961,1244166759,642480817,161047955,-1021158430,-2014938908,-1427785869,-467917532,857429648,-1524383055,1807911884,1884072061,845454838,1040479242,1471523198,1301556200,-1713993080,-1641781046,-809831772,-1713031218,-1529278125,-1361538303,1602441032,-689259628,-696342344,93197343,762073952,352644870,1972613577,223396003};
|
||||
|
||||
static final int [] ref_int_rol_shift_127 = {1073741824 ,-1073741825 ,1223742064 ,-762700135 ,1234362028 ,-1033479836 ,-1329031432 ,570007097 ,-356946468 ,956762441 ,214357412 ,1766387884 ,451977971 ,1544759839 ,-1936119939 ,-1887363838 ,-1779602849 ,325389050 ,645243554 ,-1484187086 ,871283881 ,-1501999629 ,-382319532 ,1807099072 ,400610258 ,901426917 ,899656238 ,-1050442489 ,190518488 ,-2059322431 ,1566895218 ,-1017892824};
|
||||
|
||||
static final int [] ref_int_rol_shift_128 = {-2147483648 ,2147483647 ,-1847483168 ,-1525400269 ,-1826243240 ,-2066959671 ,1636904433 ,1140014194 ,-713892935 ,1913524882 ,428714824 ,-762191528 ,903955942 ,-1205447618 ,422727419 ,520239621 ,735761599 ,650778100 ,1290487108 ,1326593125 ,1742567762 ,1290968039 ,-764639063 ,-680769152 ,801220516 ,1802853834 ,1799312476 ,-2100884977 ,381036976 ,176322435 ,-1161176860 ,-2035785647};
|
||||
|
||||
static final int [] ref_int_rol_shift_M128 = {-2147483648 ,2147483647 ,-1847483168 ,-1525400269 ,-1826243240 ,-2066959671 ,1636904433 ,1140014194 ,-713892935 ,1913524882 ,428714824 ,-762191528 ,903955942 ,-1205447618 ,422727419 ,520239621 ,735761599 ,650778100 ,1290487108 ,1326593125 ,1742567762 ,1290968039 ,-764639063 ,-680769152 ,801220516 ,1802853834 ,1799312476 ,-2100884977 ,381036976 ,176322435 ,-1161176860 ,-2035785647};
|
||||
|
||||
static final int [] ref_int_rol_shift_M129 = {1073741824 ,-1073741825 ,1223742064 ,-762700135 ,1234362028 ,-1033479836 ,-1329031432 ,570007097 ,-356946468 ,956762441 ,214357412 ,1766387884 ,451977971 ,1544759839 ,-1936119939 ,-1887363838 ,-1779602849 ,325389050 ,645243554 ,-1484187086 ,871283881 ,-1501999629 ,-382319532 ,1807099072 ,400610258 ,901426917 ,899656238 ,-1050442489 ,190518488 ,-2059322431 ,1566895218 ,-1017892824};
|
||||
|
||||
static final int [] ref_int_ror_shift_1 = {1073741824,-1073741825,1223742064,-762700135,1234362028,-1033479836,-1329031432,570007097,-356946468,956762441,214357412,1766387884,451977971,1544759839,-1936119939,-1887363838,-1779602849,325389050,645243554,-1484187086,871283881,-1501999629,-382319532,1807099072,400610258,901426917,899656238,-1050442489,190518488,-2059322431,1566895218,-1017892824};
|
||||
|
||||
static final int [] ref_int_ror_shift_127 = {1 ,-2 ,600000961 ,1244166759 ,642480817 ,161047955 ,-1021158430 ,-2014938908 ,-1427785869 ,-467917532 ,857429648 ,-1524383055 ,1807911884 ,1884072061 ,845454838 ,1040479242 ,1471523198 ,1301556200 ,-1713993080 ,-1641781046 ,-809831772 ,-1713031218 ,-1529278125 ,-1361538303 ,1602441032 ,-689259628 ,-696342344 ,93197343 ,762073952 ,352644870 ,1972613577 ,223396003};
|
||||
|
||||
static final int [] ref_int_ror_shift_128 = {-2147483648 ,2147483647 ,-1847483168 ,-1525400269 ,-1826243240 ,-2066959671 ,1636904433 ,1140014194 ,-713892935 ,1913524882 ,428714824 ,-762191528 ,903955942 ,-1205447618 ,422727419 ,520239621 ,735761599 ,650778100 ,1290487108 ,1326593125 ,1742567762 ,1290968039 ,-764639063 ,-680769152 ,801220516 ,1802853834 ,1799312476 ,-2100884977 ,381036976 ,176322435 ,-1161176860 ,-2035785647};
|
||||
|
||||
static final int [] ref_int_ror_shift_M128 = {-2147483648 ,2147483647 ,-1847483168 ,-1525400269 ,-1826243240 ,-2066959671 ,1636904433 ,1140014194 ,-713892935 ,1913524882 ,428714824 ,-762191528 ,903955942 ,-1205447618 ,422727419 ,520239621 ,735761599 ,650778100 ,1290487108 ,1326593125 ,1742567762 ,1290968039 ,-764639063 ,-680769152 ,801220516 ,1802853834 ,1799312476 ,-2100884977 ,381036976 ,176322435 ,-1161176860 ,-2035785647};
|
||||
|
||||
static final int [] ref_int_ror_shift_M129 = {1 ,-2 ,600000961 ,1244166759 ,642480817 ,161047955 ,-1021158430 ,-2014938908 ,-1427785869 ,-467917532 ,857429648 ,-1524383055 ,1807911884 ,1884072061 ,845454838 ,1040479242 ,1471523198 ,1301556200 ,-1713993080 ,-1641781046 ,-809831772 ,-1713031218 ,-1529278125 ,-1361538303 ,1602441032 ,-689259628 ,-696342344 ,93197343 ,762073952 ,352644870 ,1972613577 ,223396003};
|
||||
|
||||
|
||||
static final long [] ref_long_rol_shift_1 = {
|
||||
1L,-2L,-7931052937397542339L,1303279687165097535L,5608201114852140040L,359735415298403453L,4701815018953926360L,8969694797557082089L,324535527229983777L,-3508390168714987589L,-8153196119534272952L,-5889362595358906884L,8065135560209711367L,-3515635332702993867L,-3582426625105780649L,1632572717772861065L,3572202937482896855L,-7534931108784269461L,8161459789691976885L,5213383633793760703L,5933801933688073239L,-6730200469375698045L,6308363257973444605L,-3098812595652498694L,-541332749731694416L,9008962398204287055L,6200852250644175020L,5992317991244719550L,1486051504252676350L,-6863599526811956670L,5846438278934178867L,2838151117945983671L};
|
||||
|
||||
static final long [] ref_long_rol_shift_127 = {4611686018427387904L,-4611686018427387905L,7240608802505390223L,-4285866096636113521L,1402050278713035010L,4701619872251988767L,1175453754738481590L,6854109717816658426L,4692819900234883848L,-877097542178746898L,2573386988543819666L,3139345369587661183L,-2595402128374960063L,8344463203679027341L,-895606656276445163L,5019829197870603170L,-3718635284056663691L,-1883732777196067366L,6652050965850382125L,-3308340109978947729L,-3128235535005369595L,-1682550117343924512L,6188776832920749055L,-5386389167340512578L,4476352830994464300L,-2359445418876316141L,1550213062661043755L,-7725292539043595921L,-8851859160791606721L,-6327585900130377072L,-3150076448693843188L,-3902148238940891987L};
|
||||
|
||||
static final long [] ref_long_rol_shift_128 = {-9223372036854775808L,9223372036854775807L,-3965526468698771170L,-8571732193272227041L,2804100557426070020L,-9043504329205574082L,2350907509476963180L,-4738524638076234764L,-9061104273239783920L,-1754195084357493795L,5146773977087639332L,6278690739175322366L,-5190804256749920125L,-1757817666351496934L,-1791213312552890325L,-8407085677968345276L,-7437270568113327381L,-3767465554392134731L,-5142642142008787366L,-6616680219957895457L,-6256471070010739189L,-3365100234687849023L,-6069190407868053506L,7673965739028526461L,8952705661988928600L,-4718890837752632281L,3100426125322087510L,2996158995622359775L,743025752126338175L,5791572273448797473L,-6300152897387686375L,-7804296477881783973L};
|
||||
|
||||
static final long [] ref_long_rol_shift_M128 = {-9223372036854775808L,9223372036854775807L,-3965526468698771170L,-8571732193272227041L,2804100557426070020L,-9043504329205574082L,2350907509476963180L,-4738524638076234764L,-9061104273239783920L,-1754195084357493795L,5146773977087639332L,6278690739175322366L,-5190804256749920125L,-1757817666351496934L,-1791213312552890325L,-8407085677968345276L,-7437270568113327381L,-3767465554392134731L,-5142642142008787366L,-6616680219957895457L,-6256471070010739189L,-3365100234687849023L,-6069190407868053506L,7673965739028526461L,8952705661988928600L,-4718890837752632281L,3100426125322087510L,2996158995622359775L,743025752126338175L,5791572273448797473L,-6300152897387686375L,-7804296477881783973L};
|
||||
|
||||
|
||||
static final long [] ref_long_rol_shift_M129 = {4611686018427387904L,-4611686018427387905L,7240608802505390223L,-4285866096636113521L,1402050278713035010L,4701619872251988767L,1175453754738481590L,6854109717816658426L,4692819900234883848L,-877097542178746898L,2573386988543819666L,3139345369587661183L,-2595402128374960063L,8344463203679027341L,-895606656276445163L,5019829197870603170L,-3718635284056663691L,-1883732777196067366L,6652050965850382125L,-3308340109978947729L,-3128235535005369595L,-1682550117343924512L,6188776832920749055L,-5386389167340512578L,4476352830994464300L,-2359445418876316141L,1550213062661043755L,-7725292539043595921L,-8851859160791606721L,-6327585900130377072L,-3150076448693843188L,-3902148238940891987L};
|
||||
|
||||
static final long [] ref_long_ror_shift_1 = {4611686018427387904L,-4611686018427387905L,7240608802505390223L,-4285866096636113521L,1402050278713035010L,4701619872251988767L,1175453754738481590L,6854109717816658426L,4692819900234883848L,-877097542178746898L,2573386988543819666L,3139345369587661183L,-2595402128374960063L,8344463203679027341L,-895606656276445163L,5019829197870603170L,-3718635284056663691L,-1883732777196067366L,6652050965850382125L,-3308340109978947729L,-3128235535005369595L,-1682550117343924512L,6188776832920749055L,-5386389167340512578L,4476352830994464300L,-2359445418876316141L,1550213062661043755L,-7725292539043595921L,-8851859160791606721L,-6327585900130377072L,-3150076448693843188L,-3902148238940891987L};
|
||||
|
||||
static final long [] ref_long_ror_shift_127 = {1L,-2L,-7931052937397542339L,1303279687165097535L,5608201114852140040L,359735415298403453L,4701815018953926360L,8969694797557082089L,324535527229983777L,-3508390168714987589L,-8153196119534272952L,-5889362595358906884L,8065135560209711367L,-3515635332702993867L,-3582426625105780649L,1632572717772861065L,3572202937482896855L,-7534931108784269461L,8161459789691976885L,5213383633793760703L,5933801933688073239L,-6730200469375698045L,6308363257973444605L,-3098812595652498694L,-541332749731694416L,9008962398204287055L,6200852250644175020L,5992317991244719550L,1486051504252676350L,-6863599526811956670L,5846438278934178867L,2838151117945983671L};
|
||||
|
||||
|
||||
static final long [] ref_long_ror_shift_128 = {-9223372036854775808L,9223372036854775807L,-3965526468698771170L,-8571732193272227041L,2804100557426070020L,-9043504329205574082L,2350907509476963180L,-4738524638076234764L,-9061104273239783920L,-1754195084357493795L,5146773977087639332L,6278690739175322366L,-5190804256749920125L,-1757817666351496934L,-1791213312552890325L,-8407085677968345276L,-7437270568113327381L,-3767465554392134731L,-5142642142008787366L,-6616680219957895457L,-6256471070010739189L,-3365100234687849023L,-6069190407868053506L,7673965739028526461L,8952705661988928600L,-4718890837752632281L,3100426125322087510L,2996158995622359775L,743025752126338175L,5791572273448797473L,-6300152897387686375L,-7804296477881783973L};
|
||||
|
||||
|
||||
static final long [] ref_long_ror_shift_M128 = {-9223372036854775808L,9223372036854775807L,-3965526468698771170L,-8571732193272227041L,2804100557426070020L,-9043504329205574082L,2350907509476963180L,-4738524638076234764L,-9061104273239783920L,-1754195084357493795L,5146773977087639332L,6278690739175322366L,-5190804256749920125L,-1757817666351496934L,-1791213312552890325L,-8407085677968345276L,-7437270568113327381L,-3767465554392134731L,-5142642142008787366L,-6616680219957895457L,-6256471070010739189L,-3365100234687849023L,-6069190407868053506L,7673965739028526461L,8952705661988928600L,-4718890837752632281L,3100426125322087510L,2996158995622359775L,743025752126338175L,5791572273448797473L,-6300152897387686375L,-7804296477881783973L};
|
||||
|
||||
static final long [] ref_long_ror_shift_M129 = {1L,-2L,-7931052937397542339L,1303279687165097535L,5608201114852140040L,359735415298403453L,4701815018953926360L,8969694797557082089L,324535527229983777L,-3508390168714987589L,-8153196119534272952L,-5889362595358906884L,8065135560209711367L,-3515635332702993867L,-3582426625105780649L,1632572717772861065L,3572202937482896855L,-7534931108784269461L,8161459789691976885L,5213383633793760703L,5933801933688073239L,-6730200469375698045L,6308363257973444605L,-3098812595652498694L,-541332749731694416L,9008962398204287055L,6200852250644175020L,5992317991244719550L,1486051504252676350L,-6863599526811956670L,5846438278934178867L,2838151117945983671L};
|
||||
|
||||
static void verify(String text, long ref, long actual) {
|
||||
if (ref != actual) {
|
||||
System.err.println(text + " " + ref + " != " + actual);
|
||||
throw new Error("Fail");
|
||||
}
|
||||
}
|
||||
|
||||
public static int [] init_shift_vector(Random rand) {
|
||||
int [] vec_int = new int [SIZE];
|
||||
vec_int[0] = 127;
|
||||
vec_int[1] = -128;
|
||||
vec_int[2] = 128;
|
||||
vec_int[3] = -129;
|
||||
for (int i = 4 ; i < SIZE ; i++) {
|
||||
vec_int[i] = rand.nextInt(256);
|
||||
}
|
||||
return vec_int;
|
||||
}
|
||||
|
||||
public static int [] init_int_vector() {
|
||||
int [] vec_int = new int [SIZE];
|
||||
vec_int[0] = Integer.MIN_VALUE;
|
||||
vec_int[1] = Integer.MAX_VALUE;
|
||||
for (int i = 2 ; i < SIZE ; i++) {
|
||||
vec_int[i] = rand.nextInt();
|
||||
}
|
||||
return vec_int;
|
||||
}
|
||||
|
||||
public static long [] init_long_vector() {
|
||||
long [] vec_long = new long [SIZE];
|
||||
vec_long[0] = Long.MIN_VALUE;
|
||||
vec_long[1] = Long.MAX_VALUE;
|
||||
for (int i = 2 ; i < SIZE ; i++) {
|
||||
vec_long[i] = rand.nextLong();
|
||||
}
|
||||
return vec_long;
|
||||
}
|
||||
|
||||
public static void test_rol_int(int val, int shift, int index) {
|
||||
int actual = Integer.rotateLeft(val, shift);
|
||||
verify("Integer.rotateLeft shift = " + shift, ref_rol_int[index], actual);
|
||||
actual = (val << shift) | (val >>> -shift);
|
||||
verify("Pattern1 integer rotateLeft shift = " + shift, ref_rol_int[index], actual);
|
||||
actual = (val << shift) | (val >>> 32-shift);
|
||||
verify("Pattern2 integer rotateLeft shift = " + shift, ref_rol_int[index], actual);
|
||||
}
|
||||
|
||||
public static void test_ror_int(int val, int shift, int index) {
|
||||
int actual = Integer.rotateRight(val, shift);
|
||||
verify("Integer.rotateRight shift = " + shift, ref_ror_int[index], actual);
|
||||
actual = (val >>> shift) | (val <<-shift);
|
||||
verify("Pattern1 integer rotateRight shift = " + shift, ref_ror_int[index], actual);
|
||||
actual = (val >>> shift) | (val <<-32-shift);
|
||||
verify("Pattern2 integer rotateRight shift = " + shift, ref_ror_int[index], actual);
|
||||
}
|
||||
|
||||
public static void test_rol_long(long val, int shift, int index) {
|
||||
long actual = Long.rotateLeft(val, shift);
|
||||
verify("Long.rotateLeft shift = " + shift, ref_rol_long[index], actual);
|
||||
actual = (val << shift) | (val >>>-shift);
|
||||
verify("Pattern1 long rotateLeft shift = " + shift, ref_rol_long[index], actual);
|
||||
actual = (val << shift) | (val >>>64-shift);
|
||||
verify("Pattern2 long rotateLeft shift = " + shift, ref_rol_long[index], actual);
|
||||
}
|
||||
|
||||
public static void test_ror_long(long val, int shift, int index) {
|
||||
long actual = Long.rotateRight(val, shift);
|
||||
verify("Long.rotateRight shift = " + shift, ref_ror_long[index], actual);
|
||||
actual = (val >>> shift) | (val <<-shift);
|
||||
verify("Pattern1 long rotateRight shift = " + shift, ref_ror_long[index], actual);
|
||||
actual = (val >>> shift) | (val <<64-shift);
|
||||
verify("Pattern2 long rotateRight shift = " + shift, ref_ror_long[index], actual);
|
||||
}
|
||||
|
||||
public static void test_rol_int_const(int val, int index) {
|
||||
int res1 = Integer.rotateLeft(val, 1);
|
||||
verify("Constant integer rotateLeft shift = 1", res1 , ref_int_rol_shift_1[index]);
|
||||
int res2 = (val << 1) | (val >>> -1);
|
||||
verify("Constant integer rotateLeft shift = 1", res2 , ref_int_rol_shift_1[index]);
|
||||
|
||||
res1 = Integer.rotateLeft(val, 127);
|
||||
verify("Constant integer rotateLeft shift = 127", res1 , ref_int_rol_shift_127[index]);
|
||||
res2 = (val << 127) | (val >>> -127);
|
||||
verify("Constant integer rotateLeft shift = 127", res2 , ref_int_rol_shift_127[index]);
|
||||
|
||||
res1 = Integer.rotateLeft(val, 128);
|
||||
verify("Constant integer rotateLeft shift = 128", res1 , ref_int_rol_shift_128[index]);
|
||||
res2 = (val << 128) | (val >>> -128);
|
||||
verify("Constant integer rotateLeft pattern = 128", res2 , ref_int_rol_shift_128[index]);
|
||||
|
||||
res1 = Integer.rotateLeft(val, -128);
|
||||
verify("Constant integer rotateLeft shift = -128", res1 , ref_int_rol_shift_M128[index]);
|
||||
res2 = (val << -128) | (val >>> 128);
|
||||
verify("Constant integer rotateLeft pattern = 128", res2 , ref_int_rol_shift_M128[index]);
|
||||
|
||||
res1 = Integer.rotateLeft(val, -129);
|
||||
verify("Constant integer rotateLeft shift = -129", res1 , ref_int_rol_shift_M129[index]);
|
||||
res2 = (val << -129) | (val >>> 129);
|
||||
verify("Constant integer rotateLeft pattern = 129", res2 , ref_int_rol_shift_M129[index]);
|
||||
}
|
||||
|
||||
public static void test_ror_int_const(int val, int index) {
|
||||
int res1 = Integer.rotateRight(val, 1);
|
||||
verify("Constant integer rotateRight shift = 1", res1 , ref_int_ror_shift_1[index]);
|
||||
int res2 = (val >>> 1) | (val << -1);
|
||||
verify("Constant integer rotateRight pattern = 1", res2 , ref_int_ror_shift_1[index]);
|
||||
|
||||
res1 = Integer.rotateRight(val, 127);
|
||||
verify("Constant integer rotateRight shift = 127", res1 , ref_int_ror_shift_127[index]);
|
||||
res2 = (val >>> 127) | (val << -127);
|
||||
verify("Constant integer rotateRight pattern = 127", res2 , ref_int_ror_shift_127[index]);
|
||||
|
||||
res1 = Integer.rotateRight(val, 128);
|
||||
verify("Constant integer rotateRight shift = 128", res1 , ref_int_ror_shift_128[index]);
|
||||
res2 = (val >>> 128) | (val << -128);
|
||||
verify("Constant integer rotateRight pattern = 128", res2 , ref_int_ror_shift_128[index]);
|
||||
|
||||
res1 = Integer.rotateRight(val, -128);
|
||||
verify("Constant integer rotateRight shift = -128", res1 , ref_int_ror_shift_M128[index]);
|
||||
res2 = (val >>> -128) | (val << 128);
|
||||
verify("Constant integer rotateRight pattern = 128", res2 , ref_int_ror_shift_M128[index]);
|
||||
|
||||
res1 = Integer.rotateRight(val, -129);
|
||||
verify("Constant integer rotateRight shift = -129", res1 , ref_int_ror_shift_M129[index]);
|
||||
res2 = (val >>> -129) | (val << 129);
|
||||
verify("Constant integer rotateRight pattern = 129", res2 , ref_int_ror_shift_M129[index]);
|
||||
}
|
||||
|
||||
public static void test_rol_long_const(long val, int index) {
|
||||
long res1 = Long.rotateLeft(val, 1);
|
||||
verify("Constant long rotateLeft shift = 1", res1 , ref_long_rol_shift_1[index]);
|
||||
long res2 = (val << 1) | (val >>> -1);
|
||||
verify("Constant long rotateLeft pattern = 1", res2 , ref_long_rol_shift_1[index]);
|
||||
|
||||
res1 = Long.rotateLeft(val, 127);
|
||||
verify("Constant long rotateLeft shift = 127", res1 , ref_long_rol_shift_127[index]);
|
||||
res2 = (val << 127) | (val >>> -127);
|
||||
verify("Constant long rotateLeft pattern = 127", res2 , ref_long_rol_shift_127[index]);
|
||||
|
||||
res1 = Long.rotateLeft(val, 128);
|
||||
verify("Constant long rotateLeft shift = 128", res1 , ref_long_rol_shift_128[index]);
|
||||
res2 = (val << 128) | (val >>> -128);
|
||||
verify("Constant long rotateLeft pattern = 128", res2 , ref_long_rol_shift_128[index]);
|
||||
|
||||
res1 = Long.rotateLeft(val, -128);
|
||||
verify("Constant long rotateLeft shift = -128", res1 , ref_long_rol_shift_M128[index]);
|
||||
res2 = (val << -128) | (val >>> 128);
|
||||
verify("Constant long rotateLeft pattern = 128", res2 , ref_long_rol_shift_M128[index]);
|
||||
|
||||
res1 = Long.rotateLeft(val, -129);
|
||||
verify("Constant long rotateLeft shift = -129", res1 , ref_long_rol_shift_M129[index]);
|
||||
res2 = (val << -129) | (val >>> 129);
|
||||
verify("Constant long rotateLeft pattern = 129", res2 , ref_long_rol_shift_M129[index]);
|
||||
}
|
||||
|
||||
public static void test_ror_long_const(long val, int index) {
|
||||
long res1 = Long.rotateRight(val, 1);
|
||||
verify("Constant long rotateRight shift = 1", res1 , ref_long_ror_shift_1[index]);
|
||||
long res2 = (val >>> 1) | (val << -1);
|
||||
verify("Constant long rotateRight pattern = 1", res2 , ref_long_ror_shift_1[index]);
|
||||
|
||||
res1 = Long.rotateRight(val, 127);
|
||||
verify("Constant long rotateRight shift = 127", res1 , ref_long_ror_shift_127[index]);
|
||||
res2 = (val >>> 127) | (val << -127);
|
||||
verify("Constant long rotateRight pattern = 127", res2 , ref_long_ror_shift_127[index]);
|
||||
|
||||
res1 = Long.rotateRight(val, 128);
|
||||
verify("Constant long rotateRight shift = 128", res1 , ref_long_ror_shift_128[index]);
|
||||
res2 = (val >>> 128) | (val << -128);
|
||||
verify("Constant long rotateRight pattern = 128", res2 , ref_long_ror_shift_128[index]);
|
||||
|
||||
res1 = Long.rotateRight(val, -128);
|
||||
verify("Constant long rotateRight shift = -128", res1 , ref_long_ror_shift_M128[index]);
|
||||
res2 = (val >>> -128) | (val << 128);
|
||||
verify("Constant long rotateRight pattern = 128", res2 , ref_long_ror_shift_M128[index]);
|
||||
|
||||
res1 = Long.rotateRight(val, -129);
|
||||
verify("Constant long rotateRight shift = -129", res1 , ref_long_ror_shift_M129[index]);
|
||||
res2 = (val >>> -129) | (val << 129);
|
||||
verify("Constant long rotateRight pattern = 129", res2 , ref_long_ror_shift_M129[index]);
|
||||
}
|
||||
|
||||
public static void main(String args[]) throws Exception {
|
||||
rand = new Random(8248830);
|
||||
|
||||
int [] test_int = init_int_vector();
|
||||
long [] test_long = init_long_vector();
|
||||
int [] shift_vec = init_shift_vector(rand);
|
||||
|
||||
try {
|
||||
for (int i = 0 ; i < ITERS; i++) {
|
||||
for (int j = 0 ; j < SIZE ; j++) {
|
||||
test_rol_int(test_int[j], shift_vec[j], j);
|
||||
test_ror_int(test_int[j], shift_vec[j], j);
|
||||
test_rol_long(test_long[j], shift_vec[j], j);
|
||||
test_ror_long(test_long[j], shift_vec[j], j);
|
||||
|
||||
test_rol_int_const(test_int[j], j);
|
||||
test_ror_int_const(test_int[j], j);
|
||||
test_rol_long_const(test_long[j], j);
|
||||
test_ror_long_const(test_long[j], j);
|
||||
}
|
||||
}
|
||||
System.out.println("test status : PASS");
|
||||
} catch (Exception e) {
|
||||
System.out.println(e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
87
test/micro/org/openjdk/bench/java/lang/RotateBenchmark.java
Normal file
87
test/micro/org/openjdk/bench/java/lang/RotateBenchmark.java
Normal file
@ -0,0 +1,87 @@
|
||||
//
|
||||
// Copyright (c) 2003, 2020, 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
|
||||
// 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 java.util.Random;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import org.openjdk.jmh.annotations.*;
|
||||
import org.openjdk.jmh.infra.Blackhole;
|
||||
|
||||
@OutputTimeUnit(TimeUnit.MILLISECONDS)
|
||||
@State(Scope.Thread)
|
||||
@BenchmarkMode(Mode.Throughput)
|
||||
public class RotateBenchmark {
|
||||
|
||||
@Param({"1024"})
|
||||
public int TESTSIZE;
|
||||
|
||||
@Param({"20"})
|
||||
public int SHIFT;
|
||||
|
||||
public long [] larr;
|
||||
public int [] iarr;
|
||||
|
||||
public long [] lres;
|
||||
public int [] ires;
|
||||
|
||||
|
||||
@Setup(Level.Trial)
|
||||
public void BmSetup() {
|
||||
Random r = new Random(1024);
|
||||
larr = new long[TESTSIZE];
|
||||
iarr = new int[TESTSIZE];
|
||||
lres = new long[TESTSIZE];
|
||||
ires = new int[TESTSIZE];
|
||||
|
||||
for (int i = 0; i < TESTSIZE; i++) {
|
||||
larr[i] = r.nextLong();
|
||||
}
|
||||
|
||||
for (int i = 0; i < TESTSIZE; i++) {
|
||||
iarr[i] = r.nextInt();
|
||||
}
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public void testRotateLeftI() {
|
||||
for (int i = 0; i < TESTSIZE; i++)
|
||||
ires[i] = Integer.rotateLeft(iarr[i], SHIFT);
|
||||
}
|
||||
@Benchmark
|
||||
public void testRotateRightI() {
|
||||
for (int i = 0; i < TESTSIZE; i++)
|
||||
ires[i] = Integer.rotateRight(iarr[i], SHIFT);
|
||||
}
|
||||
@Benchmark
|
||||
public void testRotateLeftL() {
|
||||
for (int i = 0; i < TESTSIZE; i++)
|
||||
lres[i] = Long.rotateLeft(larr[i], SHIFT);
|
||||
}
|
||||
@Benchmark
|
||||
public void testRotateRightL() {
|
||||
for (int i = 0; i < TESTSIZE; i++)
|
||||
lres[i] = Long.rotateRight(larr[i], SHIFT);
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue
Block a user