diff --git a/src/dynarmic/backend/riscv64/emit_riscv64.cpp b/src/dynarmic/backend/riscv64/emit_riscv64.cpp index e5f52916..22707e3a 100644 --- a/src/dynarmic/backend/riscv64/emit_riscv64.cpp +++ b/src/dynarmic/backend/riscv64/emit_riscv64.cpp @@ -95,6 +95,7 @@ EmittedBlockInfo EmitRV64(biscuit::Assembler& as, IR::Block block, const EmitCon } } + reg_alloc.UpdateAllUses(); reg_alloc.AssertNoMoreUses(); // TODO: Add Cycles diff --git a/src/dynarmic/backend/riscv64/reg_alloc.cpp b/src/dynarmic/backend/riscv64/reg_alloc.cpp index 77e1905d..245c961f 100644 --- a/src/dynarmic/backend/riscv64/reg_alloc.cpp +++ b/src/dynarmic/backend/riscv64/reg_alloc.cpp @@ -82,7 +82,18 @@ void HostLocInfo::SetupScratchLocation() { } bool HostLocInfo::IsCompletelyEmpty() const { - return values.empty() && !locked && !realized && !accumulated_uses && !expected_uses; + return values.empty() && !locked && !realized && !accumulated_uses && !expected_uses && !uses_this_inst; +} + +void HostLocInfo::UpdateUses() { + accumulated_uses += uses_this_inst; + uses_this_inst = 0; + + if (accumulated_uses == expected_uses) { + values.clear(); + accumulated_uses = 0; + expected_uses = 0; + } } RegAlloc::ArgumentInfo RegAlloc::GetArgumentInfo(IR::Inst* inst) { @@ -92,7 +103,7 @@ RegAlloc::ArgumentInfo RegAlloc::GetArgumentInfo(IR::Inst* inst) { ret[i].value = arg; if (!arg.IsImmediate() && !IsValuelessType(arg.GetType())) { ASSERT_MSG(ValueLocation(arg.GetInst()), "argument must already been defined"); - ValueInfo(arg.GetInst()).accumulated_uses++; + ValueInfo(arg.GetInst()).uses_this_inst++; } } return ret; @@ -102,8 +113,20 @@ bool RegAlloc::IsValueLive(IR::Inst* inst) const { return !!ValueLocation(inst); } +void RegAlloc::UpdateAllUses() { + for (auto& gpr : gprs) { + gpr.UpdateUses(); + } + for (auto& fpr : fprs) { + fpr.UpdateUses(); + } + for (auto& spill : spills) { + spill.UpdateUses(); + } +} + void RegAlloc::AssertNoMoreUses() const { - const auto is_empty = [](const auto& i) { return i.values.empty() && !i.locked && !i.realized && !i.accumulated_uses && !i.expected_uses; }; + const auto is_empty = [](const auto& i) { return i.IsCompletelyEmpty(); }; ASSERT(std::all_of(gprs.begin(), gprs.end(), is_empty)); ASSERT(std::all_of(fprs.begin(), fprs.end(), is_empty)); ASSERT(std::all_of(spills.begin(), spills.end(), is_empty)); @@ -224,20 +247,6 @@ template u32 RegAlloc::RealizeReadImpl(const IR::Value& valu template u32 RegAlloc::RealizeWriteImpl(const IR::Inst* value); template u32 RegAlloc::RealizeWriteImpl(const IR::Inst* value); -void RegAlloc::Unlock(HostLoc host_loc) { - HostLocInfo& info = ValueInfo(host_loc); - if (!info.realized) { - return; - } - - if (info.accumulated_uses == info.expected_uses) { - info = {}; - } else { - info.realized = false; - info.locked = false; - } -} - u32 RegAlloc::AllocateRegister(const std::array& regs, const std::vector& order) const { const auto empty = std::find_if(order.begin(), order.end(), [&](u32 i) { return regs[i].values.empty() && !regs[i].locked; }); if (empty != order.end()) { diff --git a/src/dynarmic/backend/riscv64/reg_alloc.h b/src/dynarmic/backend/riscv64/reg_alloc.h index 0f51d0af..e457bc84 100644 --- a/src/dynarmic/backend/riscv64/reg_alloc.h +++ b/src/dynarmic/backend/riscv64/reg_alloc.h @@ -92,12 +92,14 @@ struct HostLocInfo final { std::vector values; size_t locked = 0; bool realized = false; + size_t uses_this_inst = 0; size_t accumulated_uses = 0; size_t expected_uses = 0; bool Contains(const IR::Inst*) const; void SetupScratchLocation(); bool IsCompletelyEmpty() const; + void UpdateUses(); }; class RegAlloc { @@ -124,6 +126,7 @@ public: (rs.Realize(), ...); } + void UpdateAllUses(); void AssertNoMoreUses() const; private: @@ -136,7 +139,6 @@ private: u32 RealizeReadImpl(const IR::Value& value); template u32 RealizeWriteImpl(const IR::Inst* value); - void Unlock(HostLoc host_loc); u32 AllocateRegister(const std::array& regs, const std::vector& order) const; void SpillGpr(u32 index); @@ -168,19 +170,11 @@ RAReg::RAReg(RegAlloc& reg_alloc, bool write, const IR::Value& value) template RAReg::~RAReg() { - if (value.IsImmediate()) { - if (reg) { - // Immediate in scratch register - HostLocInfo& info = reg_alloc.ValueInfo(HostLoc{kind, reg->Index()}); - info.locked--; - info.realized = false; - } - } else { - HostLocInfo& info = reg_alloc.ValueInfo(value.GetInst()); - info.locked--; - if (reg) { - info.realized = false; - } + if (!value.IsImmediate()) { + reg_alloc.ValueInfo(value.GetInst()).locked--; + } + if (reg) { + reg_alloc.ValueInfo(HostLoc{kind, reg->Index()}).realized = false; } }