提交 572eabd0 编写于 作者: T twisti

6814842: Load shortening optimizations

Summary: 6797305 handles load widening but no shortening which should be covered here.
Reviewed-by: never, kvn
上级 322c3026
......@@ -1891,15 +1891,17 @@ RegMask Matcher::modL_proj_mask() {
// 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 @@ operand immI13() %{
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 @@ operand immI_32_63() %{
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 @@ operand immI_255() %{
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 @@ operand immL13() %{
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 @@ operand indirect(sp_ptr_RegP reg) %{
%}
%}
// 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 @@ operand indOffset13(sp_ptr_RegP reg, immX13 offset) %{
%}
%}
// 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 @@ instruct loadS(iRegI dst, memory mem) %{
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 @@ instruct loadUS(iRegI dst, memory mem) %{
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 @@ instruct loadI(iRegI dst, memory mem) %{
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)));
......
......@@ -5240,6 +5240,15 @@ operand immI_255() %{
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 @@ instruct loadS(eRegI dst, memory mem) %{
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 @@ instruct loadUS(eRegI dst, memory mem) %{
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 @@ instruct loadI(eRegI dst, memory mem) %{
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 @@ instruct shrI_eReg_imm(eRegI dst, immI8 shift, eFlagsReg cr) %{
// 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);
%}
......
......@@ -6459,6 +6459,18 @@ instruct loadS(rRegI dst, memory mem)
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 @@ instruct loadUS(rRegI dst, memory mem)
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 @@ instruct loadI(rRegI dst, memory mem)
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)
%{
......
......@@ -1745,6 +1745,7 @@ void ArchDesc::defineExpand(FILE *fp, InstructForm *node) {
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 @@ bool InstructForm::define_cisc_version(ArchDesc &AD, FILE *fp_cpp) {
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");
......
/*
* 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); }
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册