8256827: C2: Avoid reallocations by pre-sizing lists in post_allocate_copy_removal

Reviewed-by: kvn, thartmann
This commit is contained in:
Claes Redestad 2020-11-23 10:18:40 +00:00
parent c0689d25fb
commit b450e7c1c5
3 changed files with 37 additions and 38 deletions

View File

@ -2281,11 +2281,6 @@ const RegMask &Node::in_RegMask(uint) const {
return RegMask::Empty;
}
// Clear all entries in _nodes to NULL but keep storage
void Node_Array::clear() {
Copy::zero_to_bytes( _nodes, _max*sizeof(Node*) );
}
void Node_Array::grow(uint i) {
assert(_max > 0, "invariant");
uint old = _max;

View File

@ -28,6 +28,7 @@
#include "libadt/vectset.hpp"
#include "opto/compile.hpp"
#include "opto/type.hpp"
#include "utilities/copy.hpp"
// Portions of code courtesy of Clifford Click
@ -1477,11 +1478,9 @@ protected:
Node** _nodes;
void grow( uint i ); // Grow array node to fit
public:
Node_Array(Arena* a) : _a(a), _max(OptoNodeListSize) {
_nodes = NEW_ARENA_ARRAY(a, Node*, OptoNodeListSize);
for (int i = 0; i < OptoNodeListSize; i++) {
_nodes[i] = NULL;
}
Node_Array(Arena* a, uint max = OptoNodeListSize) : _a(a), _max(max) {
_nodes = NEW_ARENA_ARRAY(a, Node*, max);
clear();
}
Node_Array(Node_Array* na) : _a(na->_a), _max(na->_max), _nodes(na->_nodes) {}
@ -1493,7 +1492,11 @@ public:
void map( uint i, Node *n ) { if( i>=_max ) grow(i); _nodes[i] = n; }
void insert( uint i, Node *n );
void remove( uint i ); // Remove, preserving order
void clear(); // Set all entries to NULL, keep storage
// Clear all entries in _nodes to NULL but keep storage
void clear() {
Copy::zero_to_bytes(_nodes, _max * sizeof(Node*));
}
uint Size() const { return _max; }
void dump() const;
};
@ -1502,8 +1505,8 @@ class Node_List : public Node_Array {
friend class VMStructs;
uint _cnt;
public:
Node_List() : Node_Array(Thread::current()->resource_area()), _cnt(0) {}
Node_List(Arena *a) : Node_Array(a), _cnt(0) {}
Node_List(uint max = OptoNodeListSize) : Node_Array(Thread::current()->resource_area(), max), _cnt(0) {}
Node_List(Arena *a, uint max = OptoNodeListSize) : Node_Array(a, max), _cnt(0) {}
bool contains(const Node* n) const {
for (uint e = 0; e < size(); e++) {
if (at(e) == n) return true;
@ -1516,6 +1519,14 @@ public:
void yank( Node *n ); // Find and remove
Node *pop() { return _nodes[--_cnt]; }
void clear() { _cnt = 0; Node_Array::clear(); } // retain storage
void copy(const Node_List& from) {
if (from._max > _max) {
grow(from._max);
}
_cnt = from._cnt;
Copy::conjoint_words_to_higher((HeapWord*)&from._nodes[0], (HeapWord*)&_nodes[0], from._max * sizeof(Node*));
}
uint size() const { return _cnt; }
void dump() const;
void dump_simple() const;

View File

@ -558,35 +558,28 @@ void PhaseChaitin::post_allocate_copy_removal() {
}
}
// Extract Node_List mappings. If 'freed' is non-zero, we just popped
// 'freed's blocks off the list
Node_List &regnd = *(free_list.is_empty() ? new Node_List() : free_list.pop());
Node_List &value = *(free_list.is_empty() ? new Node_List() : free_list.pop());
Node_List &regnd = *(free_list.is_empty() ? new Node_List(_max_reg) : free_list.pop());
Node_List &value = *(free_list.is_empty() ? new Node_List(_max_reg) : free_list.pop());
assert( !freed || blk2value[freed->_pre_order] == &value, "" );
value.map(_max_reg,NULL);
regnd.map(_max_reg,NULL);
// Set mappings as OUR mappings
blk2value[block->_pre_order] = &value;
blk2regnd[block->_pre_order] = &regnd;
// Initialize value & regnd for this block
if (missing_some_inputs) {
// Some predecessor has not yet been visited; zap map to empty
for (uint k = 0; k < (uint)_max_reg; k++) {
value.map(k,NULL);
regnd.map(k,NULL);
// Some predecessor has not yet been visited; zap map to empty if necessary
if (freed) {
value.clear();
regnd.clear();
}
} else {
if( !freed ) { // Didn't get a freebie prior block
if (!freed) { // Didn't get a freebie prior block
// Must clone some data
freed = _cfg.get_block_for_node(block->pred(1));
Node_List &f_value = *blk2value[freed->_pre_order];
Node_List &f_regnd = *blk2regnd[freed->_pre_order];
for( uint k = 0; k < (uint)_max_reg; k++ ) {
value.map(k,f_value[k]);
regnd.map(k,f_regnd[k]);
}
value.copy(*blk2value[freed->_pre_order]);
regnd.copy(*blk2regnd[freed->_pre_order]);
}
// Merge all inputs together, setting to NULL any conflicts.
for (j = 1; j < block->num_preds(); j++) {
@ -595,10 +588,10 @@ void PhaseChaitin::post_allocate_copy_removal() {
continue; // Did self already via freelist
}
Node_List &p_regnd = *blk2regnd[pb->_pre_order];
for( uint k = 0; k < (uint)_max_reg; k++ ) {
if( regnd[k] != p_regnd[k] ) { // Conflict on reaching defs?
value.map(k,NULL); // Then no value handy
regnd.map(k,NULL);
for (uint k = 0; k < (uint)_max_reg; k++) {
if (regnd[k] != p_regnd[k]) { // Conflict on reaching defs?
value.map(k, NULL); // Then no value handy
regnd.map(k, NULL);
}
}
}
@ -634,14 +627,14 @@ void PhaseChaitin::post_allocate_copy_removal() {
// can lead to situations where some uses are from the old and some from
// the new values. Not illegal by itself but throws the over-strong
// assert in scheduling.
if( pidx ) {
value.map(preg,phi);
regnd.map(preg,phi);
if (pidx) {
value.map(preg, phi);
regnd.map(preg, phi);
int n_regs = RegMask::num_registers(phi->ideal_reg(), lrgs(pidx));
for (int l = 1; l < n_regs; l++) {
OptoReg::Name preg_lo = OptoReg::add(preg,-l);
value.map(preg_lo,phi);
regnd.map(preg_lo,phi);
value.map(preg_lo, phi);
regnd.map(preg_lo, phi);
}
}
}