/* * Copyright (c) 1997, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. *
*/
int RegMask::num_registers(uint ireg) { switch(ireg) { case Op_VecZ: return SlotsPerVecZ; case Op_VecY: return SlotsPerVecY; case Op_VecX: return SlotsPerVecX; case Op_VecD: return SlotsPerVecD; case Op_RegVectMask: return SlotsPerRegVectMask; case Op_RegD: case Op_RegL: #ifdef _LP64 case Op_RegP: #endif return 2; case Op_VecA:
assert(Matcher::supports_scalable_vector(), "does not support scalable vector"); return SlotsPerVecA; default: // Op_VecS and the rest ideal registers.
assert(ireg == Op_VecS || !is_vector(ireg), "unexpected, possibly multi-slot register"); return 1;
}
}
int RegMask::num_registers(uint ireg, LRG &lrg) { int n_regs = num_registers(ireg);
// assigned is OptoReg which is selected by register allocator
OptoReg::Name assigned = lrg.reg();
assert(OptoReg::is_valid(assigned), "should be valid opto register");
// only indices of power 2 are accessed, so index 3 is only filled in for storage. staticconst uintptr_t low_bits[5] = { fives, // 0x5555..55
all/0xF, // 0x1111..11,
all/0xFF, // 0x0101..01,
zero, // 0x0000..00
all/0xFFFF }; // 0x0001..01
// Clear out partial bits; leave only bit pairs void RegMask::clear_to_pairs() {
assert(valid_watermarks(), "sanity"); for (unsigned i = _lwm; i <= _hwm; i++) {
uintptr_t bits = _RM_UP[i];
bits &= ((bits & fives) << 1U); // 1 hi-bit set for each pair
bits |= (bits >> 1U); // Smear 1 hi-bit into a pair
_RM_UP[i] = bits;
}
assert(is_aligned_pairs(), "mask is not aligned, adjacent pairs");
}
bool RegMask::is_aligned_pairs() const { // Assert that the register mask contains only bit pairs.
assert(valid_watermarks(), "sanity"); for (unsigned i = _lwm; i <= _hwm; i++) {
uintptr_t bits = _RM_UP[i]; while (bits) { // Check bits for pairing
uintptr_t bit = uintptr_t(1) << find_lowest_bit(bits); // Extract low bit // Low bit is not odd means its mis-aligned. if ((bit & fives) == 0) returnfalse;
bits -= bit; // Remove bit from mask // Check for aligned adjacent bit if ((bits & (bit << 1U)) == 0) returnfalse;
bits -= (bit << 1U); // Remove other halve of pair
}
} returntrue;
}
// Return TRUE if the mask contains a single bit bool RegMask::is_bound1() const { if (is_AllStack()) returnfalse;
for (unsigned i = _lwm; i <= _hwm; i++) {
uintptr_t v = _RM_UP[i]; if (v != 0) { // Only one bit allowed -> v must be a power of two if (!is_power_of_2(v)) { returnfalse;
}
// A single bit was found - check there are no bits in the rest of the mask for (i++; i <= _hwm; i++) { if (_RM_UP[i] != 0) { returnfalse;
}
} // Done; found a single bit returntrue;
}
} // No bit found returnfalse;
}
// Return TRUE if the mask contains an adjacent pair of bits and no other bits. bool RegMask::is_bound_pair() const { if (is_AllStack()) returnfalse;
assert(valid_watermarks(), "sanity"); for (unsigned i = _lwm; i <= _hwm; i++) { if (_RM_UP[i] != 0) { // Found some bits unsignedint bit_index = find_lowest_bit(_RM_UP[i]); if (bit_index != _WordBitMask) { // Bit pair stays in same word?
uintptr_t bit = uintptr_t(1) << bit_index; // Extract lowest bit from mask if ((bit | (bit << 1U)) != _RM_UP[i]) { returnfalse; // Require adjacent bit pair and no more bits
}
} else { // Else its a split-pair case
assert(is_power_of_2(_RM_UP[i]), "invariant");
i++; // Skip iteration forward if (i > _hwm || _RM_UP[i] != 1) { returnfalse; // Require 1 lo bit in next word
}
}
// A matching pair was found - check there are no bits in the rest of the mask for (i++; i <= _hwm; i++) { if (_RM_UP[i] != 0) { returnfalse;
}
} // Found a bit pair returntrue;
}
} // True for the empty mask, too returntrue;
}
// Test for a single adjacent set of ideal register's size. bool RegMask::is_bound(uint ireg) const { if (is_vector(ireg)) { if (is_bound_set(num_registers(ireg))) returntrue;
} elseif (is_bound1() || is_bound_pair()) { returntrue;
} returnfalse;
}
// Check that whether given reg number with size is valid // for current regmask, where reg is the highest number. bool RegMask::is_valid_reg(OptoReg::Name reg, constint size) const { for (int i = 0; i < size; i++) { if (!Member(reg - i)) { returnfalse;
}
} returntrue;
}
// Find the lowest-numbered register set in the mask. Return the // HIGHEST register number in the set, or BAD if no sets. // Works also for size 1.
OptoReg::Name RegMask::find_first_set(LRG &lrg, constint size) const { if (lrg.is_scalable() && lrg._is_vector) { // For scalable vector register, regmask is SlotsPerVecA bits aligned.
assert(is_aligned_sets(SlotsPerVecA), "mask is not aligned, adjacent sets");
} else {
assert(is_aligned_sets(size), "mask is not aligned, adjacent sets");
}
assert(valid_watermarks(), "sanity"); for (unsigned i = _lwm; i <= _hwm; i++) { if (_RM_UP[i]) { // Found some bits // Convert to bit number, return hi bit in pair return OptoReg::Name((i<<_LogWordBits) + find_lowest_bit(_RM_UP[i]) + (size - 1));
}
} return OptoReg::Bad;
}
// Clear out partial bits; leave only aligned adjacent bit pairs void RegMask::clear_to_sets(constunsignedint size) { if (size == 1) return;
assert(2 <= size && size <= 16, "update low bits table");
assert(is_power_of_2(size), "sanity");
assert(valid_watermarks(), "sanity");
uintptr_t low_bits_mask = low_bits[size >> 2U]; for (unsigned i = _lwm; i <= _hwm; i++) {
uintptr_t bits = _RM_UP[i];
uintptr_t sets = (bits & low_bits_mask); for (unsigned j = 1U; j < size; j++) {
sets = (bits & (sets << 1U)); // filter bits which produce whole sets
}
sets |= (sets >> 1U); // Smear 1 hi-bit into a set if (size > 2) {
sets |= (sets >> 2U); // Smear 2 hi-bits into a set if (size > 4) {
sets |= (sets >> 4U); // Smear 4 hi-bits into a set if (size > 8) {
sets |= (sets >> 8U); // Smear 8 hi-bits into a set
}
}
}
_RM_UP[i] = sets;
}
assert(is_aligned_sets(size), "mask is not aligned, adjacent sets");
}
// Smear out partial bits to aligned adjacent bit sets void RegMask::smear_to_sets(constunsignedint size) { if (size == 1) return;
assert(2 <= size && size <= 16, "update low bits table");
assert(is_power_of_2(size), "sanity");
assert(valid_watermarks(), "sanity");
uintptr_t low_bits_mask = low_bits[size >> 2U]; for (unsigned i = _lwm; i <= _hwm; i++) {
uintptr_t bits = _RM_UP[i];
uintptr_t sets = 0; for (unsigned j = 0; j < size; j++) {
sets |= (bits & low_bits_mask); // collect partial bits
bits = bits >> 1U;
}
sets |= (sets << 1U); // Smear 1 lo-bit into a set if (size > 2) {
sets |= (sets << 2U); // Smear 2 lo-bits into a set if (size > 4) {
sets |= (sets << 4U); // Smear 4 lo-bits into a set if (size > 8) {
sets |= (sets << 8U); // Smear 8 lo-bits into a set
}
}
}
_RM_UP[i] = sets;
}
assert(is_aligned_sets(size), "mask is not aligned, adjacent sets");
}
// Assert that the register mask contains only bit sets. bool RegMask::is_aligned_sets(constunsignedint size) const { if (size == 1) returntrue;
assert(2 <= size && size <= 16, "update low bits table");
assert(is_power_of_2(size), "sanity");
uintptr_t low_bits_mask = low_bits[size >> 2U];
assert(valid_watermarks(), "sanity"); for (unsigned i = _lwm; i <= _hwm; i++) {
uintptr_t bits = _RM_UP[i]; while (bits) { // Check bits for pairing
uintptr_t bit = uintptr_t(1) << find_lowest_bit(bits); // Low bit is not odd means its mis-aligned. if ((bit & low_bits_mask) == 0) { returnfalse;
} // Do extra work since (bit << size) may overflow.
uintptr_t hi_bit = bit << (size-1); // high bit
uintptr_t set = hi_bit + ((hi_bit-1) & ~(bit-1)); // Check for aligned adjacent bits in this set if ((bits & set) != set) { returnfalse;
}
bits -= set; // Remove this set
}
} returntrue;
}
// Return TRUE if the mask contains one adjacent set of bits and no other bits. // Works also for size 1. bool RegMask::is_bound_set(constunsignedint size) const { if (is_AllStack()) returnfalse;
assert(1 <= size && size <= 16, "update low bits table");
assert(valid_watermarks(), "sanity"); for (unsigned i = _lwm; i <= _hwm; i++) { if (_RM_UP[i] != 0) { // Found some bits unsigned bit_index = find_lowest_bit(_RM_UP[i]);
uintptr_t bit = uintptr_t(1) << bit_index; if (bit_index + size <= BitsPerWord) { // Bit set stays in same word?
uintptr_t hi_bit = bit << (size - 1);
uintptr_t set = hi_bit + ((hi_bit-1) & ~(bit-1)); if (set != _RM_UP[i]) { returnfalse; // Require adjacent bit set and no more bits
}
} else { // Else its a split-set case // All bits from bit to highest bit in the word must be set if ((all & ~(bit-1)) != _RM_UP[i]) { returnfalse;
}
i++; // Skip iteration forward and check high part // The lower bits should be 1 since it is split case.
uintptr_t set = (bit >> (BitsPerWord - size)) - 1; if (i > _hwm || _RM_UP[i] != set) { returnfalse; // Require expected low bits in next word
}
}
// A matching set found - check there are no bits in the rest of the mask for (i++; i <= _hwm; i++) { if (_RM_UP[i] != 0) { returnfalse;
}
} // Done - found a bit set returntrue;
}
} // True for the empty mask, too returntrue;
}
// UP means register only, Register plus stack, or stack only is DOWN bool RegMask::is_UP() const { // Quick common case check for DOWN (any stack slot is legal) if (is_AllStack()) returnfalse; // Slower check for any stack bits set (also DOWN) if (overlap(Matcher::STACK_ONLY_mask)) returnfalse; // Not DOWN, so must be UP returntrue;
}
// Compute size of register mask in bits
uint RegMask::Size() const {
uint sum = 0;
assert(valid_watermarks(), "sanity"); for (unsigned i = _lwm; i <= _hwm; i++) {
sum += population_count(_RM_UP[i]);
} return sum;
}
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 (rmi.has_next()) {
OptoReg::Name reg = rmi.next(); // Get a register
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 if (start == last) { // 1-register run; no special printing
} elseif (start+1 == last) {
st->print(","); // 2-register run; print as "rX,rY"
OptoReg::dump(last, st);
} else { // Multi-register run; print as "rX-rZ"
st->print("-");
OptoReg::dump(last, st);
}
st->print(","); // Separate start of new run
start = last = reg; // Start a new register run
OptoReg::dump(start, st); // Print register
} // End of if ending a register run or not
} // End of while regmask not empty
if (start == last) { // 1-register run; no special printing
} elseif (start+1 == last) {
st->print(","); // 2-register run; print as "rX,rY"
OptoReg::dump(last, st);
} else { // Multi-register run; print as "rX-rZ"
st->print("-");
OptoReg::dump(last, st);
} if (is_AllStack()) st->print("...");
}
st->print("]");
} #endif
Messung V0.5
¤ Dauer der Verarbeitung: 0.17 Sekunden
(vorverarbeitet)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.