8234391: C2: Generic vector operands

Reviewed-by: vlivanov, sviswanathan, thartmann, jrose
This commit is contained in:
Jatin Bhateja 2019-12-05 12:56:46 +03:00
parent f33e2e9c54
commit 979cd452ab
16 changed files with 1123 additions and 929 deletions

View File

@ -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

View File

@ -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?

View File

@ -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

View File

@ -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;

View File

@ -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

View File

@ -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 );
%}

View File

@ -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);

View File

@ -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

View File

@ -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(); )

View File

@ -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) {

View File

@ -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;

View File

@ -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.

View File

@ -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);

View File

@ -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());

View File

@ -83,6 +83,7 @@ public:
_t_barrierExpand,
_t_graphReshaping,
_t_matcher,
_t_postselect_cleanup,
_t_scheduler,
_t_registerAllocation,
_t_ctorChaitin,