8319822: Use a linear-time algorithm for assert_different_registers()

Reviewed-by: kbarrett, stefank, stuefe
This commit is contained in:
Andrew Haley 2024-06-05 17:09:55 +00:00
parent f73922b27d
commit 9b3694c4fc
4 changed files with 69 additions and 36 deletions

View File

@ -389,14 +389,14 @@ typedef AbstractRegSet<PRegister> PRegSet;
template <>
inline Register AbstractRegSet<Register>::first() {
uint32_t first = _bitset & -_bitset;
return first ? as_Register(exact_log2(first)) : noreg;
if (_bitset == 0) { return noreg; }
return as_Register(count_trailing_zeros(_bitset));
}
template <>
inline FloatRegister AbstractRegSet<FloatRegister>::first() {
uint32_t first = _bitset & -_bitset;
return first ? as_FloatRegister(exact_log2(first)) : fnoreg;
if (_bitset == 0) { return fnoreg; }
return as_FloatRegister(count_trailing_zeros(_bitset));
}
inline Register as_Register(FloatRegister reg) {

View File

@ -391,27 +391,27 @@ class ConcreteRegisterImpl : public AbstractRegisterImpl {
template <>
inline Register AbstractRegSet<Register>::first() {
uint32_t first = _bitset & -_bitset;
return first ? as_Register(exact_log2(first)) : noreg;
if (_bitset == 0) { return noreg; }
return as_Register(count_trailing_zeros(_bitset));
}
template <>
inline Register AbstractRegSet<Register>::last() {
if (_bitset == 0) { return noreg; }
uint32_t last = 31 - count_leading_zeros(_bitset);
int last = max_size() - 1 - count_leading_zeros(_bitset);
return as_Register(last);
}
template <>
inline XMMRegister AbstractRegSet<XMMRegister>::first() {
uint32_t first = _bitset & -_bitset;
return first ? as_XMMRegister(exact_log2(first)) : xnoreg;
if (_bitset == 0) { return xnoreg; }
return as_XMMRegister(count_trailing_zeros(_bitset));
}
template <>
inline XMMRegister AbstractRegSet<XMMRegister>::last() {
if (_bitset == 0) { return xnoreg; }
uint32_t last = 31 - count_leading_zeros(_bitset);
int last = max_size() - 1 - count_leading_zeros(_bitset);
return as_XMMRegister(last);
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2000, 2022, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2000, 2023, 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
@ -93,67 +93,79 @@ template <class RegImpl> class ReverseRegSetIterator;
// A set of registers
template <class RegImpl>
class AbstractRegSet {
uint32_t _bitset;
#ifndef ARM
STATIC_ASSERT(RegImpl::number_of_registers <= 64);
#endif
uint64_t _bitset;
AbstractRegSet(uint32_t bitset) : _bitset(bitset) { }
constexpr AbstractRegSet(uint64_t bitset) : _bitset(bitset) { }
static constexpr int max_size() {
return (int)(sizeof(_bitset) * BitsPerByte);
}
public:
AbstractRegSet() : _bitset(0) { }
constexpr AbstractRegSet() : _bitset(0) { }
AbstractRegSet(RegImpl r1) : _bitset(1 << r1->encoding()) { }
constexpr AbstractRegSet(RegImpl r1)
: _bitset(r1->is_valid() ? size_t(1) << r1->encoding() : 0) {
}
AbstractRegSet operator+(const AbstractRegSet aSet) const {
constexpr AbstractRegSet operator+(const AbstractRegSet aSet) const {
AbstractRegSet result(_bitset | aSet._bitset);
return result;
}
AbstractRegSet operator-(const AbstractRegSet aSet) const {
constexpr AbstractRegSet operator-(const AbstractRegSet aSet) const {
AbstractRegSet result(_bitset & ~aSet._bitset);
return result;
}
AbstractRegSet &operator+=(const AbstractRegSet aSet) {
constexpr AbstractRegSet &operator+=(const AbstractRegSet aSet) {
*this = *this + aSet;
return *this;
}
AbstractRegSet &operator-=(const AbstractRegSet aSet) {
constexpr AbstractRegSet &operator-=(const AbstractRegSet aSet) {
*this = *this - aSet;
return *this;
}
static AbstractRegSet of(RegImpl r1) {
constexpr static AbstractRegSet of(RegImpl r1) {
return AbstractRegSet(r1);
}
static AbstractRegSet of(RegImpl r1, RegImpl r2) {
constexpr static AbstractRegSet of(RegImpl r1, RegImpl r2) {
return of(r1) + r2;
}
static AbstractRegSet of(RegImpl r1, RegImpl r2, RegImpl r3) {
constexpr static AbstractRegSet of(RegImpl r1, RegImpl r2, RegImpl r3) {
return of(r1, r2) + r3;
}
static AbstractRegSet of(RegImpl r1, RegImpl r2, RegImpl r3, RegImpl r4) {
constexpr static AbstractRegSet of(RegImpl r1, RegImpl r2, RegImpl r3, RegImpl r4) {
return of(r1, r2, r3) + r4;
}
static AbstractRegSet range(RegImpl start, RegImpl end) {
constexpr static AbstractRegSet range(RegImpl start, RegImpl end) {
int start_enc = start->encoding();
int end_enc = end->encoding();
assert(start_enc <= end_enc, "must be");
uint32_t bits = ~0;
size_t bits = ~(size_t)0;
bits <<= start_enc;
bits <<= 31 - end_enc;
bits >>= 31 - end_enc;
bits <<= max_size() - 1 - end_enc;
bits >>= max_size() - 1 - end_enc;
return AbstractRegSet(bits);
}
uint size() const { return population_count(_bitset); }
constexpr bool contains(RegImpl reg) {
return (AbstractRegSet(reg).bits() & bits()) != 0;
}
uint32_t bits() const { return _bitset; }
constexpr uint size() const { return population_count(_bitset); }
constexpr uint64_t bits() const { return _bitset; }
private:
@ -243,16 +255,37 @@ inline ReverseRegSetIterator<RegImpl> AbstractRegSet<RegImpl>::rbegin() {
#include CPU_HEADER(register)
// Debugging support
// Debugging and assertion support
template<typename R>
constexpr bool different_registers(AbstractRegSet<R> allocated_regs, R first_register) {
return !allocated_regs.contains(first_register);
}
template<typename R, typename... Rx>
constexpr bool different_registers(AbstractRegSet<R> allocated_regs, R first_register, Rx... more_registers) {
if (allocated_regs.contains(first_register)) {
return false;
}
return different_registers(allocated_regs + first_register, more_registers...);
}
template<typename R, typename... Rx>
inline constexpr bool different_registers(R first_register, Rx... more_registers) {
return different_registers(AbstractRegSet<R>(first_register), more_registers...);
}
template<typename R, typename... Rx>
inline void assert_different_registers(R first_register, Rx... more_registers) {
#ifdef ASSERT
const R regs[] = { first_register, more_registers... };
// Verify there are no equal entries.
for (size_t i = 0; i < ARRAY_SIZE(regs) - 1; ++i) {
for (size_t j = i + 1; j < ARRAY_SIZE(regs); ++j) {
assert(regs[i] != regs[j], "Multiple uses of register: %s", regs[i]->name());
if (!different_registers(first_register, more_registers...)) {
const R regs[] = { first_register, more_registers... };
// Find a duplicate entry.
for (size_t i = 0; i < ARRAY_SIZE(regs) - 1; ++i) {
for (size_t j = i + 1; j < ARRAY_SIZE(regs); ++j) {
assert(!regs[i]->is_valid() || regs[i] != regs[j],
"Multiple uses of register: %s", regs[i]->name());
}
}
}
#endif

View File

@ -44,7 +44,7 @@
// generate a call to a similar but slower 64-bit version when calling with
// a 32-bit integer type.
template <typename T>
inline unsigned population_count(T x) {
constexpr unsigned population_count(T x) {
STATIC_ASSERT(BitsPerWord <= 128);
STATIC_ASSERT(BitsPerByte == 8);
STATIC_ASSERT(std::is_integral<T>::value);