diff --git a/src/dynarmic/backend/riscv64/emit_riscv64.cpp b/src/dynarmic/backend/riscv64/emit_riscv64.cpp index f75db43b..e5f52916 100644 --- a/src/dynarmic/backend/riscv64/emit_riscv64.cpp +++ b/src/dynarmic/backend/riscv64/emit_riscv64.cpp @@ -40,6 +40,7 @@ void EmitIR(biscuit::Assembler& as, EmitContext& template<> void EmitIR(biscuit::Assembler&, EmitContext& ctx, IR::Inst* inst) { + [[maybe_unused]] auto args = ctx.reg_alloc.GetArgumentInfo(inst); ASSERT(ctx.reg_alloc.IsValueLive(inst)); } @@ -93,6 +94,9 @@ EmittedBlockInfo EmitRV64(biscuit::Assembler& as, IR::Block block, const EmitCon break; } } + + reg_alloc.AssertNoMoreUses(); + // TODO: Add Cycles // TODO: Emit Terminal diff --git a/src/dynarmic/backend/riscv64/reg_alloc.cpp b/src/dynarmic/backend/riscv64/reg_alloc.cpp index 094f34dd..77e1905d 100644 --- a/src/dynarmic/backend/riscv64/reg_alloc.cpp +++ b/src/dynarmic/backend/riscv64/reg_alloc.cpp @@ -102,6 +102,13 @@ bool RegAlloc::IsValueLive(IR::Inst* inst) const { return !!ValueLocation(inst); } +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; }; + 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)); +} + template u32 RegAlloc::GenerateImmediate(const IR::Value& value) { // TODO @@ -141,26 +148,7 @@ u32 RegAlloc::RealizeReadImpl(const IR::Value& value) { ASSERT(!ValueInfo(*current_location).realized); ASSERT(!ValueInfo(*current_location).locked); - if constexpr (required_kind == HostLoc::Kind::Fpr) { - const u32 new_location_index = AllocateRegister(fprs, fpr_order); - SpillFpr(new_location_index); - - switch (current_location->kind) { - case HostLoc::Kind::Gpr: - as.FMV_D_X(biscuit::FPR{new_location_index}, biscuit::GPR(current_location->index)); - break; - case HostLoc::Kind::Fpr: - ASSERT_FALSE("Logic error"); - break; - case HostLoc::Kind::Spill: - as.FLD(biscuit::FPR{new_location_index}, spill_offset + new_location_index * spill_slot_size, biscuit::sp); - break; - } - - fprs[new_location_index] = std::exchange(ValueInfo(*current_location), {}); - fprs[new_location_index].realized = true; - return new_location_index; - } else if constexpr (required_kind == HostLoc::Kind::Gpr) { + if constexpr (required_kind == HostLoc::Kind::Gpr) { const u32 new_location_index = AllocateRegister(gprs, gpr_order); SpillGpr(new_location_index); @@ -180,6 +168,25 @@ u32 RegAlloc::RealizeReadImpl(const IR::Value& value) { gprs[new_location_index] = std::exchange(ValueInfo(*current_location), {}); gprs[new_location_index].realized = true; return new_location_index; + } else if constexpr (required_kind == HostLoc::Kind::Fpr) { + const u32 new_location_index = AllocateRegister(fprs, fpr_order); + SpillFpr(new_location_index); + + switch (current_location->kind) { + case HostLoc::Kind::Gpr: + as.FMV_D_X(biscuit::FPR{new_location_index}, biscuit::GPR(current_location->index)); + break; + case HostLoc::Kind::Fpr: + ASSERT_FALSE("Logic error"); + break; + case HostLoc::Kind::Spill: + as.FLD(biscuit::FPR{new_location_index}, spill_offset + new_location_index * spill_slot_size, biscuit::sp); + break; + } + + fprs[new_location_index] = std::exchange(ValueInfo(*current_location), {}); + fprs[new_location_index].realized = true; + return new_location_index; } else { static_assert(Common::always_false_v>); } @@ -194,19 +201,19 @@ u32 RegAlloc::RealizeWriteImpl(const IR::Inst* value) { info.values.emplace_back(value); info.locked = true; info.realized = true; - info.expected_uses += value->UseCount(); + info.expected_uses = value->UseCount(); }; - if constexpr (required_kind == HostLoc::Kind::Fpr) { - const u32 new_location_index = AllocateRegister(fprs, fpr_order); - SpillFpr(new_location_index); - setup_location(fprs[new_location_index]); - return new_location_index; - } else if constexpr (required_kind == HostLoc::Kind::Gpr) { + if constexpr (required_kind == HostLoc::Kind::Gpr) { const u32 new_location_index = AllocateRegister(gprs, gpr_order); SpillGpr(new_location_index); setup_location(gprs[new_location_index]); return new_location_index; + } else if constexpr (required_kind == HostLoc::Kind::Fpr) { + const u32 new_location_index = AllocateRegister(fprs, fpr_order); + SpillFpr(new_location_index); + setup_location(fprs[new_location_index]); + return new_location_index; } else { static_assert(Common::always_false_v>); } @@ -305,13 +312,13 @@ HostLocInfo& RegAlloc::ValueInfo(const IR::Inst* value) { return info.Contains(value); }; - if (const auto iter = std::find_if(gprs.begin(), gprs.end(), contains_value)) { + if (const auto iter = std::find_if(gprs.begin(), gprs.end(), contains_value); iter != gprs.end()) { return *iter; } - if (const auto iter = std::find_if(fprs.begin(), fprs.end(), contains_value)) { + if (const auto iter = std::find_if(fprs.begin(), fprs.end(), contains_value); iter != gprs.end()) { return *iter; } - if (const auto iter = std::find_if(spills.begin(), spills.end(), contains_value)) { + if (const auto iter = std::find_if(spills.begin(), spills.end(), contains_value); iter != gprs.end()) { return *iter; } ASSERT_FALSE("RegAlloc::ValueInfo: Value not found"); diff --git a/src/dynarmic/backend/riscv64/reg_alloc.h b/src/dynarmic/backend/riscv64/reg_alloc.h index 5b38c482..0f51d0af 100644 --- a/src/dynarmic/backend/riscv64/reg_alloc.h +++ b/src/dynarmic/backend/riscv64/reg_alloc.h @@ -124,6 +124,8 @@ public: (rs.Realize(), ...); } + void AssertNoMoreUses() const; + private: template friend struct RAReg;