--- a/src/cpu/x86/vm/vm_version_x86_32.cpp Sat Jun 21 10:03:31 2008 -0700
+++ b/src/cpu/x86/vm/vm_version_x86_32.cpp Mon Jun 23 14:11:12 2008 -0700
@@ -306,6 +306,10 @@ void VM_Version::get_processor_features(
if( supports_sse2() && FLAG_IS_DEFAULT(UseAddressNop) ) {
// Use it on new AMD cpus starting from Opteron.
UseAddressNop = true;
+ }
+ if( supports_sse2() && FLAG_IS_DEFAULT(UseNewLongLShift) ) {
+ // Use it on new AMD cpus starting from Opteron.
+ UseNewLongLShift = true;
}
if( FLAG_IS_DEFAULT(UseXmmLoadAndClearUpper) ) {
if( supports_sse4a() ) {
--- a/src/cpu/x86/vm/x86_32.ad Sat Jun 21 10:03:31 2008 -0700
+++ b/src/cpu/x86/vm/x86_32.ad Mon Jun 23 14:11:12 2008 -0700
@@ -4754,6 +4754,33 @@ operand immI_32_63() %{
interface(CONST_INTER);
%}
+operand immI_1() %{
+ predicate( n->get_int() == 1 );
+ match(ConI);
+
+ op_cost(0);
+ format %{ %}
+ interface(CONST_INTER);
+%}
+
+operand immI_2() %{
+ predicate( n->get_int() == 2 );
+ match(ConI);
+
+ op_cost(0);
+ format %{ %}
+ interface(CONST_INTER);
+%}
+
+operand immI_3() %{
+ predicate( n->get_int() == 3 );
+ match(ConI);
+
+ op_cost(0);
+ format %{ %}
+ interface(CONST_INTER);
+%}
+
// Pointer Immediate
operand immP() %{
match(ConP);
@@ -8941,6 +8968,63 @@ instruct xorl_eReg_mem(eRegL dst, load_l
opcode(0x33,0x33);
ins_encode( OpcP, RegMem( dst, mem), OpcS, RegMem_Hi(dst,mem) );
ins_pipe( ialu_reg_long_mem );
+%}
+
+// Shift Left Long by 1
+instruct shlL_eReg_1(eRegL dst, immI_1 cnt, eFlagsReg cr) %{
+ predicate(UseNewLongLShift);
+ match(Set dst (LShiftL dst cnt));
+ effect(KILL cr);
+ ins_cost(100);
+ format %{ "ADD $dst.lo,$dst.lo\n\t"
+ "ADC $dst.hi,$dst.hi" %}
+ ins_encode %{
+ __ addl($dst$$Register,$dst$$Register);
+ __ adcl(HIGH_FROM_LOW($dst$$Register),HIGH_FROM_LOW($dst$$Register));
+ %}
+ ins_pipe( ialu_reg_long );
+%}
+
+// Shift Left Long by 2
+instruct shlL_eReg_2(eRegL dst, immI_2 cnt, eFlagsReg cr) %{
+ predicate(UseNewLongLShift);
+ match(Set dst (LShiftL dst cnt));
+ effect(KILL cr);
+ ins_cost(100);
+ format %{ "ADD $dst.lo,$dst.lo\n\t"
+ "ADC $dst.hi,$dst.hi\n\t"
+ "ADD $dst.lo,$dst.lo\n\t"
+ "ADC $dst.hi,$dst.hi" %}
+ ins_encode %{
+ __ addl($dst$$Register,$dst$$Register);
+ __ adcl(HIGH_FROM_LOW($dst$$Register),HIGH_FROM_LOW($dst$$Register));
+ __ addl($dst$$Register,$dst$$Register);
+ __ adcl(HIGH_FROM_LOW($dst$$Register),HIGH_FROM_LOW($dst$$Register));
+ %}
+ ins_pipe( ialu_reg_long );
+%}
+
+// Shift Left Long by 3
+instruct shlL_eReg_3(eRegL dst, immI_3 cnt, eFlagsReg cr) %{
+ predicate(UseNewLongLShift);
+ match(Set dst (LShiftL dst cnt));
+ effect(KILL cr);
+ ins_cost(100);
+ format %{ "ADD $dst.lo,$dst.lo\n\t"
+ "ADC $dst.hi,$dst.hi\n\t"
+ "ADD $dst.lo,$dst.lo\n\t"
+ "ADC $dst.hi,$dst.hi\n\t"
+ "ADD $dst.lo,$dst.lo\n\t"
+ "ADC $dst.hi,$dst.hi" %}
+ ins_encode %{
+ __ addl($dst$$Register,$dst$$Register);
+ __ adcl(HIGH_FROM_LOW($dst$$Register),HIGH_FROM_LOW($dst$$Register));
+ __ addl($dst$$Register,$dst$$Register);
+ __ adcl(HIGH_FROM_LOW($dst$$Register),HIGH_FROM_LOW($dst$$Register));
+ __ addl($dst$$Register,$dst$$Register);
+ __ adcl(HIGH_FROM_LOW($dst$$Register),HIGH_FROM_LOW($dst$$Register));
+ %}
+ ins_pipe( ialu_reg_long );
%}
// Shift Left Long by 1-31
--- a/src/share/vm/runtime/globals.hpp Sat Jun 21 10:03:31 2008 -0700
+++ b/src/share/vm/runtime/globals.hpp Mon Jun 23 14:11:12 2008 -0700
@@ -946,6 +946,9 @@ class CommandLineFlags {
diagnostic(bool, UseIncDec, true, \
"Use INC, DEC instructions on x86") \
\
+ product(bool, UseNewLongLShift, false, \
+ "Use optimized bitwise shift left") \
+ \
product(bool, UseStoreImmI16, true, \
"Use store immediate 16-bits value instruction on x86") \
\