mirror of
https://github.com/FEX-Emu/FEX.git
synced 2026-10-06 17:00:19 +02:00
Merge pull request #1240 from phire/extract_bucketlist
Move BucketList into it's own file
This commit is contained in:
2 files changed
+139
-130
No files matched your search
@@ -4,6 +4,7 @@ tags: ir|opts
|
||||
$end_info$
|
||||
*/
|
||||
|
||||
#include <FEXCore/Utils/BucketList.h>
|
||||
#include "Common/MathUtils.h"
|
||||
#include "Interface/IR/Passes/RegisterAllocationPass.h"
|
||||
#include "Interface/IR/Passes.h"
|
||||
@@ -38,135 +39,6 @@ namespace {
|
||||
constexpr uint32_t DEFAULT_INTERFERENCE_SPAN_COUNT = 30;
|
||||
constexpr uint32_t DEFAULT_NODE_COUNT = 8192;
|
||||
|
||||
// BucketList is an optimized container, it includes an inline array of Size
|
||||
// and can overflow to a linked list of further buckets
|
||||
//
|
||||
// To optimize for best performance, Size should be big enough to allocate one or two
|
||||
// buckets for the typical case
|
||||
// Picking a Size so sizeof(Bucket<...>) is a power of two is also a small win
|
||||
template<unsigned _Size, typename T = uint32_t>
|
||||
struct BucketList {
|
||||
static constexpr const unsigned Size = _Size;
|
||||
|
||||
T Items[Size];
|
||||
std::unique_ptr<BucketList<Size>> Next;
|
||||
|
||||
void Clear() {
|
||||
Items[0] = 0;
|
||||
#ifndef NDEBUG
|
||||
for (int i = 1; i < Size; i++)
|
||||
Items[i] = 0xDEADBEEF;
|
||||
#endif
|
||||
Next.reset();
|
||||
}
|
||||
|
||||
BucketList() {
|
||||
Clear();
|
||||
}
|
||||
|
||||
template<typename EnumeratorFn>
|
||||
inline void Iterate(EnumeratorFn Enumerator) const {
|
||||
int i = 0;
|
||||
auto Bucket = this;
|
||||
|
||||
for(;;) {
|
||||
auto Item = Bucket->Items[i];
|
||||
if (Item == 0)
|
||||
break;
|
||||
|
||||
Enumerator(Item);
|
||||
|
||||
if (++i == Bucket->Size) {
|
||||
LOGMAN_THROW_A(Bucket->Next != nullptr, "Interference bug");
|
||||
Bucket = Bucket->Next.get();
|
||||
i = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<typename EnumeratorFn>
|
||||
inline bool Find(EnumeratorFn Enumerator) const {
|
||||
int i = 0;
|
||||
auto Bucket = this;
|
||||
|
||||
for(;;) {
|
||||
auto Item = Bucket->Items[i];
|
||||
if (Item == 0)
|
||||
break;
|
||||
|
||||
if (Enumerator(Item))
|
||||
return true;
|
||||
|
||||
if (++i == Bucket->Size) {
|
||||
LOGMAN_THROW_A(Bucket->Next != nullptr, "Bucket in bad state");
|
||||
Bucket = Bucket->Next.get();
|
||||
i = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void Append(uint32_t Val) {
|
||||
auto that = this;
|
||||
|
||||
while (that->Next) {
|
||||
that = that->Next.get();
|
||||
}
|
||||
|
||||
int i;
|
||||
for (i = 0; i < Size; i++) {
|
||||
if (that->Items[i] == 0) {
|
||||
that->Items[i] = Val;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (i < (Size-1)) {
|
||||
that->Items[i+1] = 0;
|
||||
} else {
|
||||
that->Next = std::make_unique<BucketList<Size, T>>();
|
||||
}
|
||||
}
|
||||
void Erase(uint32_t Val) {
|
||||
int i = 0;
|
||||
auto that = this;
|
||||
auto foundThat = this;
|
||||
auto foundI = 0;
|
||||
|
||||
for (;;) {
|
||||
if (that->Items[i] == Val) {
|
||||
foundThat = that;
|
||||
foundI = i;
|
||||
break;
|
||||
}
|
||||
else if (++i == Size) {
|
||||
i = 0;
|
||||
LOGMAN_THROW_A(that->Next != nullptr, "Bucket::Erase but element not contained");
|
||||
that = that->Next.get();
|
||||
}
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
if (that->Items[i] == 0) {
|
||||
foundThat->Items[foundI] = that->Items[i-1];
|
||||
that->Items[i-1] = 0;
|
||||
break;
|
||||
}
|
||||
else if (++i == Size) {
|
||||
if (that->Next->Items[0] == 0) {
|
||||
that->Next.reset();
|
||||
foundThat->Items[foundI] = that->Items[Size-1];
|
||||
that->Items[Size-1] = 0;
|
||||
break;
|
||||
}
|
||||
i = 0;
|
||||
that = that->Next.get();
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
struct Register {
|
||||
bool Virtual;
|
||||
uint64_t Index;
|
||||
@@ -184,7 +56,7 @@ namespace {
|
||||
RegisterNode *PhiPartner;
|
||||
} Head { ~0U, ~0U, nullptr };
|
||||
|
||||
BucketList<DEFAULT_INTERFERENCE_LIST_COUNT, uint32_t> Interferences;
|
||||
FEXCore::BucketList<DEFAULT_INTERFERENCE_LIST_COUNT, uint32_t> Interferences;
|
||||
};
|
||||
|
||||
static_assert(sizeof(RegisterNode) == 128 * 4);
|
||||
|
||||
+137
@@ -0,0 +1,137 @@
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <FEXCore/Utils/LogManager.h>
|
||||
|
||||
namespace FEXCore {
|
||||
|
||||
// BucketList is an optimized container, it includes an inline array of Size
|
||||
// and can overflow to a linked list of further buckets
|
||||
//
|
||||
// To optimize for best performance, Size should be big enough to allocate one or two
|
||||
// buckets for the typical case
|
||||
// Picking a Size so sizeof(Bucket<...>) is a power of two is also a small win
|
||||
template<unsigned _Size, typename T = uint32_t>
|
||||
struct BucketList {
|
||||
static constexpr const unsigned Size = _Size;
|
||||
|
||||
T Items[Size];
|
||||
std::unique_ptr<BucketList<Size>> Next;
|
||||
|
||||
void Clear() {
|
||||
Items[0] = 0;
|
||||
#ifndef NDEBUG
|
||||
for (int i = 1; i < Size; i++)
|
||||
Items[i] = 0xDEADBEEF;
|
||||
#endif
|
||||
Next.reset();
|
||||
}
|
||||
|
||||
BucketList() {
|
||||
Clear();
|
||||
}
|
||||
|
||||
template<typename EnumeratorFn>
|
||||
inline void Iterate(EnumeratorFn Enumerator) const {
|
||||
int i = 0;
|
||||
auto Bucket = this;
|
||||
|
||||
for(;;) {
|
||||
auto Item = Bucket->Items[i];
|
||||
if (Item == 0)
|
||||
break;
|
||||
|
||||
Enumerator(Item);
|
||||
|
||||
if (++i == Bucket->Size) {
|
||||
LOGMAN_THROW_A(Bucket->Next != nullptr, "Interference bug");
|
||||
Bucket = Bucket->Next.get();
|
||||
i = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<typename EnumeratorFn>
|
||||
inline bool Find(EnumeratorFn Enumerator) const {
|
||||
int i = 0;
|
||||
auto Bucket = this;
|
||||
|
||||
for(;;) {
|
||||
auto Item = Bucket->Items[i];
|
||||
if (Item == 0)
|
||||
break;
|
||||
|
||||
if (Enumerator(Item))
|
||||
return true;
|
||||
|
||||
if (++i == Bucket->Size) {
|
||||
LOGMAN_THROW_A(Bucket->Next != nullptr, "Bucket in bad state");
|
||||
Bucket = Bucket->Next.get();
|
||||
i = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void Append(uint32_t Val) {
|
||||
auto that = this;
|
||||
|
||||
while (that->Next) {
|
||||
that = that->Next.get();
|
||||
}
|
||||
|
||||
int i;
|
||||
for (i = 0; i < Size; i++) {
|
||||
if (that->Items[i] == 0) {
|
||||
that->Items[i] = Val;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (i < (Size-1)) {
|
||||
that->Items[i+1] = 0;
|
||||
} else {
|
||||
that->Next = std::make_unique<BucketList<Size, T>>();
|
||||
}
|
||||
}
|
||||
void Erase(uint32_t Val) {
|
||||
int i = 0;
|
||||
auto that = this;
|
||||
auto foundThat = this;
|
||||
auto foundI = 0;
|
||||
|
||||
for (;;) {
|
||||
if (that->Items[i] == Val) {
|
||||
foundThat = that;
|
||||
foundI = i;
|
||||
break;
|
||||
}
|
||||
else if (++i == Size) {
|
||||
i = 0;
|
||||
LOGMAN_THROW_A(that->Next != nullptr, "Bucket::Erase but element not contained");
|
||||
that = that->Next.get();
|
||||
}
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
if (that->Items[i] == 0) {
|
||||
foundThat->Items[foundI] = that->Items[i-1];
|
||||
that->Items[i-1] = 0;
|
||||
break;
|
||||
}
|
||||
else if (++i == Size) {
|
||||
if (that->Next->Items[0] == 0) {
|
||||
that->Next.reset();
|
||||
foundThat->Items[foundI] = that->Items[Size-1];
|
||||
that->Items[Size-1] = 0;
|
||||
break;
|
||||
}
|
||||
i = 0;
|
||||
that = that->Next.get();
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace
|
||||
Reference in new issue
Block a user