# HG changeset patch # User twisti # Date 1242200722 25200 # Node ID 2056494941dbe9763e028e02a8111933d9db30f6 # Parent b2934faac289474f3147a67e9dc0ff7d8252b3a3 6814842: Load shortening optimizations Summary: 6797305 handles load widening but no shortening which should be covered here. Reviewed-by: never, kvn diff -r b2934faac289 -r 2056494941db src/cpu/sparc/vm/sparc.ad --- a/src/cpu/sparc/vm/sparc.ad Mon May 11 18:30:13 2009 -0700 +++ b/src/cpu/sparc/vm/sparc.ad Wed May 13 00:45:22 2009 -0700 @@ -1891,15 +1891,17 @@ // The intptr_t operand types, defined by textual substitution. // (Cf. opto/type.hpp. This lets us avoid many, many other ifdefs.) #ifdef _LP64 -#define immX immL -#define immX13 immL13 -#define iRegX iRegL -#define g1RegX g1RegL +#define immX immL +#define immX13 immL13 +#define immX13m7 immL13m7 +#define iRegX iRegL +#define g1RegX g1RegL #else -#define immX immI -#define immX13 immI13 -#define iRegX iRegI -#define g1RegX g1RegI +#define immX immI +#define immX13 immI13 +#define immX13m7 immI13m7 +#define iRegX iRegI +#define g1RegX g1RegI #endif //----------ENCODING BLOCK----------------------------------------------------- @@ -3454,6 +3456,16 @@ interface(CONST_INTER); %} +// Integer Immediate: 13-bit minus 7 +operand immI13m7() %{ + predicate((-4096 < n->get_int()) && ((n->get_int() + 7) <= 4095)); + match(ConI); + op_cost(0); + + format %{ %} + interface(CONST_INTER); +%} + // Unsigned (positive) Integer Immediate: 13-bit operand immU13() %{ predicate((0 <= n->get_int()) && Assembler::is_simm13(n->get_int())); @@ -3532,6 +3544,28 @@ interface(CONST_INTER); %} +// Immediates for special shifts (sign extend) + +// Integer Immediate: the value 16 +operand immI_16() %{ + predicate(n->get_int() == 16); + match(ConI); + op_cost(0); + + format %{ %} + interface(CONST_INTER); +%} + +// Integer Immediate: the value 24 +operand immI_24() %{ + predicate(n->get_int() == 24); + match(ConI); + op_cost(0); + + format %{ %} + interface(CONST_INTER); +%} + // Integer Immediate: the value 255 operand immI_255() %{ predicate( n->get_int() == 255 ); @@ -3542,6 +3576,16 @@ interface(CONST_INTER); %} +// Integer Immediate: the value 65535 +operand immI_65535() %{ + predicate(n->get_int() == 65535); + match(ConI); + op_cost(0); + + format %{ %} + interface(CONST_INTER); +%} + // Long Immediate: the value FF operand immL_FF() %{ predicate( n->get_long() == 0xFFL ); @@ -3647,6 +3691,16 @@ interface(CONST_INTER); %} +// Long Immediate: 13-bit minus 7 +operand immL13m7() %{ + predicate((-4096L < n->get_long()) && ((n->get_long() + 7L) <= 4095L)); + match(ConL); + op_cost(0); + + format %{ %} + interface(CONST_INTER); +%} + // Long Immediate: low 32-bit mask operand immL_32bits() %{ predicate(n->get_long() == 0xFFFFFFFFL); @@ -4084,7 +4138,7 @@ %} %} -// Indirect with Offset +// Indirect with simm13 Offset operand indOffset13(sp_ptr_RegP reg, immX13 offset) %{ constraint(ALLOC_IN_RC(sp_ptr_reg)); match(AddP reg offset); @@ -4099,6 +4153,21 @@ %} %} +// Indirect with simm13 Offset minus 7 +operand indOffset13m7(sp_ptr_RegP reg, immX13m7 offset) %{ + constraint(ALLOC_IN_RC(sp_ptr_reg)); + match(AddP reg offset); + + op_cost(100); + format %{ "[$reg + $offset]" %} + interface(MEMORY_INTER) %{ + base($reg); + index(0x0); + scale(0x0); + disp($offset); + %} +%} + // Note: Intel has a swapped version also, like this: //operand indOffsetX(iRegI reg, immP offset) %{ // constraint(ALLOC_IN_RC(int_reg)); @@ -5504,6 +5573,20 @@ ins_pipe(iload_mask_mem); %} +// Load Short (16 bit signed) to Byte (8 bit signed) +instruct loadS2B(iRegI dst, indOffset13m7 mem, immI_24 twentyfour) %{ + match(Set dst (RShiftI (LShiftI (LoadS mem) twentyfour) twentyfour)); + ins_cost(MEMORY_REF_COST); + + size(4); + + format %{ "LDSB $mem+1,$dst\t! short -> byte" %} + ins_encode %{ + __ ldsb($mem$$Address, $dst$$Register, 1); + %} + ins_pipe(iload_mask_mem); +%} + // Load Short (16bit signed) into a Long Register instruct loadS2L(iRegL dst, memory mem) %{ match(Set dst (ConvI2L (LoadS mem))); @@ -5530,6 +5613,19 @@ ins_pipe(iload_mask_mem); %} +// Load Unsigned Short/Char (16 bit UNsigned) to Byte (8 bit signed) +instruct loadUS2B(iRegI dst, indOffset13m7 mem, immI_24 twentyfour) %{ + match(Set dst (RShiftI (LShiftI (LoadUS mem) twentyfour) twentyfour)); + ins_cost(MEMORY_REF_COST); + + size(4); + format %{ "LDSB $mem+1,$dst\t! ushort -> byte" %} + ins_encode %{ + __ ldsb($mem$$Address, $dst$$Register, 1); + %} + ins_pipe(iload_mask_mem); +%} + // Load Unsigned Short/Char (16bit UNsigned) into a Long Register instruct loadUS2L(iRegL dst, memory mem) %{ match(Set dst (ConvI2L (LoadUS mem))); @@ -5556,6 +5652,62 @@ ins_pipe(iload_mem); %} +// Load Integer to Byte (8 bit signed) +instruct loadI2B(iRegI dst, indOffset13m7 mem, immI_24 twentyfour) %{ + match(Set dst (RShiftI (LShiftI (LoadI mem) twentyfour) twentyfour)); + ins_cost(MEMORY_REF_COST); + + size(4); + + format %{ "LDSB $mem+3,$dst\t! int -> byte" %} + ins_encode %{ + __ ldsb($mem$$Address, $dst$$Register, 3); + %} + ins_pipe(iload_mask_mem); +%} + +// Load Integer to Unsigned Byte (8 bit UNsigned) +instruct loadI2UB(iRegI dst, indOffset13m7 mem, immI_255 mask) %{ + match(Set dst (AndI (LoadI mem) mask)); + ins_cost(MEMORY_REF_COST); + + size(4); + + format %{ "LDUB $mem+3,$dst\t! int -> ubyte" %} + ins_encode %{ + __ ldub($mem$$Address, $dst$$Register, 3); + %} + ins_pipe(iload_mask_mem); +%} + +// Load Integer to Short (16 bit signed) +instruct loadI2S(iRegI dst, indOffset13m7 mem, immI_16 sixteen) %{ + match(Set dst (RShiftI (LShiftI (LoadI mem) sixteen) sixteen)); + ins_cost(MEMORY_REF_COST); + + size(4); + + format %{ "LDSH $mem+2,$dst\t! int -> short" %} + ins_encode %{ + __ ldsh($mem$$Address, $dst$$Register, 2); + %} + ins_pipe(iload_mask_mem); +%} + +// Load Integer to Unsigned Short (16 bit UNsigned) +instruct loadI2US(iRegI dst, indOffset13m7 mem, immI_65535 mask) %{ + match(Set dst (AndI (LoadI mem) mask)); + ins_cost(MEMORY_REF_COST); + + size(4); + + format %{ "LDUH $mem+2,$dst\t! int -> ushort/char" %} + ins_encode %{ + __ lduh($mem$$Address, $dst$$Register, 2); + %} + ins_pipe(iload_mask_mem); +%} + // Load Integer into a Long Register instruct loadI2L(iRegL dst, memory mem) %{ match(Set dst (ConvI2L (LoadI mem))); diff -r b2934faac289 -r 2056494941db src/cpu/x86/vm/x86_32.ad --- a/src/cpu/x86/vm/x86_32.ad Mon May 11 18:30:13 2009 -0700 +++ b/src/cpu/x86/vm/x86_32.ad Wed May 13 00:45:22 2009 -0700 @@ -5240,6 +5240,15 @@ interface(CONST_INTER); %} +// Constant for short-wide masking +operand immI_65535() %{ + predicate(n->get_int() == 65535); + match(ConI); + + format %{ %} + interface(CONST_INTER); +%} + // Register Operands // Integer Register operand eRegI() %{ @@ -6938,6 +6947,18 @@ ins_pipe(ialu_reg_mem); %} +// Load Short (16 bit signed) to Byte (8 bit signed) +instruct loadS2B(eRegI dst, memory mem, immI_24 twentyfour) %{ + match(Set dst (RShiftI (LShiftI (LoadS mem) twentyfour) twentyfour)); + + ins_cost(125); + format %{ "MOVSX $dst, $mem\t# short -> byte" %} + ins_encode %{ + __ movsbl($dst$$Register, $mem$$Address); + %} + ins_pipe(ialu_reg_mem); +%} + // Load Short (16bit signed) into Long Register instruct loadS2L(eRegL dst, memory mem) %{ match(Set dst (ConvI2L (LoadS mem))); @@ -6970,9 +6991,20 @@ ins_pipe(ialu_reg_mem); %} +// Load Unsigned Short/Char (16 bit UNsigned) to Byte (8 bit signed) +instruct loadUS2B(eRegI dst, memory mem, immI_24 twentyfour) %{ + match(Set dst (RShiftI (LShiftI (LoadUS mem) twentyfour) twentyfour)); + + ins_cost(125); + format %{ "MOVSX $dst, $mem\t# ushort -> byte" %} + ins_encode %{ + __ movsbl($dst$$Register, $mem$$Address); + %} + ins_pipe(ialu_reg_mem); +%} + // Load Unsigned Short/Char (16 bit UNsigned) into Long Register -instruct loadUS2L(eRegL dst, memory mem) -%{ +instruct loadUS2L(eRegL dst, memory mem) %{ match(Set dst (ConvI2L (LoadUS mem))); ins_cost(250); @@ -7001,6 +7033,54 @@ ins_pipe(ialu_reg_mem); %} +// Load Integer (32 bit signed) to Byte (8 bit signed) +instruct loadI2B(eRegI dst, memory mem, immI_24 twentyfour) %{ + match(Set dst (RShiftI (LShiftI (LoadI mem) twentyfour) twentyfour)); + + ins_cost(125); + format %{ "MOVSX $dst, $mem\t# int -> byte" %} + ins_encode %{ + __ movsbl($dst$$Register, $mem$$Address); + %} + ins_pipe(ialu_reg_mem); +%} + +// Load Integer (32 bit signed) to Unsigned Byte (8 bit UNsigned) +instruct loadI2UB(eRegI dst, memory mem, immI_255 mask) %{ + match(Set dst (AndI (LoadI mem) mask)); + + ins_cost(125); + format %{ "MOVZX $dst, $mem\t# int -> ubyte" %} + ins_encode %{ + __ movzbl($dst$$Register, $mem$$Address); + %} + ins_pipe(ialu_reg_mem); +%} + +// Load Integer (32 bit signed) to Short (16 bit signed) +instruct loadI2S(eRegI dst, memory mem, immI_16 sixteen) %{ + match(Set dst (RShiftI (LShiftI (LoadI mem) sixteen) sixteen)); + + ins_cost(125); + format %{ "MOVSX $dst, $mem\t# int -> short" %} + ins_encode %{ + __ movswl($dst$$Register, $mem$$Address); + %} + ins_pipe(ialu_reg_mem); +%} + +// Load Integer (32 bit signed) to Unsigned Short/Char (16 bit UNsigned) +instruct loadI2US(eRegI dst, memory mem, immI_65535 mask) %{ + match(Set dst (AndI (LoadI mem) mask)); + + ins_cost(125); + format %{ "MOVZX $dst, $mem\t# int -> ushort/char" %} + ins_encode %{ + __ movzwl($dst$$Register, $mem$$Address); + %} + ins_pipe(ialu_reg_mem); +%} + // Load Integer into Long Register instruct loadI2L(eRegL dst, memory mem) %{ match(Set dst (ConvI2L (LoadI mem))); @@ -9034,28 +9114,28 @@ // Logical Shift Right by 24, followed by Arithmetic Shift Left by 24. // This idiom is used by the compiler for the i2b bytecode. -instruct i2b(eRegI dst, xRegI src, immI_24 twentyfour, eFlagsReg cr) %{ +instruct i2b(eRegI dst, xRegI src, immI_24 twentyfour) %{ match(Set dst (RShiftI (LShiftI src twentyfour) twentyfour)); - effect(KILL cr); size(3); format %{ "MOVSX $dst,$src :8" %} - opcode(0xBE, 0x0F); - ins_encode( OpcS, OpcP, RegReg( dst, src)); - ins_pipe( ialu_reg_reg ); + ins_encode %{ + __ movsbl($dst$$Register, $src$$Register); + %} + ins_pipe(ialu_reg_reg); %} // Logical Shift Right by 16, followed by Arithmetic Shift Left by 16. // This idiom is used by the compiler the i2s bytecode. -instruct i2s(eRegI dst, xRegI src, immI_16 sixteen, eFlagsReg cr) %{ +instruct i2s(eRegI dst, xRegI src, immI_16 sixteen) %{ match(Set dst (RShiftI (LShiftI src sixteen) sixteen)); - effect(KILL cr); size(3); format %{ "MOVSX $dst,$src :16" %} - opcode(0xBF, 0x0F); - ins_encode( OpcS, OpcP, RegReg( dst, src)); - ins_pipe( ialu_reg_reg ); + ins_encode %{ + __ movswl($dst$$Register, $src$$Register); + %} + ins_pipe(ialu_reg_reg); %} diff -r b2934faac289 -r 2056494941db src/cpu/x86/vm/x86_64.ad --- a/src/cpu/x86/vm/x86_64.ad Mon May 11 18:30:13 2009 -0700 +++ b/src/cpu/x86/vm/x86_64.ad Wed May 13 00:45:22 2009 -0700 @@ -6459,6 +6459,18 @@ ins_pipe(ialu_reg_mem); %} +// Load Short (16 bit signed) to Byte (8 bit signed) +instruct loadS2B(rRegI dst, memory mem, immI_24 twentyfour) %{ + match(Set dst (RShiftI (LShiftI (LoadS mem) twentyfour) twentyfour)); + + ins_cost(125); + format %{ "movsbl $dst, $mem\t# short -> byte" %} + ins_encode %{ + __ movsbl($dst$$Register, $mem$$Address); + %} + ins_pipe(ialu_reg_mem); +%} + // Load Short (16 bit signed) into Long Register instruct loadS2L(rRegL dst, memory mem) %{ @@ -6489,6 +6501,18 @@ ins_pipe(ialu_reg_mem); %} +// Load Unsigned Short/Char (16 bit UNsigned) to Byte (8 bit signed) +instruct loadUS2B(rRegI dst, memory mem, immI_24 twentyfour) %{ + match(Set dst (RShiftI (LShiftI (LoadUS mem) twentyfour) twentyfour)); + + ins_cost(125); + format %{ "movsbl $dst, $mem\t# ushort -> byte" %} + ins_encode %{ + __ movsbl($dst$$Register, $mem$$Address); + %} + ins_pipe(ialu_reg_mem); +%} + // Load Unsigned Short/Char (16 bit UNsigned) into Long Register instruct loadUS2L(rRegL dst, memory mem) %{ @@ -6519,6 +6543,54 @@ ins_pipe(ialu_reg_mem); %} +// Load Integer (32 bit signed) to Byte (8 bit signed) +instruct loadI2B(rRegI dst, memory mem, immI_24 twentyfour) %{ + match(Set dst (RShiftI (LShiftI (LoadI mem) twentyfour) twentyfour)); + + ins_cost(125); + format %{ "movsbl $dst, $mem\t# int -> byte" %} + ins_encode %{ + __ movsbl($dst$$Register, $mem$$Address); + %} + ins_pipe(ialu_reg_mem); +%} + +// Load Integer (32 bit signed) to Unsigned Byte (8 bit UNsigned) +instruct loadI2UB(rRegI dst, memory mem, immI_255 mask) %{ + match(Set dst (AndI (LoadI mem) mask)); + + ins_cost(125); + format %{ "movzbl $dst, $mem\t# int -> ubyte" %} + ins_encode %{ + __ movzbl($dst$$Register, $mem$$Address); + %} + ins_pipe(ialu_reg_mem); +%} + +// Load Integer (32 bit signed) to Short (16 bit signed) +instruct loadI2S(rRegI dst, memory mem, immI_16 sixteen) %{ + match(Set dst (RShiftI (LShiftI (LoadI mem) sixteen) sixteen)); + + ins_cost(125); + format %{ "movswl $dst, $mem\t# int -> short" %} + ins_encode %{ + __ movswl($dst$$Register, $mem$$Address); + %} + ins_pipe(ialu_reg_mem); +%} + +// Load Integer (32 bit signed) to Unsigned Short/Char (16 bit UNsigned) +instruct loadI2US(rRegI dst, memory mem, immI_65535 mask) %{ + match(Set dst (AndI (LoadI mem) mask)); + + ins_cost(125); + format %{ "movzwl $dst, $mem\t# int -> ushort/char" %} + ins_encode %{ + __ movzwl($dst$$Register, $mem$$Address); + %} + ins_pipe(ialu_reg_mem); +%} + // Load Integer into Long Register instruct loadI2L(rRegL dst, memory mem) %{ diff -r b2934faac289 -r 2056494941db src/share/vm/adlc/output_c.cpp --- a/src/share/vm/adlc/output_c.cpp Mon May 11 18:30:13 2009 -0700 +++ b/src/share/vm/adlc/output_c.cpp Wed May 13 00:45:22 2009 -0700 @@ -1745,6 +1745,7 @@ fprintf(fp," del_req(i);\n"); fprintf(fp," }\n"); fprintf(fp," _num_opnds = %d;\n", new_num_opnds); + assert(new_num_opnds == node->num_unique_opnds(), "what?"); } } @@ -3761,6 +3762,12 @@ if ( this->captures_bottom_type() ) { fprintf(fp_cpp, " node->_bottom_type = bottom_type();\n"); } + + uint cur_num_opnds = num_opnds(); + if (cur_num_opnds > 1 && cur_num_opnds != num_unique_opnds()) { + fprintf(fp_cpp," node->_num_opnds = %d;\n", num_unique_opnds()); + } + fprintf(fp_cpp, "\n"); fprintf(fp_cpp, " // Copy _idx, inputs and operands to new node\n"); fprintf(fp_cpp, " fill_new_machnode(node, C);\n"); diff -r b2934faac289 -r 2056494941db test/compiler/6814842/Test6814842.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/6814842/Test6814842.java Wed May 13 00:45:22 2009 -0700 @@ -0,0 +1,104 @@ +/* + * 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 6814842 + * @summary Load shortening optimizations + * + * @run main/othervm -Xcomp -XX:CompileOnly=Test6814842.loadS2B,Test6814842.loadS2Bmask255,Test6814842.loadUS2B,Test6814842.loadUS2Bmask255,Test6814842.loadI2B,Test6814842.loadI2Bmask255,Test6814842.loadI2S,Test6814842.loadI2Smask255,Test6814842.loadI2Smask65535,Test6814842.loadI2US,Test6814842.loadI2USmask255,Test6814842.loadI2USmask65535 Test6814842 + */ + +public class Test6814842 { + static final short[] sa = new short[] { (short) 0xF1F2 }; + static final char[] ca = new char[] { (char) 0xF3F4 }; + static final int[] ia = new int[] { 0xF1F2F3F4 }; + + public static void main(String[] args) + { + byte s2b = loadS2B(sa); + if (s2b != (byte) 0xF2) + throw new InternalError("loadS2B failed: " + s2b + " != " + (byte) 0xF2); + + byte s2bmask255 = loadS2Bmask255(sa); + if (s2bmask255 != (byte) 0xF2) + throw new InternalError("loadS2Bmask255 failed: " + s2bmask255 + " != " + (byte) 0xF2); + + byte us2b = loadUS2B(ca); + if (us2b != (byte) 0xF4) + throw new InternalError("loadUS2B failed: " + us2b + " != " + (byte) 0xF4); + + byte us2bmask255 = loadUS2Bmask255(ca); + if (us2bmask255 != (byte) 0xF4) + throw new InternalError("loadUS2Bmask255 failed: " + us2bmask255 + " != " + (byte) 0xF4); + + byte i2b = loadI2B(ia); + if (i2b != (byte) 0xF4) + throw new InternalError("loadI2B failed: " + i2b + " != " + (byte) 0xF4); + + byte i2bmask255 = loadI2Bmask255(ia); + if (i2bmask255 != (byte) 0xF4) + throw new InternalError("loadI2Bmask255 failed: " + i2bmask255 + " != " + (byte) 0xF4); + + short i2s = loadI2S(ia); + if (i2s != (short) 0xF3F4) + throw new InternalError("loadI2S failed: " + i2s + " != " + (short) 0xF3F4); + + short i2smask255 = loadI2Smask255(ia); + if (i2smask255 != (short) 0xF4) + throw new InternalError("loadI2Smask255 failed: " + i2smask255 + " != " + (short) 0xF4); + + short i2smask65535 = loadI2Smask65535(ia); + if (i2smask65535 != (short) 0xF3F4) + throw new InternalError("loadI2Smask65535 failed: " + i2smask65535 + " != " + (short) 0xF3F4); + + char i2us = loadI2US(ia); + if (i2us != (char) 0xF3F4) + throw new InternalError("loadI2US failed: " + (int) i2us + " != " + (char) 0xF3F4); + + char i2usmask255 = loadI2USmask255(ia); + if (i2usmask255 != (char) 0xF4) + throw new InternalError("loadI2USmask255 failed: " + (int) i2usmask255 + " != " + (char) 0xF4); + + char i2usmask65535 = loadI2USmask65535(ia); + if (i2usmask65535 != (char) 0xF3F4) + throw new InternalError("loadI2USmask65535 failed: " + (int) i2usmask65535 + " != " + (char) 0xF3F4); + } + + static byte loadS2B (short[] sa) { return (byte) (sa[0] ); } + static byte loadS2Bmask255 (short[] sa) { return (byte) (sa[0] & 0xFF ); } + + static byte loadUS2B (char[] ca) { return (byte) (ca[0] ); } + static byte loadUS2Bmask255 (char[] ca) { return (byte) (ca[0] & 0xFF ); } + + static byte loadI2B (int[] ia) { return (byte) (ia[0] ); } + static byte loadI2Bmask255 (int[] ia) { return (byte) (ia[0] & 0xFF ); } + + static short loadI2S (int[] ia) { return (short) (ia[0] ); } + static short loadI2Smask255 (int[] ia) { return (short) (ia[0] & 0xFF ); } + static short loadI2Smask65535 (int[] ia) { return (short) (ia[0] & 0xFFFF); } + + static char loadI2US (int[] ia) { return (char) (ia[0] ); } + static char loadI2USmask255 (int[] ia) { return (char) (ia[0] & 0xFF ); } + static char loadI2USmask65535(int[] ia) { return (char) (ia[0] & 0xFFFF); } +}