backend/A64/reg_alloc.cpp: cleanup

This commit is contained in:
SachinVin 2022-09-15 22:03:31 +05:30
parent 7f48f061d8
commit 2b761074d0
2 changed files with 27 additions and 40 deletions

View File

@ -1,7 +1,6 @@
/* This file is part of the dynarmic project. /* This file is part of the dynarmic project.
* Copyright (c) 2016 MerryMage * Copyright (c) 2016 MerryMage
* This software may be used and distributed according to the terms of the GNU * SPDX-License-Identifier: 0BSD
* General Public License version 2 or any later version.
*/ */
#include "dynarmic/backend/A64/reg_alloc.h" #include "dynarmic/backend/A64/reg_alloc.h"
@ -17,23 +16,6 @@
namespace Dynarmic::BackendA64 { namespace Dynarmic::BackendA64 {
static u64 ImmediateToU64(const IR::Value& imm) {
switch (imm.GetType()) {
case IR::Type::U1:
return u64(imm.GetU1());
case IR::Type::U8:
return u64(imm.GetU8());
case IR::Type::U16:
return u64(imm.GetU16());
case IR::Type::U32:
return u64(imm.GetU32());
case IR::Type::U64:
return u64(imm.GetU64());
default:
ASSERT_FALSE("This should never happen.");
}
}
static bool CanExchange(HostLoc a, HostLoc b) { static bool CanExchange(HostLoc a, HostLoc b) {
return HostLocIsGPR(a) && HostLocIsGPR(b); return HostLocIsGPR(a) && HostLocIsGPR(b);
} }
@ -51,10 +33,8 @@ static size_t GetBitWidth(IR::Type type) {
case IR::Type::Table: case IR::Type::Table:
case IR::Type::AccType: case IR::Type::AccType:
ASSERT_FALSE("Type {} cannot be represented at runtime", type); ASSERT_FALSE("Type {} cannot be represented at runtime", type);
return 0;
case IR::Type::Opaque: case IR::Type::Opaque:
ASSERT_FALSE("Not a concrete type"); ASSERT_FALSE("Not a concrete type");
return 0;
case IR::Type::U1: case IR::Type::U1:
return 8; return 8;
case IR::Type::U8: case IR::Type::U8:
@ -71,7 +51,6 @@ static size_t GetBitWidth(IR::Type type) {
return 32; // TODO: Update to 16 when flags optimization is done return 32; // TODO: Update to 16 when flags optimization is done
} }
UNREACHABLE(); UNREACHABLE();
return 0;
} }
static bool IsValuelessType(IR::Type type) { static bool IsValuelessType(IR::Type type) {
@ -171,14 +150,14 @@ bool Argument::IsVoid() const {
bool Argument::FitsInImmediateU32() const { bool Argument::FitsInImmediateU32() const {
if (!IsImmediate()) if (!IsImmediate())
return false; return false;
u64 imm = ImmediateToU64(value); const u64 imm = value.GetImmediateAsU64();
return imm < 0x100000000; return imm < 0x100000000;
} }
bool Argument::FitsInImmediateS32() const { bool Argument::FitsInImmediateS32() const {
if (!IsImmediate()) if (!IsImmediate())
return false; return false;
s64 imm = static_cast<s64>(ImmediateToU64(value)); const s64 imm = static_cast<s64>(value.GetImmediateAsU64());
return -s64(0x80000000) <= imm && imm <= s64(0x7FFFFFFF); return -s64(0x80000000) <= imm && imm <= s64(0x7FFFFFFF);
} }
@ -187,31 +166,30 @@ bool Argument::GetImmediateU1() const {
} }
u8 Argument::GetImmediateU8() const { u8 Argument::GetImmediateU8() const {
u64 imm = ImmediateToU64(value); const u64 imm = value.GetImmediateAsU64();
ASSERT(imm < 0x100); ASSERT(imm < 0x100);
return u8(imm); return u8(imm);
} }
u16 Argument::GetImmediateU16() const { u16 Argument::GetImmediateU16() const {
u64 imm = ImmediateToU64(value); const u64 imm = value.GetImmediateAsU64();
ASSERT(imm < 0x10000); ASSERT(imm < 0x10000);
return u16(imm); return u16(imm);
} }
u32 Argument::GetImmediateU32() const { u32 Argument::GetImmediateU32() const {
u64 imm = ImmediateToU64(value); const u64 imm = value.GetImmediateAsU64();
ASSERT(imm < 0x100000000); ASSERT(imm < 0x100000000);
return u32(imm); return u32(imm);
} }
u64 Argument::GetImmediateS32() const { u64 Argument::GetImmediateS32() const {
ASSERT(FitsInImmediateS32()); ASSERT(FitsInImmediateS32());
u64 imm = ImmediateToU64(value); return value.GetImmediateAsU64();
return imm;
} }
u64 Argument::GetImmediateU64() const { u64 Argument::GetImmediateU64() const {
return ImmediateToU64(value); return value.GetImmediateAsU64();
} }
IR::Cond Argument::GetImmediateCond() const { IR::Cond Argument::GetImmediateCond() const {
@ -219,6 +197,11 @@ IR::Cond Argument::GetImmediateCond() const {
return value.GetCond(); return value.GetCond();
} }
IR::AccType Argument::GetImmediateAccType() const {
ASSERT(IsImmediate() && GetType() == IR::Type::AccType);
return value.GetAccType();
}
bool Argument::IsInGpr() const { bool Argument::IsInGpr() const {
if (IsImmediate()) if (IsImmediate())
return false; return false;
@ -240,7 +223,7 @@ bool Argument::IsInMemory() const {
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++) {
const IR::Value& arg = inst->GetArg(i); const IR::Value arg = inst->GetArg(i);
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");
@ -374,7 +357,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;
@ -447,9 +430,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;
} }
@ -470,7 +455,7 @@ void RegAlloc::DefineValueImpl(IR::Inst* def_inst, const IR::Value& use_inst) {
} }
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);
} }
@ -479,14 +464,14 @@ HostLoc RegAlloc::LoadImmediate(IR::Value imm, HostLoc host_loc) {
if (HostLocIsGPR(host_loc)) { if (HostLocIsGPR(host_loc)) {
Arm64Gen::ARM64Reg reg = HostLocToReg64(host_loc); Arm64Gen::ARM64Reg reg = HostLocToReg64(host_loc);
u64 imm_value = ImmediateToU64(imm); u64 imm_value = imm.GetImmediateAsU64();
code.MOVI2R(reg, imm_value); code.MOVI2R(reg, imm_value);
return host_loc; return host_loc;
} }
if (HostLocIsFPR(host_loc)) { if (HostLocIsFPR(host_loc)) {
Arm64Gen::ARM64Reg reg = Arm64Gen::EncodeRegToDouble(HostLocToFpr(host_loc)); Arm64Gen::ARM64Reg reg = Arm64Gen::EncodeRegToDouble(HostLocToFpr(host_loc));
u64 imm_value = ImmediateToU64(imm); u64 imm_value = imm.GetImmediateAsU64();
if (imm_value == 0) if (imm_value == 0)
code.fp_emitter.FMOV(reg, 0); code.fp_emitter.FMOV(reg, 0);
else { else {
@ -551,15 +536,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_FALSE("All spill locations are full"); ASSERT_FALSE("All spill locations are full");

View File

@ -74,6 +74,7 @@ public:
u64 GetImmediateS32() const; u64 GetImmediateS32() const;
u64 GetImmediateU64() const; u64 GetImmediateU64() const;
IR::Cond GetImmediateCond() const; IR::Cond GetImmediateCond() const;
IR::AccType GetImmediateAccType() const;
/// Is this value currently in a GPR? /// Is this value currently in a GPR?
bool IsInGpr() const; bool IsInGpr() const;