diff options
author | Yang Liu <[email protected]> | 2024-01-19 23:28:29 +0800 |
---|---|---|
committer | Merry <[email protected]> | 2024-03-02 19:38:46 +0000 |
commit | cc2a6fd6fb1e12a1e916a5b3691943f6419bd9c8 (patch) | |
tree | bf3654292d84a37b0808e48edc344717bcdd22f0 | |
parent | b7cca7c53d8ce53a5f8b6ba4cd1fc8729056381e (diff) | |
download | dynarmic-cc2a6fd6fb1e12a1e916a5b3691943f6419bd9c8.tar.gz dynarmic-cc2a6fd6fb1e12a1e916a5b3691943f6419bd9c8.zip |
backend/rv64: Implement AssertNoMoreUses and some minor tweaks
-rw-r--r-- | src/dynarmic/backend/riscv64/emit_riscv64.cpp | 4 | ||||
-rw-r--r-- | src/dynarmic/backend/riscv64/reg_alloc.cpp | 61 | ||||
-rw-r--r-- | src/dynarmic/backend/riscv64/reg_alloc.h | 2 |
3 files changed, 40 insertions, 27 deletions
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<IR::Opcode::LogicalShiftLeft32>(biscuit::Assembler& as, EmitContext& template<> void EmitIR<IR::Opcode::GetCarryFromOp>(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<HostLoc::Kind kind> u32 RegAlloc::GenerateImmediate(const IR::Value& value) { // TODO @@ -141,44 +148,44 @@ 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); + if constexpr (required_kind == HostLoc::Kind::Gpr) { + const u32 new_location_index = AllocateRegister(gprs, gpr_order); + SpillGpr(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)); + ASSERT_FALSE("Logic error"); break; case HostLoc::Kind::Fpr: - ASSERT_FALSE("Logic error"); + as.FMV_X_D(biscuit::GPR(new_location_index), biscuit::FPR{current_location->index}); + // ASSERT size fits break; case HostLoc::Kind::Spill: - as.FLD(biscuit::FPR{new_location_index}, spill_offset + new_location_index * spill_slot_size, biscuit::sp); + as.LD(biscuit::GPR{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; + 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::Gpr) { - const u32 new_location_index = AllocateRegister(gprs, gpr_order); - SpillGpr(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: - ASSERT_FALSE("Logic error"); + as.FMV_D_X(biscuit::FPR{new_location_index}, biscuit::GPR(current_location->index)); break; case HostLoc::Kind::Fpr: - as.FMV_X_D(biscuit::GPR(new_location_index), biscuit::FPR{current_location->index}); - // ASSERT size fits + ASSERT_FALSE("Logic error"); break; case HostLoc::Kind::Spill: - as.LD(biscuit::GPR{new_location_index}, spill_offset + new_location_index * spill_slot_size, biscuit::sp); + as.FLD(biscuit::FPR{new_location_index}, spill_offset + new_location_index * spill_slot_size, biscuit::sp); break; } - gprs[new_location_index] = std::exchange(ValueInfo(*current_location), {}); - gprs[new_location_index].realized = true; + 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<mcl::mp::lift_value<required_kind>>); @@ -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<mcl::mp::lift_value<required_kind>>); } @@ -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<typename> friend struct RAReg; |