8320379: C2: Sort spilling/unspilling sequence for better ld/st merging into ldp/stp on AArch64

Reviewed-by: aph, kvn
This commit is contained in:
Fei Gao 2023-11-29 01:41:20 +00:00
parent 2c4c6c9ba3
commit 3ccd02f142

@ -169,6 +169,11 @@ public:
// Add a node to the current bundle // Add a node to the current bundle
void AddNodeToBundle(Node *n, const Block *bb); void AddNodeToBundle(Node *n, const Block *bb);
// Return an integer less than, equal to, or greater than zero
// if the stack offset of the first argument is respectively
// less than, equal to, or greater than the second.
int compare_two_spill_nodes(Node* first, Node* second);
// Add a node to the list of available nodes // Add a node to the list of available nodes
void AddNodeToAvailableList(Node *n); void AddNodeToAvailableList(Node *n);
@ -2271,6 +2276,29 @@ Node * Scheduling::ChooseNodeToBundle() {
return _available[0]; return _available[0];
} }
int Scheduling::compare_two_spill_nodes(Node* first, Node* second) {
assert(first->is_MachSpillCopy() && second->is_MachSpillCopy(), "");
OptoReg::Name first_src_lo = _regalloc->get_reg_first(first->in(1));
OptoReg::Name first_dst_lo = _regalloc->get_reg_first(first);
OptoReg::Name second_src_lo = _regalloc->get_reg_first(second->in(1));
OptoReg::Name second_dst_lo = _regalloc->get_reg_first(second);
// Comparison between stack -> reg and stack -> reg
if (OptoReg::is_stack(first_src_lo) && OptoReg::is_stack(second_src_lo) &&
OptoReg::is_reg(first_dst_lo) && OptoReg::is_reg(second_dst_lo)) {
return _regalloc->reg2offset(first_src_lo) - _regalloc->reg2offset(second_src_lo);
}
// Comparison between reg -> stack and reg -> stack
if (OptoReg::is_stack(first_dst_lo) && OptoReg::is_stack(second_dst_lo) &&
OptoReg::is_reg(first_src_lo) && OptoReg::is_reg(second_src_lo)) {
return _regalloc->reg2offset(first_dst_lo) - _regalloc->reg2offset(second_dst_lo);
}
return 0; // Not comparable
}
void Scheduling::AddNodeToAvailableList(Node *n) { void Scheduling::AddNodeToAvailableList(Node *n) {
assert( !n->is_Proj(), "projections never directly made available" ); assert( !n->is_Proj(), "projections never directly made available" );
#ifndef PRODUCT #ifndef PRODUCT
@ -2282,11 +2310,20 @@ void Scheduling::AddNodeToAvailableList(Node *n) {
int latency = _current_latency[n->_idx]; int latency = _current_latency[n->_idx];
// Insert in latency order (insertion sort) // Insert in latency order (insertion sort). If two MachSpillCopyNodes
// for stack spilling or unspilling have the same latency, we sort
// them in the order of stack offset. Some ports (e.g. aarch64) may also
// have more opportunities to do ld/st merging
uint i; uint i;
for ( i=0; i < _available.size(); i++ ) for (i = 0; i < _available.size(); i++) {
if (_current_latency[_available[i]->_idx] > latency) if (_current_latency[_available[i]->_idx] > latency) {
break; break;
} else if (_current_latency[_available[i]->_idx] == latency &&
n->is_MachSpillCopy() && _available[i]->is_MachSpillCopy() &&
compare_two_spill_nodes(n, _available[i]) > 0) {
break;
}
}
// Special Check for compares following branches // Special Check for compares following branches
if( n->is_Mach() && _scheduled.size() > 0 ) { if( n->is_Mach() && _scheduled.size() > 0 ) {