diff --git a/src/hotspot/cpu/aarch64/register_aarch64.hpp b/src/hotspot/cpu/aarch64/register_aarch64.hpp index 3c2571eb4a3..8e340fefbb4 100644 --- a/src/hotspot/cpu/aarch64/register_aarch64.hpp +++ b/src/hotspot/cpu/aarch64/register_aarch64.hpp @@ -389,14 +389,14 @@ typedef AbstractRegSet PRegSet; template <> inline Register AbstractRegSet::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::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) { diff --git a/src/hotspot/cpu/x86/register_x86.hpp b/src/hotspot/cpu/x86/register_x86.hpp index 2cfc3ec58ed..5449f0d9724 100644 --- a/src/hotspot/cpu/x86/register_x86.hpp +++ b/src/hotspot/cpu/x86/register_x86.hpp @@ -391,27 +391,27 @@ class ConcreteRegisterImpl : public AbstractRegisterImpl { template <> inline Register AbstractRegSet::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::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::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::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); } diff --git a/src/hotspot/share/asm/register.hpp b/src/hotspot/share/asm/register.hpp index fab548ed36d..7dfc9b03f87 100644 --- a/src/hotspot/share/asm/register.hpp +++ b/src/hotspot/share/asm/register.hpp @@ -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 ReverseRegSetIterator; // A set of registers template 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 AbstractRegSet::rbegin() { #include CPU_HEADER(register) -// Debugging support +// Debugging and assertion support + +template +constexpr bool different_registers(AbstractRegSet allocated_regs, R first_register) { + return !allocated_regs.contains(first_register); +} + +template +constexpr bool different_registers(AbstractRegSet 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 +inline constexpr bool different_registers(R first_register, Rx... more_registers) { + return different_registers(AbstractRegSet(first_register), more_registers...); +} template 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 diff --git a/src/hotspot/share/utilities/population_count.hpp b/src/hotspot/share/utilities/population_count.hpp index 97c5ce2a368..0cf35d325dc 100644 --- a/src/hotspot/share/utilities/population_count.hpp +++ b/src/hotspot/share/utilities/population_count.hpp @@ -44,7 +44,7 @@ // generate a call to a similar but slower 64-bit version when calling with // a 32-bit integer type. template -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::value);