diff --git a/src/backend_x64/emit_x64.cpp b/src/backend_x64/emit_x64.cpp index 3e824b79..c0e7d569 100644 --- a/src/backend_x64/emit_x64.cpp +++ b/src/backend_x64/emit_x64.cpp @@ -87,6 +87,11 @@ CodePtr EmitX64::Emit(const Arm::LocationDescriptor descriptor, Dynarmic::IR::Bl 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) { Arm::Reg reg = inst->GetArg(0).GetRegRef(); X64Reg result = reg_alloc.DefRegister(inst); diff --git a/src/backend_x64/emit_x64.h b/src/backend_x64/emit_x64.h index 7eeb96dd..30b43df5 100644 --- a/src/backend_x64/emit_x64.h +++ b/src/backend_x64/emit_x64.h @@ -34,6 +34,7 @@ public: private: // Microinstruction emitters + void EmitIdentity(IR::Block& block, IR::Inst* inst); void EmitGetRegister(IR::Block& block, IR::Inst* inst); void EmitSetRegister(IR::Block& block, IR::Inst* inst); void EmitGetNFlag(IR::Block& block, IR::Inst* inst); diff --git a/src/frontend/ir/ir.cpp b/src/frontend/ir/ir.cpp index f3a6d10b..fef77010 100644 --- a/src/frontend/ir/ir.cpp +++ b/src/frontend/ir/ir.cpp @@ -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) { value.GetInst()->use_count++; diff --git a/src/frontend/ir/ir.h b/src/frontend/ir/ir.h index 50d10e2c..9c8670ab 100644 --- a/src/frontend/ir/ir.h +++ b/src/frontend/ir/ir.h @@ -148,6 +148,8 @@ public: void Invalidate(); + void ReplaceUsesWith(Value& replacement); + size_t use_count = 0; Inst* carry_inst = nullptr; Inst* overflow_inst = nullptr; diff --git a/src/frontend/ir/opcodes.inc b/src/frontend/ir/opcodes.inc index 9f440384..ad75a8e6 100644 --- a/src/frontend/ir/opcodes.inc +++ b/src/frontend/ir/opcodes.inc @@ -1,5 +1,7 @@ // opcode name, return type, arg1 type, arg2 type, arg3 type, ... +OPCODE(Identity, T::Opaque, T::Opaque ) + // ARM Context getters/setters OPCODE(GetRegister, T::U32, T::RegRef ) OPCODE(SetRegister, T::Void, T::RegRef, T::U32 ) diff --git a/src/ir_opt/get_set_elimination_pass.cpp b/src/ir_opt/get_set_elimination_pass.cpp index 0ca26337..3ac3943b 100644 --- a/src/ir_opt/get_set_elimination_pass.cpp +++ b/src/ir_opt/get_set_elimination_pass.cpp @@ -12,10 +12,9 @@ namespace Dynarmic { namespace Optimization { void GetSetElimination(IR::Block& block) { -#if 0 using Iterator = decltype(block.instructions.begin()); struct RegisterInfo { - IR::ValuePtr register_value = nullptr; + IR::Value register_value; bool set_instruction_present = false; Iterator last_set_instruction; }; @@ -25,9 +24,9 @@ void GetSetElimination(IR::Block& block) { RegisterInfo c_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) { - (*info.last_set_instruction)->Invalidate(); + info.last_set_instruction->Invalidate(); 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) { - if (!info.register_value) { - info.register_value = *get_inst; + if (info.register_value.IsEmpty()) { + info.register_value = IR::Value(&*get_inst); return; } - (*get_inst)->ReplaceUsesWith(info.register_value); + get_inst->ReplaceUsesWith(info.register_value); }; - for (auto iter = block.instructions.begin(); iter != block.instructions.end(); ++iter) { - switch ((*iter)->GetOpcode()) { + for (auto inst = block.instructions.begin(); inst != block.instructions.end(); ++inst) { + switch (inst->GetOpcode()) { case IR::Opcode::SetRegister: { - auto inst = reinterpret_cast((*iter).get()); - Arm::Reg reg = reinterpret_cast(inst->GetArg(0).get())->value; + Arm::Reg reg = inst->GetArg(0).GetRegRef(); if (reg == Arm::Reg::PC) break; size_t reg_index = static_cast(reg); - do_set(reg_info[reg_index], inst->GetArg(1), iter); + do_set(reg_info[reg_index], inst->GetArg(1), inst); break; } case IR::Opcode::GetRegister: { - auto inst = reinterpret_cast((*iter).get()); - Arm::Reg reg = reinterpret_cast(inst->GetArg(0).get())->value; + Arm::Reg reg = inst->GetArg(0).GetRegRef(); ASSERT(reg != Arm::Reg::PC); size_t reg_index = static_cast(reg); - do_get(reg_info[reg_index], iter); + do_get(reg_info[reg_index], inst); break; } case IR::Opcode::SetNFlag: { - auto inst = reinterpret_cast((*iter).get()); - do_set(n_info, inst->GetArg(0), iter); + do_set(n_info, inst->GetArg(0), inst); break; } case IR::Opcode::GetNFlag: { - do_get(n_info, iter); + do_get(n_info, inst); break; } case IR::Opcode::SetZFlag: { - auto inst = reinterpret_cast((*iter).get()); - do_set(z_info, inst->GetArg(0), iter); + do_set(z_info, inst->GetArg(0), inst); break; } case IR::Opcode::GetZFlag: { - do_get(z_info, iter); + do_get(z_info, inst); break; } case IR::Opcode::SetCFlag: { - auto inst = reinterpret_cast((*iter).get()); - do_set(c_info, inst->GetArg(0), iter); + do_set(c_info, inst->GetArg(0), inst); break; } case IR::Opcode::GetCFlag: { - do_get(c_info, iter); + do_get(c_info, inst); break; } case IR::Opcode::SetVFlag: { - auto inst = reinterpret_cast((*iter).get()); - do_set(v_info, inst->GetArg(0), iter); + do_set(v_info, inst->GetArg(0), inst); break; } case IR::Opcode::GetVFlag: { - do_get(v_info, iter); + do_get(v_info, inst); break; } default: break; } } -#endif } } // namespace Optimization