IROpt: Port get/set elimination pass to current IR
This commit is contained in:
parent
e60cea3a54
commit
be87038ffd
6 changed files with 42 additions and 28 deletions
|
@ -87,6 +87,11 @@ CodePtr EmitX64::Emit(const Arm::LocationDescriptor descriptor, Dynarmic::IR::Bl
|
||||||
return code_ptr;
|
return code_ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void EmitX64::EmitIdentity(IR::Block& block, IR::Inst* inst) {
|
||||||
|
// TODO: Possible unnecessary mov here.
|
||||||
|
reg_alloc.UseDefRegister(inst->GetArg(0), inst);
|
||||||
|
}
|
||||||
|
|
||||||
void EmitX64::EmitGetRegister(IR::Block&, IR::Inst* inst) {
|
void EmitX64::EmitGetRegister(IR::Block&, IR::Inst* inst) {
|
||||||
Arm::Reg reg = inst->GetArg(0).GetRegRef();
|
Arm::Reg reg = inst->GetArg(0).GetRegRef();
|
||||||
X64Reg result = reg_alloc.DefRegister(inst);
|
X64Reg result = reg_alloc.DefRegister(inst);
|
||||||
|
|
|
@ -34,6 +34,7 @@ public:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Microinstruction emitters
|
// Microinstruction emitters
|
||||||
|
void EmitIdentity(IR::Block& block, IR::Inst* inst);
|
||||||
void EmitGetRegister(IR::Block& block, IR::Inst* inst);
|
void EmitGetRegister(IR::Block& block, IR::Inst* inst);
|
||||||
void EmitSetRegister(IR::Block& block, IR::Inst* inst);
|
void EmitSetRegister(IR::Block& block, IR::Inst* inst);
|
||||||
void EmitGetNFlag(IR::Block& block, IR::Inst* inst);
|
void EmitGetNFlag(IR::Block& block, IR::Inst* inst);
|
||||||
|
|
|
@ -87,6 +87,18 @@ void Inst::Invalidate() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Inst::ReplaceUsesWith(Value& replacement) {
|
||||||
|
Invalidate();
|
||||||
|
|
||||||
|
op = Opcode::Identity;
|
||||||
|
|
||||||
|
if (!replacement.IsImmediate()) {
|
||||||
|
Use(replacement);
|
||||||
|
}
|
||||||
|
|
||||||
|
args[0] = replacement;
|
||||||
|
}
|
||||||
|
|
||||||
void Inst::Use(Value& value) {
|
void Inst::Use(Value& value) {
|
||||||
value.GetInst()->use_count++;
|
value.GetInst()->use_count++;
|
||||||
|
|
||||||
|
|
|
@ -148,6 +148,8 @@ public:
|
||||||
|
|
||||||
void Invalidate();
|
void Invalidate();
|
||||||
|
|
||||||
|
void ReplaceUsesWith(Value& replacement);
|
||||||
|
|
||||||
size_t use_count = 0;
|
size_t use_count = 0;
|
||||||
Inst* carry_inst = nullptr;
|
Inst* carry_inst = nullptr;
|
||||||
Inst* overflow_inst = nullptr;
|
Inst* overflow_inst = nullptr;
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
// opcode name, return type, arg1 type, arg2 type, arg3 type, ...
|
// opcode name, return type, arg1 type, arg2 type, arg3 type, ...
|
||||||
|
|
||||||
|
OPCODE(Identity, T::Opaque, T::Opaque )
|
||||||
|
|
||||||
// ARM Context getters/setters
|
// ARM Context getters/setters
|
||||||
OPCODE(GetRegister, T::U32, T::RegRef )
|
OPCODE(GetRegister, T::U32, T::RegRef )
|
||||||
OPCODE(SetRegister, T::Void, T::RegRef, T::U32 )
|
OPCODE(SetRegister, T::Void, T::RegRef, T::U32 )
|
||||||
|
|
|
@ -12,10 +12,9 @@ namespace Dynarmic {
|
||||||
namespace Optimization {
|
namespace Optimization {
|
||||||
|
|
||||||
void GetSetElimination(IR::Block& block) {
|
void GetSetElimination(IR::Block& block) {
|
||||||
#if 0
|
|
||||||
using Iterator = decltype(block.instructions.begin());
|
using Iterator = decltype(block.instructions.begin());
|
||||||
struct RegisterInfo {
|
struct RegisterInfo {
|
||||||
IR::ValuePtr register_value = nullptr;
|
IR::Value register_value;
|
||||||
bool set_instruction_present = false;
|
bool set_instruction_present = false;
|
||||||
Iterator last_set_instruction;
|
Iterator last_set_instruction;
|
||||||
};
|
};
|
||||||
|
@ -25,9 +24,9 @@ void GetSetElimination(IR::Block& block) {
|
||||||
RegisterInfo c_info;
|
RegisterInfo c_info;
|
||||||
RegisterInfo v_info;
|
RegisterInfo v_info;
|
||||||
|
|
||||||
const auto do_set = [&block](RegisterInfo& info, IR::ValuePtr value, Iterator set_inst) {
|
const auto do_set = [&block](RegisterInfo& info, IR::Value value, Iterator set_inst) {
|
||||||
if (info.set_instruction_present) {
|
if (info.set_instruction_present) {
|
||||||
(*info.last_set_instruction)->Invalidate();
|
info.last_set_instruction->Invalidate();
|
||||||
block.instructions.erase(info.last_set_instruction);
|
block.instructions.erase(info.last_set_instruction);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -37,73 +36,66 @@ void GetSetElimination(IR::Block& block) {
|
||||||
};
|
};
|
||||||
|
|
||||||
const auto do_get = [](RegisterInfo& info, Iterator get_inst) {
|
const auto do_get = [](RegisterInfo& info, Iterator get_inst) {
|
||||||
if (!info.register_value) {
|
if (info.register_value.IsEmpty()) {
|
||||||
info.register_value = *get_inst;
|
info.register_value = IR::Value(&*get_inst);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
(*get_inst)->ReplaceUsesWith(info.register_value);
|
get_inst->ReplaceUsesWith(info.register_value);
|
||||||
};
|
};
|
||||||
|
|
||||||
for (auto iter = block.instructions.begin(); iter != block.instructions.end(); ++iter) {
|
for (auto inst = block.instructions.begin(); inst != block.instructions.end(); ++inst) {
|
||||||
switch ((*iter)->GetOpcode()) {
|
switch (inst->GetOpcode()) {
|
||||||
case IR::Opcode::SetRegister: {
|
case IR::Opcode::SetRegister: {
|
||||||
auto inst = reinterpret_cast<IR::Inst*>((*iter).get());
|
Arm::Reg reg = inst->GetArg(0).GetRegRef();
|
||||||
Arm::Reg reg = reinterpret_cast<IR::ImmRegRef*>(inst->GetArg(0).get())->value;
|
|
||||||
if (reg == Arm::Reg::PC)
|
if (reg == Arm::Reg::PC)
|
||||||
break;
|
break;
|
||||||
size_t reg_index = static_cast<size_t>(reg);
|
size_t reg_index = static_cast<size_t>(reg);
|
||||||
do_set(reg_info[reg_index], inst->GetArg(1), iter);
|
do_set(reg_info[reg_index], inst->GetArg(1), inst);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case IR::Opcode::GetRegister: {
|
case IR::Opcode::GetRegister: {
|
||||||
auto inst = reinterpret_cast<IR::Inst*>((*iter).get());
|
Arm::Reg reg = inst->GetArg(0).GetRegRef();
|
||||||
Arm::Reg reg = reinterpret_cast<IR::ImmRegRef*>(inst->GetArg(0).get())->value;
|
|
||||||
ASSERT(reg != Arm::Reg::PC);
|
ASSERT(reg != Arm::Reg::PC);
|
||||||
size_t reg_index = static_cast<size_t>(reg);
|
size_t reg_index = static_cast<size_t>(reg);
|
||||||
do_get(reg_info[reg_index], iter);
|
do_get(reg_info[reg_index], inst);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case IR::Opcode::SetNFlag: {
|
case IR::Opcode::SetNFlag: {
|
||||||
auto inst = reinterpret_cast<IR::Inst*>((*iter).get());
|
do_set(n_info, inst->GetArg(0), inst);
|
||||||
do_set(n_info, inst->GetArg(0), iter);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case IR::Opcode::GetNFlag: {
|
case IR::Opcode::GetNFlag: {
|
||||||
do_get(n_info, iter);
|
do_get(n_info, inst);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case IR::Opcode::SetZFlag: {
|
case IR::Opcode::SetZFlag: {
|
||||||
auto inst = reinterpret_cast<IR::Inst*>((*iter).get());
|
do_set(z_info, inst->GetArg(0), inst);
|
||||||
do_set(z_info, inst->GetArg(0), iter);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case IR::Opcode::GetZFlag: {
|
case IR::Opcode::GetZFlag: {
|
||||||
do_get(z_info, iter);
|
do_get(z_info, inst);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case IR::Opcode::SetCFlag: {
|
case IR::Opcode::SetCFlag: {
|
||||||
auto inst = reinterpret_cast<IR::Inst*>((*iter).get());
|
do_set(c_info, inst->GetArg(0), inst);
|
||||||
do_set(c_info, inst->GetArg(0), iter);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case IR::Opcode::GetCFlag: {
|
case IR::Opcode::GetCFlag: {
|
||||||
do_get(c_info, iter);
|
do_get(c_info, inst);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case IR::Opcode::SetVFlag: {
|
case IR::Opcode::SetVFlag: {
|
||||||
auto inst = reinterpret_cast<IR::Inst*>((*iter).get());
|
do_set(v_info, inst->GetArg(0), inst);
|
||||||
do_set(v_info, inst->GetArg(0), iter);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case IR::Opcode::GetVFlag: {
|
case IR::Opcode::GetVFlag: {
|
||||||
do_get(v_info, iter);
|
do_get(v_info, inst);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Optimization
|
} // namespace Optimization
|
||||||
|
|
Loading…
Reference in a new issue