diff --git a/External/FEXCore/Source/Interface/IR/Passes/RegisterAllocationPass.cpp b/External/FEXCore/Source/Interface/IR/Passes/RegisterAllocationPass.cpp index 937a1001f..96104b56b 100644 --- a/External/FEXCore/Source/Interface/IR/Passes/RegisterAllocationPass.cpp +++ b/External/FEXCore/Source/Interface/IR/Passes/RegisterAllocationPass.cpp @@ -4,6 +4,7 @@ tags: ir|opts $end_info$ */ +#include #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 - struct BucketList { - static constexpr const unsigned Size = _Size; - - T Items[Size]; - std::unique_ptr> Next; - - void Clear() { - Items[0] = 0; - #ifndef NDEBUG - for (int i = 1; i < Size; i++) - Items[i] = 0xDEADBEEF; - #endif - Next.reset(); - } - - BucketList() { - Clear(); - } - - template - 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 - 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>(); - } - } - 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 Interferences; + FEXCore::BucketList Interferences; }; static_assert(sizeof(RegisterNode) == 128 * 4); diff --git a/External/FEXCore/include/FEXCore/Utils/BucketList.h b/External/FEXCore/include/FEXCore/Utils/BucketList.h new file mode 100644 index 000000000..9275452d8 --- /dev/null +++ b/External/FEXCore/include/FEXCore/Utils/BucketList.h @@ -0,0 +1,137 @@ +#pragma once + +#include +#include + +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 + struct BucketList { + static constexpr const unsigned Size = _Size; + + T Items[Size]; + std::unique_ptr> Next; + + void Clear() { + Items[0] = 0; + #ifndef NDEBUG + for (int i = 1; i < Size; i++) + Items[i] = 0xDEADBEEF; + #endif + Next.reset(); + } + + BucketList() { + Clear(); + } + + template + 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 + 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>(); + } + } + 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 \ No newline at end of file