Skip to content

Commit

Permalink
8319822: Use a linear-time algorithm for assert_different_registers()
Browse files Browse the repository at this point in the history
Reviewed-by: kbarrett, stefank, stuefe
  • Loading branch information
Andrew Haley committed Jun 5, 2024
1 parent f73922b commit 9b3694c
Show file tree
Hide file tree
Showing 4 changed files with 69 additions and 36 deletions.
8 changes: 4 additions & 4 deletions src/hotspot/cpu/aarch64/register_aarch64.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
12 changes: 6 additions & 6 deletions src/hotspot/cpu/x86/register_x86.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}

Expand Down
83 changes: 58 additions & 25 deletions src/hotspot/share/asm/register.hpp
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -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;

constexpr AbstractRegSet(uint64_t bitset) : _bitset(bitset) { }

AbstractRegSet(uint32_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:

Expand Down Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion src/hotspot/share/utilities/population_count.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down

1 comment on commit 9b3694c

@openjdk-notifier
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.