aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorYang Liu <[email protected]>2024-01-19 23:28:29 +0800
committerMerry <[email protected]>2024-03-02 19:38:46 +0000
commitcc2a6fd6fb1e12a1e916a5b3691943f6419bd9c8 (patch)
treebf3654292d84a37b0808e48edc344717bcdd22f0
parentb7cca7c53d8ce53a5f8b6ba4cd1fc8729056381e (diff)
downloaddynarmic-cc2a6fd6fb1e12a1e916a5b3691943f6419bd9c8.tar.gz
dynarmic-cc2a6fd6fb1e12a1e916a5b3691943f6419bd9c8.zip
backend/rv64: Implement AssertNoMoreUses and some minor tweaks
-rw-r--r--src/dynarmic/backend/riscv64/emit_riscv64.cpp4
-rw-r--r--src/dynarmic/backend/riscv64/reg_alloc.cpp61
-rw-r--r--src/dynarmic/backend/riscv64/reg_alloc.h2
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;