ir_opt: Split off A32 specific passes
This commit is contained in:
parent
595f157e5e
commit
72a793f5b0
8 changed files with 95 additions and 60 deletions
|
@ -87,9 +87,10 @@ add_library(dynarmic
|
||||||
frontend/ir/terminal.h
|
frontend/ir/terminal.h
|
||||||
frontend/ir/value.cpp
|
frontend/ir/value.cpp
|
||||||
frontend/ir/value.h
|
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/constant_propagation_pass.cpp
|
||||||
ir_opt/dead_code_elimination_pass.cpp
|
ir_opt/dead_code_elimination_pass.cpp
|
||||||
ir_opt/get_set_elimination_pass.cpp
|
|
||||||
ir_opt/passes.h
|
ir_opt/passes.h
|
||||||
ir_opt/verification_pass.cpp
|
ir_opt/verification_pass.cpp
|
||||||
)
|
)
|
||||||
|
|
|
@ -160,9 +160,10 @@ private:
|
||||||
}
|
}
|
||||||
|
|
||||||
IR::Block ir_block = A32::Translate(A32::LocationDescriptor{descriptor}, callbacks.memory.ReadCode);
|
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::DeadCodeElimination(ir_block);
|
||||||
Optimization::ConstantPropagation(ir_block, callbacks.memory);
|
Optimization::A32ConstantMemoryReads(ir_block, callbacks.memory);
|
||||||
|
Optimization::ConstantPropagation(ir_block);
|
||||||
Optimization::DeadCodeElimination(ir_block);
|
Optimization::DeadCodeElimination(ir_block);
|
||||||
Optimization::VerificationPass(ir_block);
|
Optimization::VerificationPass(ir_block);
|
||||||
return emitter.Emit(ir_block);
|
return emitter.Emit(ir_block);
|
||||||
|
|
77
src/ir_opt/a32_constant_memory_reads_pass.cpp
Normal file
77
src/ir_opt/a32_constant_memory_reads_pass.cpp
Normal file
|
@ -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 <dynarmic/A32/callbacks.h>
|
||||||
|
|
||||||
|
#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
|
|
@ -15,7 +15,7 @@
|
||||||
namespace Dynarmic {
|
namespace Dynarmic {
|
||||||
namespace Optimization {
|
namespace Optimization {
|
||||||
|
|
||||||
void GetSetElimination(IR::Block& block) {
|
void A32GetSetElimination(IR::Block& block) {
|
||||||
using Iterator = IR::Block::iterator;
|
using Iterator = IR::Block::iterator;
|
||||||
struct RegisterInfo {
|
struct RegisterInfo {
|
||||||
IR::Value register_value;
|
IR::Value register_value;
|
|
@ -13,16 +13,9 @@
|
||||||
namespace Dynarmic {
|
namespace Dynarmic {
|
||||||
namespace Optimization {
|
namespace Optimization {
|
||||||
|
|
||||||
void ConstantPropagation(IR::Block& block, const A32::UserCallbacks::Memory& memory_callbacks) {
|
void ConstantPropagation(IR::Block& block) {
|
||||||
for (auto& inst : block) {
|
for (auto& inst : block) {
|
||||||
switch (inst.GetOpcode()) {
|
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::LogicalShiftLeft32:
|
||||||
case IR::Opcode::LogicalShiftRight32:
|
case IR::Opcode::LogicalShiftRight32:
|
||||||
case IR::Opcode::ArithmeticShiftRight32:
|
case IR::Opcode::ArithmeticShiftRight32:
|
||||||
|
@ -41,50 +34,6 @@ void ConstantPropagation(IR::Block& block, const A32::UserCallbacks::Memory& mem
|
||||||
}
|
}
|
||||||
break;
|
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: {
|
case IR::Opcode::ZeroExtendByteToWord: {
|
||||||
if (!inst.AreAllArgsImmediates())
|
if (!inst.AreAllArgsImmediates())
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -17,8 +17,9 @@ class Block;
|
||||||
namespace Dynarmic {
|
namespace Dynarmic {
|
||||||
namespace Optimization {
|
namespace Optimization {
|
||||||
|
|
||||||
void GetSetElimination(IR::Block& block);
|
void A32GetSetElimination(IR::Block& block);
|
||||||
void ConstantPropagation(IR::Block& block, const A32::UserCallbacks::Memory& memory_callbacks);
|
void A32ConstantMemoryReads(IR::Block& block, const A32::UserCallbacks::Memory& memory_callbacks);
|
||||||
|
void ConstantPropagation(IR::Block& block);
|
||||||
void DeadCodeElimination(IR::Block& block);
|
void DeadCodeElimination(IR::Block& block);
|
||||||
void VerificationPass(const IR::Block& block);
|
void VerificationPass(const IR::Block& block);
|
||||||
|
|
||||||
|
|
|
@ -327,7 +327,10 @@ void FuzzJitArm(const size_t instruction_count, const size_t instructions_to_exe
|
||||||
while (num_insts < instructions_to_execute_count) {
|
while (num_insts < instructions_to_execute_count) {
|
||||||
Dynarmic::A32::LocationDescriptor descriptor = {u32(num_insts * 4), Dynarmic::A32::PSR{}, Dynarmic::A32::FPSCR{}};
|
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::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::DeadCodeElimination(ir_block);
|
||||||
Dynarmic::Optimization::VerificationPass(ir_block);
|
Dynarmic::Optimization::VerificationPass(ir_block);
|
||||||
printf("\n\nIR:\n%s", Dynarmic::IR::DumpBlock(ir_block).c_str());
|
printf("\n\nIR:\n%s", Dynarmic::IR::DumpBlock(ir_block).c_str());
|
||||||
|
|
|
@ -279,7 +279,10 @@ void FuzzJitThumb(const size_t instruction_count, const size_t instructions_to_e
|
||||||
while (num_insts < instructions_to_execute_count) {
|
while (num_insts < instructions_to_execute_count) {
|
||||||
Dynarmic::A32::LocationDescriptor descriptor = {u32(num_insts * 4), cpsr, Dynarmic::A32::FPSCR{}};
|
Dynarmic::A32::LocationDescriptor descriptor = {u32(num_insts * 4), cpsr, Dynarmic::A32::FPSCR{}};
|
||||||
Dynarmic::IR::Block ir_block = Dynarmic::A32::Translate(descriptor, &MemoryReadCode);
|
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::DeadCodeElimination(ir_block);
|
||||||
Dynarmic::Optimization::VerificationPass(ir_block);
|
Dynarmic::Optimization::VerificationPass(ir_block);
|
||||||
printf("\n\nIR:\n%s", Dynarmic::IR::DumpBlock(ir_block).c_str());
|
printf("\n\nIR:\n%s", Dynarmic::IR::DumpBlock(ir_block).c_str());
|
||||||
|
|
Loading…
Reference in a new issue