backend/A64/reg_alloc.cpp: cleanup
This commit is contained in:
parent
7f48f061d8
commit
2b761074d0
@ -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");
|
||||||
|
@ -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;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user