Fri, 26 Jun 2009 07:26:10 -0700
5057225: Remove useless I2L conversions
Summary: The optimizer should be told to normalize (AndL (ConvI2L x) 0xFF) to (ConvI2L (AndI x 0xFF)), and then the existing matcher rule will work for free.
Reviewed-by: kvn
1.1 --- a/src/cpu/sparc/vm/sparc.ad Wed Jun 24 12:00:51 2009 -0700 1.2 +++ b/src/cpu/sparc/vm/sparc.ad Fri Jun 26 07:26:10 2009 -0700 1.3 @@ -1891,17 +1891,17 @@ 1.4 // The intptr_t operand types, defined by textual substitution. 1.5 // (Cf. opto/type.hpp. This lets us avoid many, many other ifdefs.) 1.6 #ifdef _LP64 1.7 -#define immX immL 1.8 -#define immX13 immL13 1.9 -#define immX13m7 immL13m7 1.10 -#define iRegX iRegL 1.11 -#define g1RegX g1RegL 1.12 +#define immX immL 1.13 +#define immX13 immL13 1.14 +#define immX13m7 immL13m7 1.15 +#define iRegX iRegL 1.16 +#define g1RegX g1RegL 1.17 #else 1.18 -#define immX immI 1.19 -#define immX13 immI13 1.20 -#define immX13m7 immI13m7 1.21 -#define iRegX iRegI 1.22 -#define g1RegX g1RegI 1.23 +#define immX immI 1.24 +#define immX13 immI13 1.25 +#define immX13m7 immI13m7 1.26 +#define iRegX iRegI 1.27 +#define g1RegX g1RegI 1.28 #endif 1.29 1.30 //----------ENCODING BLOCK----------------------------------------------------- 1.31 @@ -3446,6 +3446,15 @@ 1.32 interface(CONST_INTER); 1.33 %} 1.34 1.35 +// Integer Immediate: 8-bit 1.36 +operand immI8() %{ 1.37 + predicate(Assembler::is_simm(n->get_int(), 8)); 1.38 + match(ConI); 1.39 + op_cost(0); 1.40 + format %{ %} 1.41 + interface(CONST_INTER); 1.42 +%} 1.43 + 1.44 // Integer Immediate: 13-bit 1.45 operand immI13() %{ 1.46 predicate(Assembler::is_simm13(n->get_int())); 1.47 @@ -3466,6 +3475,15 @@ 1.48 interface(CONST_INTER); 1.49 %} 1.50 1.51 +// Integer Immediate: 16-bit 1.52 +operand immI16() %{ 1.53 + predicate(Assembler::is_simm(n->get_int(), 16)); 1.54 + match(ConI); 1.55 + op_cost(0); 1.56 + format %{ %} 1.57 + interface(CONST_INTER); 1.58 +%} 1.59 + 1.60 // Unsigned (positive) Integer Immediate: 13-bit 1.61 operand immU13() %{ 1.62 predicate((0 <= n->get_int()) && Assembler::is_simm13(n->get_int())); 1.63 @@ -5544,7 +5562,7 @@ 1.64 ins_encode %{ 1.65 __ ldub($mem$$Address, $dst$$Register); 1.66 %} 1.67 - ins_pipe(iload_mask_mem); 1.68 + ins_pipe(iload_mem); 1.69 %} 1.70 1.71 // Load Unsigned Byte (8bit UNsigned) into a Long Register 1.72 @@ -5557,7 +5575,22 @@ 1.73 ins_encode %{ 1.74 __ ldub($mem$$Address, $dst$$Register); 1.75 %} 1.76 - ins_pipe(iload_mask_mem); 1.77 + ins_pipe(iload_mem); 1.78 +%} 1.79 + 1.80 +// Load Unsigned Byte (8 bit UNsigned) with 8-bit mask into Long Register 1.81 +instruct loadUB2L_immI8(iRegL dst, memory mem, immI8 mask) %{ 1.82 + match(Set dst (ConvI2L (AndI (LoadUB mem) mask))); 1.83 + ins_cost(MEMORY_REF_COST + DEFAULT_COST); 1.84 + 1.85 + size(2*4); 1.86 + format %{ "LDUB $mem,$dst\t# ubyte & 8-bit mask -> long\n\t" 1.87 + "AND $dst,$mask,$dst" %} 1.88 + ins_encode %{ 1.89 + __ ldub($mem$$Address, $dst$$Register); 1.90 + __ and3($dst$$Register, $mask$$constant, $dst$$Register); 1.91 + %} 1.92 + ins_pipe(iload_mem); 1.93 %} 1.94 1.95 // Load Short (16bit signed) 1.96 @@ -5610,7 +5643,7 @@ 1.97 ins_encode %{ 1.98 __ lduh($mem$$Address, $dst$$Register); 1.99 %} 1.100 - ins_pipe(iload_mask_mem); 1.101 + ins_pipe(iload_mem); 1.102 %} 1.103 1.104 // Load Unsigned Short/Char (16 bit UNsigned) to Byte (8 bit signed) 1.105 @@ -5636,7 +5669,56 @@ 1.106 ins_encode %{ 1.107 __ lduh($mem$$Address, $dst$$Register); 1.108 %} 1.109 - ins_pipe(iload_mask_mem); 1.110 + ins_pipe(iload_mem); 1.111 +%} 1.112 + 1.113 +// Load Unsigned Short/Char (16bit UNsigned) with mask 0xFF into a Long Register 1.114 +instruct loadUS2L_immI_255(iRegL dst, indOffset13m7 mem, immI_255 mask) %{ 1.115 + match(Set dst (ConvI2L (AndI (LoadUS mem) mask))); 1.116 + ins_cost(MEMORY_REF_COST); 1.117 + 1.118 + size(4); 1.119 + format %{ "LDUB $mem+1,$dst\t! ushort/char & 0xFF -> long" %} 1.120 + ins_encode %{ 1.121 + __ ldub($mem$$Address, $dst$$Register, 1); // LSB is index+1 on BE 1.122 + %} 1.123 + ins_pipe(iload_mem); 1.124 +%} 1.125 + 1.126 +// Load Unsigned Short/Char (16bit UNsigned) with a 13-bit mask into a Long Register 1.127 +instruct loadUS2L_immI13(iRegL dst, memory mem, immI13 mask) %{ 1.128 + match(Set dst (ConvI2L (AndI (LoadUS mem) mask))); 1.129 + ins_cost(MEMORY_REF_COST + DEFAULT_COST); 1.130 + 1.131 + size(2*4); 1.132 + format %{ "LDUH $mem,$dst\t! ushort/char & 13-bit mask -> long\n\t" 1.133 + "AND $dst,$mask,$dst" %} 1.134 + ins_encode %{ 1.135 + Register Rdst = $dst$$Register; 1.136 + __ lduh($mem$$Address, Rdst); 1.137 + __ and3(Rdst, $mask$$constant, Rdst); 1.138 + %} 1.139 + ins_pipe(iload_mem); 1.140 +%} 1.141 + 1.142 +// Load Unsigned Short/Char (16bit UNsigned) with a 16-bit mask into a Long Register 1.143 +instruct loadUS2L_immI16(iRegL dst, memory mem, immI16 mask, iRegL tmp) %{ 1.144 + match(Set dst (ConvI2L (AndI (LoadUS mem) mask))); 1.145 + effect(TEMP dst, TEMP tmp); 1.146 + ins_cost(MEMORY_REF_COST + 2*DEFAULT_COST); 1.147 + 1.148 + size(3*4); 1.149 + format %{ "LDUH $mem,$dst\t! ushort/char & 16-bit mask -> long\n\t" 1.150 + "SET $mask,$tmp\n\t" 1.151 + "AND $dst,$tmp,$dst" %} 1.152 + ins_encode %{ 1.153 + Register Rdst = $dst$$Register; 1.154 + Register Rtmp = $tmp$$Register; 1.155 + __ lduh($mem$$Address, Rdst); 1.156 + __ set($mask$$constant, Rtmp); 1.157 + __ and3(Rdst, Rtmp, Rdst); 1.158 + %} 1.159 + ins_pipe(iload_mem); 1.160 %} 1.161 1.162 // Load Integer 1.163 @@ -5718,6 +5800,68 @@ 1.164 ins_encode %{ 1.165 __ ldsw($mem$$Address, $dst$$Register); 1.166 %} 1.167 + ins_pipe(iload_mask_mem); 1.168 +%} 1.169 + 1.170 +// Load Integer with mask 0xFF into a Long Register 1.171 +instruct loadI2L_immI_255(iRegL dst, indOffset13m7 mem, immI_255 mask) %{ 1.172 + match(Set dst (ConvI2L (AndI (LoadI mem) mask))); 1.173 + ins_cost(MEMORY_REF_COST); 1.174 + 1.175 + size(4); 1.176 + format %{ "LDUB $mem+3,$dst\t! int & 0xFF -> long" %} 1.177 + ins_encode %{ 1.178 + __ ldub($mem$$Address, $dst$$Register, 3); // LSB is index+3 on BE 1.179 + %} 1.180 + ins_pipe(iload_mem); 1.181 +%} 1.182 + 1.183 +// Load Integer with mask 0xFFFF into a Long Register 1.184 +instruct loadI2L_immI_65535(iRegL dst, indOffset13m7 mem, immI_65535 mask) %{ 1.185 + match(Set dst (ConvI2L (AndI (LoadI mem) mask))); 1.186 + ins_cost(MEMORY_REF_COST); 1.187 + 1.188 + size(4); 1.189 + format %{ "LDUH $mem+2,$dst\t! int & 0xFFFF -> long" %} 1.190 + ins_encode %{ 1.191 + __ lduh($mem$$Address, $dst$$Register, 2); // LSW is index+2 on BE 1.192 + %} 1.193 + ins_pipe(iload_mem); 1.194 +%} 1.195 + 1.196 +// Load Integer with a 13-bit mask into a Long Register 1.197 +instruct loadI2L_immI13(iRegL dst, memory mem, immI13 mask) %{ 1.198 + match(Set dst (ConvI2L (AndI (LoadI mem) mask))); 1.199 + ins_cost(MEMORY_REF_COST + DEFAULT_COST); 1.200 + 1.201 + size(2*4); 1.202 + format %{ "LDUW $mem,$dst\t! int & 13-bit mask -> long\n\t" 1.203 + "AND $dst,$mask,$dst" %} 1.204 + ins_encode %{ 1.205 + Register Rdst = $dst$$Register; 1.206 + __ lduw($mem$$Address, Rdst); 1.207 + __ and3(Rdst, $mask$$constant, Rdst); 1.208 + %} 1.209 + ins_pipe(iload_mem); 1.210 +%} 1.211 + 1.212 +// Load Integer with a 32-bit mask into a Long Register 1.213 +instruct loadI2L_immI(iRegL dst, memory mem, immI mask, iRegL tmp) %{ 1.214 + match(Set dst (ConvI2L (AndI (LoadI mem) mask))); 1.215 + effect(TEMP dst, TEMP tmp); 1.216 + ins_cost(MEMORY_REF_COST + 2*DEFAULT_COST); 1.217 + 1.218 + size(3*4); 1.219 + format %{ "LDUW $mem,$dst\t! int & 32-bit mask -> long\n\t" 1.220 + "SET $mask,$tmp\n\t" 1.221 + "AND $dst,$tmp,$dst" %} 1.222 + ins_encode %{ 1.223 + Register Rdst = $dst$$Register; 1.224 + Register Rtmp = $tmp$$Register; 1.225 + __ lduw($mem$$Address, Rdst); 1.226 + __ set($mask$$constant, Rtmp); 1.227 + __ and3(Rdst, Rtmp, Rdst); 1.228 + %} 1.229 ins_pipe(iload_mem); 1.230 %} 1.231
2.1 --- a/src/cpu/x86/vm/x86_32.ad Wed Jun 24 12:00:51 2009 -0700 2.2 +++ b/src/cpu/x86/vm/x86_32.ad Fri Jun 26 07:26:10 2009 -0700 2.3 @@ -6885,8 +6885,9 @@ 2.4 %} 2.5 2.6 // Load Byte (8bit signed) into Long Register 2.7 -instruct loadB2L(eRegL dst, memory mem) %{ 2.8 +instruct loadB2L(eRegL dst, memory mem, eFlagsReg cr) %{ 2.9 match(Set dst (ConvI2L (LoadB mem))); 2.10 + effect(KILL cr); 2.11 2.12 ins_cost(375); 2.13 format %{ "MOVSX8 $dst.lo,$mem\t# byte -> long\n\t" 2.14 @@ -6917,19 +6918,37 @@ 2.15 %} 2.16 2.17 // Load Unsigned Byte (8 bit UNsigned) into Long Register 2.18 -instruct loadUB2L(eRegL dst, memory mem) 2.19 -%{ 2.20 +instruct loadUB2L(eRegL dst, memory mem, eFlagsReg cr) %{ 2.21 match(Set dst (ConvI2L (LoadUB mem))); 2.22 + effect(KILL cr); 2.23 2.24 ins_cost(250); 2.25 format %{ "MOVZX8 $dst.lo,$mem\t# ubyte -> long\n\t" 2.26 "XOR $dst.hi,$dst.hi" %} 2.27 2.28 ins_encode %{ 2.29 - __ movzbl($dst$$Register, $mem$$Address); 2.30 - __ xorl(HIGH_FROM_LOW($dst$$Register), HIGH_FROM_LOW($dst$$Register)); 2.31 - %} 2.32 - 2.33 + Register Rdst = $dst$$Register; 2.34 + __ movzbl(Rdst, $mem$$Address); 2.35 + __ xorl(HIGH_FROM_LOW(Rdst), HIGH_FROM_LOW(Rdst)); 2.36 + %} 2.37 + 2.38 + ins_pipe(ialu_reg_mem); 2.39 +%} 2.40 + 2.41 +// Load Unsigned Byte (8 bit UNsigned) with mask into Long Register 2.42 +instruct loadUB2L_immI8(eRegL dst, memory mem, immI8 mask, eFlagsReg cr) %{ 2.43 + match(Set dst (ConvI2L (AndI (LoadUB mem) mask))); 2.44 + effect(KILL cr); 2.45 + 2.46 + format %{ "MOVZX8 $dst.lo,$mem\t# ubyte & 8-bit mask -> long\n\t" 2.47 + "XOR $dst.hi,$dst.hi\n\t" 2.48 + "AND $dst.lo,$mask" %} 2.49 + ins_encode %{ 2.50 + Register Rdst = $dst$$Register; 2.51 + __ movzbl(Rdst, $mem$$Address); 2.52 + __ xorl(HIGH_FROM_LOW(Rdst), HIGH_FROM_LOW(Rdst)); 2.53 + __ andl(Rdst, $mask$$constant); 2.54 + %} 2.55 ins_pipe(ialu_reg_mem); 2.56 %} 2.57 2.58 @@ -6960,8 +6979,9 @@ 2.59 %} 2.60 2.61 // Load Short (16bit signed) into Long Register 2.62 -instruct loadS2L(eRegL dst, memory mem) %{ 2.63 +instruct loadS2L(eRegL dst, memory mem, eFlagsReg cr) %{ 2.64 match(Set dst (ConvI2L (LoadS mem))); 2.65 + effect(KILL cr); 2.66 2.67 ins_cost(375); 2.68 format %{ "MOVSX $dst.lo,$mem\t# short -> long\n\t" 2.69 @@ -7004,8 +7024,9 @@ 2.70 %} 2.71 2.72 // Load Unsigned Short/Char (16 bit UNsigned) into Long Register 2.73 -instruct loadUS2L(eRegL dst, memory mem) %{ 2.74 +instruct loadUS2L(eRegL dst, memory mem, eFlagsReg cr) %{ 2.75 match(Set dst (ConvI2L (LoadUS mem))); 2.76 + effect(KILL cr); 2.77 2.78 ins_cost(250); 2.79 format %{ "MOVZX $dst.lo,$mem\t# ushort/char -> long\n\t" 2.80 @@ -7019,6 +7040,38 @@ 2.81 ins_pipe(ialu_reg_mem); 2.82 %} 2.83 2.84 +// Load Unsigned Short/Char (16 bit UNsigned) with mask 0xFF into Long Register 2.85 +instruct loadUS2L_immI_255(eRegL dst, memory mem, immI_255 mask, eFlagsReg cr) %{ 2.86 + match(Set dst (ConvI2L (AndI (LoadUS mem) mask))); 2.87 + effect(KILL cr); 2.88 + 2.89 + format %{ "MOVZX8 $dst.lo,$mem\t# ushort/char & 0xFF -> long\n\t" 2.90 + "XOR $dst.hi,$dst.hi" %} 2.91 + ins_encode %{ 2.92 + Register Rdst = $dst$$Register; 2.93 + __ movzbl(Rdst, $mem$$Address); 2.94 + __ xorl(HIGH_FROM_LOW(Rdst), HIGH_FROM_LOW(Rdst)); 2.95 + %} 2.96 + ins_pipe(ialu_reg_mem); 2.97 +%} 2.98 + 2.99 +// Load Unsigned Short/Char (16 bit UNsigned) with a 16-bit mask into Long Register 2.100 +instruct loadUS2L_immI16(eRegL dst, memory mem, immI16 mask, eFlagsReg cr) %{ 2.101 + match(Set dst (ConvI2L (AndI (LoadUS mem) mask))); 2.102 + effect(KILL cr); 2.103 + 2.104 + format %{ "MOVZX $dst.lo, $mem\t# ushort/char & 16-bit mask -> long\n\t" 2.105 + "XOR $dst.hi,$dst.hi\n\t" 2.106 + "AND $dst.lo,$mask" %} 2.107 + ins_encode %{ 2.108 + Register Rdst = $dst$$Register; 2.109 + __ movzwl(Rdst, $mem$$Address); 2.110 + __ xorl(HIGH_FROM_LOW(Rdst), HIGH_FROM_LOW(Rdst)); 2.111 + __ andl(Rdst, $mask$$constant); 2.112 + %} 2.113 + ins_pipe(ialu_reg_mem); 2.114 +%} 2.115 + 2.116 // Load Integer 2.117 instruct loadI(eRegI dst, memory mem) %{ 2.118 match(Set dst (LoadI mem)); 2.119 @@ -7082,8 +7135,9 @@ 2.120 %} 2.121 2.122 // Load Integer into Long Register 2.123 -instruct loadI2L(eRegL dst, memory mem) %{ 2.124 +instruct loadI2L(eRegL dst, memory mem, eFlagsReg cr) %{ 2.125 match(Set dst (ConvI2L (LoadI mem))); 2.126 + effect(KILL cr); 2.127 2.128 ins_cost(375); 2.129 format %{ "MOV $dst.lo,$mem\t# int -> long\n\t" 2.130 @@ -7099,9 +7153,57 @@ 2.131 ins_pipe(ialu_reg_mem); 2.132 %} 2.133 2.134 +// Load Integer with mask 0xFF into Long Register 2.135 +instruct loadI2L_immI_255(eRegL dst, memory mem, immI_255 mask, eFlagsReg cr) %{ 2.136 + match(Set dst (ConvI2L (AndI (LoadI mem) mask))); 2.137 + effect(KILL cr); 2.138 + 2.139 + format %{ "MOVZX8 $dst.lo,$mem\t# int & 0xFF -> long\n\t" 2.140 + "XOR $dst.hi,$dst.hi" %} 2.141 + ins_encode %{ 2.142 + Register Rdst = $dst$$Register; 2.143 + __ movzbl(Rdst, $mem$$Address); 2.144 + __ xorl(HIGH_FROM_LOW(Rdst), HIGH_FROM_LOW(Rdst)); 2.145 + %} 2.146 + ins_pipe(ialu_reg_mem); 2.147 +%} 2.148 + 2.149 +// Load Integer with mask 0xFFFF into Long Register 2.150 +instruct loadI2L_immI_65535(eRegL dst, memory mem, immI_65535 mask, eFlagsReg cr) %{ 2.151 + match(Set dst (ConvI2L (AndI (LoadI mem) mask))); 2.152 + effect(KILL cr); 2.153 + 2.154 + format %{ "MOVZX $dst.lo,$mem\t# int & 0xFFFF -> long\n\t" 2.155 + "XOR $dst.hi,$dst.hi" %} 2.156 + ins_encode %{ 2.157 + Register Rdst = $dst$$Register; 2.158 + __ movzwl(Rdst, $mem$$Address); 2.159 + __ xorl(HIGH_FROM_LOW(Rdst), HIGH_FROM_LOW(Rdst)); 2.160 + %} 2.161 + ins_pipe(ialu_reg_mem); 2.162 +%} 2.163 + 2.164 +// Load Integer with 32-bit mask into Long Register 2.165 +instruct loadI2L_immI(eRegL dst, memory mem, immI mask, eFlagsReg cr) %{ 2.166 + match(Set dst (ConvI2L (AndI (LoadI mem) mask))); 2.167 + effect(KILL cr); 2.168 + 2.169 + format %{ "MOV $dst.lo,$mem\t# int & 32-bit mask -> long\n\t" 2.170 + "XOR $dst.hi,$dst.hi\n\t" 2.171 + "AND $dst.lo,$mask" %} 2.172 + ins_encode %{ 2.173 + Register Rdst = $dst$$Register; 2.174 + __ movl(Rdst, $mem$$Address); 2.175 + __ xorl(HIGH_FROM_LOW(Rdst), HIGH_FROM_LOW(Rdst)); 2.176 + __ andl(Rdst, $mask$$constant); 2.177 + %} 2.178 + ins_pipe(ialu_reg_mem); 2.179 +%} 2.180 + 2.181 // Load Unsigned Integer into Long Register 2.182 -instruct loadUI2L(eRegL dst, memory mem) %{ 2.183 +instruct loadUI2L(eRegL dst, memory mem, eFlagsReg cr) %{ 2.184 match(Set dst (LoadUI2L mem)); 2.185 + effect(KILL cr); 2.186 2.187 ins_cost(250); 2.188 format %{ "MOV $dst.lo,$mem\t# uint -> long\n\t" 2.189 @@ -7695,6 +7797,17 @@ 2.190 ins_pipe( ialu_mem_long_reg ); 2.191 %} 2.192 2.193 +// Store Long to Integer 2.194 +instruct storeL2I(memory mem, eRegL src) %{ 2.195 + match(Set mem (StoreI mem (ConvL2I src))); 2.196 + 2.197 + format %{ "MOV $mem,$src.lo\t# long -> int" %} 2.198 + ins_encode %{ 2.199 + __ movl($mem$$Address, $src$$Register); 2.200 + %} 2.201 + ins_pipe(ialu_mem_reg); 2.202 +%} 2.203 + 2.204 // Volatile Store Long. Must be atomic, so move it into 2.205 // the FP TOS and then do a 64-bit FIST. Has to probe the 2.206 // target address before the store (for null-ptr checks)
3.1 --- a/src/cpu/x86/vm/x86_64.ad Wed Jun 24 12:00:51 2009 -0700 3.2 +++ b/src/cpu/x86/vm/x86_64.ad Fri Jun 26 07:26:10 2009 -0700 3.3 @@ -6444,6 +6444,21 @@ 3.4 ins_pipe(ialu_reg_mem); 3.5 %} 3.6 3.7 +// Load Unsigned Byte (8 bit UNsigned) with a 8-bit mask into Long Register 3.8 +instruct loadUB2L_immI8(rRegL dst, memory mem, immI8 mask, rFlagsReg cr) %{ 3.9 + match(Set dst (ConvI2L (AndI (LoadUB mem) mask))); 3.10 + effect(KILL cr); 3.11 + 3.12 + format %{ "movzbq $dst, $mem\t# ubyte & 8-bit mask -> long\n\t" 3.13 + "andl $dst, $mask" %} 3.14 + ins_encode %{ 3.15 + Register Rdst = $dst$$Register; 3.16 + __ movzbq(Rdst, $mem$$Address); 3.17 + __ andl(Rdst, $mask$$constant); 3.18 + %} 3.19 + ins_pipe(ialu_reg_mem); 3.20 +%} 3.21 + 3.22 // Load Short (16 bit signed) 3.23 instruct loadS(rRegI dst, memory mem) 3.24 %{ 3.25 @@ -6528,6 +6543,32 @@ 3.26 ins_pipe(ialu_reg_mem); 3.27 %} 3.28 3.29 +// Load Unsigned Short/Char (16 bit UNsigned) with mask 0xFF into Long Register 3.30 +instruct loadUS2L_immI_255(rRegL dst, memory mem, immI_255 mask) %{ 3.31 + match(Set dst (ConvI2L (AndI (LoadUS mem) mask))); 3.32 + 3.33 + format %{ "movzbq $dst, $mem\t# ushort/char & 0xFF -> long" %} 3.34 + ins_encode %{ 3.35 + __ movzbq($dst$$Register, $mem$$Address); 3.36 + %} 3.37 + ins_pipe(ialu_reg_mem); 3.38 +%} 3.39 + 3.40 +// Load Unsigned Short/Char (16 bit UNsigned) with mask into Long Register 3.41 +instruct loadUS2L_immI16(rRegL dst, memory mem, immI16 mask, rFlagsReg cr) %{ 3.42 + match(Set dst (ConvI2L (AndI (LoadUS mem) mask))); 3.43 + effect(KILL cr); 3.44 + 3.45 + format %{ "movzwq $dst, $mem\t# ushort/char & 16-bit mask -> long\n\t" 3.46 + "andl $dst, $mask" %} 3.47 + ins_encode %{ 3.48 + Register Rdst = $dst$$Register; 3.49 + __ movzwq(Rdst, $mem$$Address); 3.50 + __ andl(Rdst, $mask$$constant); 3.51 + %} 3.52 + ins_pipe(ialu_reg_mem); 3.53 +%} 3.54 + 3.55 // Load Integer 3.56 instruct loadI(rRegI dst, memory mem) 3.57 %{ 3.58 @@ -6606,6 +6647,43 @@ 3.59 ins_pipe(ialu_reg_mem); 3.60 %} 3.61 3.62 +// Load Integer with mask 0xFF into Long Register 3.63 +instruct loadI2L_immI_255(rRegL dst, memory mem, immI_255 mask) %{ 3.64 + match(Set dst (ConvI2L (AndI (LoadI mem) mask))); 3.65 + 3.66 + format %{ "movzbq $dst, $mem\t# int & 0xFF -> long" %} 3.67 + ins_encode %{ 3.68 + __ movzbq($dst$$Register, $mem$$Address); 3.69 + %} 3.70 + ins_pipe(ialu_reg_mem); 3.71 +%} 3.72 + 3.73 +// Load Integer with mask 0xFFFF into Long Register 3.74 +instruct loadI2L_immI_65535(rRegL dst, memory mem, immI_65535 mask) %{ 3.75 + match(Set dst (ConvI2L (AndI (LoadI mem) mask))); 3.76 + 3.77 + format %{ "movzwq $dst, $mem\t# int & 0xFFFF -> long" %} 3.78 + ins_encode %{ 3.79 + __ movzwq($dst$$Register, $mem$$Address); 3.80 + %} 3.81 + ins_pipe(ialu_reg_mem); 3.82 +%} 3.83 + 3.84 +// Load Integer with a 32-bit mask into Long Register 3.85 +instruct loadI2L_immI(rRegL dst, memory mem, immI mask, rFlagsReg cr) %{ 3.86 + match(Set dst (ConvI2L (AndI (LoadI mem) mask))); 3.87 + effect(KILL cr); 3.88 + 3.89 + format %{ "movl $dst, $mem\t# int & 32-bit mask -> long\n\t" 3.90 + "andl $dst, $mask" %} 3.91 + ins_encode %{ 3.92 + Register Rdst = $dst$$Register; 3.93 + __ movl(Rdst, $mem$$Address); 3.94 + __ andl(Rdst, $mask$$constant); 3.95 + %} 3.96 + ins_pipe(ialu_reg_mem); 3.97 +%} 3.98 + 3.99 // Load Unsigned Integer into Long Register 3.100 instruct loadUI2L(rRegL dst, memory mem) 3.101 %{ 3.102 @@ -11673,8 +11751,9 @@ 3.103 3.104 ins_cost(125); 3.105 format %{ "movslq $dst, $src\t# i2l" %} 3.106 - opcode(0x63); // needs REX.W 3.107 - ins_encode(REX_reg_reg_wide(dst, src), OpcP, reg_reg(dst,src)); 3.108 + ins_encode %{ 3.109 + __ movslq($dst$$Register, $src$$Register); 3.110 + %} 3.111 ins_pipe(ialu_reg_reg); 3.112 %} 3.113
4.1 --- a/src/share/vm/opto/mulnode.cpp Wed Jun 24 12:00:51 2009 -0700 4.2 +++ b/src/share/vm/opto/mulnode.cpp Fri Jun 26 07:26:10 2009 -0700 4.3 @@ -430,31 +430,28 @@ 4.4 // x & x => x 4.5 if (phase->eqv(in(1), in(2))) return in(1); 4.6 4.7 - Node *load = in(1); 4.8 - const TypeInt *t2 = phase->type( in(2) )->isa_int(); 4.9 - if( t2 && t2->is_con() ) { 4.10 + Node* in1 = in(1); 4.11 + uint op = in1->Opcode(); 4.12 + const TypeInt* t2 = phase->type(in(2))->isa_int(); 4.13 + if (t2 && t2->is_con()) { 4.14 int con = t2->get_con(); 4.15 // Masking off high bits which are always zero is useless. 4.16 const TypeInt* t1 = phase->type( in(1) )->isa_int(); 4.17 if (t1 != NULL && t1->_lo >= 0) { 4.18 - jint t1_support = ((jint)1 << (1 + log2_intptr(t1->_hi))) - 1; 4.19 + jint t1_support = right_n_bits(1 + log2_intptr(t1->_hi)); 4.20 if ((t1_support & con) == t1_support) 4.21 - return load; 4.22 + return in1; 4.23 } 4.24 - uint lop = load->Opcode(); 4.25 - if( lop == Op_LoadUS && 4.26 - con == 0x0000FFFF ) // Already zero-extended 4.27 - return load; 4.28 // Masking off the high bits of a unsigned-shift-right is not 4.29 // needed either. 4.30 - if( lop == Op_URShiftI ) { 4.31 - const TypeInt *t12 = phase->type( load->in(2) )->isa_int(); 4.32 - if( t12 && t12->is_con() ) { // Shift is by a constant 4.33 + if (op == Op_URShiftI) { 4.34 + const TypeInt* t12 = phase->type(in1->in(2))->isa_int(); 4.35 + if (t12 && t12->is_con()) { // Shift is by a constant 4.36 int shift = t12->get_con(); 4.37 shift &= BitsPerJavaInteger - 1; // semantics of Java shifts 4.38 int mask = max_juint >> shift; 4.39 - if( (mask&con) == mask ) // If AND is useless, skip it 4.40 - return load; 4.41 + if ((mask & con) == mask) // If AND is useless, skip it 4.42 + return in1; 4.43 } 4.44 } 4.45 } 4.46 @@ -476,26 +473,17 @@ 4.47 return new (phase->C, 3) AndINode(load,phase->intcon(mask&0xFFFF)); 4.48 4.49 // Masking bits off of a Short? Loading a Character does some masking 4.50 - if( lop == Op_LoadS && 4.51 - (mask & 0xFFFF0000) == 0 ) { 4.52 + if (lop == Op_LoadS && (mask & 0xFFFF0000) == 0 ) { 4.53 Node *ldus = new (phase->C, 3) LoadUSNode(load->in(MemNode::Control), 4.54 - load->in(MemNode::Memory), 4.55 - load->in(MemNode::Address), 4.56 - load->adr_type()); 4.57 + load->in(MemNode::Memory), 4.58 + load->in(MemNode::Address), 4.59 + load->adr_type()); 4.60 ldus = phase->transform(ldus); 4.61 - return new (phase->C, 3) AndINode(ldus, phase->intcon(mask&0xFFFF)); 4.62 + return new (phase->C, 3) AndINode(ldus, phase->intcon(mask & 0xFFFF)); 4.63 } 4.64 4.65 - // Masking sign bits off of a Byte? Do an unsigned byte load. 4.66 - if (lop == Op_LoadB && mask == 0x000000FF) { 4.67 - return new (phase->C, 3) LoadUBNode(load->in(MemNode::Control), 4.68 - load->in(MemNode::Memory), 4.69 - load->in(MemNode::Address), 4.70 - load->adr_type()); 4.71 - } 4.72 - 4.73 - // Masking sign bits off of a Byte plus additional lower bits? Do 4.74 - // an unsigned byte load plus an and. 4.75 + // Masking sign bits off of a Byte? Do an unsigned byte load plus 4.76 + // an and. 4.77 if (lop == Op_LoadB && (mask & 0xFFFFFF00) == 0) { 4.78 Node* ldub = new (phase->C, 3) LoadUBNode(load->in(MemNode::Control), 4.79 load->in(MemNode::Memory), 4.80 @@ -605,8 +593,13 @@ 4.81 Node* in1 = in(1); 4.82 uint op = in1->Opcode(); 4.83 4.84 - // Masking sign bits off of an integer? Do an unsigned integer to long load. 4.85 - if (op == Op_ConvI2L && in1->in(1)->Opcode() == Op_LoadI && mask == 0x00000000FFFFFFFFL) { 4.86 + // Masking sign bits off of an integer? Do an unsigned integer to 4.87 + // long load. 4.88 + // NOTE: This check must be *before* we try to convert the AndLNode 4.89 + // to an AndINode and commute it with ConvI2LNode because 4.90 + // 0xFFFFFFFFL masks the whole integer and we get a sign extension, 4.91 + // which is wrong. 4.92 + if (op == Op_ConvI2L && in1->in(1)->Opcode() == Op_LoadI && mask == CONST64(0x00000000FFFFFFFF)) { 4.93 Node* load = in1->in(1); 4.94 return new (phase->C, 3) LoadUI2LNode(load->in(MemNode::Control), 4.95 load->in(MemNode::Memory), 4.96 @@ -614,9 +607,22 @@ 4.97 load->adr_type()); 4.98 } 4.99 4.100 + // Are we masking a long that was converted from an int with a mask 4.101 + // that fits in 32-bits? Commute them and use an AndINode. 4.102 + if (op == Op_ConvI2L && (mask & CONST64(0xFFFFFFFF00000000)) == 0) { 4.103 + // If we are doing an UI2L conversion (i.e. the mask is 4.104 + // 0x00000000FFFFFFFF) we cannot convert the AndL to an AndI 4.105 + // because the AndI would be optimized away later in Identity. 4.106 + if (mask != CONST64(0x00000000FFFFFFFF)) { 4.107 + Node* andi = new (phase->C, 3) AndINode(in1->in(1), phase->intcon(mask)); 4.108 + andi = phase->transform(andi); 4.109 + return new (phase->C, 2) ConvI2LNode(andi); 4.110 + } 4.111 + } 4.112 + 4.113 // Masking off sign bits? Dont make them! 4.114 if (op == Op_RShiftL) { 4.115 - const TypeInt *t12 = phase->type(in1->in(2))->isa_int(); 4.116 + const TypeInt* t12 = phase->type(in1->in(2))->isa_int(); 4.117 if( t12 && t12->is_con() ) { // Shift is by a constant 4.118 int shift = t12->get_con(); 4.119 shift &= BitsPerJavaLong - 1; // semantics of Java shifts 4.120 @@ -626,7 +632,7 @@ 4.121 if( (sign_bits_mask & mask) == 0 ) { 4.122 // Use zero-fill shift instead 4.123 Node *zshift = phase->transform(new (phase->C, 3) URShiftLNode(in1->in(1), in1->in(2))); 4.124 - return new (phase->C, 3) AndLNode( zshift, in(2) ); 4.125 + return new (phase->C, 3) AndLNode(zshift, in(2)); 4.126 } 4.127 } 4.128 }
5.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 5.2 +++ b/test/compiler/5057225/Test5057225.java Fri Jun 26 07:26:10 2009 -0700 5.3 @@ -0,0 +1,140 @@ 5.4 +/* 5.5 + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. 5.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 5.7 + * 5.8 + * This code is free software; you can redistribute it and/or modify it 5.9 + * under the terms of the GNU General Public License version 2 only, as 5.10 + * published by the Free Software Foundation. 5.11 + * 5.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 5.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 5.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 5.15 + * version 2 for more details (a copy is included in the LICENSE file that 5.16 + * accompanied this code). 5.17 + * 5.18 + * You should have received a copy of the GNU General Public License version 5.19 + * 2 along with this work; if not, write to the Free Software Foundation, 5.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 5.21 + * 5.22 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, 5.23 + * CA 95054 USA or visit www.sun.com if you need additional information or 5.24 + * have any questions. 5.25 + */ 5.26 + 5.27 +/** 5.28 + * @test 5.29 + * @bug 5057225 5.30 + * @summary Remove useless I2L conversions 5.31 + * 5.32 + * @run main/othervm -Xcomp -XX:CompileOnly=Test5057225.doload Test5057225 5.33 + */ 5.34 + 5.35 +import java.net.URLClassLoader; 5.36 + 5.37 +public class Test5057225 { 5.38 + static byte[] ba = new byte[] { -1 }; 5.39 + static short[] sa = new short[] { -1 }; 5.40 + static int[] ia = new int[] { -1 }; 5.41 + 5.42 + static final long[] BYTE_MASKS = { 5.43 + 0x0FL, 5.44 + 0x7FL, // 7-bit 5.45 + 0xFFL, 5.46 + }; 5.47 + 5.48 + static final long[] SHORT_MASKS = { 5.49 + 0x000FL, 5.50 + 0x007FL, // 7-bit 5.51 + 0x00FFL, 5.52 + 0x0FFFL, 5.53 + 0x3FFFL, // 14-bit 5.54 + 0x7FFFL, // 15-bit 5.55 + 0xFFFFL, 5.56 + }; 5.57 + 5.58 + static final long[] INT_MASKS = { 5.59 + 0x0000000FL, 5.60 + 0x0000007FL, // 7-bit 5.61 + 0x000000FFL, 5.62 + 0x00000FFFL, 5.63 + 0x00003FFFL, // 14-bit 5.64 + 0x00007FFFL, // 15-bit 5.65 + 0x0000FFFFL, 5.66 + 0x00FFFFFFL, 5.67 + 0x7FFFFFFFL, // 31-bit 5.68 + 0xFFFFFFFFL, 5.69 + }; 5.70 + 5.71 + public static void main(String[] args) throws Exception { 5.72 + for (int i = 0; i < BYTE_MASKS.length; i++) { 5.73 + System.setProperty("value", "" + BYTE_MASKS[i]); 5.74 + loadAndRunClass("Test5057225$loadUB2L"); 5.75 + } 5.76 + 5.77 + for (int i = 0; i < SHORT_MASKS.length; i++) { 5.78 + System.setProperty("value", "" + SHORT_MASKS[i]); 5.79 + loadAndRunClass("Test5057225$loadUS2L"); 5.80 + } 5.81 + 5.82 + for (int i = 0; i < INT_MASKS.length; i++) { 5.83 + System.setProperty("value", "" + INT_MASKS[i]); 5.84 + loadAndRunClass("Test5057225$loadUI2L"); 5.85 + } 5.86 + } 5.87 + 5.88 + static void check(long result, long expected) { 5.89 + if (result != expected) 5.90 + throw new InternalError(result + " != " + expected); 5.91 + } 5.92 + 5.93 + static void loadAndRunClass(String classname) throws Exception { 5.94 + Class cl = Class.forName(classname); 5.95 + URLClassLoader apploader = (URLClassLoader) cl.getClassLoader(); 5.96 + ClassLoader loader = new URLClassLoader(apploader.getURLs(), apploader.getParent()); 5.97 + Class c = loader.loadClass(classname); 5.98 + Runnable r = (Runnable) c.newInstance(); 5.99 + r.run(); 5.100 + } 5.101 + 5.102 + public static class loadUB2L implements Runnable { 5.103 + static final long MASK; 5.104 + static { 5.105 + long value = 0; 5.106 + try { 5.107 + value = Long.decode(System.getProperty("value")); 5.108 + } catch (Throwable e) {} 5.109 + MASK = value; 5.110 + } 5.111 + 5.112 + public void run() { check(doload(ba), MASK); } 5.113 + static long doload(byte[] ba) { return ba[0] & MASK; } 5.114 + } 5.115 + 5.116 + public static class loadUS2L implements Runnable { 5.117 + static final long MASK; 5.118 + static { 5.119 + long value = 0; 5.120 + try { 5.121 + value = Long.decode(System.getProperty("value")); 5.122 + } catch (Throwable e) {} 5.123 + MASK = value; 5.124 + } 5.125 + 5.126 + public void run() { check(doload(sa), MASK); } 5.127 + static long doload(short[] sa) { return sa[0] & MASK; } 5.128 + } 5.129 + 5.130 + public static class loadUI2L implements Runnable { 5.131 + static final long MASK; 5.132 + static { 5.133 + long value = 0; 5.134 + try { 5.135 + value = Long.decode(System.getProperty("value")); 5.136 + } catch (Throwable e) {} 5.137 + MASK = value; 5.138 + } 5.139 + 5.140 + public void run() { check(doload(ia), MASK); } 5.141 + static long doload(int[] ia) { return ia[0] & MASK; } 5.142 + } 5.143 +}