reg_alloc: New register allocation interface
This commit is contained in:
parent
13ac0c234e
commit
f883bad2cc
2 changed files with 127 additions and 0 deletions
|
@ -22,6 +22,8 @@ static u64 ImmediateToU64(const IR::Value& imm) {
|
||||||
return u64(imm.GetU1());
|
return u64(imm.GetU1());
|
||||||
case IR::Type::U8:
|
case IR::Type::U8:
|
||||||
return u64(imm.GetU8());
|
return u64(imm.GetU8());
|
||||||
|
case IR::Type::U16:
|
||||||
|
return u64(imm.GetU16());
|
||||||
case IR::Type::U32:
|
case IR::Type::U32:
|
||||||
return u64(imm.GetU32());
|
return u64(imm.GetU32());
|
||||||
case IR::Type::U64:
|
case IR::Type::U64:
|
||||||
|
@ -80,6 +82,49 @@ static void EmitExchange(BlockOfCode* code, HostLoc a, HostLoc b) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
u8 Argument::GetImmediateU8() const {
|
||||||
|
u64 imm = ImmediateToU64(value);
|
||||||
|
ASSERT(imm < 0x100);
|
||||||
|
return u8(imm);
|
||||||
|
}
|
||||||
|
|
||||||
|
u16 Argument::GetImmediateU16() const {
|
||||||
|
u64 imm = ImmediateToU64(value);
|
||||||
|
ASSERT(imm < 0x10000);
|
||||||
|
return u16(imm);
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 Argument::GetImmediateU32() const {
|
||||||
|
u64 imm = ImmediateToU64(value);
|
||||||
|
ASSERT(imm < 0x100000000);
|
||||||
|
return u32(imm);
|
||||||
|
}
|
||||||
|
|
||||||
|
u64 Argument::GetImmediateU64() const {
|
||||||
|
return ImmediateToU64(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Argument::IsInGpr() const {
|
||||||
|
return HostLocIsGPR(*reg_alloc.ValueLocation(value.GetInst()));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Argument::IsInXmm() const {
|
||||||
|
return HostLocIsXMM(*reg_alloc.ValueLocation(value.GetInst()));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Argument::IsInMemory() const {
|
||||||
|
return HostLocIsSpill(*reg_alloc.ValueLocation(value.GetInst()));
|
||||||
|
}
|
||||||
|
|
||||||
|
std::array<Argument, 3> RegAlloc::GetArgumentInfo(IR::Inst* inst) {
|
||||||
|
std::array<Argument, 3> ret = { Argument{*this}, Argument{*this}, Argument{*this}};
|
||||||
|
for (size_t i = 0; i < inst->NumArgs(); i++) {
|
||||||
|
IR::Value arg = inst->GetArg(i);
|
||||||
|
ret[i].value = arg;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
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(!ValueLocation(def_inst), "def_inst has already been defined");
|
DEBUG_ASSERT_MSG(!ValueLocation(def_inst), "def_inst has already been defined");
|
||||||
|
|
||||||
|
|
|
@ -22,6 +22,8 @@
|
||||||
namespace Dynarmic {
|
namespace Dynarmic {
|
||||||
namespace BackendX64 {
|
namespace BackendX64 {
|
||||||
|
|
||||||
|
class RegAlloc;
|
||||||
|
|
||||||
struct HostLocInfo {
|
struct HostLocInfo {
|
||||||
public:
|
public:
|
||||||
bool IsLocked() const {
|
bool IsLocked() const {
|
||||||
|
@ -65,10 +67,88 @@ private:
|
||||||
bool is_scratch = false;
|
bool is_scratch = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct Argument {
|
||||||
|
public:
|
||||||
|
IR::Type GetType() const {
|
||||||
|
return value.GetType();
|
||||||
|
}
|
||||||
|
bool IsImmediate() const {
|
||||||
|
return value.IsImmediate();
|
||||||
|
}
|
||||||
|
|
||||||
|
u8 GetImmediateU8() const;
|
||||||
|
u16 GetImmediateU16() const;
|
||||||
|
u32 GetImmediateU32() const;
|
||||||
|
u64 GetImmediateU64() const;
|
||||||
|
|
||||||
|
/// Is this value currently in a GPR?
|
||||||
|
bool IsInGpr() const;
|
||||||
|
/// Is this value currently in a XMM?
|
||||||
|
bool IsInXmm() const;
|
||||||
|
/// Is this value currently in memory?
|
||||||
|
bool IsInMemory() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
friend class RegAlloc;
|
||||||
|
Argument(RegAlloc& reg_alloc) : reg_alloc(reg_alloc) {}
|
||||||
|
|
||||||
|
bool allocated = false;
|
||||||
|
RegAlloc& reg_alloc;
|
||||||
|
IR::Value value;
|
||||||
|
};
|
||||||
|
|
||||||
class RegAlloc final {
|
class RegAlloc final {
|
||||||
public:
|
public:
|
||||||
explicit RegAlloc(BlockOfCode* code) : code(code) {}
|
explicit RegAlloc(BlockOfCode* code) : code(code) {}
|
||||||
|
|
||||||
|
std::array<Argument, 3> GetArgumentInfo(IR::Inst* inst);
|
||||||
|
|
||||||
|
Xbyak::Reg64 UseGpr(Argument& arg) {
|
||||||
|
ASSERT(!arg.allocated);
|
||||||
|
arg.allocated = true;
|
||||||
|
return HostLocToReg64(UseHostLocReg(arg.value, any_gpr));
|
||||||
|
}
|
||||||
|
Xbyak::Xmm UseXmm(Argument& arg) {
|
||||||
|
ASSERT(!arg.allocated);
|
||||||
|
arg.allocated = true;
|
||||||
|
return HostLocToXmm(UseHostLocReg(arg.value, any_xmm));
|
||||||
|
}
|
||||||
|
void Use(Argument& arg, HostLoc host_loc) {
|
||||||
|
ASSERT(!arg.allocated);
|
||||||
|
arg.allocated = true;
|
||||||
|
UseHostLocReg(arg.value, {host_loc});
|
||||||
|
}
|
||||||
|
|
||||||
|
Xbyak::Reg64 UseScratchGpr(Argument& arg) {
|
||||||
|
ASSERT(!arg.allocated);
|
||||||
|
arg.allocated = true;
|
||||||
|
return HostLocToReg64(UseScratchHostLocReg(arg.value, any_gpr));
|
||||||
|
}
|
||||||
|
Xbyak::Xmm UseScratchXmm(Argument& arg) {
|
||||||
|
ASSERT(!arg.allocated);
|
||||||
|
arg.allocated = true;
|
||||||
|
return HostLocToXmm(UseScratchHostLocReg(arg.value, any_xmm));
|
||||||
|
}
|
||||||
|
void UseScratch(Argument& arg, HostLoc host_loc) {
|
||||||
|
ASSERT(!arg.allocated);
|
||||||
|
arg.allocated = true;
|
||||||
|
UseScratchHostLocReg(arg.value, {host_loc});
|
||||||
|
}
|
||||||
|
|
||||||
|
void DefineValue(IR::Inst* inst, const Xbyak::Reg64& reg) {
|
||||||
|
HostLoc hostloc = static_cast<HostLoc>(reg.getIdx() + static_cast<size_t>(HostLoc::RAX));
|
||||||
|
DefineValue(inst, hostloc);
|
||||||
|
}
|
||||||
|
void DefineValue(IR::Inst* inst, const Xbyak::Xmm& reg) {
|
||||||
|
HostLoc hostloc = static_cast<HostLoc>(reg.getIdx() + static_cast<size_t>(HostLoc::XMM0));
|
||||||
|
DefineValue(inst, hostloc);
|
||||||
|
}
|
||||||
|
void DefineValue(IR::Inst* inst, Argument& arg) {
|
||||||
|
ASSERT(!arg.allocated);
|
||||||
|
arg.allocated = true;
|
||||||
|
RegisterAddDef(inst, arg.value);
|
||||||
|
}
|
||||||
|
|
||||||
/// Late-def
|
/// Late-def
|
||||||
Xbyak::Reg64 DefGpr(IR::Inst* def_inst, HostLocList desired_locations = any_gpr) {
|
Xbyak::Reg64 DefGpr(IR::Inst* def_inst, HostLocList desired_locations = any_gpr) {
|
||||||
HostLoc location = ScratchHostLocReg(desired_locations);
|
HostLoc location = ScratchHostLocReg(desired_locations);
|
||||||
|
@ -139,6 +219,8 @@ public:
|
||||||
void Reset();
|
void Reset();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
friend struct Argument;
|
||||||
|
|
||||||
HostLoc SelectARegister(HostLocList desired_locations) const;
|
HostLoc SelectARegister(HostLocList desired_locations) const;
|
||||||
boost::optional<HostLoc> ValueLocation(const IR::Inst* value) const;
|
boost::optional<HostLoc> ValueLocation(const IR::Inst* value) const;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue