reg_alloc: New register allocation interface

This commit is contained in:
MerryMage 2017-02-24 21:09:12 +00:00
parent 13ac0c234e
commit f883bad2cc
2 changed files with 127 additions and 0 deletions

View file

@ -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");

View file

@ -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;