mirror of
https://github.com/openjdk/jdk.git
synced 2025-09-24 04:54:40 +02:00
8136820: Generate better code for some Unsafe addressing patterns
Reshape address computation to move invariant part out of loops Reviewed-by: kvn
This commit is contained in:
parent
4af470b866
commit
f8abd0e843
4 changed files with 79 additions and 37 deletions
|
@ -3767,6 +3767,22 @@ operand indIndexScale(any_RegP reg, rRegL lreg, immI2 scale)
|
||||||
%}
|
%}
|
||||||
%}
|
%}
|
||||||
|
|
||||||
|
operand indPosIndexScale(any_RegP reg, rRegI idx, immI2 scale)
|
||||||
|
%{
|
||||||
|
constraint(ALLOC_IN_RC(ptr_reg));
|
||||||
|
predicate(n->in(3)->in(1)->as_Type()->type()->is_long()->_lo >= 0);
|
||||||
|
match(AddP reg (LShiftL (ConvI2L idx) scale));
|
||||||
|
|
||||||
|
op_cost(10);
|
||||||
|
format %{"[$reg + pos $idx << $scale]" %}
|
||||||
|
interface(MEMORY_INTER) %{
|
||||||
|
base($reg);
|
||||||
|
index($idx);
|
||||||
|
scale($scale);
|
||||||
|
disp(0x0);
|
||||||
|
%}
|
||||||
|
%}
|
||||||
|
|
||||||
// Indirect Memory Times Scale Plus Index Register Plus Offset Operand
|
// Indirect Memory Times Scale Plus Index Register Plus Offset Operand
|
||||||
operand indIndexScaleOffset(any_RegP reg, immL32 off, rRegL lreg, immI2 scale)
|
operand indIndexScaleOffset(any_RegP reg, immL32 off, rRegL lreg, immI2 scale)
|
||||||
%{
|
%{
|
||||||
|
@ -4159,7 +4175,7 @@ operand cmpOpUCF2() %{
|
||||||
// case of this is memory operands.
|
// case of this is memory operands.
|
||||||
|
|
||||||
opclass memory(indirect, indOffset8, indOffset32, indIndexOffset, indIndex,
|
opclass memory(indirect, indOffset8, indOffset32, indIndexOffset, indIndex,
|
||||||
indIndexScale, indIndexScaleOffset, indPosIndexOffset, indPosIndexScaleOffset,
|
indIndexScale, indPosIndexScale, indIndexScaleOffset, indPosIndexOffset, indPosIndexScaleOffset,
|
||||||
indCompressedOopOffset,
|
indCompressedOopOffset,
|
||||||
indirectNarrow, indOffset8Narrow, indOffset32Narrow,
|
indirectNarrow, indOffset8Narrow, indOffset32Narrow,
|
||||||
indIndexOffsetNarrow, indIndexNarrow, indIndexScaleNarrow,
|
indIndexOffsetNarrow, indIndexNarrow, indIndexScaleNarrow,
|
||||||
|
@ -5186,6 +5202,17 @@ instruct leaPIdxScale(rRegP dst, indIndexScale mem)
|
||||||
ins_pipe(ialu_reg_reg_fat);
|
ins_pipe(ialu_reg_reg_fat);
|
||||||
%}
|
%}
|
||||||
|
|
||||||
|
instruct leaPPosIdxScale(rRegP dst, indPosIndexScale mem)
|
||||||
|
%{
|
||||||
|
match(Set dst mem);
|
||||||
|
|
||||||
|
ins_cost(110);
|
||||||
|
format %{ "leaq $dst, $mem\t# ptr idxscale" %}
|
||||||
|
opcode(0x8D);
|
||||||
|
ins_encode(REX_reg_mem_wide(dst, mem), OpcP, reg_mem(dst, mem));
|
||||||
|
ins_pipe(ialu_reg_reg_fat);
|
||||||
|
%}
|
||||||
|
|
||||||
instruct leaPIdxScaleOff(rRegP dst, indIndexScaleOffset mem)
|
instruct leaPIdxScaleOff(rRegP dst, indIndexScaleOffset mem)
|
||||||
%{
|
%{
|
||||||
match(Set dst mem);
|
match(Set dst mem);
|
||||||
|
|
|
@ -447,21 +447,21 @@ Node *PhaseIdealLoop::remix_address_expressions( Node *n ) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Replace (I1 +p (I2 + V)) with ((I1 +p I2) +p V)
|
// Replace (I1 +p (I2 + V)) with ((I1 +p I2) +p V)
|
||||||
if( n2_loop != n_loop && n3_loop == n_loop ) {
|
if (n2_loop != n_loop && n3_loop == n_loop) {
|
||||||
if( n->in(3)->Opcode() == Op_AddI ) {
|
if (n->in(3)->Opcode() == Op_AddX) {
|
||||||
Node *V = n->in(3)->in(1);
|
Node *V = n->in(3)->in(1);
|
||||||
Node *I = n->in(3)->in(2);
|
Node *I = n->in(3)->in(2);
|
||||||
if( is_member(n_loop,get_ctrl(V)) ) {
|
if (is_member(n_loop,get_ctrl(V))) {
|
||||||
} else {
|
} else {
|
||||||
Node *tmp = V; V = I; I = tmp;
|
Node *tmp = V; V = I; I = tmp;
|
||||||
}
|
}
|
||||||
if( !is_member(n_loop,get_ctrl(I)) ) {
|
if (!is_member(n_loop,get_ctrl(I))) {
|
||||||
Node *add1 = new AddPNode( n->in(1), n->in(2), I );
|
Node *add1 = new AddPNode(n->in(1), n->in(2), I);
|
||||||
// Stuff new AddP in the loop preheader
|
// Stuff new AddP in the loop preheader
|
||||||
register_new_node( add1, n_loop->_head->in(LoopNode::EntryControl) );
|
register_new_node(add1, n_loop->_head->in(LoopNode::EntryControl));
|
||||||
Node *add2 = new AddPNode( n->in(1), add1, V );
|
Node *add2 = new AddPNode(n->in(1), add1, V);
|
||||||
register_new_node( add2, n_ctrl );
|
register_new_node(add2, n_ctrl);
|
||||||
_igvn.replace_node( n, add2 );
|
_igvn.replace_node(n, add2);
|
||||||
return add2;
|
return add2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2045,6 +2045,33 @@ bool Matcher::is_bmi_pattern(Node *n, Node *m) {
|
||||||
// and then expanded into the inline_cache_reg and a method_oop register
|
// and then expanded into the inline_cache_reg and a method_oop register
|
||||||
// defined in ad_<arch>.cpp
|
// defined in ad_<arch>.cpp
|
||||||
|
|
||||||
|
// Check for shift by small constant as well
|
||||||
|
static bool clone_shift(Node* shift, Matcher* matcher, MStack& mstack, VectorSet& address_visited) {
|
||||||
|
if (shift->Opcode() == Op_LShiftX && shift->in(2)->is_Con() &&
|
||||||
|
shift->in(2)->get_int() <= 3 &&
|
||||||
|
// Are there other uses besides address expressions?
|
||||||
|
!matcher->is_visited(shift)) {
|
||||||
|
address_visited.set(shift->_idx); // Flag as address_visited
|
||||||
|
mstack.push(shift->in(2), Visit);
|
||||||
|
Node *conv = shift->in(1);
|
||||||
|
#ifdef _LP64
|
||||||
|
// Allow Matcher to match the rule which bypass
|
||||||
|
// ConvI2L operation for an array index on LP64
|
||||||
|
// if the index value is positive.
|
||||||
|
if (conv->Opcode() == Op_ConvI2L &&
|
||||||
|
conv->as_Type()->type()->is_long()->_lo >= 0 &&
|
||||||
|
// Are there other uses besides address expressions?
|
||||||
|
!matcher->is_visited(conv)) {
|
||||||
|
address_visited.set(conv->_idx); // Flag as address_visited
|
||||||
|
mstack.push(conv->in(1), Pre_Visit);
|
||||||
|
} else
|
||||||
|
#endif
|
||||||
|
mstack.push(conv, Pre_Visit);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//------------------------------find_shared------------------------------------
|
//------------------------------find_shared------------------------------------
|
||||||
// Set bits if Node is shared or otherwise a root
|
// Set bits if Node is shared or otherwise a root
|
||||||
|
@ -2205,7 +2232,10 @@ void Matcher::find_shared( Node *n ) {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Clone addressing expressions as they are "free" in memory access instructions
|
// Clone addressing expressions as they are "free" in memory access instructions
|
||||||
if( mem_op && i == MemNode::Address && mop == Op_AddP ) {
|
if (mem_op && i == MemNode::Address && mop == Op_AddP &&
|
||||||
|
// When there are other uses besides address expressions
|
||||||
|
// put it on stack and mark as shared.
|
||||||
|
!is_visited(m)) {
|
||||||
// Some inputs for address expression are not put on stack
|
// Some inputs for address expression are not put on stack
|
||||||
// to avoid marking them as shared and forcing them into register
|
// to avoid marking them as shared and forcing them into register
|
||||||
// if they are used only in address expressions.
|
// if they are used only in address expressions.
|
||||||
|
@ -2213,10 +2243,7 @@ void Matcher::find_shared( Node *n ) {
|
||||||
// besides address expressions.
|
// besides address expressions.
|
||||||
|
|
||||||
Node *off = m->in(AddPNode::Offset);
|
Node *off = m->in(AddPNode::Offset);
|
||||||
if( off->is_Con() &&
|
if (off->is_Con()) {
|
||||||
// When there are other uses besides address expressions
|
|
||||||
// put it on stack and mark as shared.
|
|
||||||
!is_visited(m) ) {
|
|
||||||
address_visited.test_set(m->_idx); // Flag as address_visited
|
address_visited.test_set(m->_idx); // Flag as address_visited
|
||||||
Node *adr = m->in(AddPNode::Address);
|
Node *adr = m->in(AddPNode::Address);
|
||||||
|
|
||||||
|
@ -2229,28 +2256,7 @@ void Matcher::find_shared( Node *n ) {
|
||||||
!is_visited(adr) ) {
|
!is_visited(adr) ) {
|
||||||
address_visited.set(adr->_idx); // Flag as address_visited
|
address_visited.set(adr->_idx); // Flag as address_visited
|
||||||
Node *shift = adr->in(AddPNode::Offset);
|
Node *shift = adr->in(AddPNode::Offset);
|
||||||
// Check for shift by small constant as well
|
if (!clone_shift(shift, this, mstack, address_visited)) {
|
||||||
if( shift->Opcode() == Op_LShiftX && shift->in(2)->is_Con() &&
|
|
||||||
shift->in(2)->get_int() <= 3 &&
|
|
||||||
// Are there other uses besides address expressions?
|
|
||||||
!is_visited(shift) ) {
|
|
||||||
address_visited.set(shift->_idx); // Flag as address_visited
|
|
||||||
mstack.push(shift->in(2), Visit);
|
|
||||||
Node *conv = shift->in(1);
|
|
||||||
#ifdef _LP64
|
|
||||||
// Allow Matcher to match the rule which bypass
|
|
||||||
// ConvI2L operation for an array index on LP64
|
|
||||||
// if the index value is positive.
|
|
||||||
if( conv->Opcode() == Op_ConvI2L &&
|
|
||||||
conv->as_Type()->type()->is_long()->_lo >= 0 &&
|
|
||||||
// Are there other uses besides address expressions?
|
|
||||||
!is_visited(conv) ) {
|
|
||||||
address_visited.set(conv->_idx); // Flag as address_visited
|
|
||||||
mstack.push(conv->in(1), Pre_Visit);
|
|
||||||
} else
|
|
||||||
#endif
|
|
||||||
mstack.push(conv, Pre_Visit);
|
|
||||||
} else {
|
|
||||||
mstack.push(shift, Pre_Visit);
|
mstack.push(shift, Pre_Visit);
|
||||||
}
|
}
|
||||||
mstack.push(adr->in(AddPNode::Address), Pre_Visit);
|
mstack.push(adr->in(AddPNode::Address), Pre_Visit);
|
||||||
|
@ -2263,6 +2269,12 @@ void Matcher::find_shared( Node *n ) {
|
||||||
mstack.push(off, Visit);
|
mstack.push(off, Visit);
|
||||||
mstack.push(m->in(AddPNode::Base), Pre_Visit);
|
mstack.push(m->in(AddPNode::Base), Pre_Visit);
|
||||||
continue; // for(int i = ...)
|
continue; // for(int i = ...)
|
||||||
|
} else if (clone_shift_expressions &&
|
||||||
|
clone_shift(off, this, mstack, address_visited)) {
|
||||||
|
address_visited.test_set(m->_idx); // Flag as address_visited
|
||||||
|
mstack.push(m->in(AddPNode::Address), Pre_Visit);
|
||||||
|
mstack.push(m->in(AddPNode::Base), Pre_Visit);
|
||||||
|
continue;
|
||||||
} // if( off->is_Con() )
|
} // if( off->is_Con() )
|
||||||
} // if( mem_op &&
|
} // if( mem_op &&
|
||||||
mstack.push(m, Pre_Visit);
|
mstack.push(m, Pre_Visit);
|
||||||
|
|
|
@ -3055,6 +3055,9 @@ bool SWPointer::offset_plus_k(Node* n, bool negate) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (invariant(n)) {
|
if (invariant(n)) {
|
||||||
|
if (opc == Op_ConvI2L) {
|
||||||
|
n = n->in(1);
|
||||||
|
}
|
||||||
_negate_invar = negate;
|
_negate_invar = negate;
|
||||||
_invar = n;
|
_invar = n;
|
||||||
NOT_PRODUCT(_tracer.offset_plus_k_10(n, _invar, _negate_invar, _offset);)
|
NOT_PRODUCT(_tracer.offset_plus_k_10(n, _invar, _negate_invar, _offset);)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue