# HG changeset patch # User duke # Date 1499280069 -7200 # Node ID 8d8f6619422292935f8713b29f4f0293f8895747 # Parent 8fc82d01db26dab8aea829531e98e369d4283c37# Parent a6d5932857d40d4bae2c0143d3d7e086679d4d0a Merge diff -r 8fc82d01db26 -r 8d8f66194222 .hgtags-top-repo --- a/.hgtags-top-repo Thu Jul 09 16:37:55 2015 -0700 +++ b/.hgtags-top-repo Wed Jul 05 20:41:09 2017 +0200 @@ -314,3 +314,4 @@ 1bcfd6b8726582cff5a42dbfc75903e36f9dd4fe jdk9-b69 eed77fcd77711fcdba05f18fc22f37d86efb243c jdk9-b70 c706ef5ea5da00078dc5e4334660315f7d99c15b jdk9-b71 +8582c35016fb6211b373810b6b172feccf9c483b jdk9-b72 diff -r 8fc82d01db26 -r 8d8f66194222 hotspot/.hgtags --- a/hotspot/.hgtags Thu Jul 09 16:37:55 2015 -0700 +++ b/hotspot/.hgtags Wed Jul 05 20:41:09 2017 +0200 @@ -474,3 +474,4 @@ ff0929a59ced0e144201aa05819ae2e47d6f2c61 jdk9-b69 8672e9264db30c21504063932dbc374eabc287a1 jdk9-b70 07c6b035d68b0c41b1dcd442157b50b41a2551e9 jdk9-b71 +c1b2825ef47e75cb34dd18450d1c4280b7c5853c jdk9-b72 diff -r 8fc82d01db26 -r 8d8f66194222 hotspot/src/cpu/aarch64/vm/aarch64.ad --- a/hotspot/src/cpu/aarch64/vm/aarch64.ad Thu Jul 09 16:37:55 2015 -0700 +++ b/hotspot/src/cpu/aarch64/vm/aarch64.ad Wed Jul 05 20:41:09 2017 +0200 @@ -865,6 +865,42 @@ V31, V31_H ); +// Class for all 64bit vector registers +reg_class vectord_reg( + V0, V0_H, + V1, V1_H, + V2, V2_H, + V3, V3_H, + V4, V4_H, + V5, V5_H, + V6, V6_H, + V7, V7_H, + V8, V8_H, + V9, V9_H, + V10, V10_H, + V11, V11_H, + V12, V12_H, + V13, V13_H, + V14, V14_H, + V15, V15_H, + V16, V16_H, + V17, V17_H, + V18, V18_H, + V19, V19_H, + V20, V20_H, + V21, V21_H, + V22, V22_H, + V23, V23_H, + V24, V24_H, + V25, V25_H, + V26, V26_H, + V27, V27_H, + V28, V28_H, + V29, V29_H, + V30, V30_H, + V31, V31_H +); + // Class for all 128bit vector registers reg_class vectorx_reg( V0, V0_H, V0_J, V0_K, @@ -2133,40 +2169,48 @@ if (bottom_type()->isa_vect() != NULL) { uint len = 4; + uint ireg = ideal_reg(); + assert(ireg == Op_VecD || ireg == Op_VecX, "must be 64 bit or 128 bit vector"); if (cbuf) { MacroAssembler _masm(cbuf); - uint ireg = ideal_reg(); assert((src_lo_rc != rc_int && dst_lo_rc != rc_int), "sanity"); - assert(ireg == Op_VecX, "sanity"); if (src_lo_rc == rc_stack && dst_lo_rc == rc_stack) { // stack->stack int src_offset = ra_->reg2offset(src_lo); int dst_offset = ra_->reg2offset(dst_lo); assert((src_offset & 7) && (dst_offset & 7), "unaligned stack offset"); len = 8; - if (src_offset < 512) { - __ ldp(rscratch1, rscratch2, Address(sp, src_offset)); - } else { + if (ireg == Op_VecD) { __ ldr(rscratch1, Address(sp, src_offset)); - __ ldr(rscratch2, Address(sp, src_offset+4)); - len += 4; - } - if (dst_offset < 512) { - __ stp(rscratch1, rscratch2, Address(sp, dst_offset)); + __ str(rscratch1, Address(sp, dst_offset)); } else { - __ str(rscratch1, Address(sp, dst_offset)); - __ str(rscratch2, Address(sp, dst_offset+4)); - len += 4; + if (src_offset < 512) { + __ ldp(rscratch1, rscratch2, Address(sp, src_offset)); + } else { + __ ldr(rscratch1, Address(sp, src_offset)); + __ ldr(rscratch2, Address(sp, src_offset+4)); + len += 4; + } + if (dst_offset < 512) { + __ stp(rscratch1, rscratch2, Address(sp, dst_offset)); + } else { + __ str(rscratch1, Address(sp, dst_offset)); + __ str(rscratch2, Address(sp, dst_offset+4)); + len += 4; + } } } else if (src_lo_rc == rc_float && dst_lo_rc == rc_float) { - __ orr(as_FloatRegister(Matcher::_regEncode[dst_lo]), __ T16B, + __ orr(as_FloatRegister(Matcher::_regEncode[dst_lo]), + ireg == Op_VecD ? __ T8B : __ T16B, as_FloatRegister(Matcher::_regEncode[src_lo]), as_FloatRegister(Matcher::_regEncode[src_lo])); } else if (src_lo_rc == rc_float && dst_lo_rc == rc_stack) { - __ str(as_FloatRegister(Matcher::_regEncode[src_lo]), __ Q, + __ str(as_FloatRegister(Matcher::_regEncode[src_lo]), + ireg == Op_VecD ? __ D : __ Q, Address(sp, ra_->reg2offset(dst_lo))); } else if (src_lo_rc == rc_stack && dst_lo_rc == rc_float) { - __ ldr(as_FloatRegister(Matcher::_regEncode[dst_lo]), __ Q, + __ ldr(as_FloatRegister(Matcher::_regEncode[dst_lo]), + ireg == Op_VecD ? __ D : __ Q, Address(sp, ra_->reg2offset(src_lo))); } else { ShouldNotReachHere(); @@ -2176,17 +2220,22 @@ // stack->stack int src_offset = ra_->reg2offset(src_lo); int dst_offset = ra_->reg2offset(dst_lo); - if (src_offset < 512) { - st->print("ldp rscratch1, rscratch2, [sp, #%d]", src_offset); - } else { + if (ireg == Op_VecD) { st->print("ldr rscratch1, [sp, #%d]", src_offset); - st->print("\nldr rscratch2, [sp, #%d]", src_offset+4); - } - if (dst_offset < 512) { - st->print("\nstp rscratch1, rscratch2, [sp, #%d]", dst_offset); + st->print("str rscratch1, [sp, #%d]", dst_offset); } else { - st->print("\nstr rscratch1, [sp, #%d]", dst_offset); - st->print("\nstr rscratch2, [sp, #%d]", dst_offset+4); + if (src_offset < 512) { + st->print("ldp rscratch1, rscratch2, [sp, #%d]", src_offset); + } else { + st->print("ldr rscratch1, [sp, #%d]", src_offset); + st->print("\nldr rscratch2, [sp, #%d]", src_offset+4); + } + if (dst_offset < 512) { + st->print("\nstp rscratch1, rscratch2, [sp, #%d]", dst_offset); + } else { + st->print("\nstr rscratch1, [sp, #%d]", dst_offset); + st->print("\nstr rscratch2, [sp, #%d]", dst_offset+4); + } } st->print("\t# vector spill, stack to stack"); } else if (src_lo_rc == rc_float && dst_lo_rc == rc_float) { @@ -2638,17 +2687,22 @@ return vector_width_in_bytes(bt)/type2aelembytes(bt); } const int Matcher::min_vector_size(const BasicType bt) { - //return (type2aelembytes(bt) == 1) ? 4 : 2; - // For the moment, only support 1 vector size, 128 bits - return max_vector_size(bt); +// For the moment limit the vector size to 8 bytes + int size = 8 / type2aelembytes(bt); + if (size < 2) size = 2; + return size; } // Vector ideal reg. const int Matcher::vector_ideal_reg(int len) { - return Op_VecX; + switch(len) { + case 8: return Op_VecD; + case 16: return Op_VecX; + } + ShouldNotReachHere(); + return 0; } -// Only lowest bits of xmm reg are used for vector shift count. const int Matcher::vector_shift_count_ideal_reg(int size) { return Op_VecX; } @@ -2660,9 +2714,7 @@ // x86 supports misaligned vectors store/load. const bool Matcher::misaligned_vectors_ok() { - // TODO fixme - // return !AlignVector; // can be changed by flag - return false; + return !AlignVector; // can be changed by flag } // false => size gets scaled to BytesPerLong, ok. @@ -3073,13 +3125,13 @@ as_Register($mem$$base), $mem$$index, $mem$$scale, $mem$$disp); %} - enc_class aarch64_enc_ldrvS(vecX dst, memory mem) %{ + enc_class aarch64_enc_ldrvS(vecD dst, memory mem) %{ FloatRegister dst_reg = as_FloatRegister($dst$$reg); loadStore(MacroAssembler(&cbuf), &MacroAssembler::ldr, dst_reg, MacroAssembler::S, $mem->opcode(), as_Register($mem$$base), $mem$$index, $mem$$scale, $mem$$disp); %} - enc_class aarch64_enc_ldrvD(vecX dst, memory mem) %{ + enc_class aarch64_enc_ldrvD(vecD dst, memory mem) %{ FloatRegister dst_reg = as_FloatRegister($dst$$reg); loadStore(MacroAssembler(&cbuf), &MacroAssembler::ldr, dst_reg, MacroAssembler::D, $mem->opcode(), as_Register($mem$$base), $mem$$index, $mem$$scale, $mem$$disp); @@ -3159,13 +3211,13 @@ as_Register($mem$$base), $mem$$index, $mem$$scale, $mem$$disp); %} - enc_class aarch64_enc_strvS(vecX src, memory mem) %{ + enc_class aarch64_enc_strvS(vecD src, memory mem) %{ FloatRegister src_reg = as_FloatRegister($src$$reg); loadStore(MacroAssembler(&cbuf), &MacroAssembler::str, src_reg, MacroAssembler::S, $mem->opcode(), as_Register($mem$$base), $mem$$index, $mem$$scale, $mem$$disp); %} - enc_class aarch64_enc_strvD(vecX src, memory mem) %{ + enc_class aarch64_enc_strvD(vecD src, memory mem) %{ FloatRegister src_reg = as_FloatRegister($src$$reg); loadStore(MacroAssembler(&cbuf), &MacroAssembler::str, src_reg, MacroAssembler::D, $mem->opcode(), as_Register($mem$$base), $mem$$index, $mem$$scale, $mem$$disp); @@ -5187,6 +5239,16 @@ interface(REG_INTER); %} +operand vecD() +%{ + constraint(ALLOC_IN_RC(vectord_reg)); + match(VecD); + + op_cost(0); + format %{ %} + interface(REG_INTER); +%} + operand vecX() %{ constraint(ALLOC_IN_RC(vectorx_reg)); @@ -7402,6 +7464,96 @@ ins_pipe(ialu_reg); %} +//---------- Population Count Instructions ------------------------------------- +// + +instruct popCountI(iRegINoSp dst, iRegIorL2I src, vRegF tmp) %{ + predicate(UsePopCountInstruction); + match(Set dst (PopCountI src)); + effect(TEMP tmp); + ins_cost(INSN_COST * 13); + + format %{ "movw $src, $src\n\t" + "mov $tmp, $src\t# vector (1D)\n\t" + "cnt $tmp, $tmp\t# vector (8B)\n\t" + "addv $tmp, $tmp\t# vector (8B)\n\t" + "mov $dst, $tmp\t# vector (1D)" %} + ins_encode %{ + __ movw($src$$Register, $src$$Register); // ensure top 32 bits 0 + __ mov($tmp$$FloatRegister, __ T1D, 0, $src$$Register); + __ cnt($tmp$$FloatRegister, __ T8B, $tmp$$FloatRegister); + __ addv($tmp$$FloatRegister, __ T8B, $tmp$$FloatRegister); + __ mov($dst$$Register, $tmp$$FloatRegister, __ T1D, 0); + %} + + ins_pipe(pipe_class_default); +%} + +instruct popCountI_mem(iRegINoSp dst, memory mem, vRegF tmp) %{ + predicate(UsePopCountInstruction); + match(Set dst (PopCountI (LoadI mem))); + effect(TEMP tmp); + ins_cost(INSN_COST * 13); + + format %{ "ldrs $tmp, $mem\n\t" + "cnt $tmp, $tmp\t# vector (8B)\n\t" + "addv $tmp, $tmp\t# vector (8B)\n\t" + "mov $dst, $tmp\t# vector (1D)" %} + ins_encode %{ + FloatRegister tmp_reg = as_FloatRegister($tmp$$reg); + loadStore(MacroAssembler(&cbuf), &MacroAssembler::ldrs, tmp_reg, $mem->opcode(), + as_Register($mem$$base), $mem$$index, $mem$$scale, $mem$$disp); + __ cnt($tmp$$FloatRegister, __ T8B, $tmp$$FloatRegister); + __ addv($tmp$$FloatRegister, __ T8B, $tmp$$FloatRegister); + __ mov($dst$$Register, $tmp$$FloatRegister, __ T1D, 0); + %} + + ins_pipe(pipe_class_default); +%} + +// Note: Long.bitCount(long) returns an int. +instruct popCountL(iRegINoSp dst, iRegL src, vRegD tmp) %{ + predicate(UsePopCountInstruction); + match(Set dst (PopCountL src)); + effect(TEMP tmp); + ins_cost(INSN_COST * 13); + + format %{ "mov $tmp, $src\t# vector (1D)\n\t" + "cnt $tmp, $tmp\t# vector (8B)\n\t" + "addv $tmp, $tmp\t# vector (8B)\n\t" + "mov $dst, $tmp\t# vector (1D)" %} + ins_encode %{ + __ mov($tmp$$FloatRegister, __ T1D, 0, $src$$Register); + __ cnt($tmp$$FloatRegister, __ T8B, $tmp$$FloatRegister); + __ addv($tmp$$FloatRegister, __ T8B, $tmp$$FloatRegister); + __ mov($dst$$Register, $tmp$$FloatRegister, __ T1D, 0); + %} + + ins_pipe(pipe_class_default); +%} + +instruct popCountL_mem(iRegINoSp dst, memory mem, vRegD tmp) %{ + predicate(UsePopCountInstruction); + match(Set dst (PopCountL (LoadL mem))); + effect(TEMP tmp); + ins_cost(INSN_COST * 13); + + format %{ "ldrd $tmp, $mem\n\t" + "cnt $tmp, $tmp\t# vector (8B)\n\t" + "addv $tmp, $tmp\t# vector (8B)\n\t" + "mov $dst, $tmp\t# vector (1D)" %} + ins_encode %{ + FloatRegister tmp_reg = as_FloatRegister($tmp$$reg); + loadStore(MacroAssembler(&cbuf), &MacroAssembler::ldrd, tmp_reg, $mem->opcode(), + as_Register($mem$$base), $mem$$index, $mem$$scale, $mem$$disp); + __ cnt($tmp$$FloatRegister, __ T8B, $tmp$$FloatRegister); + __ addv($tmp$$FloatRegister, __ T8B, $tmp$$FloatRegister); + __ mov($dst$$Register, $tmp$$FloatRegister, __ T1D, 0); + %} + + ins_pipe(pipe_class_default); +%} + // ============================================================================ // MemBar Instruction @@ -13194,7 +13346,7 @@ // ====================VECTOR INSTRUCTIONS===================================== // Load vector (32 bits) -instruct loadV4(vecX dst, vmem mem) +instruct loadV4(vecD dst, vmem mem) %{ predicate(n->as_LoadVector()->memory_size() == 4); match(Set dst (LoadVector mem)); @@ -13205,7 +13357,7 @@ %} // Load vector (64 bits) -instruct loadV8(vecX dst, vmem mem) +instruct loadV8(vecD dst, vmem mem) %{ predicate(n->as_LoadVector()->memory_size() == 8); match(Set dst (LoadVector mem)); @@ -13227,7 +13379,7 @@ %} // Store Vector (32 bits) -instruct storeV4(vecX src, vmem mem) +instruct storeV4(vecD src, vmem mem) %{ predicate(n->as_StoreVector()->memory_size() == 4); match(Set mem (StoreVector mem src)); @@ -13238,7 +13390,7 @@ %} // Store Vector (64 bits) -instruct storeV8(vecX src, vmem mem) +instruct storeV8(vecD src, vmem mem) %{ predicate(n->as_StoreVector()->memory_size() == 8); match(Set mem (StoreVector mem src)); @@ -13259,8 +13411,22 @@ ins_pipe(pipe_class_memory); %} +instruct replicate8B(vecD dst, iRegIorL2I src) +%{ + predicate(n->as_Vector()->length() == 4 || + n->as_Vector()->length() == 8); + match(Set dst (ReplicateB src)); + ins_cost(INSN_COST); + format %{ "dup $dst, $src\t# vector (8B)" %} + ins_encode %{ + __ dup(as_FloatRegister($dst$$reg), __ T8B, as_Register($src$$reg)); + %} + ins_pipe(pipe_class_default); +%} + instruct replicate16B(vecX dst, iRegIorL2I src) %{ + predicate(n->as_Vector()->length() == 16); match(Set dst (ReplicateB src)); ins_cost(INSN_COST); format %{ "dup $dst, $src\t# vector (16B)" %} @@ -13270,8 +13436,22 @@ ins_pipe(pipe_class_default); %} +instruct replicate8B_imm(vecD dst, immI con) +%{ + predicate(n->as_Vector()->length() == 4 || + n->as_Vector()->length() == 8); + match(Set dst (ReplicateB con)); + ins_cost(INSN_COST); + format %{ "movi $dst, $con\t# vector(8B)" %} + ins_encode %{ + __ mov(as_FloatRegister($dst$$reg), __ T8B, $con$$constant & 0xff); + %} + ins_pipe(pipe_class_default); +%} + instruct replicate16B_imm(vecX dst, immI con) %{ + predicate(n->as_Vector()->length() == 16); match(Set dst (ReplicateB con)); ins_cost(INSN_COST); format %{ "movi $dst, $con\t# vector(16B)" %} @@ -13281,8 +13461,22 @@ ins_pipe(pipe_class_default); %} +instruct replicate4S(vecD dst, iRegIorL2I src) +%{ + predicate(n->as_Vector()->length() == 2 || + n->as_Vector()->length() == 4); + match(Set dst (ReplicateS src)); + ins_cost(INSN_COST); + format %{ "dup $dst, $src\t# vector (4S)" %} + ins_encode %{ + __ dup(as_FloatRegister($dst$$reg), __ T4H, as_Register($src$$reg)); + %} + ins_pipe(pipe_class_default); +%} + instruct replicate8S(vecX dst, iRegIorL2I src) %{ + predicate(n->as_Vector()->length() == 8); match(Set dst (ReplicateS src)); ins_cost(INSN_COST); format %{ "dup $dst, $src\t# vector (8S)" %} @@ -13292,8 +13486,22 @@ ins_pipe(pipe_class_default); %} +instruct replicate4S_imm(vecD dst, immI con) +%{ + predicate(n->as_Vector()->length() == 2 || + n->as_Vector()->length() == 4); + match(Set dst (ReplicateS con)); + ins_cost(INSN_COST); + format %{ "movi $dst, $con\t# vector(4H)" %} + ins_encode %{ + __ mov(as_FloatRegister($dst$$reg), __ T4H, $con$$constant & 0xffff); + %} + ins_pipe(pipe_class_default); +%} + instruct replicate8S_imm(vecX dst, immI con) %{ + predicate(n->as_Vector()->length() == 8); match(Set dst (ReplicateS con)); ins_cost(INSN_COST); format %{ "movi $dst, $con\t# vector(8H)" %} @@ -13303,8 +13511,21 @@ ins_pipe(pipe_class_default); %} +instruct replicate2I(vecD dst, iRegIorL2I src) +%{ + predicate(n->as_Vector()->length() == 2); + match(Set dst (ReplicateI src)); + ins_cost(INSN_COST); + format %{ "dup $dst, $src\t# vector (2I)" %} + ins_encode %{ + __ dup(as_FloatRegister($dst$$reg), __ T2S, as_Register($src$$reg)); + %} + ins_pipe(pipe_class_default); +%} + instruct replicate4I(vecX dst, iRegIorL2I src) %{ + predicate(n->as_Vector()->length() == 4); match(Set dst (ReplicateI src)); ins_cost(INSN_COST); format %{ "dup $dst, $src\t# vector (4I)" %} @@ -13314,8 +13535,21 @@ ins_pipe(pipe_class_default); %} +instruct replicate2I_imm(vecD dst, immI con) +%{ + predicate(n->as_Vector()->length() == 2); + match(Set dst (ReplicateI con)); + ins_cost(INSN_COST); + format %{ "movi $dst, $con\t# vector(2I)" %} + ins_encode %{ + __ mov(as_FloatRegister($dst$$reg), __ T2S, $con$$constant); + %} + ins_pipe(pipe_class_default); +%} + instruct replicate4I_imm(vecX dst, immI con) %{ + predicate(n->as_Vector()->length() == 4); match(Set dst (ReplicateI con)); ins_cost(INSN_COST); format %{ "movi $dst, $con\t# vector(4I)" %} @@ -13327,6 +13561,7 @@ instruct replicate2L(vecX dst, iRegL src) %{ + predicate(n->as_Vector()->length() == 2); match(Set dst (ReplicateL src)); ins_cost(INSN_COST); format %{ "dup $dst, $src\t# vector (2L)" %} @@ -13338,6 +13573,7 @@ instruct replicate2L_zero(vecX dst, immI0 zero) %{ + predicate(n->as_Vector()->length() == 2); match(Set dst (ReplicateI zero)); ins_cost(INSN_COST); format %{ "movi $dst, $zero\t# vector(4I)" %} @@ -13349,8 +13585,22 @@ ins_pipe(pipe_class_default); %} +instruct replicate2F(vecD dst, vRegF src) +%{ + predicate(n->as_Vector()->length() == 2); + match(Set dst (ReplicateF src)); + ins_cost(INSN_COST); + format %{ "dup $dst, $src\t# vector (2F)" %} + ins_encode %{ + __ dup(as_FloatRegister($dst$$reg), __ T2S, + as_FloatRegister($src$$reg)); + %} + ins_pipe(pipe_class_default); +%} + instruct replicate4F(vecX dst, vRegF src) %{ + predicate(n->as_Vector()->length() == 4); match(Set dst (ReplicateF src)); ins_cost(INSN_COST); format %{ "dup $dst, $src\t# vector (4F)" %} @@ -13363,6 +13613,7 @@ instruct replicate2D(vecX dst, vRegD src) %{ + predicate(n->as_Vector()->length() == 2); match(Set dst (ReplicateD src)); ins_cost(INSN_COST); format %{ "dup $dst, $src\t# vector (2D)" %} @@ -13375,6 +13626,25 @@ // ====================REDUCTION ARITHMETIC==================================== +instruct reduce_add2I(iRegINoSp dst, iRegIorL2I src1, vecD src2, iRegI tmp, iRegI tmp2) +%{ + match(Set dst (AddReductionVI src1 src2)); + ins_cost(INSN_COST); + effect(TEMP tmp, TEMP tmp2); + format %{ "umov $tmp, $src2, S, 0\n\t" + "umov $tmp2, $src2, S, 1\n\t" + "addw $dst, $src1, $tmp\n\t" + "addw $dst, $dst, $tmp2\t add reduction2i" + %} + ins_encode %{ + __ umov($tmp$$Register, as_FloatRegister($src2$$reg), __ S, 0); + __ umov($tmp2$$Register, as_FloatRegister($src2$$reg), __ S, 1); + __ addw($dst$$Register, $src1$$Register, $tmp$$Register); + __ addw($dst$$Register, $dst$$Register, $tmp2$$Register); + %} + ins_pipe(pipe_class_default); +%} + instruct reduce_add4I(iRegINoSp dst, iRegIorL2I src1, vecX src2, vecX tmp, iRegI tmp2) %{ match(Set dst (AddReductionVI src1 src2)); @@ -13393,6 +13663,25 @@ ins_pipe(pipe_class_default); %} +instruct reduce_mul2I(iRegINoSp dst, iRegIorL2I src1, vecD src2, iRegI tmp) +%{ + match(Set dst (MulReductionVI src1 src2)); + ins_cost(INSN_COST); + effect(TEMP tmp, TEMP dst); + format %{ "umov $tmp, $src2, S, 0\n\t" + "mul $dst, $tmp, $src1\n\t" + "umov $tmp, $src2, S, 1\n\t" + "mul $dst, $tmp, $dst\t mul reduction2i\n\t" + %} + ins_encode %{ + __ umov($tmp$$Register, as_FloatRegister($src2$$reg), __ S, 0); + __ mul($dst$$Register, $tmp$$Register, $src1$$Register); + __ umov($tmp$$Register, as_FloatRegister($src2$$reg), __ S, 1); + __ mul($dst$$Register, $tmp$$Register, $dst$$Register); + %} + ins_pipe(pipe_class_default); +%} + instruct reduce_mul4I(iRegINoSp dst, iRegIorL2I src1, vecX src2, vecX tmp, iRegI tmp2) %{ match(Set dst (MulReductionVI src1 src2)); @@ -13418,6 +13707,26 @@ ins_pipe(pipe_class_default); %} +instruct reduce_add2F(vRegF dst, vRegF src1, vecD src2, vecD tmp) +%{ + match(Set dst (AddReductionVF src1 src2)); + ins_cost(INSN_COST); + effect(TEMP tmp, TEMP dst); + format %{ "fadds $dst, $src1, $src2\n\t" + "ins $tmp, S, $src2, 0, 1\n\t" + "fadds $dst, $dst, $tmp\t add reduction2f" + %} + ins_encode %{ + __ fadds(as_FloatRegister($dst$$reg), + as_FloatRegister($src1$$reg), as_FloatRegister($src2$$reg)); + __ ins(as_FloatRegister($tmp$$reg), __ S, + as_FloatRegister($src2$$reg), 0, 1); + __ fadds(as_FloatRegister($dst$$reg), + as_FloatRegister($dst$$reg), as_FloatRegister($tmp$$reg)); + %} + ins_pipe(pipe_class_default); +%} + instruct reduce_add4F(vRegF dst, vRegF src1, vecX src2, vecX tmp) %{ match(Set dst (AddReductionVF src1 src2)); @@ -13450,6 +13759,26 @@ ins_pipe(pipe_class_default); %} +instruct reduce_mul2F(vRegF dst, vRegF src1, vecD src2, vecD tmp) +%{ + match(Set dst (MulReductionVF src1 src2)); + ins_cost(INSN_COST); + effect(TEMP tmp, TEMP dst); + format %{ "fmuls $dst, $src1, $src2\n\t" + "ins $tmp, S, $src2, 0, 1\n\t" + "fmuls $dst, $dst, $tmp\t add reduction4f" + %} + ins_encode %{ + __ fmuls(as_FloatRegister($dst$$reg), + as_FloatRegister($src1$$reg), as_FloatRegister($src2$$reg)); + __ ins(as_FloatRegister($tmp$$reg), __ S, + as_FloatRegister($src2$$reg), 0, 1); + __ fmuls(as_FloatRegister($dst$$reg), + as_FloatRegister($dst$$reg), as_FloatRegister($tmp$$reg)); + %} + ins_pipe(pipe_class_default); +%} + instruct reduce_mul4F(vRegF dst, vRegF src1, vecX src2, vecX tmp) %{ match(Set dst (MulReductionVF src1 src2)); @@ -13526,8 +13855,24 @@ // --------------------------------- ADD -------------------------------------- +instruct vadd8B(vecD dst, vecD src1, vecD src2) +%{ + predicate(n->as_Vector()->length() == 4 || + n->as_Vector()->length() == 8); + match(Set dst (AddVB src1 src2)); + ins_cost(INSN_COST); + format %{ "addv $dst,$src1,$src2\t# vector (8B)" %} + ins_encode %{ + __ addv(as_FloatRegister($dst$$reg), __ T8B, + as_FloatRegister($src1$$reg), + as_FloatRegister($src2$$reg)); + %} + ins_pipe(pipe_class_default); +%} + instruct vadd16B(vecX dst, vecX src1, vecX src2) %{ + predicate(n->as_Vector()->length() == 16); match(Set dst (AddVB src1 src2)); ins_cost(INSN_COST); format %{ "addv $dst,$src1,$src2\t# vector (16B)" %} @@ -13539,8 +13884,24 @@ ins_pipe(pipe_class_default); %} +instruct vadd4S(vecD dst, vecD src1, vecD src2) +%{ + predicate(n->as_Vector()->length() == 2 || + n->as_Vector()->length() == 4); + match(Set dst (AddVS src1 src2)); + ins_cost(INSN_COST); + format %{ "addv $dst,$src1,$src2\t# vector (4H)" %} + ins_encode %{ + __ addv(as_FloatRegister($dst$$reg), __ T4H, + as_FloatRegister($src1$$reg), + as_FloatRegister($src2$$reg)); + %} + ins_pipe(pipe_class_default); +%} + instruct vadd8S(vecX dst, vecX src1, vecX src2) %{ + predicate(n->as_Vector()->length() == 8); match(Set dst (AddVS src1 src2)); ins_cost(INSN_COST); format %{ "addv $dst,$src1,$src2\t# vector (8H)" %} @@ -13552,8 +13913,23 @@ ins_pipe(pipe_class_default); %} +instruct vadd2I(vecD dst, vecD src1, vecD src2) +%{ + predicate(n->as_Vector()->length() == 2); + match(Set dst (AddVI src1 src2)); + ins_cost(INSN_COST); + format %{ "addv $dst,$src1,$src2\t# vector (2S)" %} + ins_encode %{ + __ addv(as_FloatRegister($dst$$reg), __ T2S, + as_FloatRegister($src1$$reg), + as_FloatRegister($src2$$reg)); + %} + ins_pipe(pipe_class_default); +%} + instruct vadd4I(vecX dst, vecX src1, vecX src2) %{ + predicate(n->as_Vector()->length() == 4); match(Set dst (AddVI src1 src2)); ins_cost(INSN_COST); format %{ "addv $dst,$src1,$src2\t# vector (4S)" %} @@ -13567,6 +13943,7 @@ instruct vadd2L(vecX dst, vecX src1, vecX src2) %{ + predicate(n->as_Vector()->length() == 2); match(Set dst (AddVL src1 src2)); ins_cost(INSN_COST); format %{ "addv $dst,$src1,$src2\t# vector (2L)" %} @@ -13578,8 +13955,23 @@ ins_pipe(pipe_class_default); %} +instruct vadd2F(vecD dst, vecD src1, vecD src2) +%{ + predicate(n->as_Vector()->length() == 2); + match(Set dst (AddVF src1 src2)); + ins_cost(INSN_COST); + format %{ "fadd $dst,$src1,$src2\t# vector (2S)" %} + ins_encode %{ + __ fadd(as_FloatRegister($dst$$reg), __ T2S, + as_FloatRegister($src1$$reg), + as_FloatRegister($src2$$reg)); + %} + ins_pipe(pipe_class_default); +%} + instruct vadd4F(vecX dst, vecX src1, vecX src2) %{ + predicate(n->as_Vector()->length() == 4); match(Set dst (AddVF src1 src2)); ins_cost(INSN_COST); format %{ "fadd $dst,$src1,$src2\t# vector (4S)" %} @@ -13606,8 +13998,24 @@ // --------------------------------- SUB -------------------------------------- +instruct vsub8B(vecD dst, vecD src1, vecD src2) +%{ + predicate(n->as_Vector()->length() == 4 || + n->as_Vector()->length() == 8); + match(Set dst (SubVB src1 src2)); + ins_cost(INSN_COST); + format %{ "subv $dst,$src1,$src2\t# vector (8B)" %} + ins_encode %{ + __ subv(as_FloatRegister($dst$$reg), __ T8B, + as_FloatRegister($src1$$reg), + as_FloatRegister($src2$$reg)); + %} + ins_pipe(pipe_class_default); +%} + instruct vsub16B(vecX dst, vecX src1, vecX src2) %{ + predicate(n->as_Vector()->length() == 16); match(Set dst (SubVB src1 src2)); ins_cost(INSN_COST); format %{ "subv $dst,$src1,$src2\t# vector (16B)" %} @@ -13619,8 +14027,24 @@ ins_pipe(pipe_class_default); %} +instruct vsub4S(vecD dst, vecD src1, vecD src2) +%{ + predicate(n->as_Vector()->length() == 2 || + n->as_Vector()->length() == 4); + match(Set dst (SubVS src1 src2)); + ins_cost(INSN_COST); + format %{ "subv $dst,$src1,$src2\t# vector (4H)" %} + ins_encode %{ + __ subv(as_FloatRegister($dst$$reg), __ T4H, + as_FloatRegister($src1$$reg), + as_FloatRegister($src2$$reg)); + %} + ins_pipe(pipe_class_default); +%} + instruct vsub8S(vecX dst, vecX src1, vecX src2) %{ + predicate(n->as_Vector()->length() == 8); match(Set dst (SubVS src1 src2)); ins_cost(INSN_COST); format %{ "subv $dst,$src1,$src2\t# vector (8H)" %} @@ -13632,8 +14056,23 @@ ins_pipe(pipe_class_default); %} +instruct vsub2I(vecD dst, vecD src1, vecD src2) +%{ + predicate(n->as_Vector()->length() == 2); + match(Set dst (SubVI src1 src2)); + ins_cost(INSN_COST); + format %{ "subv $dst,$src1,$src2\t# vector (2S)" %} + ins_encode %{ + __ subv(as_FloatRegister($dst$$reg), __ T2S, + as_FloatRegister($src1$$reg), + as_FloatRegister($src2$$reg)); + %} + ins_pipe(pipe_class_default); +%} + instruct vsub4I(vecX dst, vecX src1, vecX src2) %{ + predicate(n->as_Vector()->length() == 4); match(Set dst (SubVI src1 src2)); ins_cost(INSN_COST); format %{ "subv $dst,$src1,$src2\t# vector (4S)" %} @@ -13647,6 +14086,7 @@ instruct vsub2L(vecX dst, vecX src1, vecX src2) %{ + predicate(n->as_Vector()->length() == 2); match(Set dst (SubVL src1 src2)); ins_cost(INSN_COST); format %{ "subv $dst,$src1,$src2\t# vector (2L)" %} @@ -13658,8 +14098,23 @@ ins_pipe(pipe_class_default); %} +instruct vsub2F(vecD dst, vecD src1, vecD src2) +%{ + predicate(n->as_Vector()->length() == 2); + match(Set dst (AddVF src1 src2)); + ins_cost(INSN_COST); + format %{ "fsub $dst,$src1,$src2\t# vector (2S)" %} + ins_encode %{ + __ fsub(as_FloatRegister($dst$$reg), __ T2S, + as_FloatRegister($src1$$reg), + as_FloatRegister($src2$$reg)); + %} + ins_pipe(pipe_class_default); +%} + instruct vsub4F(vecX dst, vecX src1, vecX src2) %{ + predicate(n->as_Vector()->length() == 4); match(Set dst (SubVF src1 src2)); ins_cost(INSN_COST); format %{ "fsub $dst,$src1,$src2\t# vector (4S)" %} @@ -13673,6 +14128,7 @@ instruct vsub2D(vecX dst, vecX src1, vecX src2) %{ + predicate(n->as_Vector()->length() == 2); match(Set dst (SubVD src1 src2)); ins_cost(INSN_COST); format %{ "fsub $dst,$src1,$src2\t# vector (2D)" %} @@ -13686,8 +14142,24 @@ // --------------------------------- MUL -------------------------------------- +instruct vmul4S(vecD dst, vecD src1, vecD src2) +%{ + predicate(n->as_Vector()->length() == 2 || + n->as_Vector()->length() == 4); + match(Set dst (MulVS src1 src2)); + ins_cost(INSN_COST); + format %{ "mulv $dst,$src1,$src2\t# vector (4H)" %} + ins_encode %{ + __ mulv(as_FloatRegister($dst$$reg), __ T4H, + as_FloatRegister($src1$$reg), + as_FloatRegister($src2$$reg)); + %} + ins_pipe(pipe_class_default); +%} + instruct vmul8S(vecX dst, vecX src1, vecX src2) %{ + predicate(n->as_Vector()->length() == 8); match(Set dst (MulVS src1 src2)); ins_cost(INSN_COST); format %{ "mulv $dst,$src1,$src2\t# vector (8H)" %} @@ -13699,8 +14171,23 @@ ins_pipe(pipe_class_default); %} +instruct vmul2I(vecD dst, vecD src1, vecD src2) +%{ + predicate(n->as_Vector()->length() == 2); + match(Set dst (MulVI src1 src2)); + ins_cost(INSN_COST); + format %{ "mulv $dst,$src1,$src2\t# vector (2S)" %} + ins_encode %{ + __ mulv(as_FloatRegister($dst$$reg), __ T2S, + as_FloatRegister($src1$$reg), + as_FloatRegister($src2$$reg)); + %} + ins_pipe(pipe_class_default); +%} + instruct vmul4I(vecX dst, vecX src1, vecX src2) %{ + predicate(n->as_Vector()->length() == 4); match(Set dst (MulVI src1 src2)); ins_cost(INSN_COST); format %{ "mulv $dst,$src1,$src2\t# vector (4S)" %} @@ -13712,8 +14199,23 @@ ins_pipe(pipe_class_default); %} +instruct vmul2F(vecD dst, vecD src1, vecD src2) +%{ + predicate(n->as_Vector()->length() == 2); + match(Set dst (MulVF src1 src2)); + ins_cost(INSN_COST); + format %{ "fmul $dst,$src1,$src2\t# vector (2S)" %} + ins_encode %{ + __ fmul(as_FloatRegister($dst$$reg), __ T2S, + as_FloatRegister($src1$$reg), + as_FloatRegister($src2$$reg)); + %} + ins_pipe(pipe_class_default); +%} + instruct vmul4F(vecX dst, vecX src1, vecX src2) %{ + predicate(n->as_Vector()->length() == 4); match(Set dst (MulVF src1 src2)); ins_cost(INSN_COST); format %{ "fmul $dst,$src1,$src2\t# vector (4S)" %} @@ -13727,6 +14229,7 @@ instruct vmul2D(vecX dst, vecX src1, vecX src2) %{ + predicate(n->as_Vector()->length() == 2); match(Set dst (MulVD src1 src2)); ins_cost(INSN_COST); format %{ "fmul $dst,$src1,$src2\t# vector (2D)" %} @@ -13740,8 +14243,23 @@ // --------------------------------- DIV -------------------------------------- +instruct vdiv2F(vecD dst, vecD src1, vecD src2) +%{ + predicate(n->as_Vector()->length() == 2); + match(Set dst (DivVF src1 src2)); + ins_cost(INSN_COST); + format %{ "fdiv $dst,$src1,$src2\t# vector (2S)" %} + ins_encode %{ + __ fdiv(as_FloatRegister($dst$$reg), __ T2S, + as_FloatRegister($src1$$reg), + as_FloatRegister($src2$$reg)); + %} + ins_pipe(pipe_class_default); +%} + instruct vdiv4F(vecX dst, vecX src1, vecX src2) %{ + predicate(n->as_Vector()->length() == 4); match(Set dst (DivVF src1 src2)); ins_cost(INSN_COST); format %{ "fdiv $dst,$src1,$src2\t# vector (4S)" %} @@ -13755,6 +14273,7 @@ instruct vdiv2D(vecX dst, vecX src1, vecX src2) %{ + predicate(n->as_Vector()->length() == 2); match(Set dst (DivVD src1 src2)); ins_cost(INSN_COST); format %{ "fdiv $dst,$src1,$src2\t# vector (2D)" %} @@ -13768,8 +14287,24 @@ // --------------------------------- AND -------------------------------------- +instruct vand8B(vecD dst, vecD src1, vecD src2) +%{ + predicate(n->as_Vector()->length_in_bytes() == 4 || + n->as_Vector()->length_in_bytes() == 8); + match(Set dst (AndV src1 src2)); + ins_cost(INSN_COST); + format %{ "and $dst,$src1,$src2\t# vector (8B)" %} + ins_encode %{ + __ andr(as_FloatRegister($dst$$reg), __ T8B, + as_FloatRegister($src1$$reg), + as_FloatRegister($src2$$reg)); + %} + ins_pipe(pipe_class_default); +%} + instruct vand16B(vecX dst, vecX src1, vecX src2) %{ + predicate(n->as_Vector()->length_in_bytes() == 16); match(Set dst (AndV src1 src2)); ins_cost(INSN_COST); format %{ "and $dst,$src1,$src2\t# vector (16B)" %} @@ -13783,8 +14318,24 @@ // --------------------------------- OR --------------------------------------- +instruct vor8B(vecD dst, vecD src1, vecD src2) +%{ + predicate(n->as_Vector()->length_in_bytes() == 4 || + n->as_Vector()->length_in_bytes() == 8); + match(Set dst (OrV src1 src2)); + ins_cost(INSN_COST); + format %{ "and $dst,$src1,$src2\t# vector (8B)" %} + ins_encode %{ + __ orr(as_FloatRegister($dst$$reg), __ T8B, + as_FloatRegister($src1$$reg), + as_FloatRegister($src2$$reg)); + %} + ins_pipe(pipe_class_default); +%} + instruct vor16B(vecX dst, vecX src1, vecX src2) %{ + predicate(n->as_Vector()->length_in_bytes() == 16); match(Set dst (OrV src1 src2)); ins_cost(INSN_COST); format %{ "orr $dst,$src1,$src2\t# vector (16B)" %} @@ -13798,8 +14349,24 @@ // --------------------------------- XOR -------------------------------------- +instruct vxor8B(vecD dst, vecD src1, vecD src2) +%{ + predicate(n->as_Vector()->length_in_bytes() == 4 || + n->as_Vector()->length_in_bytes() == 8); + match(Set dst (XorV src1 src2)); + ins_cost(INSN_COST); + format %{ "xor $dst,$src1,$src2\t# vector (8B)" %} + ins_encode %{ + __ eor(as_FloatRegister($dst$$reg), __ T8B, + as_FloatRegister($src1$$reg), + as_FloatRegister($src2$$reg)); + %} + ins_pipe(pipe_class_default); +%} + instruct vxor16B(vecX dst, vecX src1, vecX src2) %{ + predicate(n->as_Vector()->length_in_bytes() == 16); match(Set dst (XorV src1 src2)); ins_cost(INSN_COST); format %{ "xor $dst,$src1,$src2\t# vector (16B)" %} @@ -13833,7 +14400,23 @@ ins_pipe(pipe_class_default); %} +instruct vsll8B(vecD dst, vecD src, vecX shift) %{ + predicate(n->as_Vector()->length() == 4 || + n->as_Vector()->length() == 8); + match(Set dst (LShiftVB src shift)); + match(Set dst (RShiftVB src shift)); + ins_cost(INSN_COST); + format %{ "sshl $dst,$src,$shift\t# vector (8B)" %} + ins_encode %{ + __ sshl(as_FloatRegister($dst$$reg), __ T8B, + as_FloatRegister($src$$reg), + as_FloatRegister($shift$$reg)); + %} + ins_pipe(pipe_class_default); +%} + instruct vsll16B(vecX dst, vecX src, vecX shift) %{ + predicate(n->as_Vector()->length() == 16); match(Set dst (LShiftVB src shift)); match(Set dst (RShiftVB src shift)); ins_cost(INSN_COST); @@ -13846,7 +14429,22 @@ ins_pipe(pipe_class_default); %} +instruct vsrl8B(vecD dst, vecD src, vecX shift) %{ + predicate(n->as_Vector()->length() == 4 || + n->as_Vector()->length() == 8); + match(Set dst (URShiftVB src shift)); + ins_cost(INSN_COST); + format %{ "ushl $dst,$src,$shift\t# vector (8B)" %} + ins_encode %{ + __ ushl(as_FloatRegister($dst$$reg), __ T8B, + as_FloatRegister($src$$reg), + as_FloatRegister($shift$$reg)); + %} + ins_pipe(pipe_class_default); +%} + instruct vsrl16B(vecX dst, vecX src, vecX shift) %{ + predicate(n->as_Vector()->length() == 16); match(Set dst (URShiftVB src shift)); ins_cost(INSN_COST); format %{ "ushl $dst,$src,$shift\t# vector (16B)" %} @@ -13858,7 +14456,28 @@ ins_pipe(pipe_class_default); %} +instruct vsll8B_imm(vecD dst, vecD src, immI shift) %{ + predicate(n->as_Vector()->length() == 4 || + n->as_Vector()->length() == 8); + match(Set dst (LShiftVB src shift)); + ins_cost(INSN_COST); + format %{ "shl $dst, $src, $shift\t# vector (8B)" %} + ins_encode %{ + int sh = (int)$shift$$constant & 31; + if (sh >= 8) { + __ eor(as_FloatRegister($dst$$reg), __ T8B, + as_FloatRegister($src$$reg), + as_FloatRegister($src$$reg)); + } else { + __ shl(as_FloatRegister($dst$$reg), __ T8B, + as_FloatRegister($src$$reg), sh); + } + %} + ins_pipe(pipe_class_default); +%} + instruct vsll16B_imm(vecX dst, vecX src, immI shift) %{ + predicate(n->as_Vector()->length() == 16); match(Set dst (LShiftVB src shift)); ins_cost(INSN_COST); format %{ "shl $dst, $src, $shift\t# vector (16B)" %} @@ -13876,7 +14495,24 @@ ins_pipe(pipe_class_default); %} +instruct vsra8B_imm(vecD dst, vecD src, immI shift) %{ + predicate(n->as_Vector()->length() == 4 || + n->as_Vector()->length() == 8); + match(Set dst (RShiftVB src shift)); + ins_cost(INSN_COST); + format %{ "sshr $dst, $src, $shift\t# vector (8B)" %} + ins_encode %{ + int sh = (int)$shift$$constant & 31; + if (sh >= 8) sh = 7; + sh = -sh & 7; + __ sshr(as_FloatRegister($dst$$reg), __ T8B, + as_FloatRegister($src$$reg), sh); + %} + ins_pipe(pipe_class_default); +%} + instruct vsra16B_imm(vecX dst, vecX src, immI shift) %{ + predicate(n->as_Vector()->length() == 16); match(Set dst (RShiftVB src shift)); ins_cost(INSN_COST); format %{ "sshr $dst, $src, $shift\t# vector (16B)" %} @@ -13890,7 +14526,28 @@ ins_pipe(pipe_class_default); %} +instruct vsrl8B_imm(vecD dst, vecD src, immI shift) %{ + predicate(n->as_Vector()->length() == 4 || + n->as_Vector()->length() == 8); + match(Set dst (URShiftVB src shift)); + ins_cost(INSN_COST); + format %{ "ushr $dst, $src, $shift\t# vector (8B)" %} + ins_encode %{ + int sh = (int)$shift$$constant & 31; + if (sh >= 8) { + __ eor(as_FloatRegister($dst$$reg), __ T8B, + as_FloatRegister($src$$reg), + as_FloatRegister($src$$reg)); + } else { + __ ushr(as_FloatRegister($dst$$reg), __ T8B, + as_FloatRegister($src$$reg), -sh & 7); + } + %} + ins_pipe(pipe_class_default); +%} + instruct vsrl16B_imm(vecX dst, vecX src, immI shift) %{ + predicate(n->as_Vector()->length() == 16); match(Set dst (URShiftVB src shift)); ins_cost(INSN_COST); format %{ "ushr $dst, $src, $shift\t# vector (16B)" %} @@ -13908,7 +14565,23 @@ ins_pipe(pipe_class_default); %} +instruct vsll4S(vecD dst, vecD src, vecX shift) %{ + predicate(n->as_Vector()->length() == 2 || + n->as_Vector()->length() == 4); + match(Set dst (LShiftVS src shift)); + match(Set dst (RShiftVS src shift)); + ins_cost(INSN_COST); + format %{ "sshl $dst,$src,$shift\t# vector (4H)" %} + ins_encode %{ + __ sshl(as_FloatRegister($dst$$reg), __ T4H, + as_FloatRegister($src$$reg), + as_FloatRegister($shift$$reg)); + %} + ins_pipe(pipe_class_default); +%} + instruct vsll8S(vecX dst, vecX src, vecX shift) %{ + predicate(n->as_Vector()->length() == 8); match(Set dst (LShiftVS src shift)); match(Set dst (RShiftVS src shift)); ins_cost(INSN_COST); @@ -13921,7 +14594,22 @@ ins_pipe(pipe_class_default); %} +instruct vsrl4S(vecD dst, vecD src, vecX shift) %{ + predicate(n->as_Vector()->length() == 2 || + n->as_Vector()->length() == 4); + match(Set dst (URShiftVS src shift)); + ins_cost(INSN_COST); + format %{ "ushl $dst,$src,$shift\t# vector (4H)" %} + ins_encode %{ + __ ushl(as_FloatRegister($dst$$reg), __ T4H, + as_FloatRegister($src$$reg), + as_FloatRegister($shift$$reg)); + %} + ins_pipe(pipe_class_default); +%} + instruct vsrl8S(vecX dst, vecX src, vecX shift) %{ + predicate(n->as_Vector()->length() == 8); match(Set dst (URShiftVS src shift)); ins_cost(INSN_COST); format %{ "ushl $dst,$src,$shift\t# vector (8H)" %} @@ -13933,7 +14621,28 @@ ins_pipe(pipe_class_default); %} +instruct vsll4S_imm(vecD dst, vecD src, immI shift) %{ + predicate(n->as_Vector()->length() == 2 || + n->as_Vector()->length() == 4); + match(Set dst (LShiftVS src shift)); + ins_cost(INSN_COST); + format %{ "shl $dst, $src, $shift\t# vector (4H)" %} + ins_encode %{ + int sh = (int)$shift$$constant & 31; + if (sh >= 16) { + __ eor(as_FloatRegister($dst$$reg), __ T8B, + as_FloatRegister($src$$reg), + as_FloatRegister($src$$reg)); + } else { + __ shl(as_FloatRegister($dst$$reg), __ T4H, + as_FloatRegister($src$$reg), sh); + } + %} + ins_pipe(pipe_class_default); +%} + instruct vsll8S_imm(vecX dst, vecX src, immI shift) %{ + predicate(n->as_Vector()->length() == 8); match(Set dst (LShiftVS src shift)); ins_cost(INSN_COST); format %{ "shl $dst, $src, $shift\t# vector (8H)" %} @@ -13951,7 +14660,24 @@ ins_pipe(pipe_class_default); %} +instruct vsra4S_imm(vecD dst, vecD src, immI shift) %{ + predicate(n->as_Vector()->length() == 2 || + n->as_Vector()->length() == 4); + match(Set dst (RShiftVS src shift)); + ins_cost(INSN_COST); + format %{ "sshr $dst, $src, $shift\t# vector (4H)" %} + ins_encode %{ + int sh = (int)$shift$$constant & 31; + if (sh >= 16) sh = 15; + sh = -sh & 15; + __ sshr(as_FloatRegister($dst$$reg), __ T4H, + as_FloatRegister($src$$reg), sh); + %} + ins_pipe(pipe_class_default); +%} + instruct vsra8S_imm(vecX dst, vecX src, immI shift) %{ + predicate(n->as_Vector()->length() == 8); match(Set dst (RShiftVS src shift)); ins_cost(INSN_COST); format %{ "sshr $dst, $src, $shift\t# vector (8H)" %} @@ -13965,7 +14691,28 @@ ins_pipe(pipe_class_default); %} +instruct vsrl4S_imm(vecD dst, vecD src, immI shift) %{ + predicate(n->as_Vector()->length() == 2 || + n->as_Vector()->length() == 4); + match(Set dst (URShiftVS src shift)); + ins_cost(INSN_COST); + format %{ "ushr $dst, $src, $shift\t# vector (4H)" %} + ins_encode %{ + int sh = (int)$shift$$constant & 31; + if (sh >= 16) { + __ eor(as_FloatRegister($dst$$reg), __ T8B, + as_FloatRegister($src$$reg), + as_FloatRegister($src$$reg)); + } else { + __ ushr(as_FloatRegister($dst$$reg), __ T4H, + as_FloatRegister($src$$reg), -sh & 15); + } + %} + ins_pipe(pipe_class_default); +%} + instruct vsrl8S_imm(vecX dst, vecX src, immI shift) %{ + predicate(n->as_Vector()->length() == 8); match(Set dst (URShiftVS src shift)); ins_cost(INSN_COST); format %{ "ushr $dst, $src, $shift\t# vector (8H)" %} @@ -13983,7 +14730,22 @@ ins_pipe(pipe_class_default); %} +instruct vsll2I(vecD dst, vecD src, vecX shift) %{ + predicate(n->as_Vector()->length() == 2); + match(Set dst (LShiftVI src shift)); + match(Set dst (RShiftVI src shift)); + ins_cost(INSN_COST); + format %{ "sshl $dst,$src,$shift\t# vector (2S)" %} + ins_encode %{ + __ sshl(as_FloatRegister($dst$$reg), __ T2S, + as_FloatRegister($src$$reg), + as_FloatRegister($shift$$reg)); + %} + ins_pipe(pipe_class_default); +%} + instruct vsll4I(vecX dst, vecX src, vecX shift) %{ + predicate(n->as_Vector()->length() == 4); match(Set dst (LShiftVI src shift)); match(Set dst (RShiftVI src shift)); ins_cost(INSN_COST); @@ -13996,7 +14758,21 @@ ins_pipe(pipe_class_default); %} +instruct vsrl2I(vecD dst, vecD src, vecX shift) %{ + predicate(n->as_Vector()->length() == 2); + match(Set dst (URShiftVI src shift)); + ins_cost(INSN_COST); + format %{ "ushl $dst,$src,$shift\t# vector (2S)" %} + ins_encode %{ + __ ushl(as_FloatRegister($dst$$reg), __ T2S, + as_FloatRegister($src$$reg), + as_FloatRegister($shift$$reg)); + %} + ins_pipe(pipe_class_default); +%} + instruct vsrl4I(vecX dst, vecX src, vecX shift) %{ + predicate(n->as_Vector()->length() == 4); match(Set dst (URShiftVI src shift)); ins_cost(INSN_COST); format %{ "ushl $dst,$src,$shift\t# vector (4S)" %} @@ -14008,7 +14784,21 @@ ins_pipe(pipe_class_default); %} +instruct vsll2I_imm(vecD dst, vecD src, immI shift) %{ + predicate(n->as_Vector()->length() == 2); + match(Set dst (LShiftVI src shift)); + ins_cost(INSN_COST); + format %{ "shl $dst, $src, $shift\t# vector (2S)" %} + ins_encode %{ + __ shl(as_FloatRegister($dst$$reg), __ T2S, + as_FloatRegister($src$$reg), + (int)$shift$$constant & 31); + %} + ins_pipe(pipe_class_default); +%} + instruct vsll4I_imm(vecX dst, vecX src, immI shift) %{ + predicate(n->as_Vector()->length() == 4); match(Set dst (LShiftVI src shift)); ins_cost(INSN_COST); format %{ "shl $dst, $src, $shift\t# vector (4S)" %} @@ -14020,7 +14810,21 @@ ins_pipe(pipe_class_default); %} +instruct vsra2I_imm(vecD dst, vecD src, immI shift) %{ + predicate(n->as_Vector()->length() == 2); + match(Set dst (RShiftVI src shift)); + ins_cost(INSN_COST); + format %{ "sshr $dst, $src, $shift\t# vector (2S)" %} + ins_encode %{ + __ sshr(as_FloatRegister($dst$$reg), __ T2S, + as_FloatRegister($src$$reg), + -(int)$shift$$constant & 31); + %} + ins_pipe(pipe_class_default); +%} + instruct vsra4I_imm(vecX dst, vecX src, immI shift) %{ + predicate(n->as_Vector()->length() == 4); match(Set dst (RShiftVI src shift)); ins_cost(INSN_COST); format %{ "sshr $dst, $src, $shift\t# vector (4S)" %} @@ -14032,7 +14836,21 @@ ins_pipe(pipe_class_default); %} +instruct vsrl2I_imm(vecD dst, vecD src, immI shift) %{ + predicate(n->as_Vector()->length() == 2); + match(Set dst (URShiftVI src shift)); + ins_cost(INSN_COST); + format %{ "ushr $dst, $src, $shift\t# vector (2S)" %} + ins_encode %{ + __ ushr(as_FloatRegister($dst$$reg), __ T2S, + as_FloatRegister($src$$reg), + -(int)$shift$$constant & 31); + %} + ins_pipe(pipe_class_default); +%} + instruct vsrl4I_imm(vecX dst, vecX src, immI shift) %{ + predicate(n->as_Vector()->length() == 4); match(Set dst (URShiftVI src shift)); ins_cost(INSN_COST); format %{ "ushr $dst, $src, $shift\t# vector (4S)" %} @@ -14045,6 +14863,7 @@ %} instruct vsll2L(vecX dst, vecX src, vecX shift) %{ + predicate(n->as_Vector()->length() == 2); match(Set dst (LShiftVL src shift)); match(Set dst (RShiftVL src shift)); ins_cost(INSN_COST); @@ -14058,6 +14877,7 @@ %} instruct vsrl2L(vecX dst, vecX src, vecX shift) %{ + predicate(n->as_Vector()->length() == 2); match(Set dst (URShiftVL src shift)); ins_cost(INSN_COST); format %{ "ushl $dst,$src,$shift\t# vector (2D)" %} @@ -14070,6 +14890,7 @@ %} instruct vsll2L_imm(vecX dst, vecX src, immI shift) %{ + predicate(n->as_Vector()->length() == 2); match(Set dst (LShiftVL src shift)); ins_cost(INSN_COST); format %{ "shl $dst, $src, $shift\t# vector (2D)" %} @@ -14082,6 +14903,7 @@ %} instruct vsra2L_imm(vecX dst, vecX src, immI shift) %{ + predicate(n->as_Vector()->length() == 2); match(Set dst (RShiftVL src shift)); ins_cost(INSN_COST); format %{ "sshr $dst, $src, $shift\t# vector (2D)" %} @@ -14094,6 +14916,7 @@ %} instruct vsrl2L_imm(vecX dst, vecX src, immI shift) %{ + predicate(n->as_Vector()->length() == 2); match(Set dst (URShiftVL src shift)); ins_cost(INSN_COST); format %{ "ushr $dst, $src, $shift\t# vector (2D)" %} diff -r 8fc82d01db26 -r 8d8f66194222 hotspot/src/cpu/aarch64/vm/assembler_aarch64.hpp --- a/hotspot/src/cpu/aarch64/vm/assembler_aarch64.hpp Thu Jul 09 16:37:55 2015 -0700 +++ b/hotspot/src/cpu/aarch64/vm/assembler_aarch64.hpp Wed Jul 05 20:41:09 2017 +0200 @@ -2055,6 +2055,9 @@ INSN(negr, 1, 0b100000101110); INSN(notr, 1, 0b100000010110); INSN(addv, 0, 0b110001101110); + INSN(cls, 0, 0b100000010010); + INSN(clz, 1, 0b100000010010); + INSN(cnt, 0, 0b100000010110); #undef INSN diff -r 8fc82d01db26 -r 8d8f66194222 hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.hpp --- a/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.hpp Thu Jul 09 16:37:55 2015 -0700 +++ b/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.hpp Wed Jul 05 20:41:09 2017 +0200 @@ -36,6 +36,7 @@ class MacroAssembler: public Assembler { friend class LIR_Assembler; + public: using Assembler::mov; using Assembler::movi; diff -r 8fc82d01db26 -r 8d8f66194222 hotspot/src/cpu/aarch64/vm/vm_version_aarch64.cpp --- a/hotspot/src/cpu/aarch64/vm/vm_version_aarch64.cpp Thu Jul 09 16:37:55 2015 -0700 +++ b/hotspot/src/cpu/aarch64/vm/vm_version_aarch64.cpp Wed Jul 05 20:41:09 2017 +0200 @@ -199,6 +199,12 @@ UseCRC32Intrinsics = true; } + if (UseCRC32CIntrinsics) { + if (!FLAG_IS_DEFAULT(UseCRC32CIntrinsics)) + warning("CRC32C intrinsics are not available on this CPU"); + FLAG_SET_DEFAULT(UseCRC32CIntrinsics, false); + } + if (auxv & (HWCAP_SHA1 | HWCAP_SHA2)) { if (FLAG_IS_DEFAULT(UseSHA)) { FLAG_SET_DEFAULT(UseSHA, true); @@ -251,6 +257,10 @@ UseBarriersForVolatile = (_cpuFeatures & CPU_DMB_ATOMICS) != 0; } + if (FLAG_IS_DEFAULT(UsePopCountInstruction)) { + UsePopCountInstruction = true; + } + #ifdef COMPILER2 if (FLAG_IS_DEFAULT(OptoScheduling)) { OptoScheduling = true; diff -r 8fc82d01db26 -r 8d8f66194222 hotspot/src/cpu/ppc/vm/vm_version_ppc.cpp --- a/hotspot/src/cpu/ppc/vm/vm_version_ppc.cpp Thu Jul 09 16:37:55 2015 -0700 +++ b/hotspot/src/cpu/ppc/vm/vm_version_ppc.cpp Wed Jul 05 20:41:09 2017 +0200 @@ -191,6 +191,13 @@ FLAG_SET_DEFAULT(UseSHA256Intrinsics, false); FLAG_SET_DEFAULT(UseSHA512Intrinsics, false); } + + if (UseCRC32CIntrinsics) { + if (!FLAG_IS_DEFAULT(UseCRC32CIntrinsics)) + warning("CRC32C intrinsics are not available on this CPU"); + FLAG_SET_DEFAULT(UseCRC32CIntrinsics, false); + } + // Adjust RTM (Restricted Transactional Memory) flags. if (!has_tcheck() && UseRTMLocking) { // Can't continue because UseRTMLocking affects UseBiasedLocking flag diff -r 8fc82d01db26 -r 8d8f66194222 hotspot/src/cpu/sparc/vm/assembler_sparc.hpp --- a/hotspot/src/cpu/sparc/vm/assembler_sparc.hpp Thu Jul 09 16:37:55 2015 -0700 +++ b/hotspot/src/cpu/sparc/vm/assembler_sparc.hpp Wed Jul 05 20:41:09 2017 +0200 @@ -128,8 +128,11 @@ faligndata_op3 = 0x36, flog3_op3 = 0x36, edge_op3 = 0x36, + fzero_op3 = 0x36, fsrc_op3 = 0x36, + fnot_op3 = 0x36, xmulx_op3 = 0x36, + crc32c_op3 = 0x36, impdep2_op3 = 0x37, stpartialf_op3 = 0x37, jmpl_op3 = 0x38, @@ -231,7 +234,9 @@ sha1_opf = 0x141, sha256_opf = 0x142, - sha512_opf = 0x143 + sha512_opf = 0x143, + + crc32c_opf = 0x147 }; enum op5s { @@ -600,6 +605,11 @@ return x & ((1 << 10) - 1); } + // create a low12 __value__ (not a field) for a given a 32-bit constant + static int low12( int x ) { + return x & ((1 << 12) - 1); + } + // AES crypto instructions supported only on certain processors static void aes_only() { assert( VM_Version::has_aes(), "This instruction only works on SPARC with AES instructions support"); } @@ -608,6 +618,9 @@ static void sha256_only() { assert( VM_Version::has_sha256(), "This instruction only works on SPARC with SHA256"); } static void sha512_only() { assert( VM_Version::has_sha512(), "This instruction only works on SPARC with SHA512"); } + // CRC32C instruction supported only on certain processors + static void crc32c_only() { assert( VM_Version::has_crc32c(), "This instruction only works on SPARC with CRC32C"); } + // instruction only in VIS1 static void vis1_only() { assert( VM_Version::has_vis1(), "This instruction only works on SPARC with VIS1"); } @@ -1022,6 +1035,7 @@ void nop() { emit_int32( op(branch_op) | op2(sethi_op2) ); } + void sw_count() { emit_int32( op(branch_op) | op2(sethi_op2) | 0x3f0 ); } // pp 202 @@ -1198,8 +1212,14 @@ void faligndata( FloatRegister s1, FloatRegister s2, FloatRegister d ) { vis1_only(); emit_int32( op(arith_op) | fd(d, FloatRegisterImpl::D) | op3(faligndata_op3) | fs1(s1, FloatRegisterImpl::D) | opf(faligndata_opf) | fs2(s2, FloatRegisterImpl::D)); } + void fzero( FloatRegisterImpl::Width w, FloatRegister d ) { vis1_only(); emit_int32( op(arith_op) | fd(d, w) | op3(fzero_op3) | opf(0x62 - w)); } + void fsrc2( FloatRegisterImpl::Width w, FloatRegister s2, FloatRegister d ) { vis1_only(); emit_int32( op(arith_op) | fd(d, w) | op3(fsrc_op3) | opf(0x7A - w) | fs2(s2, w)); } + void fnot1( FloatRegisterImpl::Width w, FloatRegister s1, FloatRegister d ) { vis1_only(); emit_int32( op(arith_op) | fd(d, w) | op3(fnot_op3) | fs1(s1, w) | opf(0x6C - w)); } + + void fpmerge( FloatRegister s1, FloatRegister s2, FloatRegister d ) { vis1_only(); emit_int32( op(arith_op) | fd(d, FloatRegisterImpl::D) | op3(0x36) | fs1(s1, FloatRegisterImpl::S) | opf(0x4b) | fs2(s2, FloatRegisterImpl::S)); } + void stpartialf( Register s1, Register s2, FloatRegister d, int ia = -1 ) { vis1_only(); emit_int32( op(ldst_op) | fd(d, FloatRegisterImpl::D) | op3(stpartialf_op3) | rs1(s1) | imm_asi(ia) | rs2(s2)); } // VIS2 instructions @@ -1224,6 +1244,10 @@ void sha256() { sha256_only(); emit_int32( op(arith_op) | op3(sha_op3) | opf(sha256_opf)); } void sha512() { sha512_only(); emit_int32( op(arith_op) | op3(sha_op3) | opf(sha512_opf)); } + // CRC32C instruction + + void crc32c( FloatRegister s1, FloatRegister s2, FloatRegister d ) { crc32c_only(); emit_int32( op(arith_op) | fd(d, FloatRegisterImpl::D) | op3(crc32c_op3) | fs1(s1, FloatRegisterImpl::D) | opf(crc32c_opf) | fs2(s2, FloatRegisterImpl::D)); } + // Creation Assembler(CodeBuffer* code) : AbstractAssembler(code) { #ifdef CHECK_DELAY diff -r 8fc82d01db26 -r 8d8f66194222 hotspot/src/cpu/sparc/vm/macroAssembler_sparc.cpp --- a/hotspot/src/cpu/sparc/vm/macroAssembler_sparc.cpp Thu Jul 09 16:37:55 2015 -0700 +++ b/hotspot/src/cpu/sparc/vm/macroAssembler_sparc.cpp Wed Jul 05 20:41:09 2017 +0200 @@ -956,6 +956,7 @@ int hi = (int)(value >> 32); int lo = (int)(value & ~0); + int bits_33to2 = (int)((value >> 2) & ~0); // (Matcher::isSimpleConstant64 knows about the following optimizations.) if (Assembler::is_simm13(lo) && value == lo) { or3(G0, lo, d); @@ -964,6 +965,12 @@ if (low10(lo) != 0) or3(d, low10(lo), d); } + else if ((hi >> 2) == 0) { + Assembler::sethi(bits_33to2, d); // hardware version zero-extends to upper 32 + sllx(d, 2, d); + if (low12(lo) != 0) + or3(d, low12(lo), d); + } else if (hi == -1) { Assembler::sethi(~lo, d); // hardware version zero-extends to upper 32 xor3(d, low10(lo) ^ ~low10(~0), d); @@ -4351,3 +4358,52 @@ cmp_and_brx_short(to, end, Assembler::lessUnsigned, Assembler::pt, small_loop); nop(); // Separate short branches } + +/** + * Update CRC-32[C] with a byte value according to constants in table + * + * @param [in,out]crc Register containing the crc. + * @param [in]val Register containing the byte to fold into the CRC. + * @param [in]table Register containing the table of crc constants. + * + * uint32_t crc; + * val = crc_table[(val ^ crc) & 0xFF]; + * crc = val ^ (crc >> 8); + */ +void MacroAssembler::update_byte_crc32(Register crc, Register val, Register table) { + xor3(val, crc, val); + and3(val, 0xFF, val); + sllx(val, 2, val); + lduw(table, val, val); + srlx(crc, 8, crc); + xor3(val, crc, crc); +} + +// Reverse byte order of lower 32 bits, assuming upper 32 bits all zeros +void MacroAssembler::reverse_bytes_32(Register src, Register dst, Register tmp) { + srlx(src, 24, dst); + + sllx(src, 32+8, tmp); + srlx(tmp, 32+24, tmp); + sllx(tmp, 8, tmp); + or3(dst, tmp, dst); + + sllx(src, 32+16, tmp); + srlx(tmp, 32+24, tmp); + sllx(tmp, 16, tmp); + or3(dst, tmp, dst); + + sllx(src, 32+24, tmp); + srlx(tmp, 32, tmp); + or3(dst, tmp, dst); +} + +void MacroAssembler::movitof_revbytes(Register src, FloatRegister dst, Register tmp1, Register tmp2) { + reverse_bytes_32(src, tmp1, tmp2); + movxtod(tmp1, dst); +} + +void MacroAssembler::movftoi_revbytes(FloatRegister src, Register dst, Register tmp1, Register tmp2) { + movdtox(src, tmp1); + reverse_bytes_32(tmp1, dst, tmp2); +} diff -r 8fc82d01db26 -r 8d8f66194222 hotspot/src/cpu/sparc/vm/macroAssembler_sparc.hpp --- a/hotspot/src/cpu/sparc/vm/macroAssembler_sparc.hpp Thu Jul 09 16:37:55 2015 -0700 +++ b/hotspot/src/cpu/sparc/vm/macroAssembler_sparc.hpp Wed Jul 05 20:41:09 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2015, 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 @@ -903,6 +903,10 @@ inline void ldf(FloatRegisterImpl::Width w, Register s1, RegisterOrConstant s2, FloatRegister d); inline void ldf(FloatRegisterImpl::Width w, const Address& a, FloatRegister d, int offset = 0); + // little-endian + inline void ldxl(Register s1, Register s2, Register d) { ldxa(s1, s2, ASI_PRIMARY_LITTLE, d); } + inline void ldfl(FloatRegisterImpl::Width w, Register s1, Register s2, FloatRegister d) { ldfa(w, s1, s2, ASI_PRIMARY_LITTLE, d); } + // membar psuedo instruction. takes into account target memory model. inline void membar( Assembler::Membar_mask_bits const7a ); @@ -1436,6 +1440,14 @@ // Use BIS for zeroing void bis_zeroing(Register to, Register count, Register temp, Label& Ldone); + // Update CRC-32[C] with a byte value according to constants in table + void update_byte_crc32(Register crc, Register val, Register table); + + // Reverse byte order of lower 32 bits, assuming upper 32 bits all zeros + void reverse_bytes_32(Register src, Register dst, Register tmp); + void movitof_revbytes(Register src, FloatRegister dst, Register tmp1, Register tmp2); + void movftoi_revbytes(FloatRegister src, Register dst, Register tmp1, Register tmp2); + #undef VIRTUAL }; diff -r 8fc82d01db26 -r 8d8f66194222 hotspot/src/cpu/sparc/vm/stubGenerator_sparc.cpp --- a/hotspot/src/cpu/sparc/vm/stubGenerator_sparc.cpp Thu Jul 09 16:37:55 2015 -0700 +++ b/hotspot/src/cpu/sparc/vm/stubGenerator_sparc.cpp Wed Jul 05 20:41:09 2017 +0200 @@ -4910,6 +4910,206 @@ return start; } +#define CHUNK_LEN 128 /* 128 x 8B = 1KB */ +#define CHUNK_K1 0x1307a0206 /* reverseBits(pow(x, CHUNK_LEN*8*8*3 - 32) mod P(x)) << 1 */ +#define CHUNK_K2 0x1a0f717c4 /* reverseBits(pow(x, CHUNK_LEN*8*8*2 - 32) mod P(x)) << 1 */ +#define CHUNK_K3 0x0170076fa /* reverseBits(pow(x, CHUNK_LEN*8*8*1 - 32) mod P(x)) << 1 */ + + /** + * Arguments: + * + * Inputs: + * O0 - int crc + * O1 - byte* buf + * O2 - int len + * O3 - int* table + * + * Output: + * O0 - int crc result + */ + address generate_updateBytesCRC32C() { + assert(UseCRC32CIntrinsics, "need CRC32C instruction"); + + __ align(CodeEntryAlignment); + StubCodeMark mark(this, "StubRoutines", "updateBytesCRC32C"); + address start = __ pc(); + + const Register crc = O0; // crc + const Register buf = O1; // source java byte array address + const Register len = O2; // number of bytes + const Register table = O3; // byteTable + + Label L_crc32c_head, L_crc32c_aligned; + Label L_crc32c_parallel, L_crc32c_parallel_loop; + Label L_crc32c_serial, L_crc32c_x32_loop, L_crc32c_x8, L_crc32c_x8_loop; + Label L_crc32c_done, L_crc32c_tail, L_crc32c_return; + + __ cmp_and_br_short(len, 0, Assembler::lessEqual, Assembler::pn, L_crc32c_return); + + // clear upper 32 bits of crc + __ clruwu(crc); + + __ and3(buf, 7, G4); + __ cmp_and_brx_short(G4, 0, Assembler::equal, Assembler::pt, L_crc32c_aligned); + + __ mov(8, G1); + __ sub(G1, G4, G4); + + // ------ process the misaligned head (7 bytes or less) ------ + __ BIND(L_crc32c_head); + + // crc = (crc >>> 8) ^ byteTable[(crc ^ b) & 0xFF]; + __ ldub(buf, 0, G1); + __ update_byte_crc32(crc, G1, table); + + __ inc(buf); + __ dec(len); + __ cmp_and_br_short(len, 0, Assembler::equal, Assembler::pn, L_crc32c_return); + __ dec(G4); + __ cmp_and_br_short(G4, 0, Assembler::greater, Assembler::pt, L_crc32c_head); + + // ------ process the 8-byte-aligned body ------ + __ BIND(L_crc32c_aligned); + __ nop(); + __ cmp_and_br_short(len, 8, Assembler::less, Assembler::pn, L_crc32c_tail); + + // reverse the byte order of lower 32 bits to big endian, and move to FP side + __ movitof_revbytes(crc, F0, G1, G3); + + __ set(CHUNK_LEN*8*4, G4); + __ cmp_and_br_short(len, G4, Assembler::less, Assembler::pt, L_crc32c_serial); + + // ------ process four 1KB chunks in parallel ------ + __ BIND(L_crc32c_parallel); + + __ fzero(FloatRegisterImpl::D, F2); + __ fzero(FloatRegisterImpl::D, F4); + __ fzero(FloatRegisterImpl::D, F6); + + __ mov(CHUNK_LEN - 1, G4); + __ BIND(L_crc32c_parallel_loop); + // schedule ldf's ahead of crc32c's to hide the load-use latency + __ ldf(FloatRegisterImpl::D, buf, 0, F8); + __ ldf(FloatRegisterImpl::D, buf, CHUNK_LEN*8, F10); + __ ldf(FloatRegisterImpl::D, buf, CHUNK_LEN*16, F12); + __ ldf(FloatRegisterImpl::D, buf, CHUNK_LEN*24, F14); + __ crc32c(F0, F8, F0); + __ crc32c(F2, F10, F2); + __ crc32c(F4, F12, F4); + __ crc32c(F6, F14, F6); + __ inc(buf, 8); + __ dec(G4); + __ cmp_and_br_short(G4, 0, Assembler::greater, Assembler::pt, L_crc32c_parallel_loop); + + __ ldf(FloatRegisterImpl::D, buf, 0, F8); + __ ldf(FloatRegisterImpl::D, buf, CHUNK_LEN*8, F10); + __ ldf(FloatRegisterImpl::D, buf, CHUNK_LEN*16, F12); + __ crc32c(F0, F8, F0); + __ crc32c(F2, F10, F2); + __ crc32c(F4, F12, F4); + + __ inc(buf, CHUNK_LEN*24); + __ ldfl(FloatRegisterImpl::D, buf, G0, F14); // load in little endian + __ inc(buf, 8); + + __ prefetch(buf, 0, Assembler::severalReads); + __ prefetch(buf, CHUNK_LEN*8, Assembler::severalReads); + __ prefetch(buf, CHUNK_LEN*16, Assembler::severalReads); + __ prefetch(buf, CHUNK_LEN*24, Assembler::severalReads); + + // move to INT side, and reverse the byte order of lower 32 bits to little endian + __ movftoi_revbytes(F0, O4, G1, G4); + __ movftoi_revbytes(F2, O5, G1, G4); + __ movftoi_revbytes(F4, G5, G1, G4); + + // combine the results of 4 chunks + __ set64(CHUNK_K1, G3, G1); + __ xmulx(O4, G3, O4); + __ set64(CHUNK_K2, G3, G1); + __ xmulx(O5, G3, O5); + __ set64(CHUNK_K3, G3, G1); + __ xmulx(G5, G3, G5); + + __ movdtox(F14, G4); + __ xor3(O4, O5, O5); + __ xor3(G5, O5, O5); + __ xor3(G4, O5, O5); + + // reverse the byte order to big endian, via stack, and move to FP side + __ add(SP, -8, G1); + __ srlx(G1, 3, G1); + __ sllx(G1, 3, G1); + __ stx(O5, G1, G0); + __ ldfl(FloatRegisterImpl::D, G1, G0, F2); // load in little endian + + __ crc32c(F6, F2, F0); + + __ set(CHUNK_LEN*8*4, G4); + __ sub(len, G4, len); + __ cmp_and_br_short(len, G4, Assembler::greaterEqual, Assembler::pt, L_crc32c_parallel); + __ nop(); + __ cmp_and_br_short(len, 0, Assembler::equal, Assembler::pt, L_crc32c_done); + + __ BIND(L_crc32c_serial); + + __ mov(32, G4); + __ cmp_and_br_short(len, G4, Assembler::less, Assembler::pn, L_crc32c_x8); + + // ------ process 32B chunks ------ + __ BIND(L_crc32c_x32_loop); + __ ldf(FloatRegisterImpl::D, buf, 0, F2); + __ inc(buf, 8); + __ crc32c(F0, F2, F0); + __ ldf(FloatRegisterImpl::D, buf, 0, F2); + __ inc(buf, 8); + __ crc32c(F0, F2, F0); + __ ldf(FloatRegisterImpl::D, buf, 0, F2); + __ inc(buf, 8); + __ crc32c(F0, F2, F0); + __ ldf(FloatRegisterImpl::D, buf, 0, F2); + __ inc(buf, 8); + __ crc32c(F0, F2, F0); + __ dec(len, 32); + __ cmp_and_br_short(len, G4, Assembler::greaterEqual, Assembler::pt, L_crc32c_x32_loop); + + __ BIND(L_crc32c_x8); + __ nop(); + __ cmp_and_br_short(len, 8, Assembler::less, Assembler::pt, L_crc32c_done); + + // ------ process 8B chunks ------ + __ BIND(L_crc32c_x8_loop); + __ ldf(FloatRegisterImpl::D, buf, 0, F2); + __ inc(buf, 8); + __ crc32c(F0, F2, F0); + __ dec(len, 8); + __ cmp_and_br_short(len, 8, Assembler::greaterEqual, Assembler::pt, L_crc32c_x8_loop); + + __ BIND(L_crc32c_done); + + // move to INT side, and reverse the byte order of lower 32 bits to little endian + __ movftoi_revbytes(F0, crc, G1, G3); + + __ cmp_and_br_short(len, 0, Assembler::equal, Assembler::pt, L_crc32c_return); + + // ------ process the misaligned tail (7 bytes or less) ------ + __ BIND(L_crc32c_tail); + + // crc = (crc >>> 8) ^ byteTable[(crc ^ b) & 0xFF]; + __ ldub(buf, 0, G1); + __ update_byte_crc32(crc, G1, table); + + __ inc(buf); + __ dec(len); + __ cmp_and_br_short(len, 0, Assembler::greater, Assembler::pt, L_crc32c_tail); + + __ BIND(L_crc32c_return); + __ nop(); + __ retl(); + __ delayed()->nop(); + + return start; + } + void generate_initial() { // Generates all stubs and initializes the entry points @@ -5001,6 +5201,11 @@ StubRoutines::_sha512_implCompress = generate_sha512_implCompress(false, "sha512_implCompress"); StubRoutines::_sha512_implCompressMB = generate_sha512_implCompress(true, "sha512_implCompressMB"); } + + // generate CRC32C intrinsic code + if (UseCRC32CIntrinsics) { + StubRoutines::_updateBytesCRC32C = generate_updateBytesCRC32C(); + } } diff -r 8fc82d01db26 -r 8d8f66194222 hotspot/src/cpu/sparc/vm/stubRoutines_sparc.hpp --- a/hotspot/src/cpu/sparc/vm/stubRoutines_sparc.hpp Thu Jul 09 16:37:55 2015 -0700 +++ b/hotspot/src/cpu/sparc/vm/stubRoutines_sparc.hpp Wed Jul 05 20:41:09 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2015, 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 @@ -41,7 +41,7 @@ enum /* platform_dependent_constants */ { // %%%%%%%% May be able to shrink this a lot code_size1 = 20000, // simply increase if too small (assembler will crash if too small) - code_size2 = 23000 // simply increase if too small (assembler will crash if too small) + code_size2 = 24000 // simply increase if too small (assembler will crash if too small) }; class Sparc { diff -r 8fc82d01db26 -r 8d8f66194222 hotspot/src/cpu/sparc/vm/vm_version_sparc.cpp --- a/hotspot/src/cpu/sparc/vm/vm_version_sparc.cpp Thu Jul 09 16:37:55 2015 -0700 +++ b/hotspot/src/cpu/sparc/vm/vm_version_sparc.cpp Wed Jul 05 20:41:09 2017 +0200 @@ -230,7 +230,7 @@ assert((OptoLoopAlignment % relocInfo::addr_unit()) == 0, "alignment is not a multiple of NOP size"); char buf[512]; - jio_snprintf(buf, sizeof(buf), "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s", + jio_snprintf(buf, sizeof(buf), "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s", (has_v9() ? ", v9" : (has_v8() ? ", v8" : "")), (has_hardware_popc() ? ", popc" : ""), (has_vis1() ? ", vis1" : ""), @@ -242,6 +242,7 @@ (has_sha1() ? ", sha1" : ""), (has_sha256() ? ", sha256" : ""), (has_sha512() ? ", sha512" : ""), + (has_crc32c() ? ", crc32c" : ""), (is_ultra3() ? ", ultra3" : ""), (is_sun4v() ? ", sun4v" : ""), (is_niagara_plus() ? ", niagara_plus" : (is_niagara() ? ", niagara" : "")), @@ -363,6 +364,23 @@ } } + // SPARC T4 and above should have support for CRC32C instruction + if (has_crc32c()) { + if (UseVIS > 2) { // CRC32C intrinsics use VIS3 instructions + if (FLAG_IS_DEFAULT(UseCRC32CIntrinsics)) { + FLAG_SET_DEFAULT(UseCRC32CIntrinsics, true); + } + } else { + if (UseCRC32CIntrinsics) { + warning("SPARC CRC32C intrinsics require VIS3 instruction support. Intrinsics will be disabled."); + FLAG_SET_DEFAULT(UseCRC32CIntrinsics, false); + } + } + } else if (UseCRC32CIntrinsics) { + warning("CRC32C instruction is not available on this CPU"); + FLAG_SET_DEFAULT(UseCRC32CIntrinsics, false); + } + if (FLAG_IS_DEFAULT(ContendedPaddingWidth) && (cache_line_size > ContendedPaddingWidth)) ContendedPaddingWidth = cache_line_size; diff -r 8fc82d01db26 -r 8d8f66194222 hotspot/src/cpu/sparc/vm/vm_version_sparc.hpp --- a/hotspot/src/cpu/sparc/vm/vm_version_sparc.hpp Thu Jul 09 16:37:55 2015 -0700 +++ b/hotspot/src/cpu/sparc/vm/vm_version_sparc.hpp Wed Jul 05 20:41:09 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2015, 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 @@ -53,7 +53,8 @@ aes_instructions = 19, sha1_instruction = 20, sha256_instruction = 21, - sha512_instruction = 22 + sha512_instruction = 22, + crc32c_instruction = 23 }; enum Feature_Flag_Set { @@ -83,6 +84,7 @@ sha1_instruction_m = 1 << sha1_instruction, sha256_instruction_m = 1 << sha256_instruction, sha512_instruction_m = 1 << sha512_instruction, + crc32c_instruction_m = 1 << crc32c_instruction, generic_v8_m = v8_instructions_m | hardware_mul32_m | hardware_div32_m | hardware_fsmuld_m, generic_v9_m = generic_v8_m | v9_instructions_m, @@ -141,6 +143,7 @@ static bool has_sha1() { return (_features & sha1_instruction_m) != 0; } static bool has_sha256() { return (_features & sha256_instruction_m) != 0; } static bool has_sha512() { return (_features & sha512_instruction_m) != 0; } + static bool has_crc32c() { return (_features & crc32c_instruction_m) != 0; } static bool supports_compare_and_exchange() { return has_v9(); } diff -r 8fc82d01db26 -r 8d8f66194222 hotspot/src/cpu/x86/vm/vm_version_x86.cpp --- a/hotspot/src/cpu/x86/vm/vm_version_x86.cpp Thu Jul 09 16:37:55 2015 -0700 +++ b/hotspot/src/cpu/x86/vm/vm_version_x86.cpp Wed Jul 05 20:41:09 2017 +0200 @@ -699,6 +699,12 @@ FLAG_SET_DEFAULT(UseSHA512Intrinsics, false); } + if (UseCRC32CIntrinsics) { + if (!FLAG_IS_DEFAULT(UseCRC32CIntrinsics)) + warning("CRC32C intrinsics are not available on this CPU"); + FLAG_SET_DEFAULT(UseCRC32CIntrinsics, false); + } + // Adjust RTM (Restricted Transactional Memory) flags if (!supports_rtm() && UseRTMLocking) { // Can't continue because UseRTMLocking affects UseBiasedLocking flag diff -r 8fc82d01db26 -r 8d8f66194222 hotspot/src/os_cpu/solaris_sparc/vm/vm_version_solaris_sparc.cpp --- a/hotspot/src/os_cpu/solaris_sparc/vm/vm_version_solaris_sparc.cpp Thu Jul 09 16:37:55 2015 -0700 +++ b/hotspot/src/os_cpu/solaris_sparc/vm/vm_version_solaris_sparc.cpp Wed Jul 05 20:41:09 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2006, 2015, 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 @@ -363,6 +363,11 @@ #endif if (av & AV_SPARC_CBCOND) features |= cbcond_instructions_m; +#ifndef AV_SPARC_CRC32C +#define AV_SPARC_CRC32C 0x20000000 /* crc32c instruction supported */ +#endif + if (av & AV_SPARC_CRC32C) features |= crc32c_instruction_m; + #ifndef AV_SPARC_AES #define AV_SPARC_AES 0x00020000 /* aes instrs supported */ #endif diff -r 8fc82d01db26 -r 8d8f66194222 hotspot/src/share/vm/ci/ciField.cpp --- a/hotspot/src/share/vm/ci/ciField.cpp Thu Jul 09 16:37:55 2015 -0700 +++ b/hotspot/src/share/vm/ci/ciField.cpp Wed Jul 05 20:41:09 2017 +0200 @@ -186,6 +186,10 @@ // Even if general trusting is disabled, trust system-built closures in these packages. if (holder->is_in_package("java/lang/invoke") || holder->is_in_package("sun/invoke")) return true; + // Trust VM anonymous classes. They are private API (sun.misc.Unsafe) and can't be serialized, + // so there is no hacking of finals going on with them. + if (holder->is_anonymous()) + return true; return TrustFinalNonStaticFields; } diff -r 8fc82d01db26 -r 8d8f66194222 hotspot/src/share/vm/ci/ciInstanceKlass.cpp --- a/hotspot/src/share/vm/ci/ciInstanceKlass.cpp Thu Jul 09 16:37:55 2015 -0700 +++ b/hotspot/src/share/vm/ci/ciInstanceKlass.cpp Wed Jul 05 20:41:09 2017 +0200 @@ -58,6 +58,7 @@ _nonstatic_field_size = ik->nonstatic_field_size(); _has_nonstatic_fields = ik->has_nonstatic_fields(); _has_default_methods = ik->has_default_methods(); + _is_anonymous = ik->is_anonymous(); _nonstatic_fields = NULL; // initialized lazily by compute_nonstatic_fields: _has_injected_fields = -1; _implementor = NULL; // we will fill these lazily @@ -101,6 +102,7 @@ _has_nonstatic_fields = false; _nonstatic_fields = NULL; _has_injected_fields = -1; + _is_anonymous = false; _loader = loader; _protection_domain = protection_domain; _is_shared = false; diff -r 8fc82d01db26 -r 8d8f66194222 hotspot/src/share/vm/ci/ciInstanceKlass.hpp --- a/hotspot/src/share/vm/ci/ciInstanceKlass.hpp Thu Jul 09 16:37:55 2015 -0700 +++ b/hotspot/src/share/vm/ci/ciInstanceKlass.hpp Wed Jul 05 20:41:09 2017 +0200 @@ -53,6 +53,7 @@ bool _has_subklass; bool _has_nonstatic_fields; bool _has_default_methods; + bool _is_anonymous; ciFlags _flags; jint _nonstatic_field_size; @@ -179,6 +180,10 @@ return _has_default_methods; } + bool is_anonymous() { + return _is_anonymous; + } + ciInstanceKlass* get_canonical_holder(int offset); ciField* get_field_by_offset(int field_offset, bool is_static); ciField* get_field_by_name(ciSymbol* name, ciSymbol* signature, bool is_static); diff -r 8fc82d01db26 -r 8d8f66194222 hotspot/src/share/vm/classfile/vmSymbols.hpp --- a/hotspot/src/share/vm/classfile/vmSymbols.hpp Thu Jul 09 16:37:55 2015 -0700 +++ b/hotspot/src/share/vm/classfile/vmSymbols.hpp Wed Jul 05 20:41:09 2017 +0200 @@ -863,6 +863,12 @@ do_name( updateByteBuffer_name, "updateByteBuffer") \ do_signature(updateByteBuffer_signature, "(IJII)I") \ \ + /* support for java.util.zip.CRC32C */ \ + do_class(java_util_zip_CRC32C, "java/util/zip/CRC32C") \ + do_intrinsic(_updateBytesCRC32C, java_util_zip_CRC32C, updateBytes_name, updateBytes_signature, F_S) \ + do_intrinsic(_updateDirectByteBufferCRC32C, java_util_zip_CRC32C, updateDirectByteBuffer_name, updateByteBuffer_signature, F_S) \ + do_name( updateDirectByteBuffer_name, "updateDirectByteBuffer") \ + \ /* support for sun.misc.Unsafe */ \ do_class(sun_misc_Unsafe, "sun/misc/Unsafe") \ \ diff -r 8fc82d01db26 -r 8d8f66194222 hotspot/src/share/vm/opto/escape.cpp --- a/hotspot/src/share/vm/opto/escape.cpp Thu Jul 09 16:37:55 2015 -0700 +++ b/hotspot/src/share/vm/opto/escape.cpp Wed Jul 05 20:41:09 2017 +0200 @@ -962,6 +962,7 @@ (strcmp(call->as_CallLeaf()->_name, "g1_wb_pre") == 0 || strcmp(call->as_CallLeaf()->_name, "g1_wb_post") == 0 || strcmp(call->as_CallLeaf()->_name, "updateBytesCRC32") == 0 || + strcmp(call->as_CallLeaf()->_name, "updateBytesCRC32C") == 0 || strcmp(call->as_CallLeaf()->_name, "aescrypt_encryptBlock") == 0 || strcmp(call->as_CallLeaf()->_name, "aescrypt_decryptBlock") == 0 || strcmp(call->as_CallLeaf()->_name, "cipherBlockChaining_encryptAESCrypt") == 0 || diff -r 8fc82d01db26 -r 8d8f66194222 hotspot/src/share/vm/opto/library_call.cpp --- a/hotspot/src/share/vm/opto/library_call.cpp Thu Jul 09 16:37:55 2015 -0700 +++ b/hotspot/src/share/vm/opto/library_call.cpp Wed Jul 05 20:41:09 2017 +0200 @@ -197,7 +197,7 @@ CallJavaNode* generate_method_call_virtual(vmIntrinsics::ID method_id) { return generate_method_call(method_id, true, false); } - Node * load_field_from_object(Node * fromObj, const char * fieldName, const char * fieldTypeString, bool is_exact, bool is_static); + Node * load_field_from_object(Node * fromObj, const char * fieldName, const char * fieldTypeString, bool is_exact, bool is_static, ciInstanceKlass * fromKls); Node* make_string_method_node(int opcode, Node* str1_start, Node* cnt1, Node* str2_start, Node* cnt2); Node* make_string_method_node(int opcode, Node* str1, Node* str2); @@ -291,6 +291,9 @@ bool inline_updateCRC32(); bool inline_updateBytesCRC32(); bool inline_updateByteBufferCRC32(); + Node* get_table_from_crc32c_class(ciInstanceKlass *crc32c_class); + bool inline_updateBytesCRC32C(); + bool inline_updateDirectByteBufferCRC32C(); bool inline_multiplyToLen(); bool inline_squareToLen(); bool inline_mulAdd(); @@ -539,6 +542,11 @@ if (!UseCRC32Intrinsics) return NULL; break; + case vmIntrinsics::_updateBytesCRC32C: + case vmIntrinsics::_updateDirectByteBufferCRC32C: + if (!UseCRC32CIntrinsics) return NULL; + break; + case vmIntrinsics::_incrementExactI: case vmIntrinsics::_addExactI: if (!Matcher::match_rule_supported(Op_OverflowAddI) || !UseMathExactIntrinsics) return NULL; @@ -947,6 +955,11 @@ case vmIntrinsics::_updateByteBufferCRC32: return inline_updateByteBufferCRC32(); + case vmIntrinsics::_updateBytesCRC32C: + return inline_updateBytesCRC32C(); + case vmIntrinsics::_updateDirectByteBufferCRC32C: + return inline_updateDirectByteBufferCRC32C(); + case vmIntrinsics::_profileBoolean: return inline_profileBoolean(); case vmIntrinsics::_isCompileConstant: @@ -5536,6 +5549,106 @@ return true; } +//------------------------------get_table_from_crc32c_class----------------------- +Node * LibraryCallKit::get_table_from_crc32c_class(ciInstanceKlass *crc32c_class) { + Node* table = load_field_from_object(NULL, "byteTable", "[I", /*is_exact*/ false, /*is_static*/ true, crc32c_class); + assert (table != NULL, "wrong version of java.util.zip.CRC32C"); + + return table; +} + +//------------------------------inline_updateBytesCRC32C----------------------- +// +// Calculate CRC32C for byte[] array. +// int java.util.zip.CRC32C.updateBytes(int crc, byte[] buf, int off, int end) +// +bool LibraryCallKit::inline_updateBytesCRC32C() { + assert(UseCRC32CIntrinsics, "need CRC32C instruction support"); + assert(callee()->signature()->size() == 4, "updateBytes has 4 parameters"); + assert(callee()->holder()->is_loaded(), "CRC32C class must be loaded"); + // no receiver since it is a static method + Node* crc = argument(0); // type: int + Node* src = argument(1); // type: oop + Node* offset = argument(2); // type: int + Node* end = argument(3); // type: int + + Node* length = _gvn.transform(new SubINode(end, offset)); + + const Type* src_type = src->Value(&_gvn); + const TypeAryPtr* top_src = src_type->isa_aryptr(); + if (top_src == NULL || top_src->klass() == NULL) { + // failed array check + return false; + } + + // Figure out the size and type of the elements we will be copying. + BasicType src_elem = src_type->isa_aryptr()->klass()->as_array_klass()->element_type()->basic_type(); + if (src_elem != T_BYTE) { + return false; + } + + // 'src_start' points to src array + scaled offset + Node* src_start = array_element_address(src, offset, src_elem); + + // static final int[] byteTable in class CRC32C + Node* table = get_table_from_crc32c_class(callee()->holder()); + Node* table_start = array_element_address(table, intcon(0), T_INT); + + // We assume that range check is done by caller. + // TODO: generate range check (offset+length < src.length) in debug VM. + + // Call the stub. + address stubAddr = StubRoutines::updateBytesCRC32C(); + const char *stubName = "updateBytesCRC32C"; + + Node* call = make_runtime_call(RC_LEAF, OptoRuntime::updateBytesCRC32C_Type(), + stubAddr, stubName, TypePtr::BOTTOM, + crc, src_start, length, table_start); + Node* result = _gvn.transform(new ProjNode(call, TypeFunc::Parms)); + set_result(result); + return true; +} + +//------------------------------inline_updateDirectByteBufferCRC32C----------------------- +// +// Calculate CRC32C for DirectByteBuffer. +// int java.util.zip.CRC32C.updateDirectByteBuffer(int crc, long buf, int off, int end) +// +bool LibraryCallKit::inline_updateDirectByteBufferCRC32C() { + assert(UseCRC32CIntrinsics, "need CRC32C instruction support"); + assert(callee()->signature()->size() == 5, "updateDirectByteBuffer has 4 parameters and one is long"); + assert(callee()->holder()->is_loaded(), "CRC32C class must be loaded"); + // no receiver since it is a static method + Node* crc = argument(0); // type: int + Node* src = argument(1); // type: long + Node* offset = argument(3); // type: int + Node* end = argument(4); // type: int + + Node* length = _gvn.transform(new SubINode(end, offset)); + + src = ConvL2X(src); // adjust Java long to machine word + Node* base = _gvn.transform(new CastX2PNode(src)); + offset = ConvI2X(offset); + + // 'src_start' points to src array + scaled offset + Node* src_start = basic_plus_adr(top(), base, offset); + + // static final int[] byteTable in class CRC32C + Node* table = get_table_from_crc32c_class(callee()->holder()); + Node* table_start = array_element_address(table, intcon(0), T_INT); + + // Call the stub. + address stubAddr = StubRoutines::updateBytesCRC32C(); + const char *stubName = "updateBytesCRC32C"; + + Node* call = make_runtime_call(RC_LEAF, OptoRuntime::updateBytesCRC32C_Type(), + stubAddr, stubName, TypePtr::BOTTOM, + crc, src_start, length, table_start); + Node* result = _gvn.transform(new ProjNode(call, TypeFunc::Parms)); + set_result(result); + return true; +} + //----------------------------inline_reference_get---------------------------- // public T java.lang.ref.Reference.get(); bool LibraryCallKit::inline_reference_get() { @@ -5571,18 +5684,28 @@ Node * LibraryCallKit::load_field_from_object(Node * fromObj, const char * fieldName, const char * fieldTypeString, - bool is_exact=true, bool is_static=false) { - - const TypeInstPtr* tinst = _gvn.type(fromObj)->isa_instptr(); - assert(tinst != NULL, "obj is null"); - assert(tinst->klass()->is_loaded(), "obj is not loaded"); - assert(!is_exact || tinst->klass_is_exact(), "klass not exact"); - - ciField* field = tinst->klass()->as_instance_klass()->get_field_by_name(ciSymbol::make(fieldName), - ciSymbol::make(fieldTypeString), - is_static); + bool is_exact=true, bool is_static=false, + ciInstanceKlass * fromKls=NULL) { + if (fromKls == NULL) { + const TypeInstPtr* tinst = _gvn.type(fromObj)->isa_instptr(); + assert(tinst != NULL, "obj is null"); + assert(tinst->klass()->is_loaded(), "obj is not loaded"); + assert(!is_exact || tinst->klass_is_exact(), "klass not exact"); + fromKls = tinst->klass()->as_instance_klass(); + } else { + assert(is_static, "only for static field access"); + } + ciField* field = fromKls->get_field_by_name(ciSymbol::make(fieldName), + ciSymbol::make(fieldTypeString), + is_static); + + assert (field != NULL, "undefined field"); if (field == NULL) return (Node *) NULL; - assert (field != NULL, "undefined field"); + + if (is_static) { + const TypeInstPtr* tip = TypeInstPtr::make(fromKls->java_mirror()); + fromObj = makecon(tip); + } // Next code copied from Parse::do_get_xxx(): diff -r 8fc82d01db26 -r 8d8f66194222 hotspot/src/share/vm/opto/runtime.cpp --- a/hotspot/src/share/vm/opto/runtime.cpp Thu Jul 09 16:37:55 2015 -0700 +++ b/hotspot/src/share/vm/opto/runtime.cpp Wed Jul 05 20:41:09 2017 +0200 @@ -851,6 +851,29 @@ return TypeFunc::make(domain, range); } +/** + * int updateBytesCRC32C(int crc, byte* buf, int len, int* table) + */ +const TypeFunc* OptoRuntime::updateBytesCRC32C_Type() { + // create input type (domain) + int num_args = 4; + int argcnt = num_args; + const Type** fields = TypeTuple::fields(argcnt); + int argp = TypeFunc::Parms; + fields[argp++] = TypeInt::INT; // crc + fields[argp++] = TypePtr::NOTNULL; // buf + fields[argp++] = TypeInt::INT; // len + fields[argp++] = TypePtr::NOTNULL; // table + assert(argp == TypeFunc::Parms+argcnt, "correct decoding"); + const TypeTuple* domain = TypeTuple::make(TypeFunc::Parms+argcnt, fields); + + // result type needed + fields = TypeTuple::fields(1); + fields[TypeFunc::Parms+0] = TypeInt::INT; // crc result + const TypeTuple* range = TypeTuple::make(TypeFunc::Parms+1, fields); + return TypeFunc::make(domain, range); +} + // for cipherBlockChaining calls of aescrypt encrypt/decrypt, four pointers and a length, returning int const TypeFunc* OptoRuntime::cipherBlockChaining_aescrypt_Type() { // create input type (domain) diff -r 8fc82d01db26 -r 8d8f66194222 hotspot/src/share/vm/opto/runtime.hpp --- a/hotspot/src/share/vm/opto/runtime.hpp Thu Jul 09 16:37:55 2015 -0700 +++ b/hotspot/src/share/vm/opto/runtime.hpp Wed Jul 05 20:41:09 2017 +0200 @@ -319,6 +319,7 @@ static const TypeFunc* ghash_processBlocks_Type(); static const TypeFunc* updateBytesCRC32_Type(); + static const TypeFunc* updateBytesCRC32C_Type(); // leaf on stack replacement interpreter accessor types static const TypeFunc* osr_end_Type(); diff -r 8fc82d01db26 -r 8d8f66194222 hotspot/src/share/vm/opto/superword.cpp --- a/hotspot/src/share/vm/opto/superword.cpp Thu Jul 09 16:37:55 2015 -0700 +++ b/hotspot/src/share/vm/opto/superword.cpp Wed Jul 05 20:41:09 2017 +0200 @@ -183,13 +183,20 @@ break; } + // Ignore nodes with non-primitive type. + BasicType bt; + if (n->is_Mem()) { + bt = n->as_Mem()->memory_type(); + } else { + bt = n->bottom_type()->basic_type(); + } + if (is_java_primitive(bt) == false) { + ignored_loop_nodes[i] = n->_idx; + continue; + } + if (n->is_Mem()) { MemNode* current = n->as_Mem(); - BasicType bt = current->memory_type(); - if (is_java_primitive(bt) == false) { - ignored_loop_nodes[i] = n->_idx; - continue; - } Node* adr = n->in(MemNode::Address); Node* n_ctrl = _phase->get_ctrl(adr); @@ -231,11 +238,12 @@ BasicType bt; Node* n = lpt()->_body.at(i); - if (n->is_Store()) { + if (n->is_Mem()) { bt = n->as_Mem()->memory_type(); } else { bt = n->bottom_type()->basic_type(); } + if (is_java_primitive(bt) == false) continue; int cur_max_vector = Matcher::max_vector_size(bt); diff -r 8fc82d01db26 -r 8d8f66194222 hotspot/src/share/vm/runtime/arguments.cpp --- a/hotspot/src/share/vm/runtime/arguments.cpp Thu Jul 09 16:37:55 2015 -0700 +++ b/hotspot/src/share/vm/runtime/arguments.cpp Wed Jul 05 20:41:09 2017 +0200 @@ -3753,8 +3753,12 @@ if (TieredCompilation) { set_tiered_flags(); } else { - // Check if the policy is valid. Policies 0 and 1 are valid for non-tiered setup. - if (CompilationPolicyChoice >= 2) { + int max_compilation_policy_choice = 1; +#ifdef COMPILER2 + max_compilation_policy_choice = 2; +#endif + // Check if the policy is valid. + if (CompilationPolicyChoice >= max_compilation_policy_choice) { vm_exit_during_initialization( "Incompatible compilation policy selected", NULL); } diff -r 8fc82d01db26 -r 8d8f66194222 hotspot/src/share/vm/runtime/compilationPolicy.cpp --- a/hotspot/src/share/vm/runtime/compilationPolicy.cpp Thu Jul 09 16:37:55 2015 -0700 +++ b/hotspot/src/share/vm/runtime/compilationPolicy.cpp Wed Jul 05 20:41:09 2017 +0200 @@ -512,7 +512,7 @@ RegisterMap reg_map(thread, false); javaVFrame* triggerVF = thread->last_java_vframe(®_map); // triggerVF is the frame that triggered its counter - RFrame* first = new InterpretedRFrame(triggerVF->fr(), thread, m); + RFrame* first = new InterpretedRFrame(triggerVF->fr(), thread, m()); if (first->top_method()->code() != NULL) { // called obsolete method/nmethod -- no need to recompile @@ -557,8 +557,8 @@ if( !next ) // No next frame up the stack? break; // Then compile with current frame - methodHandle m = current->top_method(); - methodHandle next_m = next->top_method(); + Method* m = current->top_method(); + Method* next_m = next->top_method(); if (TraceCompilationPolicy && Verbose) { tty->print("[caller: "); @@ -644,7 +644,7 @@ if (TraceCompilationPolicy && Verbose) { tty->print("\n\t check caller: "); next_m->print_short_name(tty); - tty->print(" ( interpreted " INTPTR_FORMAT ", size=%d ) ", p2i((address)next_m()), next_m->code_size()); + tty->print(" ( interpreted " INTPTR_FORMAT ", size=%d ) ", p2i((address)next_m), next_m->code_size()); } current = next; diff -r 8fc82d01db26 -r 8d8f66194222 hotspot/src/share/vm/runtime/globals.hpp --- a/hotspot/src/share/vm/runtime/globals.hpp Thu Jul 09 16:37:55 2015 -0700 +++ b/hotspot/src/share/vm/runtime/globals.hpp Wed Jul 05 20:41:09 2017 +0200 @@ -848,6 +848,9 @@ product(bool, UseCRC32Intrinsics, false, \ "use intrinsics for java.util.zip.CRC32") \ \ + product(bool, UseCRC32CIntrinsics, false, \ + "use intrinsics for java.util.zip.CRC32C") \ + \ develop(bool, TraceCallFixup, false, \ "Trace all call fixups") \ \ diff -r 8fc82d01db26 -r 8d8f66194222 hotspot/src/share/vm/runtime/rframe.cpp --- a/hotspot/src/share/vm/runtime/rframe.cpp Thu Jul 09 16:37:55 2015 -0700 +++ b/hotspot/src/share/vm/runtime/rframe.cpp Wed Jul 05 20:41:09 2017 +0200 @@ -52,12 +52,12 @@ : RFrame(fr, thread, callee) { RegisterMap map(thread, false); _vf = javaVFrame::cast(vframe::new_vframe(&_fr, &map, thread)); - _method = methodHandle(thread, _vf->method()); + _method = _vf->method(); assert( _vf->is_interpreted_frame(), "must be interpreted"); init(); } -InterpretedRFrame::InterpretedRFrame(frame fr, JavaThread* thread, methodHandle m) +InterpretedRFrame::InterpretedRFrame(frame fr, JavaThread* thread, Method* m) : RFrame(fr, thread, NULL) { RegisterMap map(thread, false); _vf = javaVFrame::cast(vframe::new_vframe(&_fr, &map, thread)); @@ -140,8 +140,8 @@ _nm = compiledVFrame::cast(vf)->code(); vf = vf->top(); _vf = javaVFrame::cast(vf); - _method = methodHandle(thread(), CodeCache::find_nmethod(_fr.pc())->method()); - assert(_method(), "should have found a method"); + _method = CodeCache::find_nmethod(_fr.pc())->method(); + assert(_method, "should have found a method"); #ifndef PRODUCT _invocations = _method->compiled_invocation_count(); #endif diff -r 8fc82d01db26 -r 8d8f66194222 hotspot/src/share/vm/runtime/rframe.hpp --- a/hotspot/src/share/vm/runtime/rframe.hpp Thu Jul 09 16:37:55 2015 -0700 +++ b/hotspot/src/share/vm/runtime/rframe.hpp Wed Jul 05 20:41:09 2017 +0200 @@ -60,7 +60,7 @@ frame fr() const { return _fr; } JavaThread* thread() const { return _thread; } virtual int cost() const = 0; // estimated inlining cost (size) - virtual methodHandle top_method() const = 0; + virtual Method* top_method() const = 0; virtual javaVFrame* top_vframe() const = 0; virtual nmethod* nm() const { ShouldNotCallThis(); return NULL; } @@ -79,7 +79,7 @@ protected: nmethod* _nm; javaVFrame* _vf; // top vframe; may be NULL (for most recent frame) - methodHandle _method; // top method + Method* _method; // top method CompiledRFrame(frame fr, JavaThread* thread, RFrame*const callee); void init(); @@ -88,7 +88,7 @@ public: CompiledRFrame(frame fr, JavaThread* thread); // for nmethod triggering its counter (callee == NULL) bool is_compiled() const { return true; } - methodHandle top_method() const { return _method; } + Method* top_method() const { return _method; } javaVFrame* top_vframe() const { return _vf; } nmethod* nm() const { return _nm; } int cost() const; @@ -98,16 +98,16 @@ class InterpretedRFrame : public RFrame { // interpreter frame protected: javaVFrame* _vf; // may be NULL (for most recent frame) - methodHandle _method; + Method* _method; InterpretedRFrame(frame fr, JavaThread* thread, RFrame*const callee); void init(); friend class RFrame; public: - InterpretedRFrame(frame fr, JavaThread* thread, methodHandle m); // constructor for method triggering its invocation counter + InterpretedRFrame(frame fr, JavaThread* thread, Method* m); // constructor for method triggering its invocation counter bool is_interpreted() const { return true; } - methodHandle top_method() const { return _method; } + Method* top_method() const { return _method; } javaVFrame* top_vframe() const { return _vf; } int cost() const; void print(); diff -r 8fc82d01db26 -r 8d8f66194222 hotspot/src/share/vm/runtime/stubRoutines.cpp --- a/hotspot/src/share/vm/runtime/stubRoutines.cpp Thu Jul 09 16:37:55 2015 -0700 +++ b/hotspot/src/share/vm/runtime/stubRoutines.cpp Wed Jul 05 20:41:09 2017 +0200 @@ -137,6 +137,8 @@ address StubRoutines::_updateBytesCRC32 = NULL; address StubRoutines::_crc_table_adr = NULL; +address StubRoutines::_updateBytesCRC32C = NULL; + address StubRoutines::_multiplyToLen = NULL; address StubRoutines::_squareToLen = NULL; address StubRoutines::_mulAdd = NULL; diff -r 8fc82d01db26 -r 8d8f66194222 hotspot/src/share/vm/runtime/stubRoutines.hpp --- a/hotspot/src/share/vm/runtime/stubRoutines.hpp Thu Jul 09 16:37:55 2015 -0700 +++ b/hotspot/src/share/vm/runtime/stubRoutines.hpp Wed Jul 05 20:41:09 2017 +0200 @@ -197,6 +197,8 @@ static address _updateBytesCRC32; static address _crc_table_adr; + static address _updateBytesCRC32C; + static address _multiplyToLen; static address _squareToLen; static address _mulAdd; @@ -359,6 +361,8 @@ static address updateBytesCRC32() { return _updateBytesCRC32; } static address crc_table_addr() { return _crc_table_adr; } + static address updateBytesCRC32C() { return _updateBytesCRC32C; } + static address multiplyToLen() {return _multiplyToLen; } static address squareToLen() {return _squareToLen; } static address mulAdd() {return _mulAdd; } diff -r 8fc82d01db26 -r 8d8f66194222 hotspot/src/share/vm/runtime/vmStructs.cpp --- a/hotspot/src/share/vm/runtime/vmStructs.cpp Thu Jul 09 16:37:55 2015 -0700 +++ b/hotspot/src/share/vm/runtime/vmStructs.cpp Wed Jul 05 20:41:09 2017 +0200 @@ -830,6 +830,7 @@ static_field(StubRoutines, _ghash_processBlocks, address) \ static_field(StubRoutines, _updateBytesCRC32, address) \ static_field(StubRoutines, _crc_table_adr, address) \ + static_field(StubRoutines, _updateBytesCRC32C, address) \ static_field(StubRoutines, _multiplyToLen, address) \ static_field(StubRoutines, _squareToLen, address) \ static_field(StubRoutines, _mulAdd, address) \ diff -r 8fc82d01db26 -r 8d8f66194222 hotspot/test/TEST.groups --- a/hotspot/test/TEST.groups Thu Jul 09 16:37:55 2015 -0700 +++ b/hotspot/test/TEST.groups Wed Jul 05 20:41:09 2017 +0200 @@ -147,12 +147,16 @@ gc/survivorAlignment \ gc/TestGCLogRotationViaJcmd.java \ runtime/InternalApi/ThreadCpuTimesDeadlock.java \ + runtime/NMT/JcmdSummaryDiff.java \ + runtime/RedefineTests/RedefineAnnotations.java serviceability/sa/jmap-hashcode/Test8028623.java \ serviceability/threads/TestFalseDeadLock.java \ compiler/codecache/jmx \ compiler/jsr292/RedefineMethodUsedByMultipleMethodHandles.java \ compiler/rangechecks/TestRangeCheckSmearing.java \ - serviceability/dcmd + compiler/whitebox/DeoptimizeMultipleOSRTest.java \ + serviceability/dcmd \ + testlibrary_tests/whitebox/vm_flags # Compact 2 adds full VM tests compact2 = \ diff -r 8fc82d01db26 -r 8d8f66194222 hotspot/test/compiler/codecache/jmx/CodeCacheUtils.java --- a/hotspot/test/compiler/codecache/jmx/CodeCacheUtils.java Thu Jul 09 16:37:55 2015 -0700 +++ b/hotspot/test/compiler/codecache/jmx/CodeCacheUtils.java Wed Jul 05 20:41:09 2017 +0200 @@ -21,6 +21,7 @@ * questions. */ +import jdk.test.lib.Asserts; import jdk.test.lib.Utils; import java.lang.management.MemoryPoolMXBean; import javax.management.Notification; @@ -80,19 +81,42 @@ } /** - * A "non-nmethods" code heap is used by interpreter during bytecode - * execution, thus, it can't be predicted if this code heap usage will be - * increased or not. Same goes for 'All'. + * Checks if the usage of the code heap corresponding to 'btype' can be + * predicted at runtime if we disable compilation. The usage of the + * 'NonNMethod' code heap can not be predicted because we generate adapters + * and buffers at runtime. The 'MethodNonProfiled' code heap is also not + * predictable because we may generate compiled versions of method handle + * intrinsics while resolving methods at runtime. Same applies to 'All'. * * @param btype BlobType to be checked * @return boolean value, true if respective code heap is predictable */ public static boolean isCodeHeapPredictable(BlobType btype) { - return btype == BlobType.MethodNonProfiled - || btype == BlobType.MethodProfiled; + return btype == BlobType.MethodProfiled; } - public static void disableCollectionUsageThresholds(){ + /** + * Verifies that 'newValue' is equal to 'oldValue' if usage of the + * corresponding code heap is predictable. Checks the weaker condition + * 'newValue >= oldValue' if usage is not predictable because intermediate + * allocations may happen. + * + * @param btype BlobType of the code heap to be checked + * @param newValue New value to be verified + * @param oldValue Old value to be verified + * @param msg Error message if verification fails + */ + public static void assertEQorGTE(BlobType btype, long newValue, long oldValue, String msg) { + if (CodeCacheUtils.isCodeHeapPredictable(btype)) { + // Usage is predictable, check strong == condition + Asserts.assertEQ(newValue, oldValue, msg); + } else { + // Usage is not predictable, check weaker >= condition + Asserts.assertGTE(newValue, oldValue, msg); + } + } + + public static void disableCollectionUsageThresholds() { BlobType.getAvailable().stream() .map(BlobType::getMemoryPool) .filter(MemoryPoolMXBean::isCollectionUsageThresholdSupported) diff -r 8fc82d01db26 -r 8d8f66194222 hotspot/test/compiler/codecache/jmx/GetUsageTest.java --- a/hotspot/test/compiler/codecache/jmx/GetUsageTest.java Thu Jul 09 16:37:55 2015 -0700 +++ b/hotspot/test/compiler/codecache/jmx/GetUsageTest.java Wed Jul 05 20:41:09 2017 +0200 @@ -52,10 +52,8 @@ public static void main(String[] args) throws Exception { for (BlobType btype : BlobType.getAvailable()) { - if (CodeCacheUtils.isCodeHeapPredictable(btype)) { - for (int allocSize = 10; allocSize < 100000; allocSize *= 10) { - new GetUsageTest(btype, allocSize).runTest(); - } + for (int allocSize = 10; allocSize < 100000; allocSize *= 10) { + new GetUsageTest(btype, allocSize).runTest(); } } } @@ -87,13 +85,15 @@ for (MemoryPoolMXBean entry : predictableBeans) { long diff = current.get(entry) - initial.get(entry); if (entry.equals(btype.getMemoryPool())) { - Asserts.assertFalse(diff <= 0L || diff > usageUpperEstimate, - String.format("Pool %s usage increase was reported " - + "unexpectedly as increased by %d using " - + "allocation size %d", entry.getName(), - diff, allocateSize)); + if (CodeCacheUtils.isCodeHeapPredictable(btype)) { + Asserts.assertFalse(diff <= 0L || diff > usageUpperEstimate, + String.format("Pool %s usage increase was reported " + + "unexpectedly as increased by %d using " + + "allocation size %d", entry.getName(), + diff, allocateSize)); + } } else { - Asserts.assertEQ(diff, 0L, + CodeCacheUtils.assertEQorGTE(btype, diff, 0L, String.format("Pool %s usage changed unexpectedly while" + " trying to increase: %s using allocation " + "size %d", entry.getName(), diff -r 8fc82d01db26 -r 8d8f66194222 hotspot/test/compiler/codecache/jmx/PeakUsageTest.java --- a/hotspot/test/compiler/codecache/jmx/PeakUsageTest.java Thu Jul 09 16:37:55 2015 -0700 +++ b/hotspot/test/compiler/codecache/jmx/PeakUsageTest.java Wed Jul 05 20:41:09 2017 +0200 @@ -52,9 +52,7 @@ public static void main(String[] args) { for (BlobType btype : BlobType.getAvailable()) { - if (CodeCacheUtils.isCodeHeapPredictable(btype)) { - new PeakUsageTest(btype).runTest(); - } + new PeakUsageTest(btype).runTest(); } } @@ -65,7 +63,7 @@ CodeCacheUtils.ALLOCATION_SIZE, btype.id); long newPeakUsage = bean.getPeakUsage().getUsed(); try { - Asserts.assertEQ(newPeakUsage, bean.getUsage().getUsed(), + CodeCacheUtils.assertEQorGTE(btype, newPeakUsage, bean.getUsage().getUsed(), "Peak usage does not match usage after allocation for " + bean.getName()); } finally { @@ -73,18 +71,18 @@ CodeCacheUtils.WB.freeCodeBlob(addr); } } - Asserts.assertEQ(newPeakUsage, bean.getPeakUsage().getUsed(), + CodeCacheUtils.assertEQorGTE(btype, newPeakUsage, bean.getPeakUsage().getUsed(), "Code cache peak usage has changed after usage decreased for " + bean.getName()); bean.resetPeakUsage(); - Asserts.assertEQ(bean.getPeakUsage().getUsed(), + CodeCacheUtils.assertEQorGTE(btype, bean.getPeakUsage().getUsed(), bean.getUsage().getUsed(), "Code cache peak usage is not equal to usage after reset for " + bean.getName()); long addr2 = CodeCacheUtils.WB.allocateCodeBlob( CodeCacheUtils.ALLOCATION_SIZE, btype.id); try { - Asserts.assertEQ(bean.getPeakUsage().getUsed(), + CodeCacheUtils.assertEQorGTE(btype, bean.getPeakUsage().getUsed(), bean.getUsage().getUsed(), "Code cache peak usage is not equal to usage after fresh " + "allocation for " + bean.getName()); diff -r 8fc82d01db26 -r 8d8f66194222 hotspot/test/compiler/codecache/jmx/PoolsIndependenceTest.java --- a/hotspot/test/compiler/codecache/jmx/PoolsIndependenceTest.java Thu Jul 09 16:37:55 2015 -0700 +++ b/hotspot/test/compiler/codecache/jmx/PoolsIndependenceTest.java Wed Jul 05 20:41:09 2017 +0200 @@ -97,13 +97,11 @@ return false; }); for (BlobType bt : BlobType.getAvailable()) { - if (CodeCacheUtils.isCodeHeapPredictable(bt)) { - int expectedNotificationsAmount = bt.equals(btype) ? 1 : 0; - Asserts.assertEQ(counters.get(bt.getMemoryPool().getName()).get(), - expectedNotificationsAmount, String.format("Unexpected " - + "amount of notifications for pool: %s", - bt.getMemoryPool().getName())); - } + int expectedNotificationsAmount = bt.equals(btype) ? 1 : 0; + CodeCacheUtils.assertEQorGTE(btype, counters.get(bt.getMemoryPool().getName()).get(), + expectedNotificationsAmount, String.format("Unexpected " + + "amount of notifications for pool: %s", + bt.getMemoryPool().getName())); } try { ((NotificationEmitter) ManagementFactory.getMemoryMXBean()). diff -r 8fc82d01db26 -r 8d8f66194222 hotspot/test/compiler/codecache/jmx/ThresholdNotificationsTest.java --- a/hotspot/test/compiler/codecache/jmx/ThresholdNotificationsTest.java Thu Jul 09 16:37:55 2015 -0700 +++ b/hotspot/test/compiler/codecache/jmx/ThresholdNotificationsTest.java Wed Jul 05 20:41:09 2017 +0200 @@ -54,9 +54,7 @@ public static void main(String[] args) { for (BlobType bt : BlobType.getAvailable()) { - if (CodeCacheUtils.isCodeHeapPredictable(bt)) { - new ThresholdNotificationsTest(bt).runTest(); - } + new ThresholdNotificationsTest(bt).runTest(); } } @@ -92,7 +90,9 @@ } Asserts.assertTrue( Utils.waitForCondition( - () -> counter == iterationsCount, WAIT_TIME), + () -> (CodeCacheUtils.isCodeHeapPredictable(btype) ? + (counter == iterationsCount) : (counter >= iterationsCount)), + WAIT_TIME), "Couldn't receive expected notifications count"); try { ((NotificationEmitter) ManagementFactory.getMemoryMXBean()). diff -r 8fc82d01db26 -r 8d8f66194222 hotspot/test/compiler/codecache/jmx/UsageThresholdExceededTest.java --- a/hotspot/test/compiler/codecache/jmx/UsageThresholdExceededTest.java Thu Jul 09 16:37:55 2015 -0700 +++ b/hotspot/test/compiler/codecache/jmx/UsageThresholdExceededTest.java Wed Jul 05 20:41:09 2017 +0200 @@ -51,13 +51,9 @@ } public static void main(String[] args) { - int iterationsCount = - Integer.getInteger("jdk.test.lib.iterations", 1); + int iterationsCount = Integer.getInteger("jdk.test.lib.iterations", 1); for (BlobType btype : BlobType.getAvailable()) { - if (CodeCacheUtils.isCodeHeapPredictable(btype)) { - new UsageThresholdExceededTest(btype, iterationsCount) - .runTest(); - } + new UsageThresholdExceededTest(btype, iterationsCount).runTest(); } } @@ -67,9 +63,8 @@ for (int i = 0; i < iterations; i++) { CodeCacheUtils.hitUsageThreshold(bean, btype); } - Asserts.assertEQ(bean.getUsageThresholdCount(), oldValue + iterations, + CodeCacheUtils.assertEQorGTE(btype, bean.getUsageThresholdCount(), oldValue + iterations, "Unexpected threshold usage count"); - System.out.printf("INFO: Scenario finished successfully for %s%n", - bean.getName()); + System.out.printf("INFO: Scenario finished successfully for %s%n", bean.getName()); } } diff -r 8fc82d01db26 -r 8d8f66194222 hotspot/test/compiler/codecache/jmx/UsageThresholdIncreasedTest.java --- a/hotspot/test/compiler/codecache/jmx/UsageThresholdIncreasedTest.java Thu Jul 09 16:37:55 2015 -0700 +++ b/hotspot/test/compiler/codecache/jmx/UsageThresholdIncreasedTest.java Wed Jul 05 20:41:09 2017 +0200 @@ -27,7 +27,6 @@ /* * @test UsageThresholdIncreasedTest - * @ignore 8129937 * @library /testlibrary /../../test/lib * @modules java.base/sun.misc * java.management @@ -54,14 +53,12 @@ public static void main(String[] args) { for (BlobType btype : BlobType.getAvailable()) { - if (CodeCacheUtils.isCodeHeapPredictable(btype)) { - new UsageThresholdIncreasedTest(btype).runTest(); - } + new UsageThresholdIncreasedTest(btype).runTest(); } } private void checkUsageThresholdCount(MemoryPoolMXBean bean, long count){ - Asserts.assertEQ(bean.getUsageThresholdCount(), count, + CodeCacheUtils.assertEQorGTE(btype, bean.getUsageThresholdCount(), count, String.format("Usage threshold was hit: %d times for %s " + "Threshold value: %d with current usage: %d", bean.getUsageThresholdCount(), bean.getName(), diff -r 8fc82d01db26 -r 8d8f66194222 hotspot/test/compiler/codecache/jmx/UsageThresholdNotExceededTest.java --- a/hotspot/test/compiler/codecache/jmx/UsageThresholdNotExceededTest.java Thu Jul 09 16:37:55 2015 -0700 +++ b/hotspot/test/compiler/codecache/jmx/UsageThresholdNotExceededTest.java Wed Jul 05 20:41:09 2017 +0200 @@ -50,9 +50,7 @@ public static void main(String[] args) { for (BlobType btype : BlobType.getAvailable()) { - if (CodeCacheUtils.isCodeHeapPredictable(btype)) { - new UsageThresholdNotExceededTest(btype).runTest(); - } + new UsageThresholdNotExceededTest(btype).runTest(); } } @@ -65,13 +63,11 @@ - CodeCacheUtils.getHeaderSize(btype), btype.id); // a gc cycle triggers usage threshold recalculation CodeCacheUtils.WB.fullGC(); - Asserts.assertEQ(bean.getUsageThresholdCount(), initialThresholdCount, - String.format("Usage threshold was hit: %d times for %s. " + CodeCacheUtils.assertEQorGTE(btype, bean.getUsageThresholdCount(), initialThresholdCount, + String.format("Usage threshold was hit: %d times for %s. " + "Threshold value: %d with current usage: %d", bean.getUsageThresholdCount(), bean.getName(), bean.getUsageThreshold(), bean.getUsage().getUsed())); - - System.out.println("INFO: Case finished successfully for " - + bean.getName()); + System.out.println("INFO: Case finished successfully for " + bean.getName()); } } diff -r 8fc82d01db26 -r 8d8f66194222 hotspot/test/compiler/intrinsics/crc32c/TestCRC32C.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/intrinsics/crc32c/TestCRC32C.java Wed Jul 05 20:41:09 2017 +0200 @@ -0,0 +1,221 @@ +/* + * Copyright (c) 2015, 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 8073583 + * @summary C2 support for CRC32C on SPARC + * + * @run main/othervm/timeout=600 -Xbatch TestCRC32C -m + */ + +import java.nio.ByteBuffer; +import java.util.zip.Checksum; +import java.util.zip.CRC32C; + +public class TestCRC32C { + public static void main(String[] args) { + int offset = Integer.getInteger("offset", 0); + int msgSize = Integer.getInteger("msgSize", 512); + boolean multi = false; + int iters = 20000; + int warmupIters = 20000; + + if (args.length > 0) { + if (args[0].equals("-m")) { + multi = true; + } else { + iters = Integer.valueOf(args[0]); + } + if (args.length > 1) { + warmupIters = Integer.valueOf(args[1]); + } + } + + if (multi) { + test_multi(warmupIters); + return; + } + + System.out.println(" offset = " + offset); + System.out.println("msgSize = " + msgSize + " bytes"); + System.out.println(" iters = " + iters); + + byte[] b = initializedBytes(msgSize, offset); + + CRC32C crc0 = new CRC32C(); + CRC32C crc1 = new CRC32C(); + CRC32C crc2 = new CRC32C(); + + crc0.update(b, offset, msgSize); + + System.out.println("-------------------------------------------------------"); + + /* warm up */ + for (int i = 0; i < warmupIters; i++) { + crc1.reset(); + crc1.update(b, offset, msgSize); + } + + /* measure performance */ + long start = System.nanoTime(); + for (int i = 0; i < iters; i++) { + crc1.reset(); + crc1.update(b, offset, msgSize); + } + long end = System.nanoTime(); + double total = (double)(end - start)/1e9; // in seconds + double thruput = (double)msgSize*iters/1e6/total; // in MB/s + System.out.println("CRC32C.update(byte[]) runtime = " + total + " seconds"); + System.out.println("CRC32C.update(byte[]) throughput = " + thruput + " MB/s"); + + /* check correctness */ + for (int i = 0; i < iters; i++) { + crc1.reset(); + crc1.update(b, offset, msgSize); + if (!check(crc0, crc1)) break; + } + report("CRCs", crc0, crc1); + + System.out.println("-------------------------------------------------------"); + + ByteBuffer buf = ByteBuffer.allocateDirect(msgSize); + buf.put(b, offset, msgSize); + buf.flip(); + + /* warm up */ + for (int i = 0; i < warmupIters; i++) { + crc2.reset(); + crc2.update(buf); + buf.rewind(); + } + + /* measure performance */ + start = System.nanoTime(); + for (int i = 0; i < iters; i++) { + crc2.reset(); + crc2.update(buf); + buf.rewind(); + } + end = System.nanoTime(); + total = (double)(end - start)/1e9; // in seconds + thruput = (double)msgSize*iters/1e6/total; // in MB/s + System.out.println("CRC32C.update(ByteBuffer) runtime = " + total + " seconds"); + System.out.println("CRC32C.update(ByteBuffer) throughput = " + thruput + " MB/s"); + + /* check correctness */ + for (int i = 0; i < iters; i++) { + crc2.reset(); + crc2.update(buf); + buf.rewind(); + if (!check(crc0, crc2)) break; + } + report("CRCs", crc0, crc2); + + System.out.println("-------------------------------------------------------"); + } + + private static void report(String s, Checksum crc0, Checksum crc1) { + System.out.printf("%s: crc0 = %08x, crc1 = %08x\n", + s, crc0.getValue(), crc1.getValue()); + } + + private static boolean check(Checksum crc0, Checksum crc1) { + if (crc0.getValue() != crc1.getValue()) { + System.err.printf("ERROR: crc0 = %08x, crc1 = %08x\n", + crc0.getValue(), crc1.getValue()); + return false; + } + return true; + } + + private static byte[] initializedBytes(int M, int offset) { + byte[] bytes = new byte[M + offset]; + for (int i = 0; i < offset; i++) { + bytes[i] = (byte) i; + } + for (int i = offset; i < bytes.length; i++) { + bytes[i] = (byte) (i - offset); + } + return bytes; + } + + private static void test_multi(int iters) { + int len1 = 8; // the 8B/iteration loop + int len2 = 32; // the 32B/iteration loop + int len3 = 4096; // the 4KB/iteration loop + + byte[] b = initializedBytes(len3*16, 0); + int[] offsets = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 16, 32, 64, 128, 256, 512 }; + int[] sizes = { 0, 1, 2, 3, 4, 5, 6, 7, + len1, len1+1, len1+2, len1+3, len1+4, len1+5, len1+6, len1+7, + len1*2, len1*2+1, len1*2+3, len1*2+5, len1*2+7, + len2, len2+1, len2+3, len2+5, len2+7, + len2*2, len2*4, len2*8, len2*16, len2*32, len2*64, + len3, len3+1, len3+3, len3+5, len3+7, + len3*2, len3*4, len3*8, + len1+len2, len1+len2+1, len1+len2+3, len1+len2+5, len1+len2+7, + len1+len3, len1+len3+1, len1+len3+3, len1+len3+5, len1+len3+7, + len2+len3, len2+len3+1, len2+len3+3, len2+len3+5, len2+len3+7, + len1+len2+len3, len1+len2+len3+1, len1+len2+len3+3, + len1+len2+len3+5, len1+len2+len3+7, + (len1+len2+len3)*2, (len1+len2+len3)*2+1, (len1+len2+len3)*2+3, + (len1+len2+len3)*2+5, (len1+len2+len3)*2+7, + (len1+len2+len3)*3, (len1+len2+len3)*3-1, (len1+len2+len3)*3-3, + (len1+len2+len3)*3-5, (len1+len2+len3)*3-7 }; + CRC32C[] crc0 = new CRC32C[offsets.length*sizes.length]; + CRC32C[] crc1 = new CRC32C[offsets.length*sizes.length]; + int i, j, k; + + System.out.printf("testing %d cases ...\n", offsets.length*sizes.length); + + /* set the result from interpreter as reference */ + for (i = 0; i < offsets.length; i++) { + for (j = 0; j < sizes.length; j++) { + crc0[i*sizes.length + j] = new CRC32C(); + crc1[i*sizes.length + j] = new CRC32C(); + crc0[i*sizes.length + j].update(b, offsets[i], sizes[j]); + } + } + + /* warm up the JIT compiler and get result */ + for (k = 0; k < iters; k++) { + for (i = 0; i < offsets.length; i++) { + for (j = 0; j < sizes.length; j++) { + crc1[i*sizes.length + j].reset(); + crc1[i*sizes.length + j].update(b, offsets[i], sizes[j]); + } + } + } + + /* check correctness */ + for (i = 0; i < offsets.length; i++) { + for (j = 0; j < sizes.length; j++) { + if (!check(crc0[i*sizes.length + j], crc1[i*sizes.length + j])) { + System.out.printf("offsets[%d] = %d", i, offsets[i]); + System.out.printf("\tsizes[%d] = %d\n", j, sizes[j]); + } + } + } + } +} diff -r 8fc82d01db26 -r 8d8f66194222 make/CompileJavaModules.gmk --- a/make/CompileJavaModules.gmk Thu Jul 09 16:37:55 2015 -0700 +++ b/make/CompileJavaModules.gmk Wed Jul 05 20:41:09 2017 +0200 @@ -368,6 +368,10 @@ ################################################################################ +jdk.internal.le_COPY := .properties + +################################################################################ + jdk.jcmd_COPY := _options ################################################################################ diff -r 8fc82d01db26 -r 8d8f66194222 make/Images.gmk --- a/make/Images.gmk Thu Jul 09 16:37:55 2015 -0700 +++ b/make/Images.gmk Wed Jul 05 20:41:09 2017 +0200 @@ -46,7 +46,7 @@ jdk.naming.dns jdk.naming.rmi jdk.scripting.nashorn jdk.zipfs # tools -TOOLS_MODULES += jdk.attach jdk.compiler jdk.dev jdk.javadoc jdk.jcmd jdk.jconsole \ +TOOLS_MODULES += jdk.attach jdk.compiler jdk.dev jdk.internal.le jdk.javadoc jdk.jcmd jdk.jconsole \ jdk.hotspot.agent jdk.hprof.agent jdk.jartool jdk.jdeps jdk.jdi jdk.jdwp.agent \ jdk.policytool jdk.rmic jdk.xml.bind jdk.xml.ws diff -r 8fc82d01db26 -r 8d8f66194222 modules.xml --- a/modules.xml Thu Jul 09 16:37:55 2015 -0700 +++ b/modules.xml Wed Jul 05 20:41:09 2017 +0200 @@ -1625,6 +1625,26 @@ + jdk.internal.le + java.base + + jdk.internal.jline + jdk.scripting.nashorn.shell + + + jdk.internal.jline.console + jdk.scripting.nashorn.shell + + + jdk.internal.jline.console.completer + jdk.scripting.nashorn.shell + + + jdk.internal.jline.console.history + jdk.scripting.nashorn.shell + + + jdk.jartool java.base