backend/arm64/reg_alloc: Tidy up HostLocInfo
This commit is contained in:
parent
01f28facbd
commit
d69582f548
2 changed files with 38 additions and 20 deletions
|
@ -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;
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
Loading…
Reference in a new issue