backend/rv64: Implement UpdateAllUses

This commit is contained in:
Yang Liu 2024-01-20 17:19:54 +08:00 committed by Merry
parent cc2a6fd6fb
commit 3ff8b9d346
3 changed files with 35 additions and 31 deletions

View file

@ -95,6 +95,7 @@ EmittedBlockInfo EmitRV64(biscuit::Assembler& as, IR::Block block, const EmitCon
} }
} }
reg_alloc.UpdateAllUses();
reg_alloc.AssertNoMoreUses(); reg_alloc.AssertNoMoreUses();
// TODO: Add Cycles // TODO: Add Cycles

View file

@ -82,7 +82,18 @@ void HostLocInfo::SetupScratchLocation() {
} }
bool HostLocInfo::IsCompletelyEmpty() const { 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) { RegAlloc::ArgumentInfo RegAlloc::GetArgumentInfo(IR::Inst* inst) {
@ -92,7 +103,7 @@ RegAlloc::ArgumentInfo RegAlloc::GetArgumentInfo(IR::Inst* inst) {
ret[i].value = arg; ret[i].value = arg;
if (!arg.IsImmediate() && !IsValuelessType(arg.GetType())) { if (!arg.IsImmediate() && !IsValuelessType(arg.GetType())) {
ASSERT_MSG(ValueLocation(arg.GetInst()), "argument must already been defined"); ASSERT_MSG(ValueLocation(arg.GetInst()), "argument must already been defined");
ValueInfo(arg.GetInst()).accumulated_uses++; ValueInfo(arg.GetInst()).uses_this_inst++;
} }
} }
return ret; return ret;
@ -102,8 +113,20 @@ bool RegAlloc::IsValueLive(IR::Inst* inst) const {
return !!ValueLocation(inst); 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 { 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(gprs.begin(), gprs.end(), is_empty));
ASSERT(std::all_of(fprs.begin(), fprs.end(), is_empty)); ASSERT(std::all_of(fprs.begin(), fprs.end(), is_empty));
ASSERT(std::all_of(spills.begin(), spills.end(), is_empty)); ASSERT(std::all_of(spills.begin(), spills.end(), is_empty));
@ -224,20 +247,6 @@ template u32 RegAlloc::RealizeReadImpl<HostLoc::Kind::Fpr>(const IR::Value& valu
template u32 RegAlloc::RealizeWriteImpl<HostLoc::Kind::Gpr>(const IR::Inst* value); template u32 RegAlloc::RealizeWriteImpl<HostLoc::Kind::Gpr>(const IR::Inst* value);
template u32 RegAlloc::RealizeWriteImpl<HostLoc::Kind::Fpr>(const IR::Inst* value); template u32 RegAlloc::RealizeWriteImpl<HostLoc::Kind::Fpr>(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<HostLocInfo, 32>& regs, const std::vector<u32>& order) const { u32 RegAlloc::AllocateRegister(const std::array<HostLocInfo, 32>& regs, const std::vector<u32>& order) const {
const auto empty = std::find_if(order.begin(), order.end(), [&](u32 i) { return regs[i].values.empty() && !regs[i].locked; }); const auto empty = std::find_if(order.begin(), order.end(), [&](u32 i) { return regs[i].values.empty() && !regs[i].locked; });
if (empty != order.end()) { if (empty != order.end()) {

View file

@ -92,12 +92,14 @@ struct HostLocInfo final {
std::vector<const IR::Inst*> values; std::vector<const IR::Inst*> values;
size_t locked = 0; size_t locked = 0;
bool realized = false; bool realized = false;
size_t uses_this_inst = 0;
size_t accumulated_uses = 0; size_t accumulated_uses = 0;
size_t expected_uses = 0; size_t expected_uses = 0;
bool Contains(const IR::Inst*) const; bool Contains(const IR::Inst*) const;
void SetupScratchLocation(); void SetupScratchLocation();
bool IsCompletelyEmpty() const; bool IsCompletelyEmpty() const;
void UpdateUses();
}; };
class RegAlloc { class RegAlloc {
@ -124,6 +126,7 @@ public:
(rs.Realize(), ...); (rs.Realize(), ...);
} }
void UpdateAllUses();
void AssertNoMoreUses() const; void AssertNoMoreUses() const;
private: private:
@ -136,7 +139,6 @@ private:
u32 RealizeReadImpl(const IR::Value& value); u32 RealizeReadImpl(const IR::Value& value);
template<HostLoc::Kind kind> template<HostLoc::Kind kind>
u32 RealizeWriteImpl(const IR::Inst* value); u32 RealizeWriteImpl(const IR::Inst* value);
void Unlock(HostLoc host_loc);
u32 AllocateRegister(const std::array<HostLocInfo, 32>& regs, const std::vector<u32>& order) const; u32 AllocateRegister(const std::array<HostLocInfo, 32>& regs, const std::vector<u32>& order) const;
void SpillGpr(u32 index); void SpillGpr(u32 index);
@ -168,19 +170,11 @@ RAReg<T>::RAReg(RegAlloc& reg_alloc, bool write, const IR::Value& value)
template<typename T> template<typename T>
RAReg<T>::~RAReg() { RAReg<T>::~RAReg() {
if (value.IsImmediate()) { if (!value.IsImmediate()) {
if (reg) { reg_alloc.ValueInfo(value.GetInst()).locked--;
// 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) { if (reg) {
info.realized = false; reg_alloc.ValueInfo(HostLoc{kind, reg->Index()}).realized = false;
}
} }
} }