5057225: Remove useless I2L conversions

Fri, 26 Jun 2009 07:26:10 -0700

author
twisti
date
Fri, 26 Jun 2009 07:26:10 -0700
changeset 1259
18a08a7e16b5
parent 1258
14367225a853
child 1260
8f5825e0aeaa

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

src/cpu/sparc/vm/sparc.ad file | annotate | diff | comparison | revisions
src/cpu/x86/vm/x86_32.ad file | annotate | diff | comparison | revisions
src/cpu/x86/vm/x86_64.ad file | annotate | diff | comparison | revisions
src/share/vm/opto/mulnode.cpp file | annotate | diff | comparison | revisions
test/compiler/5057225/Test5057225.java file | annotate | diff | comparison | revisions
     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 +}

mercurial