diff options
| author | Takoroka <137927095+Takoroka@users.noreply.github.com> | 2026-11-01 15:13:32 -0500 |
|---|---|---|
| committer | Takoroka <137927095+Takoroka@users.noreply.github.com> | 2026-11-01 15:13:32 -0500 |
| commit | ebd9a4aaf9f00cd787ec9b8623b6066cca3f9f02 (patch) | |
| tree | fb769f131fccde65c6b842d52ec4fc18a64c8339 /src | |
| parent | f21d6c0a49a90fd6ec919de438a07da11ead12d9 (diff) | |
| parent | e6d53e728a93fe6d97a243de41301b9f7c54df5a (diff) | |
Merge remote-tracking branch 'origin/fix/dynarmic-faster-regalloc' into test/linux-all-prs-plus
Diffstat (limited to 'src')
| -rw-r--r-- | src/dynarmic/src/dynarmic/backend/x64/reg_alloc.cpp | 14 | ||||
| -rw-r--r-- | src/dynarmic/src/dynarmic/backend/x64/reg_alloc.h | 9 |
2 files changed, 16 insertions, 7 deletions
diff --git a/src/dynarmic/src/dynarmic/backend/x64/reg_alloc.cpp b/src/dynarmic/src/dynarmic/backend/x64/reg_alloc.cpp index 5a828839c1..4f3d253441 100644 --- a/src/dynarmic/src/dynarmic/backend/x64/reg_alloc.cpp +++ b/src/dynarmic/src/dynarmic/backend/x64/reg_alloc.cpp @@ -465,22 +465,24 @@ std::optional<HostLoc> RegAlloc::ValueLocation(const IR::Inst* value) const noex return std::nullopt; } +// The checks that scan every location for def_inst are debug-only: per IR instruction they cost as +// much as the rest of register allocation. void RegAlloc::DefineValueImpl(BlockOfCode& code, IR::Inst* def_inst, HostLoc host_loc) noexcept { - ASSERT(!ValueLocation(def_inst) && "def_inst has already been defined"); + DEBUG_ASSERT(!ValueLocation(def_inst) && "def_inst has already been defined"); LocInfo(host_loc).AddValue(host_loc, def_inst); - ASSERT(*ValueLocation(def_inst) == host_loc); + DEBUG_ASSERT(*ValueLocation(def_inst) == host_loc); } void RegAlloc::DefineValueImpl(BlockOfCode& code, IR::Inst* def_inst, const IR::Value& use_inst) noexcept { - ASSERT(!ValueLocation(def_inst) && "def_inst has already been defined"); + DEBUG_ASSERT(!ValueLocation(def_inst) && "def_inst has already been defined"); if (use_inst.IsImmediate()) { const HostLoc location = ScratchImpl(code, gpr_order); DefineValueImpl(code, def_inst, location); LoadImmediate(code, use_inst, location); } else { - ASSERT(ValueLocation(use_inst.GetInst()) && "use_inst must already be defined"); - const HostLoc location = *ValueLocation(use_inst.GetInst()); - DefineValueImpl(code, def_inst, location); + const auto location = ValueLocation(use_inst.GetInst()); + ASSERT(location && "use_inst must already be defined"); + DefineValueImpl(code, def_inst, *location); } } diff --git a/src/dynarmic/src/dynarmic/backend/x64/reg_alloc.h b/src/dynarmic/src/dynarmic/backend/x64/reg_alloc.h index 455c6a970a..0cad07796c 100644 --- a/src/dynarmic/src/dynarmic/backend/x64/reg_alloc.h +++ b/src/dynarmic/src/dynarmic/backend/x64/reg_alloc.h @@ -65,6 +65,11 @@ public: } void ReleaseOne() noexcept; void ReleaseAll() noexcept; + /// True when ReleaseAll would change nothing, as for most of the spill slots most of the time. + inline bool IsReleased() const noexcept { + return current_references == 0 && is_being_used_count == 0 && !is_scratch && !is_set_last_use && + (total_uses != accumulated_uses || (values.empty() && total_uses == 0 && max_bit_width == 0)); + } constexpr size_t GetMaxBitWidth() const noexcept { return 1 << max_bit_width; } void AddValue(HostLoc loc, IR::Inst* inst) noexcept; /// Checks if the given instruction is in our values set @@ -201,8 +206,10 @@ public: void ReleaseStackSpace(BlockOfCode& code, const size_t stack_space) noexcept; inline void EndOfAllocScope() noexcept { + // After every IR instruction: skip the locations it left alone. for (auto& iter : hostloc_info) - iter.ReleaseAll(); + if (!iter.IsReleased()) + iter.ReleaseAll(); } inline void AssertNoMoreUses() noexcept { ASSERT(std::all_of(hostloc_info.begin(), hostloc_info.end(), [](const auto& i) noexcept { return i.IsEmpty(); })); |
