提交 15677263 编写于 作者: T twisti

6378821: bitCount() should use POPC on SPARC processors and AMD+10h

Summary: bitCount() should use POPC on SPARC processors where POPC is implemented directly in hardware.
Reviewed-by: kvn, never
上级 abb8b5ba
...@@ -9015,6 +9015,33 @@ instruct string_compare(o0RegP str1, o1RegP str2, g3RegP tmp1, g4RegP tmp2, note ...@@ -9015,6 +9015,33 @@ instruct string_compare(o0RegP str1, o1RegP str2, g3RegP tmp1, g4RegP tmp2, note
ins_pipe(long_memory_op); 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-------------------------------------------------- //------------Bytes reverse--------------------------------------------------
......
...@@ -92,10 +92,18 @@ void VM_Version::initialize() { ...@@ -92,10 +92,18 @@ void VM_Version::initialize() {
#endif #endif
} }
// Use hardware population count instruction if available.
if (has_hardware_popc()) {
if (FLAG_IS_DEFAULT(UsePopCountInstruction)) {
UsePopCountInstruction = true;
}
}
char buf[512]; 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_v8() ? ", has_v8" : ""),
(has_v9() ? ", has_v9" : ""), (has_v9() ? ", has_v9" : ""),
(has_hardware_popc() ? ", popc" : ""),
(has_vis1() ? ", has_vis1" : ""), (has_vis1() ? ", has_vis1" : ""),
(has_vis2() ? ", has_vis2" : ""), (has_vis2() ? ", has_vis2" : ""),
(is_ultra3() ? ", is_ultra3" : ""), (is_ultra3() ? ", is_ultra3" : ""),
......
...@@ -29,10 +29,11 @@ protected: ...@@ -29,10 +29,11 @@ protected:
hardware_mul32 = 1, hardware_mul32 = 1,
hardware_div32 = 2, hardware_div32 = 2,
hardware_fsmuld = 3, hardware_fsmuld = 3,
v9_instructions = 4, hardware_popc = 4,
vis1_instructions = 5, v9_instructions = 5,
vis2_instructions = 6, vis1_instructions = 6,
sun4v_instructions = 7 vis2_instructions = 7,
sun4v_instructions = 8
}; };
enum Feature_Flag_Set { enum Feature_Flag_Set {
...@@ -43,6 +44,7 @@ protected: ...@@ -43,6 +44,7 @@ protected:
hardware_mul32_m = 1 << hardware_mul32, hardware_mul32_m = 1 << hardware_mul32,
hardware_div32_m = 1 << hardware_div32, hardware_div32_m = 1 << hardware_div32,
hardware_fsmuld_m = 1 << hardware_fsmuld, hardware_fsmuld_m = 1 << hardware_fsmuld,
hardware_popc_m = 1 << hardware_popc,
v9_instructions_m = 1 << v9_instructions, v9_instructions_m = 1 << v9_instructions,
vis1_instructions_m = 1 << vis1_instructions, vis1_instructions_m = 1 << vis1_instructions,
vis2_instructions_m = 1 << vis2_instructions, vis2_instructions_m = 1 << vis2_instructions,
...@@ -81,6 +83,7 @@ public: ...@@ -81,6 +83,7 @@ public:
static bool has_hardware_mul32() { return (_features & hardware_mul32_m) != 0; } 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_div32() { return (_features & hardware_div32_m) != 0; }
static bool has_hardware_fsmuld() { return (_features & hardware_fsmuld_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_vis1() { return (_features & vis1_instructions_m) != 0; }
static bool has_vis2() { return (_features & vis2_instructions_m) != 0; } static bool has_vis2() { return (_features & vis2_instructions_m) != 0; }
......
...@@ -2193,6 +2193,25 @@ void Assembler::pop(Register dst) { ...@@ -2193,6 +2193,25 @@ void Assembler::pop(Register dst) {
emit_byte(0x58 | encode); 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() { void Assembler::popf() {
emit_byte(0x9D); emit_byte(0x9D);
} }
...@@ -4080,6 +4099,25 @@ void Assembler::popa() { // 64bit ...@@ -4080,6 +4099,25 @@ void Assembler::popa() { // 64bit
addq(rsp, 16 * wordSize); 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) { void Assembler::popq(Address dst) {
InstructionMark im(this); InstructionMark im(this);
prefixq(dst); prefixq(dst);
......
...@@ -1224,6 +1224,14 @@ private: ...@@ -1224,6 +1224,14 @@ private:
void popq(Address dst); void popq(Address dst);
#endif #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) // Prefetches (SSE, SSE2, 3DNOW only)
void prefetchnta(Address src); void prefetchnta(Address src);
......
...@@ -284,7 +284,7 @@ void VM_Version::get_processor_features() { ...@@ -284,7 +284,7 @@ void VM_Version::get_processor_features() {
} }
char buf[256]; 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(), cores_per_cpu(), threads_per_core(),
cpu_family(), _model, _stepping, cpu_family(), _model, _stepping,
(supports_cmov() ? ", cmov" : ""), (supports_cmov() ? ", cmov" : ""),
...@@ -297,6 +297,7 @@ void VM_Version::get_processor_features() { ...@@ -297,6 +297,7 @@ void VM_Version::get_processor_features() {
(supports_ssse3()? ", ssse3": ""), (supports_ssse3()? ", ssse3": ""),
(supports_sse4_1() ? ", sse4.1" : ""), (supports_sse4_1() ? ", sse4.1" : ""),
(supports_sse4_2() ? ", sse4.2" : ""), (supports_sse4_2() ? ", sse4.2" : ""),
(supports_popcnt() ? ", popcnt" : ""),
(supports_mmx_ext() ? ", mmxext" : ""), (supports_mmx_ext() ? ", mmxext" : ""),
(supports_3dnow() ? ", 3dnow" : ""), (supports_3dnow() ? ", 3dnow" : ""),
(supports_3dnow2() ? ", 3dnowext" : ""), (supports_3dnow2() ? ", 3dnowext" : ""),
...@@ -410,6 +411,13 @@ void VM_Version::get_processor_features() { ...@@ -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 <= ReadPrefetchInstr && ReadPrefetchInstr <= 3, "invalid value");
assert(0 <= AllocatePrefetchInstr && AllocatePrefetchInstr <= 3, "invalid value"); assert(0 <= AllocatePrefetchInstr && AllocatePrefetchInstr <= 3, "invalid value");
......
...@@ -70,7 +70,9 @@ public: ...@@ -70,7 +70,9 @@ public:
dca : 1, dca : 1,
sse4_1 : 1, sse4_1 : 1,
sse4_2 : 1, sse4_2 : 1,
: 11; : 2,
popcnt : 1,
: 8;
} bits; } bits;
}; };
...@@ -179,7 +181,8 @@ protected: ...@@ -179,7 +181,8 @@ protected:
CPU_SSSE3 = (1 << 9), CPU_SSSE3 = (1 << 9),
CPU_SSE4A = (1 << 10), CPU_SSE4A = (1 << 10),
CPU_SSE4_1 = (1 << 11), CPU_SSE4_1 = (1 << 11),
CPU_SSE4_2 = (1 << 12) CPU_SSE4_2 = (1 << 12),
CPU_POPCNT = (1 << 13)
} cpuFeatureFlags; } cpuFeatureFlags;
// cpuid information block. All info derived from executing cpuid with // cpuid information block. All info derived from executing cpuid with
...@@ -290,6 +293,8 @@ protected: ...@@ -290,6 +293,8 @@ protected:
result |= CPU_SSE4_1; result |= CPU_SSE4_1;
if (_cpuid_info.std_cpuid1_ecx.bits.sse4_2 != 0) if (_cpuid_info.std_cpuid1_ecx.bits.sse4_2 != 0)
result |= CPU_SSE4_2; result |= CPU_SSE4_2;
if (_cpuid_info.std_cpuid1_ecx.bits.popcnt != 0)
result |= CPU_POPCNT;
return result; return result;
} }
...@@ -379,6 +384,7 @@ public: ...@@ -379,6 +384,7 @@ public:
static bool supports_ssse3() { return (_cpuFeatures & CPU_SSSE3)!= 0; } static bool supports_ssse3() { return (_cpuFeatures & CPU_SSSE3)!= 0; }
static bool supports_sse4_1() { return (_cpuFeatures & CPU_SSE4_1) != 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_sse4_2() { return (_cpuFeatures & CPU_SSE4_2) != 0; }
static bool supports_popcnt() { return (_cpuFeatures & CPU_POPCNT) != 0; }
// //
// AMD features // AMD features
// //
......
...@@ -1483,16 +1483,20 @@ encode %{ ...@@ -1483,16 +1483,20 @@ encode %{
// main source block for now. In future, we can generalize this by // main source block for now. In future, we can generalize this by
// adding a syntax that specifies the sizes of fields in an order, // adding a syntax that specifies the sizes of fields in an order,
// so that the adlc can build the emit functions automagically // 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 secondary opcode
emit_opcode(cbuf,$secondary); enc_class OpcS %{
emit_opcode(cbuf, $secondary);
%} %}
enc_class Opcode(immI d8 ) %{ // Emit opcode // Emit opcode directly
emit_opcode(cbuf,$d8$$constant); enc_class Opcode(immI d8) %{
emit_opcode(cbuf, $d8$$constant);
%} %}
enc_class SizePrefix %{ enc_class SizePrefix %{
...@@ -6387,6 +6391,67 @@ instruct bytes_reverse_long(eRegL dst) %{ ...@@ -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/Store/Move Instructions---------------------------------------
//----------Load Instructions-------------------------------------------------- //----------Load Instructions--------------------------------------------------
// Load Byte (8bit signed) // Load Byte (8bit signed)
......
...@@ -7429,6 +7429,56 @@ instruct storeL_reversed(memory dst, rRegL src) %{ ...@@ -7429,6 +7429,56 @@ instruct storeL_reversed(memory dst, rRegL src) %{
ins_pipe( ialu_mem_reg ); 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----------------------------------------------- //----------MemBar Instructions-----------------------------------------------
// Memory barrier flavors // Memory barrier flavors
......
...@@ -85,6 +85,7 @@ int VM_Version::platform_features(int features) { ...@@ -85,6 +85,7 @@ int VM_Version::platform_features(int features) {
if (av & AV_SPARC_DIV32) features |= hardware_div32_m; if (av & AV_SPARC_DIV32) features |= hardware_div32_m;
if (av & AV_SPARC_FSMULD) features |= hardware_fsmuld_m; if (av & AV_SPARC_FSMULD) features |= hardware_fsmuld_m;
if (av & AV_SPARC_V8PLUS) features |= v9_instructions_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_VIS) features |= vis1_instructions_m;
if (av & AV_SPARC_VIS2) features |= vis2_instructions_m; if (av & AV_SPARC_VIS2) features |= vis2_instructions_m;
} else { } else {
......
/* /*
* 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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -284,6 +284,7 @@ ...@@ -284,6 +284,7 @@
template(value_name, "value") \ template(value_name, "value") \
template(frontCacheEnabled_name, "frontCacheEnabled") \ template(frontCacheEnabled_name, "frontCacheEnabled") \
template(stringCacheEnabled_name, "stringCacheEnabled") \ template(stringCacheEnabled_name, "stringCacheEnabled") \
template(bitCount_name, "bitCount") \
\ \
/* non-intrinsic name/signature pairs: */ \ /* non-intrinsic name/signature pairs: */ \
template(register_method_name, "register") \ template(register_method_name, "register") \
...@@ -304,6 +305,7 @@ ...@@ -304,6 +305,7 @@
template(double_long_signature, "(D)J") \ template(double_long_signature, "(D)J") \
template(double_double_signature, "(D)D") \ template(double_double_signature, "(D)D") \
template(int_float_signature, "(I)F") \ template(int_float_signature, "(I)F") \
template(long_int_signature, "(J)I") \
template(long_long_signature, "(J)J") \ template(long_long_signature, "(J)J") \
template(long_double_signature, "(J)D") \ template(long_double_signature, "(J)D") \
template(byte_signature, "B") \ template(byte_signature, "B") \
...@@ -507,6 +509,10 @@ ...@@ -507,6 +509,10 @@
do_name( doubleToLongBits_name, "doubleToLongBits") \ do_name( doubleToLongBits_name, "doubleToLongBits") \
do_intrinsic(_longBitsToDouble, java_lang_Double, longBitsToDouble_name, long_double_signature, F_S) \ do_intrinsic(_longBitsToDouble, java_lang_Double, longBitsToDouble_name, long_double_signature, F_S) \
do_name( longBitsToDouble_name, "longBitsToDouble") \ 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_intrinsic(_reverseBytes_i, java_lang_Integer, reverseBytes_name, int_int_signature, F_S) \
do_name( reverseBytes_name, "reverseBytes") \ do_name( reverseBytes_name, "reverseBytes") \
do_intrinsic(_reverseBytes_l, java_lang_Long, reverseBytes_name, long_long_signature, F_S) \ do_intrinsic(_reverseBytes_l, java_lang_Long, reverseBytes_name, long_long_signature, F_S) \
...@@ -696,7 +702,6 @@ ...@@ -696,7 +702,6 @@
do_signature(putShort_raw_signature, "(JS)V") \ do_signature(putShort_raw_signature, "(JS)V") \
do_signature(getChar_raw_signature, "(J)C") \ do_signature(getChar_raw_signature, "(J)C") \
do_signature(putChar_raw_signature, "(JC)V") \ do_signature(putChar_raw_signature, "(JC)V") \
do_signature(getInt_raw_signature, "(J)I") \
do_signature(putInt_raw_signature, "(JI)V") \ do_signature(putInt_raw_signature, "(JI)V") \
do_alias(getLong_raw_signature, /*(J)J*/ long_long_signature) \ do_alias(getLong_raw_signature, /*(J)J*/ long_long_signature) \
do_alias(putLong_raw_signature, /*(JJ)V*/ long_long_void_signature) \ do_alias(putLong_raw_signature, /*(JJ)V*/ long_long_void_signature) \
...@@ -713,7 +718,7 @@ ...@@ -713,7 +718,7 @@
do_intrinsic(_getByte_raw, sun_misc_Unsafe, getByte_name, getByte_raw_signature, F_RN) \ 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(_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(_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(_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(_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) \ do_intrinsic(_getDouble_raw, sun_misc_Unsafe, getDouble_name, getDouble_raw_signature, F_RN) \
......
...@@ -184,6 +184,8 @@ macro(PCTable) ...@@ -184,6 +184,8 @@ macro(PCTable)
macro(Parm) macro(Parm)
macro(PartialSubtypeCheck) macro(PartialSubtypeCheck)
macro(Phi) macro(Phi)
macro(PopCountI)
macro(PopCountL)
macro(PowD) macro(PowD)
macro(PrefetchRead) macro(PrefetchRead)
macro(PrefetchWrite) macro(PrefetchWrite)
......
/* /*
* 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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -635,3 +635,23 @@ class MoveD2LNode : public Node { ...@@ -635,3 +635,23 @@ class MoveD2LNode : public Node {
virtual uint ideal_reg() const { return Op_RegL; } virtual uint ideal_reg() const { return Op_RegL; }
virtual const Type* Value( PhaseTransform *phase ) const; 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; }
};
/* /*
* 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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -221,6 +221,7 @@ class LibraryCallKit : public GraphKit { ...@@ -221,6 +221,7 @@ class LibraryCallKit : public GraphKit {
bool inline_unsafe_CAS(BasicType type); bool inline_unsafe_CAS(BasicType type);
bool inline_unsafe_ordered_store(BasicType type); bool inline_unsafe_ordered_store(BasicType type);
bool inline_fp_conversions(vmIntrinsics::ID id); bool inline_fp_conversions(vmIntrinsics::ID id);
bool inline_bitCount(vmIntrinsics::ID id);
bool inline_reverseBytes(vmIntrinsics::ID id); bool inline_reverseBytes(vmIntrinsics::ID id);
}; };
...@@ -314,6 +315,11 @@ CallGenerator* Compile::make_vm_intrinsic(ciMethod* m, bool is_virtual) { ...@@ -314,6 +315,11 @@ CallGenerator* Compile::make_vm_intrinsic(ciMethod* m, bool is_virtual) {
if (!JDK_Version::is_gte_jdk14x_version()) return NULL; if (!JDK_Version::is_gte_jdk14x_version()) return NULL;
break; break;
case vmIntrinsics::_bitCount_i:
case vmIntrinsics::_bitCount_l:
if (!UsePopCountInstruction) return NULL;
break;
default: default:
break; break;
} }
...@@ -617,6 +623,10 @@ bool LibraryCallKit::try_to_inline() { ...@@ -617,6 +623,10 @@ bool LibraryCallKit::try_to_inline() {
case vmIntrinsics::_longBitsToDouble: case vmIntrinsics::_longBitsToDouble:
return inline_fp_conversions(intrinsic_id()); 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_i:
case vmIntrinsics::_reverseBytes_l: case vmIntrinsics::_reverseBytes_l:
return inline_reverseBytes((vmIntrinsics::ID) intrinsic_id()); return inline_reverseBytes((vmIntrinsics::ID) intrinsic_id());
...@@ -1714,6 +1724,27 @@ inline Node* LibraryCallKit::make_unsafe_address(Node* base, Node* offset) { ...@@ -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_reverseBytes_int/long-------------------
// inline Integer.reverseBytes(int) // inline Integer.reverseBytes(int)
// inline Long.reverseBytes(long) // inline Long.reverseBytes(long)
......
/* /*
* 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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -2172,6 +2172,9 @@ class CommandLineFlags { ...@@ -2172,6 +2172,9 @@ class CommandLineFlags {
diagnostic(bool, PrintIntrinsics, false, \ diagnostic(bool, PrintIntrinsics, false, \
"prints attempted and successful inlining of intrinsics") \ "prints attempted and successful inlining of intrinsics") \
\ \
product(bool, UsePopCountInstruction, false, \
"Use population count instruction") \
\
diagnostic(ccstrlist, DisableIntrinsic, "", \ diagnostic(ccstrlist, DisableIntrinsic, "", \
"do not expand intrinsics whose (internal) names appear here") \ "do not expand intrinsics whose (internal) names appear here") \
\ \
......
/*
* 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]); }
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册