8256883: C2: Add a RegMask iterator

Reviewed-by: kvn, pliden, eosterlund
This commit is contained in:
Claes Redestad 2020-11-24 14:35:51 +00:00
parent f55ae9595e
commit fa3cfcd0cd
6 changed files with 78 additions and 45 deletions

View File

@ -318,13 +318,10 @@ private:
public:
void initialize(ZLoadBarrierStubC2* stub) {
// Create mask of live registers
RegMask live = stub->live();
// Record registers that needs to be saved/restored
while (live.is_NotEmpty()) {
const OptoReg::Name opto_reg = live.find_first_elem();
live.Remove(opto_reg);
RegMaskIterator rmi(stub->live());
while (rmi.has_next()) {
const OptoReg::Name opto_reg = rmi.next();
if (OptoReg::is_reg(opto_reg)) {
const VMReg vm_reg = OptoReg::as_VMReg(opto_reg);
if (vm_reg->is_Register()) {

View File

@ -480,12 +480,11 @@ private:
int xmm_spill_size = 0;
// Record registers that needs to be saved/restored
while (live.is_NotEmpty()) {
const OptoReg::Name opto_reg = live.find_first_elem();
RegMaskIterator rmi(live);
while (rmi.has_next()) {
const OptoReg::Name opto_reg = rmi.next();
const VMReg vm_reg = OptoReg::as_VMReg(opto_reg);
live.Remove(opto_reg);
if (vm_reg->is_Register()) {
if (caller_saved.Member(opto_reg)) {
_gp_registers.append(vm_reg->as_Register());

View File

@ -2870,11 +2870,10 @@ void Scheduling::verify_good_schedule( Block *b, const char *msg ) {
int n_op = n->Opcode();
if( n_op == Op_MachProj && n->ideal_reg() == MachProjNode::fat_proj ) {
// Fat-proj kills a slew of registers
RegMask rm = n->out_RegMask();// Make local copy
while( rm.is_NotEmpty() ) {
OptoReg::Name kill = rm.find_first_elem();
rm.Remove(kill);
verify_do_def( n, kill, msg );
RegMaskIterator rmi(n->out_RegMask());
while (rmi.has_next()) {
OptoReg::Name kill = rmi.next();
verify_do_def(n, kill, msg);
}
} else if( n_op != Op_Node ) { // Avoid brand new antidependence nodes
// Get DEF'd registers the normal way
@ -3061,11 +3060,10 @@ void Scheduling::ComputeRegisterAntidependencies(Block *b) {
// This can add edges to 'n' and obscure whether or not it was a def,
// hence the is_def flag.
fat_proj_seen = true;
RegMask rm = n->out_RegMask();// Make local copy
while( rm.is_NotEmpty() ) {
OptoReg::Name kill = rm.find_first_elem();
rm.Remove(kill);
anti_do_def( b, n, kill, is_def );
RegMaskIterator rmi(n->out_RegMask());
while (rmi.has_next()) {
OptoReg::Name kill = rmi.next();
anti_do_def(b, n, kill, is_def);
}
} else {
// Get DEF'd registers the normal way
@ -3080,11 +3078,10 @@ void Scheduling::ComputeRegisterAntidependencies(Block *b) {
for (DUIterator_Fast imax, i = n->fast_outs(imax); i < imax; i++) {
Node* use = n->fast_out(i);
if (use->is_Proj()) {
RegMask rm = use->out_RegMask();// Make local copy
while( rm.is_NotEmpty() ) {
OptoReg::Name kill = rm.find_first_elem();
rm.Remove(kill);
anti_do_def( b, n, kill, false );
RegMaskIterator rmi(use->out_RegMask());
while (rmi.has_next()) {
OptoReg::Name kill = rmi.next();
anti_do_def(b, n, kill, false);
}
}
}

View File

@ -784,15 +784,12 @@ void PhaseChaitin::post_allocate_copy_removal() {
}
// Fat projections kill many registers
if( n_ideal_reg == MachProjNode::fat_proj ) {
RegMask rm = n->out_RegMask();
// wow, what an expensive iterator...
nreg = rm.find_first_elem();
while( OptoReg::is_valid(nreg)) {
rm.Remove(nreg);
value.map(nreg,n);
regnd.map(nreg,n);
nreg = rm.find_first_elem();
if (n_ideal_reg == MachProjNode::fat_proj) {
RegMaskIterator rmi(n->out_RegMask());
while (rmi.has_next()) {
nreg = rmi.next();
value.map(nreg, n);
regnd.map(nreg, n);
}
}

View File

@ -355,24 +355,21 @@ uint RegMask::Size() const {
#ifndef PRODUCT
void RegMask::dump(outputStream *st) const {
st->print("[");
RegMask rm = *this; // Structure copy into local temp
OptoReg::Name start = rm.find_first_elem(); // Get a register
if (OptoReg::is_valid(start)) { // Check for empty mask
rm.Remove(start); // Yank from mask
RegMaskIterator rmi(*this);
if (rmi.has_next()) {
OptoReg::Name start = rmi.next();
OptoReg::dump(start, st); // Print register
OptoReg::Name last = start;
// Now I have printed an initial register.
// Print adjacent registers as "rX-rZ" instead of "rX,rY,rZ".
// Begin looping over the remaining registers.
while (1) { //
OptoReg::Name reg = rm.find_first_elem(); // Get a register
if (!OptoReg::is_valid(reg))
break; // Empty mask, end loop
rm.Remove(reg); // Yank from mask
while (rmi.has_next()) {
OptoReg::Name reg = rmi.next(); // Get a register
if (last+1 == reg) { // See if they are adjacent
if (last + 1 == reg) { // See if they are adjacent
// Adjacent registers just collect into long runs, no printing.
last = reg;
} else { // Ending some kind of run
@ -398,7 +395,7 @@ void RegMask::dump(outputStream *st) const {
st->print("-");
OptoReg::dump(last, st);
}
if (rm.is_AllStack()) st->print("...");
if (is_AllStack()) st->print("...");
}
st->print("]");
}

View File

@ -56,6 +56,8 @@ static unsigned int find_highest_bit(uintptr_t mask) {
class RegMask {
friend class RegMaskIterator;
enum {
_WordBits = BitsPerWord,
_LogWordBits = LogBitsPerWord,
@ -362,6 +364,50 @@ class RegMask {
}
};
class RegMaskIterator {
private:
uintptr_t _current_word;
unsigned int _next_index;
OptoReg::Name _reg;
const RegMask& _rm;
public:
RegMaskIterator(const RegMask& rm) : _current_word(0), _next_index(rm._lwm), _reg(OptoReg::Special), _rm(rm) {
// Calculate the first element
next();
}
bool has_next() {
return _reg != OptoReg::Bad;
}
// Get the current element and calculate the next
OptoReg::Name next() {
OptoReg::Name r = _reg;
if (_current_word != 0) {
unsigned int next_bit = find_lowest_bit(_current_word);
assert(next_bit > 0, "must be");
assert(((_current_word >> next_bit) & 0x1) == 1, "sanity");
_current_word = (_current_word >> next_bit) - 1;
_reg = OptoReg::add(_reg, next_bit);
return r;
}
while (_next_index <= _rm._hwm) {
_current_word = _rm._RM_UP[_next_index++];
if (_current_word != 0) {
unsigned int next_bit = find_lowest_bit(_current_word);
assert(((_current_word >> next_bit) & 0x1) == 1, "sanity");
_current_word = (_current_word >> next_bit) - 1;
_reg = OptoReg::Name(((_next_index - 1) << RegMask::_LogWordBits) + next_bit);
return r;
}
}
_reg = OptoReg::Name(OptoReg::Bad);
return r;
}
};
// Do not use this constant directly in client code!
#undef RM_SIZE