BackendX64/RegAlloc: Correct debugging asserts and correct UseDef behaviour for spill locations

This commit is contained in:
MerryMage 2016-08-05 18:40:28 +01:00
parent d2aeb56503
commit 742eeb8913

View file

@ -46,7 +46,7 @@ static Gen::OpArg SpillToOpArg(HostLoc loc) {
Gen::X64Reg RegAlloc::DefRegister(IR::Inst* def_inst, HostLocList desired_locations) { Gen::X64Reg RegAlloc::DefRegister(IR::Inst* def_inst, HostLocList desired_locations) {
DEBUG_ASSERT(std::all_of(desired_locations.begin(), desired_locations.end(), HostLocIsRegister)); DEBUG_ASSERT(std::all_of(desired_locations.begin(), desired_locations.end(), HostLocIsRegister));
DEBUG_ASSERT_MSG(!ValueLocations(def_inst), "def_inst has already been defined"); DEBUG_ASSERT_MSG(!ValueLocation(def_inst), "def_inst has already been defined");
HostLoc location = SelectARegister(desired_locations); HostLoc location = SelectARegister(desired_locations);
@ -62,14 +62,14 @@ Gen::X64Reg RegAlloc::DefRegister(IR::Inst* def_inst, HostLocList desired_locati
} }
void RegAlloc::RegisterAddDef(IR::Inst* def_inst, const IR::Value& use_inst) { void RegAlloc::RegisterAddDef(IR::Inst* def_inst, const IR::Value& use_inst) {
DEBUG_ASSERT_MSG(!ValueLocations(def_inst), "def_inst has already been defined"); DEBUG_ASSERT_MSG(!ValueLocation(def_inst), "def_inst has already been defined");
if (use_inst.IsImmediate()) { if (use_inst.IsImmediate()) {
LoadImmediateIntoRegister(use_inst, DefRegister(def_inst, any_gpr)); LoadImmediateIntoRegister(use_inst, DefRegister(def_inst, any_gpr));
return; return;
} }
DEBUG_ASSERT_MSG(ValueLocations(use_inst.GetInst()), "use_inst must already be defined"); DEBUG_ASSERT_MSG(ValueLocation(use_inst.GetInst()), "use_inst must already be defined");
HostLoc location = *ValueLocation(use_inst.GetInst()); HostLoc location = *ValueLocation(use_inst.GetInst());
LocInfo(location).values.emplace_back(def_inst); LocInfo(location).values.emplace_back(def_inst);
DecrementRemainingUses(use_inst.GetInst()); DecrementRemainingUses(use_inst.GetInst());
@ -86,8 +86,8 @@ Gen::X64Reg RegAlloc::UseDefRegister(IR::Value use_value, IR::Inst* def_inst, Ho
Gen::X64Reg RegAlloc::UseDefRegister(IR::Inst* use_inst, IR::Inst* def_inst, HostLocList desired_locations) { Gen::X64Reg RegAlloc::UseDefRegister(IR::Inst* use_inst, IR::Inst* def_inst, HostLocList desired_locations) {
DEBUG_ASSERT(std::all_of(desired_locations.begin(), desired_locations.end(), HostLocIsRegister)); DEBUG_ASSERT(std::all_of(desired_locations.begin(), desired_locations.end(), HostLocIsRegister));
DEBUG_ASSERT_MSG(ValueLocation(def_inst), "def_inst has already been defined"); DEBUG_ASSERT_MSG(!ValueLocation(def_inst), "def_inst has already been defined");
DEBUG_ASSERT_MSG(!ValueLocation(use_inst), "use_inst has not been defined"); DEBUG_ASSERT_MSG(ValueLocation(use_inst), "use_inst has not been defined");
if (IsLastUse(use_inst)) { if (IsLastUse(use_inst)) {
HostLoc current_location = *ValueLocation(use_inst); HostLoc current_location = *ValueLocation(use_inst);
@ -96,9 +96,20 @@ Gen::X64Reg RegAlloc::UseDefRegister(IR::Inst* use_inst, IR::Inst* def_inst, Hos
loc_info.is_being_used = true; loc_info.is_being_used = true;
loc_info.def = def_inst; loc_info.def = def_inst;
DEBUG_ASSERT(loc_info.IsUseDef()); DEBUG_ASSERT(loc_info.IsUseDef());
if (HostLocIsSpill(current_location)) {
HostLoc new_location = SelectARegister(desired_locations);
if (IsRegisterOccupied(new_location)) {
SpillRegister(new_location);
}
EmitMove(new_location, current_location);
LocInfo(new_location) = LocInfo(current_location);
LocInfo(current_location) = {};
return HostLocToX64(new_location);
} else {
return HostLocToX64(current_location); return HostLocToX64(current_location);
} }
} }
}
Gen::X64Reg use_reg = UseRegister(use_inst, any_gpr); Gen::X64Reg use_reg = UseRegister(use_inst, any_gpr);
Gen::X64Reg def_reg = DefRegister(def_inst, desired_locations); Gen::X64Reg def_reg = DefRegister(def_inst, desired_locations);
@ -108,8 +119,8 @@ Gen::X64Reg RegAlloc::UseDefRegister(IR::Inst* use_inst, IR::Inst* def_inst, Hos
std::tuple<Gen::OpArg, Gen::X64Reg> RegAlloc::UseDefOpArg(IR::Value use_value, IR::Inst* def_inst, HostLocList desired_locations) { std::tuple<Gen::OpArg, Gen::X64Reg> RegAlloc::UseDefOpArg(IR::Value use_value, IR::Inst* def_inst, HostLocList desired_locations) {
DEBUG_ASSERT(std::all_of(desired_locations.begin(), desired_locations.end(), HostLocIsRegister)); DEBUG_ASSERT(std::all_of(desired_locations.begin(), desired_locations.end(), HostLocIsRegister));
DEBUG_ASSERT_MSG(ValueLocation(def_inst), "def_inst has already been defined"); DEBUG_ASSERT_MSG(!ValueLocation(def_inst), "def_inst has already been defined");
DEBUG_ASSERT_MSG(!ValueLocation(use_inst), "use_inst has not been defined"); DEBUG_ASSERT_MSG(use_value.IsImmediate() || ValueLocation(use_value.GetInst()), "use_inst has not been defined");
if (!use_value.IsImmediate()) { if (!use_value.IsImmediate()) {
IR::Inst* use_inst = use_value.GetInst(); IR::Inst* use_inst = use_value.GetInst();
@ -118,6 +129,11 @@ std::tuple<Gen::OpArg, Gen::X64Reg> RegAlloc::UseDefOpArg(IR::Value use_value, I
HostLoc current_location = *ValueLocation(use_inst); HostLoc current_location = *ValueLocation(use_inst);
auto& loc_info = LocInfo(current_location); auto& loc_info = LocInfo(current_location);
if (!loc_info.IsIdle()) { if (!loc_info.IsIdle()) {
if (HostLocIsSpill(current_location)) {
loc_info.is_being_used = true;
DEBUG_ASSERT(loc_info.IsUse());
return std::make_tuple(SpillToOpArg(current_location), DefRegister(def_inst, desired_locations));
} else {
loc_info.is_being_used = true; loc_info.is_being_used = true;
loc_info.def = def_inst; loc_info.def = def_inst;
DEBUG_ASSERT(loc_info.IsUseDef()); DEBUG_ASSERT(loc_info.IsUseDef());
@ -125,6 +141,7 @@ std::tuple<Gen::OpArg, Gen::X64Reg> RegAlloc::UseDefOpArg(IR::Value use_value, I
} }
} }
} }
}
Gen::OpArg use_oparg = UseOpArg(use_value, any_gpr); Gen::OpArg use_oparg = UseOpArg(use_value, any_gpr);
Gen::X64Reg def_reg = DefRegister(def_inst, desired_locations); Gen::X64Reg def_reg = DefRegister(def_inst, desired_locations);
@ -309,9 +326,9 @@ boost::optional<HostLoc> RegAlloc::ValueLocation(IR::Inst* value) const {
for (size_t i = 0; i < HostLocCount; i++) for (size_t i = 0; i < HostLocCount; i++)
for (IR::Inst* v : hostloc_info[i].values) for (IR::Inst* v : hostloc_info[i].values)
if (v == value) if (v == value)
return {static_cast<HostLoc>(i)}; return boost::make_optional<HostLoc>(static_cast<HostLoc>(i));
return {}; return boost::none;
} }
bool RegAlloc::IsRegisterOccupied(HostLoc loc) const { bool RegAlloc::IsRegisterOccupied(HostLoc loc) const {
@ -428,7 +445,7 @@ std::tuple<HostLoc, bool> RegAlloc::UseHostLoc(IR::Inst* use_inst, HostLocList d
ASSERT(LocInfo(current_location).IsUse() || LocInfo(current_location).IsIdle()); ASSERT(LocInfo(current_location).IsUse() || LocInfo(current_location).IsIdle());
LocInfo(current_location).is_being_used = true; LocInfo(current_location).is_being_used = true;
DecrementRemainingUses(use_inst); DecrementRemainingUses(use_inst);
DEBUG_ASSERT(LocInfo(new_location).IsUse()); DEBUG_ASSERT(LocInfo(current_location).IsUse());
return std::make_tuple(current_location, was_being_used); return std::make_tuple(current_location, was_being_used);
} }
} }