backend/arm64/reg_alloc: Tidy up HostLocInfo

This commit is contained in:
Merry 2022-07-23 11:47:12 +01:00 committed by merry
parent 01f28facbd
commit d69582f548
2 changed files with 38 additions and 20 deletions

View file

@ -79,6 +79,28 @@ bool HostLocInfo::Contains(const IR::Inst* value) const {
return std::find(values.begin(), values.end(), value) != values.end(); return std::find(values.begin(), values.end(), value) != values.end();
} }
void HostLocInfo::SetupLocation(const IR::Inst* value) {
values.clear();
values.emplace_back(value);
locked = true;
realized = true;
uses_this_inst = 0;
accumulated_uses = 0;
expected_uses = value->UseCount();
}
bool HostLocInfo::IsCompletelyEmpty() const {
return values.empty() && !locked && !realized && !accumulated_uses && !expected_uses && !uses_this_inst;
}
bool HostLocInfo::IsImmediatelyAllocatable() const {
return values.empty() && !locked;
}
bool HostLocInfo::IsOneRemainingUse() const {
return accumulated_uses + 1 == expected_uses && uses_this_inst == 1;
}
RegAlloc::ArgumentInfo RegAlloc::GetArgumentInfo(IR::Inst* inst) { RegAlloc::ArgumentInfo RegAlloc::GetArgumentInfo(IR::Inst* inst) {
ArgumentInfo ret = {Argument{*this}, Argument{*this}, Argument{*this}, Argument{*this}}; ArgumentInfo ret = {Argument{*this}, Argument{*this}, Argument{*this}, Argument{*this}};
for (size_t i = 0; i < inst->NumArgs(); i++) { for (size_t i = 0; i < inst->NumArgs(); i++) {
@ -86,7 +108,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;
@ -103,7 +125,7 @@ void RegAlloc::DefineAsExisting(IR::Inst* inst, Argument& arg) {
} }
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(is_empty(flags)); ASSERT(is_empty(flags));
@ -179,27 +201,19 @@ template<HostLoc::Kind kind>
int RegAlloc::RealizeWriteImpl(const IR::Inst* value) { int RegAlloc::RealizeWriteImpl(const IR::Inst* value) {
ASSERT(!ValueLocation(value)); ASSERT(!ValueLocation(value));
const auto setup_location = [&](HostLocInfo& info) {
info = {};
info.values.emplace_back(value);
info.locked = true;
info.realized = true;
info.expected_uses = value->UseCount();
};
if constexpr (kind == HostLoc::Kind::Gpr) { if constexpr (kind == HostLoc::Kind::Gpr) {
const int new_location_index = AllocateRegister(gprs, gpr_order); const int new_location_index = AllocateRegister(gprs, gpr_order);
SpillGpr(new_location_index); SpillGpr(new_location_index);
setup_location(gprs[new_location_index]); gprs[new_location_index].SetupLocation(value);
return new_location_index; return new_location_index;
} else if constexpr (kind == HostLoc::Kind::Fpr) { } else if constexpr (kind == HostLoc::Kind::Fpr) {
const int new_location_index = AllocateRegister(fprs, fpr_order); const int new_location_index = AllocateRegister(fprs, fpr_order);
SpillFpr(new_location_index); SpillFpr(new_location_index);
setup_location(fprs[new_location_index]); fprs[new_location_index].SetupLocation(value);
return new_location_index; return new_location_index;
} else if constexpr (kind == HostLoc::Kind::Flags) { } else if constexpr (kind == HostLoc::Kind::Flags) {
ASSERT(flags.values.empty()); ASSERT(flags.values.empty());
setup_location(flags); flags.SetupLocation(value);
return 0; return 0;
} else { } else {
static_assert(kind == HostLoc::Kind::Fpr || kind == HostLoc::Kind::Gpr || kind == HostLoc::Kind::Flags); static_assert(kind == HostLoc::Kind::Fpr || kind == HostLoc::Kind::Gpr || kind == HostLoc::Kind::Flags);
@ -219,6 +233,9 @@ void RegAlloc::Unlock(HostLoc host_loc) {
return; return;
} }
info.accumulated_uses += info.uses_this_inst;
info.uses_this_inst = 0;
if (info.accumulated_uses == info.expected_uses) { if (info.accumulated_uses == info.expected_uses) {
info = {}; info = {};
} else { } else {
@ -228,7 +245,7 @@ void RegAlloc::Unlock(HostLoc host_loc) {
} }
int RegAlloc::AllocateRegister(const std::array<HostLocInfo, 32>& regs, const std::vector<int>& order) const { int RegAlloc::AllocateRegister(const std::array<HostLocInfo, 32>& regs, const std::vector<int>& order) const {
const auto empty = std::find_if(order.begin(), order.end(), [&](int i) { return regs[i].values.empty() && !regs[i].locked; }); const auto empty = std::find_if(order.begin(), order.end(), [&](int i) { return regs[i].IsImmediatelyAllocatable(); });
if (empty != order.end()) { if (empty != order.end()) {
return *empty; return *empty;
} }
@ -279,9 +296,7 @@ int RegAlloc::FindFreeSpill() const {
} }
std::optional<HostLoc> RegAlloc::ValueLocation(const IR::Inst* value) const { std::optional<HostLoc> RegAlloc::ValueLocation(const IR::Inst* value) const {
const auto contains_value = [value](const HostLocInfo& info) { const auto contains_value = [value](const HostLocInfo& info) { return info.Contains(value); };
return info.Contains(value);
};
if (const auto iter = std::find_if(gprs.begin(), gprs.end(), contains_value); iter != gprs.end()) { if (const auto iter = std::find_if(gprs.begin(), gprs.end(), contains_value); iter != gprs.end()) {
return HostLoc{HostLoc::Kind::Gpr, static_cast<int>(iter - gprs.begin())}; return HostLoc{HostLoc::Kind::Gpr, static_cast<int>(iter - gprs.begin())};
@ -313,9 +328,7 @@ HostLocInfo& RegAlloc::ValueInfo(HostLoc host_loc) {
} }
HostLocInfo& RegAlloc::ValueInfo(const IR::Inst* value) { HostLocInfo& RegAlloc::ValueInfo(const IR::Inst* value) {
const auto contains_value = [value](const HostLocInfo& info) { const auto contains_value = [value](const HostLocInfo& info) { return info.Contains(value); };
return info.Contains(value);
};
if (const auto iter = std::find_if(gprs.begin(), gprs.end(), contains_value); iter != gprs.end()) { if (const auto iter = std::find_if(gprs.begin(), gprs.end(), contains_value); iter != gprs.end()) {
return *iter; return *iter;

View file

@ -115,10 +115,15 @@ struct HostLocInfo {
std::vector<const IR::Inst*> values; std::vector<const IR::Inst*> values;
bool locked = false; bool locked = false;
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 SetupLocation(const IR::Inst*);
bool IsCompletelyEmpty() const;
bool IsImmediatelyAllocatable() const;
bool IsOneRemainingUse() const;
}; };
class RegAlloc { class RegAlloc {