backend/rv64: Implement UpdateAllUses
This commit is contained in:
parent
cc2a6fd6fb
commit
3ff8b9d346
3 changed files with 35 additions and 31 deletions
|
@ -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
|
||||||
|
|
|
@ -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()) {
|
||||||
|
|
|
@ -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;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue