backend/x64/reg_alloc: Apply const where applicable
Also tidies up bracing where applicable along the way.
This commit is contained in:
parent
cba9351b82
commit
22bd95902d
1 changed files with 26 additions and 20 deletions
|
@ -282,7 +282,7 @@ void RegAlloc::UseScratch(Argument& arg, HostLoc host_loc) {
|
||||||
|
|
||||||
void RegAlloc::DefineValue(IR::Inst* inst, const Xbyak::Reg& reg) {
|
void RegAlloc::DefineValue(IR::Inst* inst, const Xbyak::Reg& reg) {
|
||||||
ASSERT(reg.getKind() == Xbyak::Operand::XMM || reg.getKind() == Xbyak::Operand::REG);
|
ASSERT(reg.getKind() == Xbyak::Operand::XMM || reg.getKind() == Xbyak::Operand::REG);
|
||||||
HostLoc hostloc = static_cast<HostLoc>(reg.getIdx() + static_cast<size_t>(reg.getKind() == Xbyak::Operand::XMM ? HostLoc::XMM0 : HostLoc::RAX));
|
const auto hostloc = static_cast<HostLoc>(reg.getIdx() + static_cast<size_t>(reg.getKind() == Xbyak::Operand::XMM ? HostLoc::XMM0 : HostLoc::RAX));
|
||||||
DefineValueImpl(inst, hostloc);
|
DefineValueImpl(inst, hostloc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -294,7 +294,7 @@ void RegAlloc::DefineValue(IR::Inst* inst, Argument& arg) {
|
||||||
|
|
||||||
void RegAlloc::Release(const Xbyak::Reg& reg) {
|
void RegAlloc::Release(const Xbyak::Reg& reg) {
|
||||||
ASSERT(reg.getKind() == Xbyak::Operand::XMM || reg.getKind() == Xbyak::Operand::REG);
|
ASSERT(reg.getKind() == Xbyak::Operand::XMM || reg.getKind() == Xbyak::Operand::REG);
|
||||||
const HostLoc hostloc = static_cast<HostLoc>(reg.getIdx() + static_cast<size_t>(reg.getKind() == Xbyak::Operand::XMM ? HostLoc::XMM0 : HostLoc::RAX));
|
const auto hostloc = static_cast<HostLoc>(reg.getIdx() + static_cast<size_t>(reg.getKind() == Xbyak::Operand::XMM ? HostLoc::XMM0 : HostLoc::RAX));
|
||||||
LocInfo(hostloc).ReleaseOne();
|
LocInfo(hostloc).ReleaseOne();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -364,7 +364,7 @@ HostLoc RegAlloc::UseScratchImpl(IR::Value use_value, HostLocList desired_locati
|
||||||
}
|
}
|
||||||
|
|
||||||
HostLoc RegAlloc::ScratchImpl(HostLocList desired_locations) {
|
HostLoc RegAlloc::ScratchImpl(HostLocList desired_locations) {
|
||||||
HostLoc location = SelectARegister(desired_locations);
|
const HostLoc location = SelectARegister(desired_locations);
|
||||||
MoveOutOfTheWay(location);
|
MoveOutOfTheWay(location);
|
||||||
LocInfo(location).WriteLock();
|
LocInfo(location).WriteLock();
|
||||||
return location;
|
return location;
|
||||||
|
@ -382,8 +382,9 @@ void RegAlloc::HostCall(IR::Inst* result_def, std::optional<Argument::copyable_r
|
||||||
std::vector<HostLoc> ret(ABI_ALL_CALLER_SAVE.begin(), ABI_ALL_CALLER_SAVE.end());
|
std::vector<HostLoc> ret(ABI_ALL_CALLER_SAVE.begin(), ABI_ALL_CALLER_SAVE.end());
|
||||||
|
|
||||||
ret.erase(std::find(ret.begin(), ret.end(), ABI_RETURN));
|
ret.erase(std::find(ret.begin(), ret.end(), ABI_RETURN));
|
||||||
for (auto hostloc : args_hostloc)
|
for (auto hostloc : args_hostloc) {
|
||||||
ret.erase(std::find(ret.begin(), ret.end(), hostloc));
|
ret.erase(std::find(ret.begin(), ret.end(), hostloc));
|
||||||
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}();
|
}();
|
||||||
|
@ -398,7 +399,7 @@ void RegAlloc::HostCall(IR::Inst* result_def, std::optional<Argument::copyable_r
|
||||||
UseScratch(*args[i], args_hostloc[i]);
|
UseScratch(*args[i], args_hostloc[i]);
|
||||||
#if defined(__llvm__) && !defined(_WIN32)
|
#if defined(__llvm__) && !defined(_WIN32)
|
||||||
// LLVM puts the burden of zero-extension of 8 and 16 bit values on the caller instead of the callee
|
// LLVM puts the burden of zero-extension of 8 and 16 bit values on the caller instead of the callee
|
||||||
Xbyak::Reg64 reg = HostLocToReg64(args_hostloc[i]);
|
const Xbyak::Reg64 reg = HostLocToReg64(args_hostloc[i]);
|
||||||
switch (args[i]->get().GetType()) {
|
switch (args[i]->get().GetType()) {
|
||||||
case IR::Type::U8:
|
case IR::Type::U8:
|
||||||
code.movzx(reg.cvt32(), reg.cvt8());
|
code.movzx(reg.cvt32(), reg.cvt8());
|
||||||
|
@ -439,7 +440,7 @@ HostLoc RegAlloc::SelectARegister(HostLocList desired_locations) const {
|
||||||
std::vector<HostLoc> candidates = desired_locations;
|
std::vector<HostLoc> candidates = desired_locations;
|
||||||
|
|
||||||
// Find all locations that have not been allocated..
|
// Find all locations that have not been allocated..
|
||||||
auto allocated_locs = std::partition(candidates.begin(), candidates.end(), [this](auto loc){
|
const auto allocated_locs = std::partition(candidates.begin(), candidates.end(), [this](auto loc) {
|
||||||
return !this->LocInfo(loc).IsLocked();
|
return !this->LocInfo(loc).IsLocked();
|
||||||
});
|
});
|
||||||
candidates.erase(allocated_locs, candidates.end());
|
candidates.erase(allocated_locs, candidates.end());
|
||||||
|
@ -448,7 +449,7 @@ HostLoc RegAlloc::SelectARegister(HostLocList desired_locations) const {
|
||||||
// Selects the best location out of the available locations.
|
// Selects the best location out of the available locations.
|
||||||
// TODO: Actually do LRU or something. Currently we just try to pick something without a value if possible.
|
// TODO: Actually do LRU or something. Currently we just try to pick something without a value if possible.
|
||||||
|
|
||||||
std::partition(candidates.begin(), candidates.end(), [this](auto loc){
|
std::partition(candidates.begin(), candidates.end(), [this](auto loc) {
|
||||||
return this->LocInfo(loc).IsEmpty();
|
return this->LocInfo(loc).IsEmpty();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -456,9 +457,11 @@ HostLoc RegAlloc::SelectARegister(HostLocList desired_locations) const {
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<HostLoc> RegAlloc::ValueLocation(const IR::Inst* value) const {
|
std::optional<HostLoc> RegAlloc::ValueLocation(const IR::Inst* value) const {
|
||||||
for (size_t i = 0; i < hostloc_info.size(); i++)
|
for (size_t i = 0; i < hostloc_info.size(); i++) {
|
||||||
if (hostloc_info[i].ContainsValue(value))
|
if (hostloc_info[i].ContainsValue(value)) {
|
||||||
return static_cast<HostLoc>(i);
|
return static_cast<HostLoc>(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
@ -472,14 +475,14 @@ void RegAlloc::DefineValueImpl(IR::Inst* def_inst, const IR::Value& use_inst) {
|
||||||
ASSERT_MSG(!ValueLocation(def_inst), "def_inst has already been defined");
|
ASSERT_MSG(!ValueLocation(def_inst), "def_inst has already been defined");
|
||||||
|
|
||||||
if (use_inst.IsImmediate()) {
|
if (use_inst.IsImmediate()) {
|
||||||
HostLoc location = ScratchImpl(any_gpr);
|
const HostLoc location = ScratchImpl(any_gpr);
|
||||||
DefineValueImpl(def_inst, location);
|
DefineValueImpl(def_inst, location);
|
||||||
LoadImmediate(use_inst, location);
|
LoadImmediate(use_inst, location);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ASSERT_MSG(ValueLocation(use_inst.GetInst()), "use_inst must already be defined");
|
ASSERT_MSG(ValueLocation(use_inst.GetInst()), "use_inst must already be defined");
|
||||||
HostLoc location = *ValueLocation(use_inst.GetInst());
|
const HostLoc location = *ValueLocation(use_inst.GetInst());
|
||||||
DefineValueImpl(def_inst, location);
|
DefineValueImpl(def_inst, location);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -489,20 +492,22 @@ HostLoc RegAlloc::LoadImmediate(IR::Value imm, HostLoc host_loc) {
|
||||||
if (HostLocIsGPR(host_loc)) {
|
if (HostLocIsGPR(host_loc)) {
|
||||||
const Xbyak::Reg64 reg = HostLocToReg64(host_loc);
|
const Xbyak::Reg64 reg = HostLocToReg64(host_loc);
|
||||||
const u64 imm_value = imm.GetImmediateAsU64();
|
const u64 imm_value = imm.GetImmediateAsU64();
|
||||||
if (imm_value == 0)
|
if (imm_value == 0) {
|
||||||
code.xor_(reg.cvt32(), reg.cvt32());
|
code.xor_(reg.cvt32(), reg.cvt32());
|
||||||
else
|
} else {
|
||||||
code.mov(reg, imm_value);
|
code.mov(reg, imm_value);
|
||||||
|
}
|
||||||
return host_loc;
|
return host_loc;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (HostLocIsXMM(host_loc)) {
|
if (HostLocIsXMM(host_loc)) {
|
||||||
const Xbyak::Xmm reg = HostLocToXmm(host_loc);
|
const Xbyak::Xmm reg = HostLocToXmm(host_loc);
|
||||||
const u64 imm_value = imm.GetImmediateAsU64();
|
const u64 imm_value = imm.GetImmediateAsU64();
|
||||||
if (imm_value == 0)
|
if (imm_value == 0) {
|
||||||
MAYBE_AVX(xorps, reg, reg);
|
MAYBE_AVX(xorps, reg, reg);
|
||||||
else
|
} else {
|
||||||
MAYBE_AVX(movaps, reg, code.MConst(code.xword, imm_value));
|
MAYBE_AVX(movaps, reg, code.MConst(code.xword, imm_value));
|
||||||
|
}
|
||||||
return host_loc;
|
return host_loc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -562,15 +567,16 @@ void RegAlloc::SpillRegister(HostLoc loc) {
|
||||||
ASSERT_MSG(!LocInfo(loc).IsEmpty(), "There is no need to spill unoccupied registers");
|
ASSERT_MSG(!LocInfo(loc).IsEmpty(), "There is no need to spill unoccupied registers");
|
||||||
ASSERT_MSG(!LocInfo(loc).IsLocked(), "Registers that have been allocated must not be spilt");
|
ASSERT_MSG(!LocInfo(loc).IsLocked(), "Registers that have been allocated must not be spilt");
|
||||||
|
|
||||||
HostLoc new_loc = FindFreeSpill();
|
const HostLoc new_loc = FindFreeSpill();
|
||||||
Move(new_loc, loc);
|
Move(new_loc, loc);
|
||||||
}
|
}
|
||||||
|
|
||||||
HostLoc RegAlloc::FindFreeSpill() const {
|
HostLoc RegAlloc::FindFreeSpill() const {
|
||||||
for (size_t i = static_cast<size_t>(HostLoc::FirstSpill); i < hostloc_info.size(); i++) {
|
for (size_t i = static_cast<size_t>(HostLoc::FirstSpill); i < hostloc_info.size(); i++) {
|
||||||
HostLoc loc = static_cast<HostLoc>(i);
|
const auto loc = static_cast<HostLoc>(i);
|
||||||
if (LocInfo(loc).IsEmpty())
|
if (LocInfo(loc).IsEmpty()) {
|
||||||
return loc;
|
return loc;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ASSERT_MSG(false, "All spill locations are full");
|
ASSERT_MSG(false, "All spill locations are full");
|
||||||
|
@ -611,7 +617,7 @@ void RegAlloc::EmitMove(size_t bit_width, HostLoc to, HostLoc from) {
|
||||||
MAYBE_AVX(movd, HostLocToReg64(to).cvt32(), HostLocToXmm(from));
|
MAYBE_AVX(movd, HostLocToReg64(to).cvt32(), HostLocToXmm(from));
|
||||||
}
|
}
|
||||||
} else if (HostLocIsXMM(to) && HostLocIsSpill(from)) {
|
} else if (HostLocIsXMM(to) && HostLocIsSpill(from)) {
|
||||||
Xbyak::Address spill_addr = spill_to_addr(from);
|
const Xbyak::Address spill_addr = spill_to_addr(from);
|
||||||
ASSERT(spill_addr.getBit() >= bit_width);
|
ASSERT(spill_addr.getBit() >= bit_width);
|
||||||
switch (bit_width) {
|
switch (bit_width) {
|
||||||
case 128:
|
case 128:
|
||||||
|
@ -629,7 +635,7 @@ void RegAlloc::EmitMove(size_t bit_width, HostLoc to, HostLoc from) {
|
||||||
UNREACHABLE();
|
UNREACHABLE();
|
||||||
}
|
}
|
||||||
} else if (HostLocIsSpill(to) && HostLocIsXMM(from)) {
|
} else if (HostLocIsSpill(to) && HostLocIsXMM(from)) {
|
||||||
Xbyak::Address spill_addr = spill_to_addr(to);
|
const Xbyak::Address spill_addr = spill_to_addr(to);
|
||||||
ASSERT(spill_addr.getBit() >= bit_width);
|
ASSERT(spill_addr.getBit() >= bit_width);
|
||||||
switch (bit_width) {
|
switch (bit_width) {
|
||||||
case 128:
|
case 128:
|
||||||
|
|
Loading…
Reference in a new issue