From 72a793f5b009a8c959b88c87d8319db741b111a2 Mon Sep 17 00:00:00 2001 From: MerryMage Date: Wed, 10 Jan 2018 19:24:19 +0000 Subject: [PATCH] ir_opt: Split off A32 specific passes --- src/CMakeLists.txt | 3 +- src/backend_x64/a32_interface.cpp | 5 +- src/ir_opt/a32_constant_memory_reads_pass.cpp | 77 +++++++++++++++++++ ...s.cpp => a32_get_set_elimination_pass.cpp} | 2 +- src/ir_opt/constant_propagation_pass.cpp | 53 +------------ src/ir_opt/passes.h | 5 +- tests/A32/fuzz_arm.cpp | 5 +- tests/A32/fuzz_thumb.cpp | 5 +- 8 files changed, 95 insertions(+), 60 deletions(-) create mode 100644 src/ir_opt/a32_constant_memory_reads_pass.cpp rename src/ir_opt/{get_set_elimination_pass.cpp => a32_get_set_elimination_pass.cpp} (99%) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 5c28bf3a..09475fcd 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -87,9 +87,10 @@ add_library(dynarmic frontend/ir/terminal.h frontend/ir/value.cpp frontend/ir/value.h + ir_opt/a32_constant_memory_reads_pass.cpp + ir_opt/a32_get_set_elimination_pass.cpp ir_opt/constant_propagation_pass.cpp ir_opt/dead_code_elimination_pass.cpp - ir_opt/get_set_elimination_pass.cpp ir_opt/passes.h ir_opt/verification_pass.cpp ) diff --git a/src/backend_x64/a32_interface.cpp b/src/backend_x64/a32_interface.cpp index 5e127e7d..e5739aad 100644 --- a/src/backend_x64/a32_interface.cpp +++ b/src/backend_x64/a32_interface.cpp @@ -160,9 +160,10 @@ private: } IR::Block ir_block = A32::Translate(A32::LocationDescriptor{descriptor}, callbacks.memory.ReadCode); - Optimization::GetSetElimination(ir_block); + Optimization::A32GetSetElimination(ir_block); Optimization::DeadCodeElimination(ir_block); - Optimization::ConstantPropagation(ir_block, callbacks.memory); + Optimization::A32ConstantMemoryReads(ir_block, callbacks.memory); + Optimization::ConstantPropagation(ir_block); Optimization::DeadCodeElimination(ir_block); Optimization::VerificationPass(ir_block); return emitter.Emit(ir_block); diff --git a/src/ir_opt/a32_constant_memory_reads_pass.cpp b/src/ir_opt/a32_constant_memory_reads_pass.cpp new file mode 100644 index 00000000..41bd4364 --- /dev/null +++ b/src/ir_opt/a32_constant_memory_reads_pass.cpp @@ -0,0 +1,77 @@ +/* This file is part of the dynarmic project. + * Copyright (c) 2016 MerryMage + * This software may be used and distributed according to the terms of the GNU + * General Public License version 2 or any later version. + */ + +#include + +#include "frontend/ir/basic_block.h" +#include "frontend/ir/opcodes.h" +#include "ir_opt/passes.h" + +namespace Dynarmic { +namespace Optimization { + +void A32ConstantMemoryReads(IR::Block& block, const A32::UserCallbacks::Memory& memory_callbacks) { + for (auto& inst : block) { + switch (inst.GetOpcode()) { + case IR::Opcode::A32SetCFlag: { + IR::Value arg = inst.GetArg(0); + if (!arg.IsImmediate() && arg.GetInst()->GetOpcode() == IR::Opcode::A32GetCFlag) { + inst.Invalidate(); + } + break; + } + case IR::Opcode::A32ReadMemory8: { + if (!inst.AreAllArgsImmediates()) + break; + + u32 vaddr = inst.GetArg(0).GetU32(); + if (memory_callbacks.IsReadOnlyMemory(vaddr)) { + u8 value_from_memory = memory_callbacks.Read8(vaddr); + inst.ReplaceUsesWith(IR::Value{value_from_memory}); + } + break; + } + case IR::Opcode::A32ReadMemory16: { + if (!inst.AreAllArgsImmediates()) + break; + + u32 vaddr = inst.GetArg(0).GetU32(); + if (memory_callbacks.IsReadOnlyMemory(vaddr)) { + u16 value_from_memory = memory_callbacks.Read16(vaddr); + inst.ReplaceUsesWith(IR::Value{value_from_memory}); + } + break; + } + case IR::Opcode::A32ReadMemory32: { + if (!inst.AreAllArgsImmediates()) + break; + + u32 vaddr = inst.GetArg(0).GetU32(); + if (memory_callbacks.IsReadOnlyMemory(vaddr)) { + u32 value_from_memory = memory_callbacks.Read32(vaddr); + inst.ReplaceUsesWith(IR::Value{value_from_memory}); + } + break; + } + case IR::Opcode::A32ReadMemory64: { + if (!inst.AreAllArgsImmediates()) + break; + + u32 vaddr = inst.GetArg(0).GetU32(); + if (memory_callbacks.IsReadOnlyMemory(vaddr)) { + u64 value_from_memory = memory_callbacks.Read64(vaddr); + inst.ReplaceUsesWith(IR::Value{value_from_memory}); + } + break; + } + default: + break; + } + } +} + +} // namespace Optimization +} // namespace Dynarmic diff --git a/src/ir_opt/get_set_elimination_pass.cpp b/src/ir_opt/a32_get_set_elimination_pass.cpp similarity index 99% rename from src/ir_opt/get_set_elimination_pass.cpp rename to src/ir_opt/a32_get_set_elimination_pass.cpp index 1a6622ba..8ddc1134 100644 --- a/src/ir_opt/get_set_elimination_pass.cpp +++ b/src/ir_opt/a32_get_set_elimination_pass.cpp @@ -15,7 +15,7 @@ namespace Dynarmic { namespace Optimization { -void GetSetElimination(IR::Block& block) { +void A32GetSetElimination(IR::Block& block) { using Iterator = IR::Block::iterator; struct RegisterInfo { IR::Value register_value; diff --git a/src/ir_opt/constant_propagation_pass.cpp b/src/ir_opt/constant_propagation_pass.cpp index 07c15971..0ab8d63b 100644 --- a/src/ir_opt/constant_propagation_pass.cpp +++ b/src/ir_opt/constant_propagation_pass.cpp @@ -13,16 +13,9 @@ namespace Dynarmic { namespace Optimization { -void ConstantPropagation(IR::Block& block, const A32::UserCallbacks::Memory& memory_callbacks) { +void ConstantPropagation(IR::Block& block) { for (auto& inst : block) { switch (inst.GetOpcode()) { - case IR::Opcode::A32SetCFlag: { - IR::Value arg = inst.GetArg(0); - if (!arg.IsImmediate() && arg.GetInst()->GetOpcode() == IR::Opcode::A32GetCFlag) { - inst.Invalidate(); - } - break; - } case IR::Opcode::LogicalShiftLeft32: case IR::Opcode::LogicalShiftRight32: case IR::Opcode::ArithmeticShiftRight32: @@ -41,50 +34,6 @@ void ConstantPropagation(IR::Block& block, const A32::UserCallbacks::Memory& mem } break; } - case IR::Opcode::A32ReadMemory8: { - if (!inst.AreAllArgsImmediates()) - break; - - u32 vaddr = inst.GetArg(0).GetU32(); - if (memory_callbacks.IsReadOnlyMemory(vaddr)) { - u8 value_from_memory = memory_callbacks.Read8(vaddr); - inst.ReplaceUsesWith(IR::Value{value_from_memory}); - } - break; - } - case IR::Opcode::A32ReadMemory16: { - if (!inst.AreAllArgsImmediates()) - break; - - u32 vaddr = inst.GetArg(0).GetU32(); - if (memory_callbacks.IsReadOnlyMemory(vaddr)) { - u16 value_from_memory = memory_callbacks.Read16(vaddr); - inst.ReplaceUsesWith(IR::Value{value_from_memory}); - } - break; - } - case IR::Opcode::A32ReadMemory32: { - if (!inst.AreAllArgsImmediates()) - break; - - u32 vaddr = inst.GetArg(0).GetU32(); - if (memory_callbacks.IsReadOnlyMemory(vaddr)) { - u32 value_from_memory = memory_callbacks.Read32(vaddr); - inst.ReplaceUsesWith(IR::Value{value_from_memory}); - } - break; - } - case IR::Opcode::A32ReadMemory64: { - if (!inst.AreAllArgsImmediates()) - break; - - u32 vaddr = inst.GetArg(0).GetU32(); - if (memory_callbacks.IsReadOnlyMemory(vaddr)) { - u64 value_from_memory = memory_callbacks.Read64(vaddr); - inst.ReplaceUsesWith(IR::Value{value_from_memory}); - } - break; - } case IR::Opcode::ZeroExtendByteToWord: { if (!inst.AreAllArgsImmediates()) break; diff --git a/src/ir_opt/passes.h b/src/ir_opt/passes.h index 9a69fd3c..d94be7ad 100644 --- a/src/ir_opt/passes.h +++ b/src/ir_opt/passes.h @@ -17,8 +17,9 @@ class Block; namespace Dynarmic { namespace Optimization { -void GetSetElimination(IR::Block& block); -void ConstantPropagation(IR::Block& block, const A32::UserCallbacks::Memory& memory_callbacks); +void A32GetSetElimination(IR::Block& block); +void A32ConstantMemoryReads(IR::Block& block, const A32::UserCallbacks::Memory& memory_callbacks); +void ConstantPropagation(IR::Block& block); void DeadCodeElimination(IR::Block& block); void VerificationPass(const IR::Block& block); diff --git a/tests/A32/fuzz_arm.cpp b/tests/A32/fuzz_arm.cpp index d1fd1eba..79dd5d68 100644 --- a/tests/A32/fuzz_arm.cpp +++ b/tests/A32/fuzz_arm.cpp @@ -327,7 +327,10 @@ void FuzzJitArm(const size_t instruction_count, const size_t instructions_to_exe while (num_insts < instructions_to_execute_count) { Dynarmic::A32::LocationDescriptor descriptor = {u32(num_insts * 4), Dynarmic::A32::PSR{}, Dynarmic::A32::FPSCR{}}; Dynarmic::IR::Block ir_block = Dynarmic::A32::Translate(descriptor, &MemoryReadCode); - Dynarmic::Optimization::GetSetElimination(ir_block); + Dynarmic::Optimization::A32GetSetElimination(ir_block); + Dynarmic::Optimization::DeadCodeElimination(ir_block); + Dynarmic::Optimization::A32ConstantMemoryReads(ir_block, GetUserCallbacks().memory); + Dynarmic::Optimization::ConstantPropagation(ir_block); Dynarmic::Optimization::DeadCodeElimination(ir_block); Dynarmic::Optimization::VerificationPass(ir_block); printf("\n\nIR:\n%s", Dynarmic::IR::DumpBlock(ir_block).c_str()); diff --git a/tests/A32/fuzz_thumb.cpp b/tests/A32/fuzz_thumb.cpp index 46c7eb70..96aae3e0 100644 --- a/tests/A32/fuzz_thumb.cpp +++ b/tests/A32/fuzz_thumb.cpp @@ -279,7 +279,10 @@ void FuzzJitThumb(const size_t instruction_count, const size_t instructions_to_e while (num_insts < instructions_to_execute_count) { Dynarmic::A32::LocationDescriptor descriptor = {u32(num_insts * 4), cpsr, Dynarmic::A32::FPSCR{}}; Dynarmic::IR::Block ir_block = Dynarmic::A32::Translate(descriptor, &MemoryReadCode); - Dynarmic::Optimization::GetSetElimination(ir_block); + Dynarmic::Optimization::A32GetSetElimination(ir_block); + Dynarmic::Optimization::DeadCodeElimination(ir_block); + Dynarmic::Optimization::A32ConstantMemoryReads(ir_block, GetUserCallbacks().memory); + Dynarmic::Optimization::ConstantPropagation(ir_block); Dynarmic::Optimization::DeadCodeElimination(ir_block); Dynarmic::Optimization::VerificationPass(ir_block); printf("\n\nIR:\n%s", Dynarmic::IR::DumpBlock(ir_block).c_str());