IROpt: Port get/set elimination pass to current IR

This commit is contained in:
MerryMage 2016-08-02 11:51:05 +01:00
parent e60cea3a54
commit be87038ffd
6 changed files with 42 additions and 28 deletions

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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