aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorTakoroka <137927095+Takoroka@users.noreply.github.com>2026-11-01 15:13:32 -0500
committerTakoroka <137927095+Takoroka@users.noreply.github.com>2026-11-01 15:13:32 -0500
commitebd9a4aaf9f00cd787ec9b8623b6066cca3f9f02 (patch)
treefb769f131fccde65c6b842d52ec4fc18a64c8339 /src
parentf21d6c0a49a90fd6ec919de438a07da11ead12d9 (diff)
parente6d53e728a93fe6d97a243de41301b9f7c54df5a (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.cpp14
-rw-r--r--src/dynarmic/src/dynarmic/backend/x64/reg_alloc.h9
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(); }));