8234391: C2: Generic vector operands
Reviewed-by: vlivanov, sviswanathan, thartmann, jrose
This commit is contained in:
parent
f33e2e9c54
commit
979cd452ab
@ -2293,6 +2293,24 @@ const bool Matcher::require_postalloc_expand = false;
|
||||
// the cpu only look at the lower 5/6 bits anyway?
|
||||
const bool Matcher::need_masked_shift_count = false;
|
||||
|
||||
// No support for generic vector operands.
|
||||
const bool Matcher::supports_generic_vector_operands = false;
|
||||
|
||||
MachOper* Matcher::specialize_generic_vector_operand(MachOper* original_opnd, uint ideal_reg) {
|
||||
ShouldNotReachHere(); // generic vector operands not supported
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool Matcher::is_generic_reg2reg_move(MachNode* m) {
|
||||
ShouldNotReachHere(); // generic vector operands not supported
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Matcher::is_generic_vector(MachOper* opnd) {
|
||||
ShouldNotReachHere(); // generic vector operands not supported
|
||||
return false;
|
||||
}
|
||||
|
||||
// This affects two different things:
|
||||
// - how Decode nodes are matched
|
||||
// - how ImplicitNullCheck opportunities are recognized
|
||||
|
@ -1077,6 +1077,24 @@ const bool Matcher::need_masked_shift_count = true;
|
||||
|
||||
const bool Matcher::convi2l_type_required = true;
|
||||
|
||||
// No support for generic vector operands.
|
||||
const bool Matcher::supports_generic_vector_operands = false;
|
||||
|
||||
MachOper* Matcher::specialize_generic_vector_operand(MachOper* original_opnd, uint ideal_reg) {
|
||||
ShouldNotReachHere(); // generic vector operands not supported
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool Matcher::is_generic_reg2reg_move(MachNode* m) {
|
||||
ShouldNotReachHere(); // generic vector operands not supported
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Matcher::is_generic_vector(MachOper* opnd) {
|
||||
ShouldNotReachHere(); // generic vector operands not supported
|
||||
return false;
|
||||
}
|
||||
|
||||
// Should the Matcher clone shifts on addressing modes, expecting them
|
||||
// to be subsumed into complex addressing expressions or compute them
|
||||
// into registers?
|
||||
|
@ -2426,6 +2426,24 @@ const bool Matcher::require_postalloc_expand = true;
|
||||
// PowerPC requires masked shift counts.
|
||||
const bool Matcher::need_masked_shift_count = true;
|
||||
|
||||
// No support for generic vector operands.
|
||||
const bool Matcher::supports_generic_vector_operands = false;
|
||||
|
||||
MachOper* Matcher::specialize_generic_vector_operand(MachOper* original_opnd, uint ideal_reg) {
|
||||
ShouldNotReachHere(); // generic vector operands not supported
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool Matcher::is_generic_reg2reg_move(MachNode* m) {
|
||||
ShouldNotReachHere(); // generic vector operands not supported
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Matcher::is_generic_vector(MachOper* opnd) {
|
||||
ShouldNotReachHere(); // generic vector operands not supported
|
||||
return false;
|
||||
}
|
||||
|
||||
// This affects two different things:
|
||||
// - how Decode nodes are matched
|
||||
// - how ImplicitNullCheck opportunities are recognized
|
||||
|
@ -1658,6 +1658,24 @@ const bool Matcher::require_postalloc_expand = false;
|
||||
// Constant shift counts are handled in Ideal phase.
|
||||
const bool Matcher::need_masked_shift_count = false;
|
||||
|
||||
// No support for generic vector operands.
|
||||
const bool Matcher::supports_generic_vector_operands = false;
|
||||
|
||||
MachOper* Matcher::specialize_generic_vector_operand(MachOper* original_opnd, uint ideal_reg) {
|
||||
ShouldNotReachHere(); // generic vector operands not supported
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool Matcher::is_generic_reg2reg_move(MachNode* m) {
|
||||
ShouldNotReachHere(); // generic vector operands not supported
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Matcher::is_generic_vector(MachOper* opnd) {
|
||||
ShouldNotReachHere(); // generic vector operands not supported
|
||||
return false;
|
||||
}
|
||||
|
||||
// Set this as clone_shift_expressions.
|
||||
bool Matcher::narrow_oop_use_complex_address() {
|
||||
if (CompressedOops::base() == NULL && CompressedOops::shift() == 0) return true;
|
||||
|
@ -1815,6 +1815,24 @@ const bool Matcher::require_postalloc_expand = false;
|
||||
// the cpu only look at the lower 5/6 bits anyway?
|
||||
const bool Matcher::need_masked_shift_count = false;
|
||||
|
||||
// No support for generic vector operands.
|
||||
const bool Matcher::supports_generic_vector_operands = false;
|
||||
|
||||
MachOper* Matcher::specialize_generic_vector_operand(MachOper* original_opnd, uint ideal_reg) {
|
||||
ShouldNotReachHere(); // generic vector operands not supported
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool Matcher::is_generic_reg2reg_move(MachNode* m) {
|
||||
ShouldNotReachHere(); // generic vector operands not supported
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Matcher::is_generic_vector(MachOper* opnd) {
|
||||
ShouldNotReachHere(); // generic vector operands not supported
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Matcher::narrow_oop_use_complex_address() {
|
||||
assert(UseCompressedOops, "only for compressed oops code");
|
||||
return false;
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -4130,72 +4130,6 @@ operand vlRegD() %{
|
||||
interface(REG_INTER);
|
||||
%}
|
||||
|
||||
// Vectors : note, we use legacy registers to avoid extra (unneeded in 32-bit VM)
|
||||
// runtime code generation via reg_class_dynamic.
|
||||
operand vecS() %{
|
||||
constraint(ALLOC_IN_RC(vectors_reg_legacy));
|
||||
match(VecS);
|
||||
|
||||
format %{ %}
|
||||
interface(REG_INTER);
|
||||
%}
|
||||
|
||||
operand legVecS() %{
|
||||
constraint(ALLOC_IN_RC(vectors_reg_legacy));
|
||||
match(VecS);
|
||||
|
||||
format %{ %}
|
||||
interface(REG_INTER);
|
||||
%}
|
||||
|
||||
operand vecD() %{
|
||||
constraint(ALLOC_IN_RC(vectord_reg_legacy));
|
||||
match(VecD);
|
||||
|
||||
format %{ %}
|
||||
interface(REG_INTER);
|
||||
%}
|
||||
|
||||
operand legVecD() %{
|
||||
constraint(ALLOC_IN_RC(vectord_reg_legacy));
|
||||
match(VecD);
|
||||
|
||||
format %{ %}
|
||||
interface(REG_INTER);
|
||||
%}
|
||||
|
||||
operand vecX() %{
|
||||
constraint(ALLOC_IN_RC(vectorx_reg_legacy));
|
||||
match(VecX);
|
||||
|
||||
format %{ %}
|
||||
interface(REG_INTER);
|
||||
%}
|
||||
|
||||
operand legVecX() %{
|
||||
constraint(ALLOC_IN_RC(vectorx_reg_legacy));
|
||||
match(VecX);
|
||||
|
||||
format %{ %}
|
||||
interface(REG_INTER);
|
||||
%}
|
||||
|
||||
operand vecY() %{
|
||||
constraint(ALLOC_IN_RC(vectory_reg_legacy));
|
||||
match(VecY);
|
||||
|
||||
format %{ %}
|
||||
interface(REG_INTER);
|
||||
%}
|
||||
|
||||
operand legVecY() %{
|
||||
constraint(ALLOC_IN_RC(vectory_reg_legacy));
|
||||
match(VecY);
|
||||
|
||||
format %{ %}
|
||||
interface(REG_INTER);
|
||||
%}
|
||||
|
||||
//----------Memory Operands----------------------------------------------------
|
||||
// Direct Memory Operand
|
||||
operand direct(immP addr) %{
|
||||
@ -11795,12 +11729,12 @@ instruct string_equals(eDIRegP str1, eSIRegP str2, eCXRegI cnt, eAXRegI result,
|
||||
|
||||
// fast search of substring with known size.
|
||||
instruct string_indexof_conL(eDIRegP str1, eDXRegI cnt1, eSIRegP str2, immI int_cnt2,
|
||||
eBXRegI result, regD vec, eAXRegI cnt2, eCXRegI tmp, eFlagsReg cr) %{
|
||||
eBXRegI result, regD vec1, eAXRegI cnt2, eCXRegI tmp, eFlagsReg cr) %{
|
||||
predicate(UseSSE42Intrinsics && (((StrIndexOfNode*)n)->encoding() == StrIntrinsicNode::LL));
|
||||
match(Set result (StrIndexOf (Binary str1 cnt1) (Binary str2 int_cnt2)));
|
||||
effect(TEMP vec, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, KILL cnt2, KILL tmp, KILL cr);
|
||||
effect(TEMP vec1, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, KILL cnt2, KILL tmp, KILL cr);
|
||||
|
||||
format %{ "String IndexOf byte[] $str1,$cnt1,$str2,$int_cnt2 -> $result // KILL $vec, $cnt1, $cnt2, $tmp" %}
|
||||
format %{ "String IndexOf byte[] $str1,$cnt1,$str2,$int_cnt2 -> $result // KILL $vec1, $cnt1, $cnt2, $tmp" %}
|
||||
ins_encode %{
|
||||
int icnt2 = (int)$int_cnt2$$constant;
|
||||
if (icnt2 >= 16) {
|
||||
@ -11809,13 +11743,13 @@ instruct string_indexof_conL(eDIRegP str1, eDXRegI cnt1, eSIRegP str2, immI int_
|
||||
__ string_indexofC8($str1$$Register, $str2$$Register,
|
||||
$cnt1$$Register, $cnt2$$Register,
|
||||
icnt2, $result$$Register,
|
||||
$vec$$XMMRegister, $tmp$$Register, StrIntrinsicNode::LL);
|
||||
$vec1$$XMMRegister, $tmp$$Register, StrIntrinsicNode::LL);
|
||||
} else {
|
||||
// Small strings are loaded through stack if they cross page boundary.
|
||||
__ string_indexof($str1$$Register, $str2$$Register,
|
||||
$cnt1$$Register, $cnt2$$Register,
|
||||
icnt2, $result$$Register,
|
||||
$vec$$XMMRegister, $tmp$$Register, StrIntrinsicNode::LL);
|
||||
$vec1$$XMMRegister, $tmp$$Register, StrIntrinsicNode::LL);
|
||||
}
|
||||
%}
|
||||
ins_pipe( pipe_slow );
|
||||
@ -11823,12 +11757,12 @@ instruct string_indexof_conL(eDIRegP str1, eDXRegI cnt1, eSIRegP str2, immI int_
|
||||
|
||||
// fast search of substring with known size.
|
||||
instruct string_indexof_conU(eDIRegP str1, eDXRegI cnt1, eSIRegP str2, immI int_cnt2,
|
||||
eBXRegI result, regD vec, eAXRegI cnt2, eCXRegI tmp, eFlagsReg cr) %{
|
||||
eBXRegI result, regD vec1, eAXRegI cnt2, eCXRegI tmp, eFlagsReg cr) %{
|
||||
predicate(UseSSE42Intrinsics && (((StrIndexOfNode*)n)->encoding() == StrIntrinsicNode::UU));
|
||||
match(Set result (StrIndexOf (Binary str1 cnt1) (Binary str2 int_cnt2)));
|
||||
effect(TEMP vec, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, KILL cnt2, KILL tmp, KILL cr);
|
||||
effect(TEMP vec1, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, KILL cnt2, KILL tmp, KILL cr);
|
||||
|
||||
format %{ "String IndexOf char[] $str1,$cnt1,$str2,$int_cnt2 -> $result // KILL $vec, $cnt1, $cnt2, $tmp" %}
|
||||
format %{ "String IndexOf char[] $str1,$cnt1,$str2,$int_cnt2 -> $result // KILL $vec1, $cnt1, $cnt2, $tmp" %}
|
||||
ins_encode %{
|
||||
int icnt2 = (int)$int_cnt2$$constant;
|
||||
if (icnt2 >= 8) {
|
||||
@ -11837,13 +11771,13 @@ instruct string_indexof_conU(eDIRegP str1, eDXRegI cnt1, eSIRegP str2, immI int_
|
||||
__ string_indexofC8($str1$$Register, $str2$$Register,
|
||||
$cnt1$$Register, $cnt2$$Register,
|
||||
icnt2, $result$$Register,
|
||||
$vec$$XMMRegister, $tmp$$Register, StrIntrinsicNode::UU);
|
||||
$vec1$$XMMRegister, $tmp$$Register, StrIntrinsicNode::UU);
|
||||
} else {
|
||||
// Small strings are loaded through stack if they cross page boundary.
|
||||
__ string_indexof($str1$$Register, $str2$$Register,
|
||||
$cnt1$$Register, $cnt2$$Register,
|
||||
icnt2, $result$$Register,
|
||||
$vec$$XMMRegister, $tmp$$Register, StrIntrinsicNode::UU);
|
||||
$vec1$$XMMRegister, $tmp$$Register, StrIntrinsicNode::UU);
|
||||
}
|
||||
%}
|
||||
ins_pipe( pipe_slow );
|
||||
@ -11851,12 +11785,12 @@ instruct string_indexof_conU(eDIRegP str1, eDXRegI cnt1, eSIRegP str2, immI int_
|
||||
|
||||
// fast search of substring with known size.
|
||||
instruct string_indexof_conUL(eDIRegP str1, eDXRegI cnt1, eSIRegP str2, immI int_cnt2,
|
||||
eBXRegI result, regD vec, eAXRegI cnt2, eCXRegI tmp, eFlagsReg cr) %{
|
||||
eBXRegI result, regD vec1, eAXRegI cnt2, eCXRegI tmp, eFlagsReg cr) %{
|
||||
predicate(UseSSE42Intrinsics && (((StrIndexOfNode*)n)->encoding() == StrIntrinsicNode::UL));
|
||||
match(Set result (StrIndexOf (Binary str1 cnt1) (Binary str2 int_cnt2)));
|
||||
effect(TEMP vec, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, KILL cnt2, KILL tmp, KILL cr);
|
||||
effect(TEMP vec1, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, KILL cnt2, KILL tmp, KILL cr);
|
||||
|
||||
format %{ "String IndexOf char[] $str1,$cnt1,$str2,$int_cnt2 -> $result // KILL $vec, $cnt1, $cnt2, $tmp" %}
|
||||
format %{ "String IndexOf char[] $str1,$cnt1,$str2,$int_cnt2 -> $result // KILL $vec1, $cnt1, $cnt2, $tmp" %}
|
||||
ins_encode %{
|
||||
int icnt2 = (int)$int_cnt2$$constant;
|
||||
if (icnt2 >= 8) {
|
||||
@ -11865,62 +11799,62 @@ instruct string_indexof_conUL(eDIRegP str1, eDXRegI cnt1, eSIRegP str2, immI int
|
||||
__ string_indexofC8($str1$$Register, $str2$$Register,
|
||||
$cnt1$$Register, $cnt2$$Register,
|
||||
icnt2, $result$$Register,
|
||||
$vec$$XMMRegister, $tmp$$Register, StrIntrinsicNode::UL);
|
||||
$vec1$$XMMRegister, $tmp$$Register, StrIntrinsicNode::UL);
|
||||
} else {
|
||||
// Small strings are loaded through stack if they cross page boundary.
|
||||
__ string_indexof($str1$$Register, $str2$$Register,
|
||||
$cnt1$$Register, $cnt2$$Register,
|
||||
icnt2, $result$$Register,
|
||||
$vec$$XMMRegister, $tmp$$Register, StrIntrinsicNode::UL);
|
||||
$vec1$$XMMRegister, $tmp$$Register, StrIntrinsicNode::UL);
|
||||
}
|
||||
%}
|
||||
ins_pipe( pipe_slow );
|
||||
%}
|
||||
|
||||
instruct string_indexofL(eDIRegP str1, eDXRegI cnt1, eSIRegP str2, eAXRegI cnt2,
|
||||
eBXRegI result, regD vec, eCXRegI tmp, eFlagsReg cr) %{
|
||||
eBXRegI result, regD vec1, eCXRegI tmp, eFlagsReg cr) %{
|
||||
predicate(UseSSE42Intrinsics && (((StrIndexOfNode*)n)->encoding() == StrIntrinsicNode::LL));
|
||||
match(Set result (StrIndexOf (Binary str1 cnt1) (Binary str2 cnt2)));
|
||||
effect(TEMP vec, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL tmp, KILL cr);
|
||||
effect(TEMP vec1, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL tmp, KILL cr);
|
||||
|
||||
format %{ "String IndexOf byte[] $str1,$cnt1,$str2,$cnt2 -> $result // KILL all" %}
|
||||
ins_encode %{
|
||||
__ string_indexof($str1$$Register, $str2$$Register,
|
||||
$cnt1$$Register, $cnt2$$Register,
|
||||
(-1), $result$$Register,
|
||||
$vec$$XMMRegister, $tmp$$Register, StrIntrinsicNode::LL);
|
||||
$vec1$$XMMRegister, $tmp$$Register, StrIntrinsicNode::LL);
|
||||
%}
|
||||
ins_pipe( pipe_slow );
|
||||
%}
|
||||
|
||||
instruct string_indexofU(eDIRegP str1, eDXRegI cnt1, eSIRegP str2, eAXRegI cnt2,
|
||||
eBXRegI result, regD vec, eCXRegI tmp, eFlagsReg cr) %{
|
||||
eBXRegI result, regD vec1, eCXRegI tmp, eFlagsReg cr) %{
|
||||
predicate(UseSSE42Intrinsics && (((StrIndexOfNode*)n)->encoding() == StrIntrinsicNode::UU));
|
||||
match(Set result (StrIndexOf (Binary str1 cnt1) (Binary str2 cnt2)));
|
||||
effect(TEMP vec, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL tmp, KILL cr);
|
||||
effect(TEMP vec1, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL tmp, KILL cr);
|
||||
|
||||
format %{ "String IndexOf char[] $str1,$cnt1,$str2,$cnt2 -> $result // KILL all" %}
|
||||
ins_encode %{
|
||||
__ string_indexof($str1$$Register, $str2$$Register,
|
||||
$cnt1$$Register, $cnt2$$Register,
|
||||
(-1), $result$$Register,
|
||||
$vec$$XMMRegister, $tmp$$Register, StrIntrinsicNode::UU);
|
||||
$vec1$$XMMRegister, $tmp$$Register, StrIntrinsicNode::UU);
|
||||
%}
|
||||
ins_pipe( pipe_slow );
|
||||
%}
|
||||
|
||||
instruct string_indexofUL(eDIRegP str1, eDXRegI cnt1, eSIRegP str2, eAXRegI cnt2,
|
||||
eBXRegI result, regD vec, eCXRegI tmp, eFlagsReg cr) %{
|
||||
eBXRegI result, regD vec1, eCXRegI tmp, eFlagsReg cr) %{
|
||||
predicate(UseSSE42Intrinsics && (((StrIndexOfNode*)n)->encoding() == StrIntrinsicNode::UL));
|
||||
match(Set result (StrIndexOf (Binary str1 cnt1) (Binary str2 cnt2)));
|
||||
effect(TEMP vec, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL tmp, KILL cr);
|
||||
effect(TEMP vec1, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL tmp, KILL cr);
|
||||
|
||||
format %{ "String IndexOf char[] $str1,$cnt1,$str2,$cnt2 -> $result // KILL all" %}
|
||||
ins_encode %{
|
||||
__ string_indexof($str1$$Register, $str2$$Register,
|
||||
$cnt1$$Register, $cnt2$$Register,
|
||||
(-1), $result$$Register,
|
||||
$vec$$XMMRegister, $tmp$$Register, StrIntrinsicNode::UL);
|
||||
$vec1$$XMMRegister, $tmp$$Register, StrIntrinsicNode::UL);
|
||||
%}
|
||||
ins_pipe( pipe_slow );
|
||||
%}
|
||||
|
@ -3720,72 +3720,6 @@ operand vlRegD() %{
|
||||
interface(REG_INTER);
|
||||
%}
|
||||
|
||||
// Vectors
|
||||
operand vecS() %{
|
||||
constraint(ALLOC_IN_RC(vectors_reg_vlbwdq));
|
||||
match(VecS);
|
||||
|
||||
format %{ %}
|
||||
interface(REG_INTER);
|
||||
%}
|
||||
|
||||
// Vectors
|
||||
operand legVecS() %{
|
||||
constraint(ALLOC_IN_RC(vectors_reg_legacy));
|
||||
match(VecS);
|
||||
|
||||
format %{ %}
|
||||
interface(REG_INTER);
|
||||
%}
|
||||
|
||||
operand vecD() %{
|
||||
constraint(ALLOC_IN_RC(vectord_reg_vlbwdq));
|
||||
match(VecD);
|
||||
|
||||
format %{ %}
|
||||
interface(REG_INTER);
|
||||
%}
|
||||
|
||||
operand legVecD() %{
|
||||
constraint(ALLOC_IN_RC(vectord_reg_legacy));
|
||||
match(VecD);
|
||||
|
||||
format %{ %}
|
||||
interface(REG_INTER);
|
||||
%}
|
||||
|
||||
operand vecX() %{
|
||||
constraint(ALLOC_IN_RC(vectorx_reg_vlbwdq));
|
||||
match(VecX);
|
||||
|
||||
format %{ %}
|
||||
interface(REG_INTER);
|
||||
%}
|
||||
|
||||
operand legVecX() %{
|
||||
constraint(ALLOC_IN_RC(vectorx_reg_legacy));
|
||||
match(VecX);
|
||||
|
||||
format %{ %}
|
||||
interface(REG_INTER);
|
||||
%}
|
||||
|
||||
operand vecY() %{
|
||||
constraint(ALLOC_IN_RC(vectory_reg_vlbwdq));
|
||||
match(VecY);
|
||||
|
||||
format %{ %}
|
||||
interface(REG_INTER);
|
||||
%}
|
||||
|
||||
operand legVecY() %{
|
||||
constraint(ALLOC_IN_RC(vectory_reg_legacy));
|
||||
match(VecY);
|
||||
|
||||
format %{ %}
|
||||
interface(REG_INTER);
|
||||
%}
|
||||
|
||||
//----------Memory Operands----------------------------------------------------
|
||||
// Direct Memory Operand
|
||||
// operand direct(immP addr)
|
||||
@ -11224,7 +11158,7 @@ instruct rep_stos_large(rcx_RegL cnt, rdi_RegP base, regD tmp, rax_RegI zero,
|
||||
%}
|
||||
|
||||
instruct string_compareL(rdi_RegP str1, rcx_RegI cnt1, rsi_RegP str2, rdx_RegI cnt2,
|
||||
rax_RegI result, legVecS tmp1, rFlagsReg cr)
|
||||
rax_RegI result, legRegD tmp1, rFlagsReg cr)
|
||||
%{
|
||||
predicate(((StrCompNode*)n)->encoding() == StrIntrinsicNode::LL);
|
||||
match(Set result (StrComp (Binary str1 cnt1) (Binary str2 cnt2)));
|
||||
@ -11240,7 +11174,7 @@ instruct string_compareL(rdi_RegP str1, rcx_RegI cnt1, rsi_RegP str2, rdx_RegI c
|
||||
%}
|
||||
|
||||
instruct string_compareU(rdi_RegP str1, rcx_RegI cnt1, rsi_RegP str2, rdx_RegI cnt2,
|
||||
rax_RegI result, legVecS tmp1, rFlagsReg cr)
|
||||
rax_RegI result, legRegD tmp1, rFlagsReg cr)
|
||||
%{
|
||||
predicate(((StrCompNode*)n)->encoding() == StrIntrinsicNode::UU);
|
||||
match(Set result (StrComp (Binary str1 cnt1) (Binary str2 cnt2)));
|
||||
@ -11256,7 +11190,7 @@ instruct string_compareU(rdi_RegP str1, rcx_RegI cnt1, rsi_RegP str2, rdx_RegI c
|
||||
%}
|
||||
|
||||
instruct string_compareLU(rdi_RegP str1, rcx_RegI cnt1, rsi_RegP str2, rdx_RegI cnt2,
|
||||
rax_RegI result, legVecS tmp1, rFlagsReg cr)
|
||||
rax_RegI result, legRegD tmp1, rFlagsReg cr)
|
||||
%{
|
||||
predicate(((StrCompNode*)n)->encoding() == StrIntrinsicNode::LU);
|
||||
match(Set result (StrComp (Binary str1 cnt1) (Binary str2 cnt2)));
|
||||
@ -11272,7 +11206,7 @@ instruct string_compareLU(rdi_RegP str1, rcx_RegI cnt1, rsi_RegP str2, rdx_RegI
|
||||
%}
|
||||
|
||||
instruct string_compareUL(rsi_RegP str1, rdx_RegI cnt1, rdi_RegP str2, rcx_RegI cnt2,
|
||||
rax_RegI result, legVecS tmp1, rFlagsReg cr)
|
||||
rax_RegI result, legRegD tmp1, rFlagsReg cr)
|
||||
%{
|
||||
predicate(((StrCompNode*)n)->encoding() == StrIntrinsicNode::UL);
|
||||
match(Set result (StrComp (Binary str1 cnt1) (Binary str2 cnt2)));
|
||||
@ -11289,13 +11223,13 @@ instruct string_compareUL(rsi_RegP str1, rdx_RegI cnt1, rdi_RegP str2, rcx_RegI
|
||||
|
||||
// fast search of substring with known size.
|
||||
instruct string_indexof_conL(rdi_RegP str1, rdx_RegI cnt1, rsi_RegP str2, immI int_cnt2,
|
||||
rbx_RegI result, legVecS vec, rax_RegI cnt2, rcx_RegI tmp, rFlagsReg cr)
|
||||
rbx_RegI result, legRegD tmp_vec, rax_RegI cnt2, rcx_RegI tmp, rFlagsReg cr)
|
||||
%{
|
||||
predicate(UseSSE42Intrinsics && (((StrIndexOfNode*)n)->encoding() == StrIntrinsicNode::LL));
|
||||
match(Set result (StrIndexOf (Binary str1 cnt1) (Binary str2 int_cnt2)));
|
||||
effect(TEMP vec, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, KILL cnt2, KILL tmp, KILL cr);
|
||||
effect(TEMP tmp_vec, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, KILL cnt2, KILL tmp, KILL cr);
|
||||
|
||||
format %{ "String IndexOf byte[] $str1,$cnt1,$str2,$int_cnt2 -> $result // KILL $vec, $cnt1, $cnt2, $tmp" %}
|
||||
format %{ "String IndexOf byte[] $str1,$cnt1,$str2,$int_cnt2 -> $result // KILL $tmp_vec, $cnt1, $cnt2, $tmp" %}
|
||||
ins_encode %{
|
||||
int icnt2 = (int)$int_cnt2$$constant;
|
||||
if (icnt2 >= 16) {
|
||||
@ -11304,13 +11238,13 @@ instruct string_indexof_conL(rdi_RegP str1, rdx_RegI cnt1, rsi_RegP str2, immI i
|
||||
__ string_indexofC8($str1$$Register, $str2$$Register,
|
||||
$cnt1$$Register, $cnt2$$Register,
|
||||
icnt2, $result$$Register,
|
||||
$vec$$XMMRegister, $tmp$$Register, StrIntrinsicNode::LL);
|
||||
$tmp_vec$$XMMRegister, $tmp$$Register, StrIntrinsicNode::LL);
|
||||
} else {
|
||||
// Small strings are loaded through stack if they cross page boundary.
|
||||
__ string_indexof($str1$$Register, $str2$$Register,
|
||||
$cnt1$$Register, $cnt2$$Register,
|
||||
icnt2, $result$$Register,
|
||||
$vec$$XMMRegister, $tmp$$Register, StrIntrinsicNode::LL);
|
||||
$tmp_vec$$XMMRegister, $tmp$$Register, StrIntrinsicNode::LL);
|
||||
}
|
||||
%}
|
||||
ins_pipe( pipe_slow );
|
||||
@ -11318,13 +11252,13 @@ instruct string_indexof_conL(rdi_RegP str1, rdx_RegI cnt1, rsi_RegP str2, immI i
|
||||
|
||||
// fast search of substring with known size.
|
||||
instruct string_indexof_conU(rdi_RegP str1, rdx_RegI cnt1, rsi_RegP str2, immI int_cnt2,
|
||||
rbx_RegI result, legVecS vec, rax_RegI cnt2, rcx_RegI tmp, rFlagsReg cr)
|
||||
rbx_RegI result, legRegD tmp_vec, rax_RegI cnt2, rcx_RegI tmp, rFlagsReg cr)
|
||||
%{
|
||||
predicate(UseSSE42Intrinsics && (((StrIndexOfNode*)n)->encoding() == StrIntrinsicNode::UU));
|
||||
match(Set result (StrIndexOf (Binary str1 cnt1) (Binary str2 int_cnt2)));
|
||||
effect(TEMP vec, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, KILL cnt2, KILL tmp, KILL cr);
|
||||
effect(TEMP tmp_vec, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, KILL cnt2, KILL tmp, KILL cr);
|
||||
|
||||
format %{ "String IndexOf char[] $str1,$cnt1,$str2,$int_cnt2 -> $result // KILL $vec, $cnt1, $cnt2, $tmp" %}
|
||||
format %{ "String IndexOf char[] $str1,$cnt1,$str2,$int_cnt2 -> $result // KILL $tmp_vec, $cnt1, $cnt2, $tmp" %}
|
||||
ins_encode %{
|
||||
int icnt2 = (int)$int_cnt2$$constant;
|
||||
if (icnt2 >= 8) {
|
||||
@ -11333,13 +11267,13 @@ instruct string_indexof_conU(rdi_RegP str1, rdx_RegI cnt1, rsi_RegP str2, immI i
|
||||
__ string_indexofC8($str1$$Register, $str2$$Register,
|
||||
$cnt1$$Register, $cnt2$$Register,
|
||||
icnt2, $result$$Register,
|
||||
$vec$$XMMRegister, $tmp$$Register, StrIntrinsicNode::UU);
|
||||
$tmp_vec$$XMMRegister, $tmp$$Register, StrIntrinsicNode::UU);
|
||||
} else {
|
||||
// Small strings are loaded through stack if they cross page boundary.
|
||||
__ string_indexof($str1$$Register, $str2$$Register,
|
||||
$cnt1$$Register, $cnt2$$Register,
|
||||
icnt2, $result$$Register,
|
||||
$vec$$XMMRegister, $tmp$$Register, StrIntrinsicNode::UU);
|
||||
$tmp_vec$$XMMRegister, $tmp$$Register, StrIntrinsicNode::UU);
|
||||
}
|
||||
%}
|
||||
ins_pipe( pipe_slow );
|
||||
@ -11347,13 +11281,13 @@ instruct string_indexof_conU(rdi_RegP str1, rdx_RegI cnt1, rsi_RegP str2, immI i
|
||||
|
||||
// fast search of substring with known size.
|
||||
instruct string_indexof_conUL(rdi_RegP str1, rdx_RegI cnt1, rsi_RegP str2, immI int_cnt2,
|
||||
rbx_RegI result, legVecS vec, rax_RegI cnt2, rcx_RegI tmp, rFlagsReg cr)
|
||||
rbx_RegI result, legRegD tmp_vec, rax_RegI cnt2, rcx_RegI tmp, rFlagsReg cr)
|
||||
%{
|
||||
predicate(UseSSE42Intrinsics && (((StrIndexOfNode*)n)->encoding() == StrIntrinsicNode::UL));
|
||||
match(Set result (StrIndexOf (Binary str1 cnt1) (Binary str2 int_cnt2)));
|
||||
effect(TEMP vec, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, KILL cnt2, KILL tmp, KILL cr);
|
||||
effect(TEMP tmp_vec, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, KILL cnt2, KILL tmp, KILL cr);
|
||||
|
||||
format %{ "String IndexOf char[] $str1,$cnt1,$str2,$int_cnt2 -> $result // KILL $vec, $cnt1, $cnt2, $tmp" %}
|
||||
format %{ "String IndexOf char[] $str1,$cnt1,$str2,$int_cnt2 -> $result // KILL $tmp_vec, $cnt1, $cnt2, $tmp" %}
|
||||
ins_encode %{
|
||||
int icnt2 = (int)$int_cnt2$$constant;
|
||||
if (icnt2 >= 8) {
|
||||
@ -11362,86 +11296,86 @@ instruct string_indexof_conUL(rdi_RegP str1, rdx_RegI cnt1, rsi_RegP str2, immI
|
||||
__ string_indexofC8($str1$$Register, $str2$$Register,
|
||||
$cnt1$$Register, $cnt2$$Register,
|
||||
icnt2, $result$$Register,
|
||||
$vec$$XMMRegister, $tmp$$Register, StrIntrinsicNode::UL);
|
||||
$tmp_vec$$XMMRegister, $tmp$$Register, StrIntrinsicNode::UL);
|
||||
} else {
|
||||
// Small strings are loaded through stack if they cross page boundary.
|
||||
__ string_indexof($str1$$Register, $str2$$Register,
|
||||
$cnt1$$Register, $cnt2$$Register,
|
||||
icnt2, $result$$Register,
|
||||
$vec$$XMMRegister, $tmp$$Register, StrIntrinsicNode::UL);
|
||||
$tmp_vec$$XMMRegister, $tmp$$Register, StrIntrinsicNode::UL);
|
||||
}
|
||||
%}
|
||||
ins_pipe( pipe_slow );
|
||||
%}
|
||||
|
||||
instruct string_indexofL(rdi_RegP str1, rdx_RegI cnt1, rsi_RegP str2, rax_RegI cnt2,
|
||||
rbx_RegI result, legVecS vec, rcx_RegI tmp, rFlagsReg cr)
|
||||
rbx_RegI result, legRegD tmp_vec, rcx_RegI tmp, rFlagsReg cr)
|
||||
%{
|
||||
predicate(UseSSE42Intrinsics && (((StrIndexOfNode*)n)->encoding() == StrIntrinsicNode::LL));
|
||||
match(Set result (StrIndexOf (Binary str1 cnt1) (Binary str2 cnt2)));
|
||||
effect(TEMP vec, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL tmp, KILL cr);
|
||||
effect(TEMP tmp_vec, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL tmp, KILL cr);
|
||||
|
||||
format %{ "String IndexOf byte[] $str1,$cnt1,$str2,$cnt2 -> $result // KILL all" %}
|
||||
ins_encode %{
|
||||
__ string_indexof($str1$$Register, $str2$$Register,
|
||||
$cnt1$$Register, $cnt2$$Register,
|
||||
(-1), $result$$Register,
|
||||
$vec$$XMMRegister, $tmp$$Register, StrIntrinsicNode::LL);
|
||||
$tmp_vec$$XMMRegister, $tmp$$Register, StrIntrinsicNode::LL);
|
||||
%}
|
||||
ins_pipe( pipe_slow );
|
||||
%}
|
||||
|
||||
instruct string_indexofU(rdi_RegP str1, rdx_RegI cnt1, rsi_RegP str2, rax_RegI cnt2,
|
||||
rbx_RegI result, legVecS vec, rcx_RegI tmp, rFlagsReg cr)
|
||||
rbx_RegI result, legRegD tmp_vec, rcx_RegI tmp, rFlagsReg cr)
|
||||
%{
|
||||
predicate(UseSSE42Intrinsics && (((StrIndexOfNode*)n)->encoding() == StrIntrinsicNode::UU));
|
||||
match(Set result (StrIndexOf (Binary str1 cnt1) (Binary str2 cnt2)));
|
||||
effect(TEMP vec, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL tmp, KILL cr);
|
||||
effect(TEMP tmp_vec, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL tmp, KILL cr);
|
||||
|
||||
format %{ "String IndexOf char[] $str1,$cnt1,$str2,$cnt2 -> $result // KILL all" %}
|
||||
ins_encode %{
|
||||
__ string_indexof($str1$$Register, $str2$$Register,
|
||||
$cnt1$$Register, $cnt2$$Register,
|
||||
(-1), $result$$Register,
|
||||
$vec$$XMMRegister, $tmp$$Register, StrIntrinsicNode::UU);
|
||||
$tmp_vec$$XMMRegister, $tmp$$Register, StrIntrinsicNode::UU);
|
||||
%}
|
||||
ins_pipe( pipe_slow );
|
||||
%}
|
||||
|
||||
instruct string_indexofUL(rdi_RegP str1, rdx_RegI cnt1, rsi_RegP str2, rax_RegI cnt2,
|
||||
rbx_RegI result, legVecS vec, rcx_RegI tmp, rFlagsReg cr)
|
||||
rbx_RegI result, legRegD tmp_vec, rcx_RegI tmp, rFlagsReg cr)
|
||||
%{
|
||||
predicate(UseSSE42Intrinsics && (((StrIndexOfNode*)n)->encoding() == StrIntrinsicNode::UL));
|
||||
match(Set result (StrIndexOf (Binary str1 cnt1) (Binary str2 cnt2)));
|
||||
effect(TEMP vec, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL tmp, KILL cr);
|
||||
effect(TEMP tmp_vec, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL tmp, KILL cr);
|
||||
|
||||
format %{ "String IndexOf char[] $str1,$cnt1,$str2,$cnt2 -> $result // KILL all" %}
|
||||
ins_encode %{
|
||||
__ string_indexof($str1$$Register, $str2$$Register,
|
||||
$cnt1$$Register, $cnt2$$Register,
|
||||
(-1), $result$$Register,
|
||||
$vec$$XMMRegister, $tmp$$Register, StrIntrinsicNode::UL);
|
||||
$tmp_vec$$XMMRegister, $tmp$$Register, StrIntrinsicNode::UL);
|
||||
%}
|
||||
ins_pipe( pipe_slow );
|
||||
%}
|
||||
|
||||
instruct string_indexofU_char(rdi_RegP str1, rdx_RegI cnt1, rax_RegI ch,
|
||||
rbx_RegI result, legVecS vec1, legVecS vec2, legVecS vec3, rcx_RegI tmp, rFlagsReg cr)
|
||||
rbx_RegI result, legRegD tmp_vec1, legRegD tmp_vec2, legRegD tmp_vec3, rcx_RegI tmp, rFlagsReg cr)
|
||||
%{
|
||||
predicate(UseSSE42Intrinsics);
|
||||
match(Set result (StrIndexOfChar (Binary str1 cnt1) ch));
|
||||
effect(TEMP vec1, TEMP vec2, TEMP vec3, USE_KILL str1, USE_KILL cnt1, USE_KILL ch, TEMP tmp, KILL cr);
|
||||
effect(TEMP tmp_vec1, TEMP tmp_vec2, TEMP tmp_vec3, USE_KILL str1, USE_KILL cnt1, USE_KILL ch, TEMP tmp, KILL cr);
|
||||
format %{ "String IndexOf char[] $str1,$cnt1,$ch -> $result // KILL all" %}
|
||||
ins_encode %{
|
||||
__ string_indexof_char($str1$$Register, $cnt1$$Register, $ch$$Register, $result$$Register,
|
||||
$vec1$$XMMRegister, $vec2$$XMMRegister, $vec3$$XMMRegister, $tmp$$Register);
|
||||
$tmp_vec1$$XMMRegister, $tmp_vec2$$XMMRegister, $tmp_vec3$$XMMRegister, $tmp$$Register);
|
||||
%}
|
||||
ins_pipe( pipe_slow );
|
||||
%}
|
||||
|
||||
// fast string equals
|
||||
instruct string_equals(rdi_RegP str1, rsi_RegP str2, rcx_RegI cnt, rax_RegI result,
|
||||
legVecS tmp1, legVecS tmp2, rbx_RegI tmp3, rFlagsReg cr)
|
||||
legRegD tmp1, legRegD tmp2, rbx_RegI tmp3, rFlagsReg cr)
|
||||
%{
|
||||
match(Set result (StrEquals (Binary str1 str2) cnt));
|
||||
effect(TEMP tmp1, TEMP tmp2, USE_KILL str1, USE_KILL str2, USE_KILL cnt, KILL tmp3, KILL cr);
|
||||
@ -11457,7 +11391,7 @@ instruct string_equals(rdi_RegP str1, rsi_RegP str2, rcx_RegI cnt, rax_RegI resu
|
||||
|
||||
// fast array equals
|
||||
instruct array_equalsB(rdi_RegP ary1, rsi_RegP ary2, rax_RegI result,
|
||||
legVecS tmp1, legVecS tmp2, rcx_RegI tmp3, rbx_RegI tmp4, rFlagsReg cr)
|
||||
legRegD tmp1, legRegD tmp2, rcx_RegI tmp3, rbx_RegI tmp4, rFlagsReg cr)
|
||||
%{
|
||||
predicate(((AryEqNode*)n)->encoding() == StrIntrinsicNode::LL);
|
||||
match(Set result (AryEq ary1 ary2));
|
||||
@ -11473,7 +11407,7 @@ instruct array_equalsB(rdi_RegP ary1, rsi_RegP ary2, rax_RegI result,
|
||||
%}
|
||||
|
||||
instruct array_equalsC(rdi_RegP ary1, rsi_RegP ary2, rax_RegI result,
|
||||
legVecS tmp1, legVecS tmp2, rcx_RegI tmp3, rbx_RegI tmp4, rFlagsReg cr)
|
||||
legRegD tmp1, legRegD tmp2, rcx_RegI tmp3, rbx_RegI tmp4, rFlagsReg cr)
|
||||
%{
|
||||
predicate(((AryEqNode*)n)->encoding() == StrIntrinsicNode::UU);
|
||||
match(Set result (AryEq ary1 ary2));
|
||||
@ -11489,7 +11423,7 @@ instruct array_equalsC(rdi_RegP ary1, rsi_RegP ary2, rax_RegI result,
|
||||
%}
|
||||
|
||||
instruct has_negatives(rsi_RegP ary1, rcx_RegI len, rax_RegI result,
|
||||
legVecS tmp1, legVecS tmp2, rbx_RegI tmp3, rFlagsReg cr)
|
||||
legRegD tmp1, legRegD tmp2, rbx_RegI tmp3, rFlagsReg cr)
|
||||
%{
|
||||
match(Set result (HasNegatives ary1 len));
|
||||
effect(TEMP tmp1, TEMP tmp2, USE_KILL ary1, USE_KILL len, KILL tmp3, KILL cr);
|
||||
@ -11504,7 +11438,7 @@ instruct has_negatives(rsi_RegP ary1, rcx_RegI len, rax_RegI result,
|
||||
%}
|
||||
|
||||
// fast char[] to byte[] compression
|
||||
instruct string_compress(rsi_RegP src, rdi_RegP dst, rdx_RegI len, legVecS tmp1, legVecS tmp2, legVecS tmp3, legVecS tmp4,
|
||||
instruct string_compress(rsi_RegP src, rdi_RegP dst, rdx_RegI len, legRegD tmp1, legRegD tmp2, legRegD tmp3, legRegD tmp4,
|
||||
rcx_RegI tmp5, rax_RegI result, rFlagsReg cr) %{
|
||||
match(Set result (StrCompressedCopy src (Binary dst len)));
|
||||
effect(TEMP tmp1, TEMP tmp2, TEMP tmp3, TEMP tmp4, USE_KILL src, USE_KILL dst, USE_KILL len, KILL tmp5, KILL cr);
|
||||
@ -11520,7 +11454,7 @@ instruct string_compress(rsi_RegP src, rdi_RegP dst, rdx_RegI len, legVecS tmp1,
|
||||
|
||||
// fast byte[] to char[] inflation
|
||||
instruct string_inflate(Universe dummy, rsi_RegP src, rdi_RegP dst, rdx_RegI len,
|
||||
legVecS tmp1, rcx_RegI tmp2, rFlagsReg cr) %{
|
||||
legRegD tmp1, rcx_RegI tmp2, rFlagsReg cr) %{
|
||||
match(Set dummy (StrInflatedCopy src (Binary dst len)));
|
||||
effect(TEMP tmp1, TEMP tmp2, USE_KILL src, USE_KILL dst, USE_KILL len, KILL cr);
|
||||
|
||||
@ -11534,7 +11468,7 @@ instruct string_inflate(Universe dummy, rsi_RegP src, rdi_RegP dst, rdx_RegI len
|
||||
|
||||
// encode char[] to byte[] in ISO_8859_1
|
||||
instruct encode_iso_array(rsi_RegP src, rdi_RegP dst, rdx_RegI len,
|
||||
legVecS tmp1, legVecS tmp2, legVecS tmp3, legVecS tmp4,
|
||||
legRegD tmp1, legRegD tmp2, legRegD tmp3, legRegD tmp4,
|
||||
rcx_RegI tmp5, rax_RegI result, rFlagsReg cr) %{
|
||||
match(Set result (EncodeISOArray src (Binary dst len)));
|
||||
effect(TEMP tmp1, TEMP tmp2, TEMP tmp3, TEMP tmp4, USE_KILL src, USE_KILL dst, USE_KILL len, KILL tmp5, KILL cr);
|
||||
|
@ -1568,6 +1568,8 @@ void ArchDesc::declareClasses(FILE *fp) {
|
||||
fprintf(fp," assert(operand_index < _num_opnds, \"invalid _opnd_array index\");\n");
|
||||
fprintf(fp," _opnd_array[operand_index] = operand;\n");
|
||||
fprintf(fp," }\n");
|
||||
fprintf(fp," virtual uint rule() const { return %s_rule; }\n",
|
||||
instr->_ident);
|
||||
fprintf(fp,"private:\n");
|
||||
if ( instr->is_ideal_jump() ) {
|
||||
fprintf(fp," virtual void add_case_label(int index_num, Label* blockLabel) {\n");
|
||||
@ -1579,8 +1581,6 @@ void ArchDesc::declareClasses(FILE *fp) {
|
||||
}
|
||||
|
||||
out_RegMask(fp); // output register mask
|
||||
fprintf(fp," virtual uint rule() const { return %s_rule; }\n",
|
||||
instr->_ident);
|
||||
|
||||
// If this instruction contains a labelOper
|
||||
// Declare Node::methods that set operand Label's contents
|
||||
|
@ -2466,7 +2466,11 @@ void Compile::Code_Gen() {
|
||||
{
|
||||
TracePhase tp("matcher", &timers[_t_matcher]);
|
||||
matcher.match();
|
||||
if (failing()) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// In debug mode can dump m._nodes.dump() for mapping of ideal to machine
|
||||
// nodes. Mapping is only valid at the root of each matched subtree.
|
||||
NOT_PRODUCT( verify_graph_edges(); )
|
||||
|
@ -387,10 +387,10 @@ const class TypePtr *MachNode::adr_type() const {
|
||||
|
||||
|
||||
//-----------------------------operand_index---------------------------------
|
||||
int MachNode::operand_index( uint operand ) const {
|
||||
if( operand < 1 ) return -1;
|
||||
int MachNode::operand_index(uint operand) const {
|
||||
if (operand < 1) return -1;
|
||||
assert(operand < num_opnds(), "oob");
|
||||
if( _opnds[operand]->num_edges() == 0 ) return -1;
|
||||
if (_opnds[operand]->num_edges() == 0) return -1;
|
||||
|
||||
uint skipped = oper_input_base(); // Sum of leaves skipped so far
|
||||
for (uint opcnt = 1; opcnt < operand; opcnt++) {
|
||||
@ -412,6 +412,20 @@ int MachNode::operand_index(const MachOper *oper) const {
|
||||
return skipped;
|
||||
}
|
||||
|
||||
int MachNode::operand_index(Node* def) const {
|
||||
uint skipped = oper_input_base(); // Sum of leaves skipped so far
|
||||
for (uint opcnt = 1; opcnt < num_opnds(); opcnt++) {
|
||||
uint num_edges = _opnds[opcnt]->num_edges(); // leaves for operand
|
||||
for (uint i = 0; i < num_edges; i++) {
|
||||
if (in(skipped + i) == def) {
|
||||
return opcnt;
|
||||
}
|
||||
}
|
||||
skipped += num_edges;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
//------------------------------peephole---------------------------------------
|
||||
// Apply peephole rule(s) to this instruction
|
||||
MachNode *MachNode::peephole(Block *block, int block_index, PhaseRegAlloc *ra_, int &deleted) {
|
||||
|
@ -243,6 +243,7 @@ public:
|
||||
// First index in _in[] corresponding to operand, or -1 if there is none
|
||||
int operand_index(uint operand) const;
|
||||
int operand_index(const MachOper *oper) const;
|
||||
int operand_index(Node* m) const;
|
||||
|
||||
// Register class input is expected in
|
||||
virtual const RegMask &in_RegMask(uint) const;
|
||||
|
@ -392,10 +392,16 @@ void Matcher::match( ) {
|
||||
NOT_DEBUG( old->destruct_contents() );
|
||||
|
||||
// ------------------------
|
||||
// Set up save-on-entry registers
|
||||
// Set up save-on-entry registers.
|
||||
Fixup_Save_On_Entry( );
|
||||
}
|
||||
|
||||
{ // Cleanup mach IR after selection phase is over.
|
||||
Compile::TracePhase tp("postselect_cleanup", &timers[_t_postselect_cleanup]);
|
||||
do_postselect_cleanup();
|
||||
if (C->failing()) return;
|
||||
assert(verify_after_postselect_cleanup(), "");
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------Fixup_Save_On_Entry----------------------------
|
||||
// The stated purpose of this routine is to take care of save-on-entry
|
||||
@ -851,54 +857,23 @@ void Matcher::init_spill_mask( Node *ret ) {
|
||||
|
||||
// Grab the Frame Pointer
|
||||
Node *fp = ret->in(TypeFunc::FramePtr);
|
||||
Node *mem = ret->in(TypeFunc::Memory);
|
||||
const TypePtr* atp = TypePtr::BOTTOM;
|
||||
// Share frame pointer while making spill ops
|
||||
set_shared(fp);
|
||||
|
||||
// Compute generic short-offset Loads
|
||||
// Get the ADLC notion of the right regmask, for each basic type.
|
||||
#ifdef _LP64
|
||||
MachNode *spillCP = match_tree(new LoadNNode(NULL,mem,fp,atp,TypeInstPtr::BOTTOM,MemNode::unordered));
|
||||
idealreg2regmask[Op_RegN] = regmask_for_ideal_register(Op_RegN, ret);
|
||||
#endif
|
||||
MachNode *spillI = match_tree(new LoadINode(NULL,mem,fp,atp,TypeInt::INT,MemNode::unordered));
|
||||
MachNode *spillL = match_tree(new LoadLNode(NULL,mem,fp,atp,TypeLong::LONG,MemNode::unordered, LoadNode::DependsOnlyOnTest, false));
|
||||
MachNode *spillF = match_tree(new LoadFNode(NULL,mem,fp,atp,Type::FLOAT,MemNode::unordered));
|
||||
MachNode *spillD = match_tree(new LoadDNode(NULL,mem,fp,atp,Type::DOUBLE,MemNode::unordered));
|
||||
MachNode *spillP = match_tree(new LoadPNode(NULL,mem,fp,atp,TypeInstPtr::BOTTOM,MemNode::unordered));
|
||||
assert(spillI != NULL && spillL != NULL && spillF != NULL &&
|
||||
spillD != NULL && spillP != NULL, "");
|
||||
// Get the ADLC notion of the right regmask, for each basic type.
|
||||
#ifdef _LP64
|
||||
idealreg2regmask[Op_RegN] = &spillCP->out_RegMask();
|
||||
#endif
|
||||
idealreg2regmask[Op_RegI] = &spillI->out_RegMask();
|
||||
idealreg2regmask[Op_RegL] = &spillL->out_RegMask();
|
||||
idealreg2regmask[Op_RegF] = &spillF->out_RegMask();
|
||||
idealreg2regmask[Op_RegD] = &spillD->out_RegMask();
|
||||
idealreg2regmask[Op_RegP] = &spillP->out_RegMask();
|
||||
|
||||
// Vector regmasks.
|
||||
if (Matcher::vector_size_supported(T_BYTE,4)) {
|
||||
TypeVect::VECTS = TypeVect::make(T_BYTE, 4);
|
||||
MachNode *spillVectS = match_tree(new LoadVectorNode(NULL,mem,fp,atp,TypeVect::VECTS));
|
||||
idealreg2regmask[Op_VecS] = &spillVectS->out_RegMask();
|
||||
}
|
||||
if (Matcher::vector_size_supported(T_FLOAT,2)) {
|
||||
MachNode *spillVectD = match_tree(new LoadVectorNode(NULL,mem,fp,atp,TypeVect::VECTD));
|
||||
idealreg2regmask[Op_VecD] = &spillVectD->out_RegMask();
|
||||
}
|
||||
if (Matcher::vector_size_supported(T_FLOAT,4)) {
|
||||
MachNode *spillVectX = match_tree(new LoadVectorNode(NULL,mem,fp,atp,TypeVect::VECTX));
|
||||
idealreg2regmask[Op_VecX] = &spillVectX->out_RegMask();
|
||||
}
|
||||
if (Matcher::vector_size_supported(T_FLOAT,8)) {
|
||||
MachNode *spillVectY = match_tree(new LoadVectorNode(NULL,mem,fp,atp,TypeVect::VECTY));
|
||||
idealreg2regmask[Op_VecY] = &spillVectY->out_RegMask();
|
||||
}
|
||||
if (Matcher::vector_size_supported(T_FLOAT,16)) {
|
||||
MachNode *spillVectZ = match_tree(new LoadVectorNode(NULL,mem,fp,atp,TypeVect::VECTZ));
|
||||
idealreg2regmask[Op_VecZ] = &spillVectZ->out_RegMask();
|
||||
}
|
||||
idealreg2regmask[Op_RegI] = regmask_for_ideal_register(Op_RegI, ret);
|
||||
idealreg2regmask[Op_RegP] = regmask_for_ideal_register(Op_RegP, ret);
|
||||
idealreg2regmask[Op_RegF] = regmask_for_ideal_register(Op_RegF, ret);
|
||||
idealreg2regmask[Op_RegD] = regmask_for_ideal_register(Op_RegD, ret);
|
||||
idealreg2regmask[Op_RegL] = regmask_for_ideal_register(Op_RegL, ret);
|
||||
idealreg2regmask[Op_VecS] = regmask_for_ideal_register(Op_VecS, ret);
|
||||
idealreg2regmask[Op_VecD] = regmask_for_ideal_register(Op_VecD, ret);
|
||||
idealreg2regmask[Op_VecX] = regmask_for_ideal_register(Op_VecX, ret);
|
||||
idealreg2regmask[Op_VecY] = regmask_for_ideal_register(Op_VecY, ret);
|
||||
idealreg2regmask[Op_VecZ] = regmask_for_ideal_register(Op_VecZ, ret);
|
||||
}
|
||||
|
||||
#ifdef ASSERT
|
||||
@ -2502,6 +2477,167 @@ bool Matcher::gen_narrow_oop_implicit_null_checks() {
|
||||
CompressedOops::base() != NULL);
|
||||
}
|
||||
|
||||
// Compute RegMask for an ideal register.
|
||||
const RegMask* Matcher::regmask_for_ideal_register(uint ideal_reg, Node* ret) {
|
||||
const Type* t = Type::mreg2type[ideal_reg];
|
||||
if (t == NULL) {
|
||||
assert(ideal_reg >= Op_VecS && ideal_reg <= Op_VecZ, "not a vector: %d", ideal_reg);
|
||||
return NULL; // not supported
|
||||
}
|
||||
Node* fp = ret->in(TypeFunc::FramePtr);
|
||||
Node* mem = ret->in(TypeFunc::Memory);
|
||||
const TypePtr* atp = TypePtr::BOTTOM;
|
||||
MemNode::MemOrd mo = MemNode::unordered;
|
||||
|
||||
Node* spill;
|
||||
switch (ideal_reg) {
|
||||
case Op_RegN: spill = new LoadNNode(NULL, mem, fp, atp, t->is_narrowoop(), mo); break;
|
||||
case Op_RegI: spill = new LoadINode(NULL, mem, fp, atp, t->is_int(), mo); break;
|
||||
case Op_RegP: spill = new LoadPNode(NULL, mem, fp, atp, t->is_ptr(), mo); break;
|
||||
case Op_RegF: spill = new LoadFNode(NULL, mem, fp, atp, t, mo); break;
|
||||
case Op_RegD: spill = new LoadDNode(NULL, mem, fp, atp, t, mo); break;
|
||||
case Op_RegL: spill = new LoadLNode(NULL, mem, fp, atp, t->is_long(), mo); break;
|
||||
|
||||
case Op_VecS: // fall-through
|
||||
case Op_VecD: // fall-through
|
||||
case Op_VecX: // fall-through
|
||||
case Op_VecY: // fall-through
|
||||
case Op_VecZ: spill = new LoadVectorNode(NULL, mem, fp, atp, t->is_vect()); break;
|
||||
|
||||
default: ShouldNotReachHere();
|
||||
}
|
||||
MachNode* mspill = match_tree(spill);
|
||||
assert(mspill != NULL, "matching failed: %d", ideal_reg);
|
||||
// Handle generic vector operand case
|
||||
if (Matcher::supports_generic_vector_operands && t->isa_vect()) {
|
||||
specialize_mach_node(mspill);
|
||||
}
|
||||
return &mspill->out_RegMask();
|
||||
}
|
||||
|
||||
// Process Mach IR right after selection phase is over.
|
||||
void Matcher::do_postselect_cleanup() {
|
||||
if (supports_generic_vector_operands) {
|
||||
specialize_generic_vector_operands();
|
||||
if (C->failing()) return;
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// Generic machine operands elision.
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
// Convert (leg)Vec to (leg)Vec[SDXYZ].
|
||||
MachOper* Matcher::specialize_vector_operand_helper(MachNode* m, MachOper* original_opnd) {
|
||||
const Type* t = m->bottom_type();
|
||||
uint ideal_reg = t->ideal_reg();
|
||||
// Handle special cases
|
||||
if (t->isa_vect()) {
|
||||
// RShiftCntV/RShiftCntV report wide vector type, but VecS as ideal register (see vectornode.hpp).
|
||||
if (m->ideal_Opcode() == Op_RShiftCntV || m->ideal_Opcode() == Op_LShiftCntV) {
|
||||
ideal_reg = TypeVect::VECTS->ideal_reg(); // ideal_reg == Op_VecS
|
||||
}
|
||||
} else {
|
||||
// Chain instructions which convert scalar to vector (e.g., vshiftcntimm on x86) don't have vector type.
|
||||
int size_in_bytes = 4 * type2size[t->basic_type()];
|
||||
ideal_reg = Matcher::vector_ideal_reg(size_in_bytes);
|
||||
}
|
||||
return Matcher::specialize_generic_vector_operand(original_opnd, ideal_reg);
|
||||
}
|
||||
|
||||
// Compute concrete vector operand for a generic TEMP vector mach node based on its user info.
|
||||
void Matcher::specialize_temp_node(MachTempNode* tmp, MachNode* use, uint idx) {
|
||||
assert(use->in(idx) == tmp, "not a user");
|
||||
assert(!Matcher::is_generic_vector(use->_opnds[0]), "use not processed yet");
|
||||
|
||||
if ((uint)idx == use->two_adr()) { // DEF_TEMP case
|
||||
tmp->_opnds[0] = use->_opnds[0]->clone();
|
||||
} else {
|
||||
uint ideal_vreg = vector_ideal_reg(C->max_vector_size());
|
||||
tmp->_opnds[0] = specialize_generic_vector_operand(tmp->_opnds[0], ideal_vreg);
|
||||
}
|
||||
}
|
||||
|
||||
// Compute concrete vector operand for a generic DEF/USE vector operand (of mach node m at index idx).
|
||||
MachOper* Matcher::specialize_vector_operand(MachNode* m, uint idx) {
|
||||
assert(Matcher::is_generic_vector(m->_opnds[idx]), "repeated updates");
|
||||
if (idx == 0) { // DEF
|
||||
// Use mach node itself to compute vector operand type.
|
||||
return specialize_vector_operand_helper(m, m->_opnds[0]);
|
||||
} else {
|
||||
// Use def node to compute operand type.
|
||||
int base_idx = m->operand_index(idx);
|
||||
MachNode* in = m->in(base_idx)->as_Mach();
|
||||
if (in->is_MachTemp() && Matcher::is_generic_vector(in->_opnds[0])) {
|
||||
specialize_temp_node(in->as_MachTemp(), m, base_idx); // MachTemp node use site
|
||||
} else if (is_generic_reg2reg_move(in)) {
|
||||
in = in->in(1)->as_Mach(); // skip over generic reg-to-reg moves
|
||||
}
|
||||
return specialize_vector_operand_helper(in, m->_opnds[idx]);
|
||||
}
|
||||
}
|
||||
|
||||
void Matcher::specialize_mach_node(MachNode* m) {
|
||||
assert(!m->is_MachTemp(), "processed along with its user");
|
||||
// For generic use operands pull specific register class operands from
|
||||
// its def instruction's output operand (def operand).
|
||||
for (uint i = 0; i < m->num_opnds(); i++) {
|
||||
if (Matcher::is_generic_vector(m->_opnds[i])) {
|
||||
m->_opnds[i] = specialize_vector_operand(m, i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Replace generic vector operands with concrete vector operands and eliminate generic reg-to-reg moves from the graph.
|
||||
void Matcher::specialize_generic_vector_operands() {
|
||||
assert(supports_generic_vector_operands, "sanity");
|
||||
ResourceMark rm;
|
||||
|
||||
if (C->max_vector_size() == 0) {
|
||||
return; // no vector instructions or operands
|
||||
}
|
||||
// Replace generic vector operands (vec/legVec) with concrete ones (vec[SDXYZ]/legVec[SDXYZ])
|
||||
// and remove reg-to-reg vector moves (MoveVec2Leg and MoveLeg2Vec).
|
||||
Unique_Node_List live_nodes;
|
||||
C->identify_useful_nodes(live_nodes);
|
||||
|
||||
while (live_nodes.size() > 0) {
|
||||
MachNode* m = live_nodes.pop()->isa_Mach();
|
||||
if (m != NULL) {
|
||||
if (Matcher::is_generic_reg2reg_move(m)) {
|
||||
// Register allocator properly handles vec <=> leg moves using register masks.
|
||||
int opnd_idx = m->operand_index(1);
|
||||
Node* def = m->in(opnd_idx);
|
||||
m->subsume_by(def, C);
|
||||
} else if (m->is_MachTemp()) {
|
||||
// process MachTemp nodes at use site (see Matcher::specialize_vector_operand)
|
||||
} else {
|
||||
specialize_mach_node(m);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef ASSERT
|
||||
bool Matcher::verify_after_postselect_cleanup() {
|
||||
assert(!C->failing(), "sanity");
|
||||
if (supports_generic_vector_operands) {
|
||||
Unique_Node_List useful;
|
||||
C->identify_useful_nodes(useful);
|
||||
for (uint i = 0; i < useful.size(); i++) {
|
||||
MachNode* m = useful.at(i)->isa_Mach();
|
||||
if (m != NULL) {
|
||||
assert(!Matcher::is_generic_reg2reg_move(m), "no MoveVec nodes allowed");
|
||||
for (uint j = 0; j < m->num_opnds(); j++) {
|
||||
assert(!Matcher::is_generic_vector(m->_opnds[j]), "no generic vector operands allowed");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
#endif // ASSERT
|
||||
|
||||
// Used by the DFA in dfa_xxx.cpp. Check for a following barrier or
|
||||
// atomic instruction acting as a store_load barrier without any
|
||||
// intervening volatile load, and thus we don't need a barrier here.
|
||||
|
@ -506,6 +506,30 @@ public:
|
||||
// postalloc expand)?
|
||||
static const bool require_postalloc_expand;
|
||||
|
||||
// Does the platform support generic vector operands?
|
||||
// Requires cleanup after selection phase.
|
||||
static const bool supports_generic_vector_operands;
|
||||
|
||||
private:
|
||||
void do_postselect_cleanup();
|
||||
|
||||
void specialize_generic_vector_operands();
|
||||
void specialize_mach_node(MachNode* m);
|
||||
void specialize_temp_node(MachTempNode* tmp, MachNode* use, uint idx);
|
||||
MachOper* specialize_vector_operand(MachNode* m, uint idx);
|
||||
MachOper* specialize_vector_operand_helper(MachNode* m, MachOper* generic_opnd);
|
||||
|
||||
static MachOper* specialize_generic_vector_operand(MachOper* generic_opnd, uint ideal_reg);
|
||||
|
||||
static bool is_generic_reg2reg_move(MachNode* m);
|
||||
static bool is_generic_vector(MachOper* opnd);
|
||||
|
||||
const RegMask* regmask_for_ideal_register(uint ideal_reg, Node* ret);
|
||||
|
||||
// Graph verification code
|
||||
DEBUG_ONLY( bool verify_after_postselect_cleanup(); )
|
||||
|
||||
public:
|
||||
// Perform a platform dependent implicit null fixup. This is needed
|
||||
// on windows95 to take care of some unusual register constraints.
|
||||
void pd_implicit_null_fixup(MachNode *load, uint idx);
|
||||
|
@ -103,8 +103,11 @@ void Phase::print_timers() {
|
||||
}
|
||||
}
|
||||
|
||||
tty->print_cr (" Matcher: %7.3f s", timers[_t_matcher].seconds());
|
||||
tty->print_cr (" Scheduler: %7.3f s", timers[_t_scheduler].seconds());
|
||||
tty->print_cr (" Matcher: %7.3f s", timers[_t_matcher].seconds());
|
||||
if (Matcher::supports_generic_vector_operands) {
|
||||
tty->print_cr (" Post Selection Cleanup: %7.3f s", timers[_t_postselect_cleanup].seconds());
|
||||
}
|
||||
tty->print_cr (" Scheduler: %7.3f s", timers[_t_scheduler].seconds());
|
||||
|
||||
{
|
||||
tty->print_cr (" Regalloc: %7.3f s", timers[_t_registerAllocation].seconds());
|
||||
|
@ -83,6 +83,7 @@ public:
|
||||
_t_barrierExpand,
|
||||
_t_graphReshaping,
|
||||
_t_matcher,
|
||||
_t_postselect_cleanup,
|
||||
_t_scheduler,
|
||||
_t_registerAllocation,
|
||||
_t_ctorChaitin,
|
||||
|
Loading…
x
Reference in New Issue
Block a user