diff --git a/src/cpu/sparc/vm/sparc.ad b/src/cpu/sparc/vm/sparc.ad index 03c79b5a294ea69b206a234c9e05dbc8badfc213..df6e9049ebb245f172e9348488839702254f81a3 100644 --- a/src/cpu/sparc/vm/sparc.ad +++ b/src/cpu/sparc/vm/sparc.ad @@ -9015,6 +9015,33 @@ instruct string_compare(o0RegP str1, o1RegP str2, g3RegP tmp1, g4RegP tmp2, note ins_pipe(long_memory_op); %} + +//---------- Population Count Instructions ------------------------------------- + +instruct popCountI(iRegI dst, iRegI src) %{ + predicate(UsePopCountInstruction); + match(Set dst (PopCountI src)); + + format %{ "POPC $src, $dst" %} + ins_encode %{ + __ popc($src$$Register, $dst$$Register); + %} + ins_pipe(ialu_reg); +%} + +// Note: Long.bitCount(long) returns an int. +instruct popCountL(iRegI dst, iRegL src) %{ + predicate(UsePopCountInstruction); + match(Set dst (PopCountL src)); + + format %{ "POPC $src, $dst" %} + ins_encode %{ + __ popc($src$$Register, $dst$$Register); + %} + ins_pipe(ialu_reg); +%} + + // ============================================================================ //------------Bytes reverse-------------------------------------------------- diff --git a/src/cpu/sparc/vm/vm_version_sparc.cpp b/src/cpu/sparc/vm/vm_version_sparc.cpp index 96d399fc6d7b4d4808adfac6c84b85527e5b2079..dc7f6b5bdbe4cbd66891f9595538c664a4cb840a 100644 --- a/src/cpu/sparc/vm/vm_version_sparc.cpp +++ b/src/cpu/sparc/vm/vm_version_sparc.cpp @@ -92,10 +92,18 @@ void VM_Version::initialize() { #endif } + // Use hardware population count instruction if available. + if (has_hardware_popc()) { + if (FLAG_IS_DEFAULT(UsePopCountInstruction)) { + UsePopCountInstruction = true; + } + } + char buf[512]; - jio_snprintf(buf, sizeof(buf), "%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", (has_v8() ? ", has_v8" : ""), (has_v9() ? ", has_v9" : ""), + (has_hardware_popc() ? ", popc" : ""), (has_vis1() ? ", has_vis1" : ""), (has_vis2() ? ", has_vis2" : ""), (is_ultra3() ? ", is_ultra3" : ""), diff --git a/src/cpu/sparc/vm/vm_version_sparc.hpp b/src/cpu/sparc/vm/vm_version_sparc.hpp index 92133fa9bfec855936399f8eaf8ab4b7d6e58827..e057c608ce88fc298f4f20f8bb10830249c58b45 100644 --- a/src/cpu/sparc/vm/vm_version_sparc.hpp +++ b/src/cpu/sparc/vm/vm_version_sparc.hpp @@ -29,10 +29,11 @@ protected: hardware_mul32 = 1, hardware_div32 = 2, hardware_fsmuld = 3, - v9_instructions = 4, - vis1_instructions = 5, - vis2_instructions = 6, - sun4v_instructions = 7 + hardware_popc = 4, + v9_instructions = 5, + vis1_instructions = 6, + vis2_instructions = 7, + sun4v_instructions = 8 }; enum Feature_Flag_Set { @@ -43,6 +44,7 @@ protected: hardware_mul32_m = 1 << hardware_mul32, hardware_div32_m = 1 << hardware_div32, hardware_fsmuld_m = 1 << hardware_fsmuld, + hardware_popc_m = 1 << hardware_popc, v9_instructions_m = 1 << v9_instructions, vis1_instructions_m = 1 << vis1_instructions, vis2_instructions_m = 1 << vis2_instructions, @@ -81,6 +83,7 @@ public: static bool has_hardware_mul32() { return (_features & hardware_mul32_m) != 0; } static bool has_hardware_div32() { return (_features & hardware_div32_m) != 0; } static bool has_hardware_fsmuld() { return (_features & hardware_fsmuld_m) != 0; } + static bool has_hardware_popc() { return (_features & hardware_popc_m) != 0; } static bool has_vis1() { return (_features & vis1_instructions_m) != 0; } static bool has_vis2() { return (_features & vis2_instructions_m) != 0; } diff --git a/src/cpu/x86/vm/assembler_x86.cpp b/src/cpu/x86/vm/assembler_x86.cpp index 4bae526f39512f9de9ec098b915e1541ad00589b..dcb9585f1efe5a9e6cc2cf60fb82c7ff2a8c2a3a 100644 --- a/src/cpu/x86/vm/assembler_x86.cpp +++ b/src/cpu/x86/vm/assembler_x86.cpp @@ -2193,6 +2193,25 @@ void Assembler::pop(Register dst) { emit_byte(0x58 | encode); } +void Assembler::popcntl(Register dst, Address src) { + assert(VM_Version::supports_popcnt(), "must support"); + InstructionMark im(this); + emit_byte(0xF3); + prefix(src, dst); + emit_byte(0x0F); + emit_byte(0xB8); + emit_operand(dst, src); +} + +void Assembler::popcntl(Register dst, Register src) { + assert(VM_Version::supports_popcnt(), "must support"); + emit_byte(0xF3); + int encode = prefix_and_encode(dst->encoding(), src->encoding()); + emit_byte(0x0F); + emit_byte(0xB8); + emit_byte(0xC0 | encode); +} + void Assembler::popf() { emit_byte(0x9D); } @@ -4080,6 +4099,25 @@ void Assembler::popa() { // 64bit addq(rsp, 16 * wordSize); } +void Assembler::popcntq(Register dst, Address src) { + assert(VM_Version::supports_popcnt(), "must support"); + InstructionMark im(this); + emit_byte(0xF3); + prefixq(src, dst); + emit_byte(0x0F); + emit_byte(0xB8); + emit_operand(dst, src); +} + +void Assembler::popcntq(Register dst, Register src) { + assert(VM_Version::supports_popcnt(), "must support"); + emit_byte(0xF3); + int encode = prefixq_and_encode(dst->encoding(), src->encoding()); + emit_byte(0x0F); + emit_byte(0xB8); + emit_byte(0xC0 | encode); +} + void Assembler::popq(Address dst) { InstructionMark im(this); prefixq(dst); diff --git a/src/cpu/x86/vm/assembler_x86.hpp b/src/cpu/x86/vm/assembler_x86.hpp index 76b4559527a80f7f88f53a45b4dd38938940727c..f369d4760fb290b5b649cf4799b688172028cd2d 100644 --- a/src/cpu/x86/vm/assembler_x86.hpp +++ b/src/cpu/x86/vm/assembler_x86.hpp @@ -1224,6 +1224,14 @@ private: void popq(Address dst); #endif + void popcntl(Register dst, Address src); + void popcntl(Register dst, Register src); + +#ifdef _LP64 + void popcntq(Register dst, Address src); + void popcntq(Register dst, Register src); +#endif + // Prefetches (SSE, SSE2, 3DNOW only) void prefetchnta(Address src); diff --git a/src/cpu/x86/vm/vm_version_x86.cpp b/src/cpu/x86/vm/vm_version_x86.cpp index cf112067fe454076bc9f499b689742be3fadedc6..1307dd1e54fe9facab069d5c753d85a897a0acce 100644 --- a/src/cpu/x86/vm/vm_version_x86.cpp +++ b/src/cpu/x86/vm/vm_version_x86.cpp @@ -284,7 +284,7 @@ void VM_Version::get_processor_features() { } char buf[256]; - jio_snprintf(buf, sizeof(buf), "(%u cores per cpu, %u threads per core) family %d model %d stepping %d%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s", + jio_snprintf(buf, sizeof(buf), "(%u cores per cpu, %u threads per core) family %d model %d stepping %d%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s", cores_per_cpu(), threads_per_core(), cpu_family(), _model, _stepping, (supports_cmov() ? ", cmov" : ""), @@ -297,6 +297,7 @@ void VM_Version::get_processor_features() { (supports_ssse3()? ", ssse3": ""), (supports_sse4_1() ? ", sse4.1" : ""), (supports_sse4_2() ? ", sse4.2" : ""), + (supports_popcnt() ? ", popcnt" : ""), (supports_mmx_ext() ? ", mmxext" : ""), (supports_3dnow() ? ", 3dnow" : ""), (supports_3dnow2() ? ", 3dnowext" : ""), @@ -410,6 +411,13 @@ void VM_Version::get_processor_features() { } } + // Use population count instruction if available. + if (supports_popcnt()) { + if (FLAG_IS_DEFAULT(UsePopCountInstruction)) { + UsePopCountInstruction = true; + } + } + assert(0 <= ReadPrefetchInstr && ReadPrefetchInstr <= 3, "invalid value"); assert(0 <= AllocatePrefetchInstr && AllocatePrefetchInstr <= 3, "invalid value"); diff --git a/src/cpu/x86/vm/vm_version_x86.hpp b/src/cpu/x86/vm/vm_version_x86.hpp index bf876fc92a67c9dcf44870264e6bf846f268ca64..7b6206b0e32a7f38d1dded970879fd838eaa7f1b 100644 --- a/src/cpu/x86/vm/vm_version_x86.hpp +++ b/src/cpu/x86/vm/vm_version_x86.hpp @@ -70,7 +70,9 @@ public: dca : 1, sse4_1 : 1, sse4_2 : 1, - : 11; + : 2, + popcnt : 1, + : 8; } bits; }; @@ -179,7 +181,8 @@ protected: CPU_SSSE3 = (1 << 9), CPU_SSE4A = (1 << 10), CPU_SSE4_1 = (1 << 11), - CPU_SSE4_2 = (1 << 12) + CPU_SSE4_2 = (1 << 12), + CPU_POPCNT = (1 << 13) } cpuFeatureFlags; // cpuid information block. All info derived from executing cpuid with @@ -290,6 +293,8 @@ protected: result |= CPU_SSE4_1; if (_cpuid_info.std_cpuid1_ecx.bits.sse4_2 != 0) result |= CPU_SSE4_2; + if (_cpuid_info.std_cpuid1_ecx.bits.popcnt != 0) + result |= CPU_POPCNT; return result; } @@ -379,6 +384,7 @@ public: static bool supports_ssse3() { return (_cpuFeatures & CPU_SSSE3)!= 0; } static bool supports_sse4_1() { return (_cpuFeatures & CPU_SSE4_1) != 0; } static bool supports_sse4_2() { return (_cpuFeatures & CPU_SSE4_2) != 0; } + static bool supports_popcnt() { return (_cpuFeatures & CPU_POPCNT) != 0; } // // AMD features // diff --git a/src/cpu/x86/vm/x86_32.ad b/src/cpu/x86/vm/x86_32.ad index 1e770159226b2e4a79212dcff119eb5aa83026f9..9f09138bc559c35180fd231dbfcf5b7219c69279 100644 --- a/src/cpu/x86/vm/x86_32.ad +++ b/src/cpu/x86/vm/x86_32.ad @@ -1483,16 +1483,20 @@ encode %{ // main source block for now. In future, we can generalize this by // adding a syntax that specifies the sizes of fields in an order, // so that the adlc can build the emit functions automagically - enc_class OpcP %{ // Emit opcode - emit_opcode(cbuf,$primary); + + // Emit primary opcode + enc_class OpcP %{ + emit_opcode(cbuf, $primary); %} - enc_class OpcS %{ // Emit opcode - emit_opcode(cbuf,$secondary); + // Emit secondary opcode + enc_class OpcS %{ + emit_opcode(cbuf, $secondary); %} - enc_class Opcode(immI d8 ) %{ // Emit opcode - emit_opcode(cbuf,$d8$$constant); + // Emit opcode directly + enc_class Opcode(immI d8) %{ + emit_opcode(cbuf, $d8$$constant); %} enc_class SizePrefix %{ @@ -6387,6 +6391,67 @@ instruct bytes_reverse_long(eRegL dst) %{ %} +//---------- Population Count Instructions ------------------------------------- + +instruct popCountI(eRegI dst, eRegI src) %{ + predicate(UsePopCountInstruction); + match(Set dst (PopCountI src)); + + format %{ "POPCNT $dst, $src" %} + ins_encode %{ + __ popcntl($dst$$Register, $src$$Register); + %} + ins_pipe(ialu_reg); +%} + +instruct popCountI_mem(eRegI dst, memory mem) %{ + predicate(UsePopCountInstruction); + match(Set dst (PopCountI (LoadI mem))); + + format %{ "POPCNT $dst, $mem" %} + ins_encode %{ + __ popcntl($dst$$Register, $mem$$Address); + %} + ins_pipe(ialu_reg); +%} + +// Note: Long.bitCount(long) returns an int. +instruct popCountL(eRegI dst, eRegL src, eRegI tmp, eFlagsReg cr) %{ + predicate(UsePopCountInstruction); + match(Set dst (PopCountL src)); + effect(KILL cr, TEMP tmp, TEMP dst); + + format %{ "POPCNT $dst, $src.lo\n\t" + "POPCNT $tmp, $src.hi\n\t" + "ADD $dst, $tmp" %} + ins_encode %{ + __ popcntl($dst$$Register, $src$$Register); + __ popcntl($tmp$$Register, HIGH_FROM_LOW($src$$Register)); + __ addl($dst$$Register, $tmp$$Register); + %} + ins_pipe(ialu_reg); +%} + +// Note: Long.bitCount(long) returns an int. +instruct popCountL_mem(eRegI dst, memory mem, eRegI tmp, eFlagsReg cr) %{ + predicate(UsePopCountInstruction); + match(Set dst (PopCountL (LoadL mem))); + effect(KILL cr, TEMP tmp, TEMP dst); + + format %{ "POPCNT $dst, $mem\n\t" + "POPCNT $tmp, $mem+4\n\t" + "ADD $dst, $tmp" %} + ins_encode %{ + //__ popcntl($dst$$Register, $mem$$Address$$first); + //__ popcntl($tmp$$Register, $mem$$Address$$second); + __ popcntl($dst$$Register, Address::make_raw($mem$$base, $mem$$index, $mem$$scale, $mem$$disp, false)); + __ popcntl($tmp$$Register, Address::make_raw($mem$$base, $mem$$index, $mem$$scale, $mem$$disp + 4, false)); + __ addl($dst$$Register, $tmp$$Register); + %} + ins_pipe(ialu_reg); +%} + + //----------Load/Store/Move Instructions--------------------------------------- //----------Load Instructions-------------------------------------------------- // Load Byte (8bit signed) diff --git a/src/cpu/x86/vm/x86_64.ad b/src/cpu/x86/vm/x86_64.ad index 163c87ca18ce1b73ab74295a74aa13f374e554d9..5872d2b6d4a207ffbdbe5bcc1f326bdde39a04cf 100644 --- a/src/cpu/x86/vm/x86_64.ad +++ b/src/cpu/x86/vm/x86_64.ad @@ -7429,6 +7429,56 @@ instruct storeL_reversed(memory dst, rRegL src) %{ ins_pipe( ialu_mem_reg ); %} + +//---------- Population Count Instructions ------------------------------------- + +instruct popCountI(rRegI dst, rRegI src) %{ + predicate(UsePopCountInstruction); + match(Set dst (PopCountI src)); + + format %{ "popcnt $dst, $src" %} + ins_encode %{ + __ popcntl($dst$$Register, $src$$Register); + %} + ins_pipe(ialu_reg); +%} + +instruct popCountI_mem(rRegI dst, memory mem) %{ + predicate(UsePopCountInstruction); + match(Set dst (PopCountI (LoadI mem))); + + format %{ "popcnt $dst, $mem" %} + ins_encode %{ + __ popcntl($dst$$Register, $mem$$Address); + %} + ins_pipe(ialu_reg); +%} + +// Note: Long.bitCount(long) returns an int. +instruct popCountL(rRegI dst, rRegL src) %{ + predicate(UsePopCountInstruction); + match(Set dst (PopCountL src)); + + format %{ "popcnt $dst, $src" %} + ins_encode %{ + __ popcntq($dst$$Register, $src$$Register); + %} + ins_pipe(ialu_reg); +%} + +// Note: Long.bitCount(long) returns an int. +instruct popCountL_mem(rRegI dst, memory mem) %{ + predicate(UsePopCountInstruction); + match(Set dst (PopCountL (LoadL mem))); + + format %{ "popcnt $dst, $mem" %} + ins_encode %{ + __ popcntq($dst$$Register, $mem$$Address); + %} + ins_pipe(ialu_reg); +%} + + //----------MemBar Instructions----------------------------------------------- // Memory barrier flavors diff --git a/src/os_cpu/solaris_sparc/vm/vm_version_solaris_sparc.cpp b/src/os_cpu/solaris_sparc/vm/vm_version_solaris_sparc.cpp index d2c5baa5fd36fddde5ab934e88e4ca3453505c73..ec537c7fe54c3e141799c7020bc4631ea6a3a4ce 100644 --- a/src/os_cpu/solaris_sparc/vm/vm_version_solaris_sparc.cpp +++ b/src/os_cpu/solaris_sparc/vm/vm_version_solaris_sparc.cpp @@ -85,6 +85,7 @@ int VM_Version::platform_features(int features) { if (av & AV_SPARC_DIV32) features |= hardware_div32_m; if (av & AV_SPARC_FSMULD) features |= hardware_fsmuld_m; if (av & AV_SPARC_V8PLUS) features |= v9_instructions_m; + if (av & AV_SPARC_POPC) features |= hardware_popc_m; if (av & AV_SPARC_VIS) features |= vis1_instructions_m; if (av & AV_SPARC_VIS2) features |= vis2_instructions_m; } else { diff --git a/src/share/vm/classfile/vmSymbols.hpp b/src/share/vm/classfile/vmSymbols.hpp index 8379af9c414dffb1f5aa4005242f330ccd665e25..b9c17c2e2d24801d9d8f4b55fcd9abf84bf8bdff 100644 --- a/src/share/vm/classfile/vmSymbols.hpp +++ b/src/share/vm/classfile/vmSymbols.hpp @@ -1,5 +1,5 @@ /* - * Copyright 1997-2008 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1997-2009 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -284,6 +284,7 @@ template(value_name, "value") \ template(frontCacheEnabled_name, "frontCacheEnabled") \ template(stringCacheEnabled_name, "stringCacheEnabled") \ + template(bitCount_name, "bitCount") \ \ /* non-intrinsic name/signature pairs: */ \ template(register_method_name, "register") \ @@ -304,6 +305,7 @@ template(double_long_signature, "(D)J") \ template(double_double_signature, "(D)D") \ template(int_float_signature, "(I)F") \ + template(long_int_signature, "(J)I") \ template(long_long_signature, "(J)J") \ template(long_double_signature, "(J)D") \ template(byte_signature, "B") \ @@ -507,6 +509,10 @@ do_name( doubleToLongBits_name, "doubleToLongBits") \ do_intrinsic(_longBitsToDouble, java_lang_Double, longBitsToDouble_name, long_double_signature, F_S) \ do_name( longBitsToDouble_name, "longBitsToDouble") \ + \ + do_intrinsic(_bitCount_i, java_lang_Integer, bitCount_name, int_int_signature, F_S) \ + do_intrinsic(_bitCount_l, java_lang_Long, bitCount_name, long_int_signature, F_S) \ + \ do_intrinsic(_reverseBytes_i, java_lang_Integer, reverseBytes_name, int_int_signature, F_S) \ do_name( reverseBytes_name, "reverseBytes") \ do_intrinsic(_reverseBytes_l, java_lang_Long, reverseBytes_name, long_long_signature, F_S) \ @@ -696,7 +702,6 @@ do_signature(putShort_raw_signature, "(JS)V") \ do_signature(getChar_raw_signature, "(J)C") \ do_signature(putChar_raw_signature, "(JC)V") \ - do_signature(getInt_raw_signature, "(J)I") \ do_signature(putInt_raw_signature, "(JI)V") \ do_alias(getLong_raw_signature, /*(J)J*/ long_long_signature) \ do_alias(putLong_raw_signature, /*(JJ)V*/ long_long_void_signature) \ @@ -713,7 +718,7 @@ do_intrinsic(_getByte_raw, sun_misc_Unsafe, getByte_name, getByte_raw_signature, F_RN) \ do_intrinsic(_getShort_raw, sun_misc_Unsafe, getShort_name, getShort_raw_signature, F_RN) \ do_intrinsic(_getChar_raw, sun_misc_Unsafe, getChar_name, getChar_raw_signature, F_RN) \ - do_intrinsic(_getInt_raw, sun_misc_Unsafe, getInt_name, getInt_raw_signature, F_RN) \ + do_intrinsic(_getInt_raw, sun_misc_Unsafe, getInt_name, long_int_signature, F_RN) \ do_intrinsic(_getLong_raw, sun_misc_Unsafe, getLong_name, getLong_raw_signature, F_RN) \ do_intrinsic(_getFloat_raw, sun_misc_Unsafe, getFloat_name, getFloat_raw_signature, F_RN) \ do_intrinsic(_getDouble_raw, sun_misc_Unsafe, getDouble_name, getDouble_raw_signature, F_RN) \ diff --git a/src/share/vm/opto/classes.hpp b/src/share/vm/opto/classes.hpp index d527f5ea475271223d32d488c2e8d4548bd74898..87adb737cb7c4f1e580b817a772b436c45de124b 100644 --- a/src/share/vm/opto/classes.hpp +++ b/src/share/vm/opto/classes.hpp @@ -184,6 +184,8 @@ macro(PCTable) macro(Parm) macro(PartialSubtypeCheck) macro(Phi) +macro(PopCountI) +macro(PopCountL) macro(PowD) macro(PrefetchRead) macro(PrefetchWrite) diff --git a/src/share/vm/opto/connode.hpp b/src/share/vm/opto/connode.hpp index a16d7f2ee84d2df5acbc12cb9d6d960e0775a8a7..4c078d1b091caa82379d67a0f36b6f570142393c 100644 --- a/src/share/vm/opto/connode.hpp +++ b/src/share/vm/opto/connode.hpp @@ -1,5 +1,5 @@ /* - * Copyright 1997-2008 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1997-2009 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -635,3 +635,23 @@ class MoveD2LNode : public Node { virtual uint ideal_reg() const { return Op_RegL; } virtual const Type* Value( PhaseTransform *phase ) const; }; + +//---------- PopCountINode ----------------------------------------------------- +// Population count (bit count) of an integer. +class PopCountINode : public Node { +public: + PopCountINode(Node* in1) : Node(0, in1) {} + virtual int Opcode() const; + const Type* bottom_type() const { return TypeInt::INT; } + virtual uint ideal_reg() const { return Op_RegI; } +}; + +//---------- PopCountLNode ----------------------------------------------------- +// Population count (bit count) of a long. +class PopCountLNode : public Node { +public: + PopCountLNode(Node* in1) : Node(0, in1) {} + virtual int Opcode() const; + const Type* bottom_type() const { return TypeInt::INT; } + virtual uint ideal_reg() const { return Op_RegI; } +}; diff --git a/src/share/vm/opto/library_call.cpp b/src/share/vm/opto/library_call.cpp index 6cbcee84b51ad76ab292498a57d16a84f159700a..b5b7136a375e36e7e114226de35f79afc09d1fa4 100644 --- a/src/share/vm/opto/library_call.cpp +++ b/src/share/vm/opto/library_call.cpp @@ -1,5 +1,5 @@ /* - * Copyright 1999-2008 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1999-2009 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -221,6 +221,7 @@ class LibraryCallKit : public GraphKit { bool inline_unsafe_CAS(BasicType type); bool inline_unsafe_ordered_store(BasicType type); bool inline_fp_conversions(vmIntrinsics::ID id); + bool inline_bitCount(vmIntrinsics::ID id); bool inline_reverseBytes(vmIntrinsics::ID id); }; @@ -314,6 +315,11 @@ CallGenerator* Compile::make_vm_intrinsic(ciMethod* m, bool is_virtual) { if (!JDK_Version::is_gte_jdk14x_version()) return NULL; break; + case vmIntrinsics::_bitCount_i: + case vmIntrinsics::_bitCount_l: + if (!UsePopCountInstruction) return NULL; + break; + default: break; } @@ -617,6 +623,10 @@ bool LibraryCallKit::try_to_inline() { case vmIntrinsics::_longBitsToDouble: return inline_fp_conversions(intrinsic_id()); + case vmIntrinsics::_bitCount_i: + case vmIntrinsics::_bitCount_l: + return inline_bitCount(intrinsic_id()); + case vmIntrinsics::_reverseBytes_i: case vmIntrinsics::_reverseBytes_l: return inline_reverseBytes((vmIntrinsics::ID) intrinsic_id()); @@ -1714,6 +1724,27 @@ inline Node* LibraryCallKit::make_unsafe_address(Node* base, Node* offset) { } } +//----------------------------inline_bitCount_int/long----------------------- +// inline int Integer.bitCount(int) +// inline int Long.bitCount(long) +bool LibraryCallKit::inline_bitCount(vmIntrinsics::ID id) { + assert(id == vmIntrinsics::_bitCount_i || id == vmIntrinsics::_bitCount_l, "not bitCount"); + if (id == vmIntrinsics::_bitCount_i && !Matcher::has_match_rule(Op_PopCountI)) return false; + if (id == vmIntrinsics::_bitCount_l && !Matcher::has_match_rule(Op_PopCountL)) return false; + _sp += arg_size(); // restore stack pointer + switch (id) { + case vmIntrinsics::_bitCount_i: + push(_gvn.transform(new (C, 2) PopCountINode(pop()))); + break; + case vmIntrinsics::_bitCount_l: + push(_gvn.transform(new (C, 2) PopCountLNode(pop_pair()))); + break; + default: + ShouldNotReachHere(); + } + return true; +} + //----------------------------inline_reverseBytes_int/long------------------- // inline Integer.reverseBytes(int) // inline Long.reverseBytes(long) diff --git a/src/share/vm/runtime/globals.hpp b/src/share/vm/runtime/globals.hpp index 9855d5b8e5b4e0b1e0a2f053785f09541b811980..2d33287fcd4b874063a98afee69e06dc6711c967 100644 --- a/src/share/vm/runtime/globals.hpp +++ b/src/share/vm/runtime/globals.hpp @@ -1,5 +1,5 @@ /* - * Copyright 1997-2008 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1997-2009 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -2172,6 +2172,9 @@ class CommandLineFlags { diagnostic(bool, PrintIntrinsics, false, \ "prints attempted and successful inlining of intrinsics") \ \ + product(bool, UsePopCountInstruction, false, \ + "Use population count instruction") \ + \ diagnostic(ccstrlist, DisableIntrinsic, "", \ "do not expand intrinsics whose (internal) names appear here") \ \ diff --git a/test/compiler/6378821/Test6378821.java b/test/compiler/6378821/Test6378821.java new file mode 100644 index 0000000000000000000000000000000000000000..83c52decb41045ccd49b4021ef49e1e732c09a79 --- /dev/null +++ b/test/compiler/6378821/Test6378821.java @@ -0,0 +1,75 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/** + * @test + * @bug 6378821 + * @summary where available, bitCount() should use POPC on SPARC processors and AMD+10h + * + * @run main/othervm -Xcomp -XX:CompileOnly=Test6378821.fcomp Test6378821 + */ + +public class Test6378821 { + static final int[] ia = new int[] { 0x12345678 }; + static final long[] la = new long[] { 0x12345678abcdefL }; + + public static void main(String [] args) { + // Resolve the class and the method. + Integer.bitCount(1); + Long.bitCount(1); + + sub(ia[0]); + sub(la[0]); + sub(ia); + sub(la); + } + + static void check(int i, int expected, int result) { + if (result != expected) { + throw new InternalError("Wrong population count for " + i + ": " + result + " != " + expected); + } + } + + static void check(long l, int expected, int result) { + if (result != expected) { + throw new InternalError("Wrong population count for " + l + ": " + result + " != " + expected); + } + } + + static void sub(int i) { check(i, fint(i), fcomp(i) ); } + static void sub(int[] ia) { check(ia[0], fint(ia), fcomp(ia)); } + static void sub(long l) { check(l, fint(l), fcomp(l) ); } + static void sub(long[] la) { check(la[0], fint(la), fcomp(la)); } + + static int fint (int i) { return Integer.bitCount(i); } + static int fcomp(int i) { return Integer.bitCount(i); } + + static int fint (int[] ia) { return Integer.bitCount(ia[0]); } + static int fcomp(int[] ia) { return Integer.bitCount(ia[0]); } + + static int fint (long l) { return Long.bitCount(l); } + static int fcomp(long l) { return Long.bitCount(l); } + + static int fint (long[] la) { return Long.bitCount(la[0]); } + static int fcomp(long[] la) { return Long.bitCount(la[0]); } +}