From bbeea72ebab913fb0b3be8c74efc78b6215f238b Mon Sep 17 00:00:00 2001 From: MerryMage Date: Sat, 18 Feb 2017 21:46:36 +0000 Subject: [PATCH] ir_opt: Remove redundant shift instructions --- src/backend_x64/emit_x64.cpp | 7 ++-- src/frontend/ir/microinstruction.cpp | 1 + src/frontend/ir/opcodes.inc | 1 + src/ir_opt/constant_propagation_pass.cpp | 46 ++++++++++++++++++++++-- 4 files changed, 48 insertions(+), 7 deletions(-) diff --git a/src/backend_x64/emit_x64.cpp b/src/backend_x64/emit_x64.cpp index 64197be7..8ec41bf8 100644 --- a/src/backend_x64/emit_x64.cpp +++ b/src/backend_x64/emit_x64.cpp @@ -110,6 +110,9 @@ boost::optional EmitX64::GetBasicBlock(IR::LocationDes return boost::make_optional(iter->second); } +void EmitX64::EmitVoid(RegAlloc&, IR::Block&, IR::Inst*) { +} + void EmitX64::EmitBreakpoint(RegAlloc&, IR::Block&, IR::Inst*) { code->int3(); } @@ -546,7 +549,6 @@ void EmitX64::EmitLogicalShiftLeft(RegAlloc& reg_alloc, IR::Block& block, IR::In if (!carry_inst) { if (!inst->GetArg(2).IsImmediate()) { - // TODO: Remove redundant argument. inst->GetArg(2).GetInst()->DecrementRemainingUses(); } @@ -638,7 +640,6 @@ void EmitX64::EmitLogicalShiftRight(RegAlloc& reg_alloc, IR::Block& block, IR::I if (!carry_inst) { if (!inst->GetArg(2).IsImmediate()) { - // TODO: Remove redundant argument. inst->GetArg(2).GetInst()->DecrementRemainingUses(); } @@ -742,7 +743,6 @@ void EmitX64::EmitArithmeticShiftRight(RegAlloc& reg_alloc, IR::Block& block, IR if (!carry_inst) { if (!inst->GetArg(2).IsImmediate()) { - // TODO: Remove redundant argument. inst->GetArg(2).GetInst()->DecrementRemainingUses(); } @@ -824,7 +824,6 @@ void EmitX64::EmitRotateRight(RegAlloc& reg_alloc, IR::Block& block, IR::Inst* i if (!carry_inst) { if (!inst->GetArg(2).IsImmediate()) { - // TODO: Remove redundant argument. inst->GetArg(2).GetInst()->DecrementRemainingUses(); } diff --git a/src/frontend/ir/microinstruction.cpp b/src/frontend/ir/microinstruction.cpp index ee01729e..b5d89188 100644 --- a/src/frontend/ir/microinstruction.cpp +++ b/src/frontend/ir/microinstruction.cpp @@ -305,6 +305,7 @@ void Inst::Invalidate() { } value = {}; } + op = Opcode::Void; } void Inst::ReplaceUsesWith(Value replacement) { diff --git a/src/frontend/ir/opcodes.inc b/src/frontend/ir/opcodes.inc index 1d4c39fe..d6339799 100644 --- a/src/frontend/ir/opcodes.inc +++ b/src/frontend/ir/opcodes.inc @@ -1,5 +1,6 @@ // opcode name, return type, arg1 type, arg2 type, arg3 type, ... +OPCODE(Void, T::Void, ) OPCODE(Identity, T::Opaque, T::Opaque ) OPCODE(Breakpoint, T::Void, ) diff --git a/src/ir_opt/constant_propagation_pass.cpp b/src/ir_opt/constant_propagation_pass.cpp index cb925f9a..84fd5376 100644 --- a/src/ir_opt/constant_propagation_pass.cpp +++ b/src/ir_opt/constant_propagation_pass.cpp @@ -15,11 +15,36 @@ namespace Optimization { void ConstantPropagation(IR::Block& block, const UserCallbacks::Memory& memory_callbacks) { for (auto& inst : block) { - if (!inst.AreAllArgsImmediates()) - continue; - switch (inst.GetOpcode()) { + case IR::Opcode::SetCFlag: { + IR::Value arg = inst.GetArg(0); + if (!arg.IsImmediate() && arg.GetInst()->GetOpcode() == IR::Opcode::GetCFlag) { + inst.Invalidate(); + } + break; + } + case IR::Opcode::LogicalShiftLeft: + case IR::Opcode::LogicalShiftRight: + case IR::Opcode::ArithmeticShiftRight: + case IR::Opcode::RotateRight: { + if (!inst.GetAssociatedPseudoOperation(IR::Opcode::GetCarryFromOp)) { + inst.SetArg(2, IR::Value(false)); + } + + auto shift_amount = inst.GetArg(1); + if (shift_amount.IsImmediate() && shift_amount.GetU8() == 0) { + IR::Inst* carry_inst = inst.GetAssociatedPseudoOperation(IR::Opcode::GetCarryFromOp); + if (carry_inst) { + carry_inst->ReplaceUsesWith(inst.GetArg(2)); + } + inst.ReplaceUsesWith(inst.GetArg(0)); + } + break; + } case IR::Opcode::ReadMemory8: { + if (!inst.AreAllArgsImmediates()) + break; + u32 vaddr = inst.GetArg(0).GetU32(); if (memory_callbacks.IsReadOnlyMemory(vaddr)) { u8 value_from_memory = memory_callbacks.Read8(vaddr); @@ -28,6 +53,9 @@ void ConstantPropagation(IR::Block& block, const UserCallbacks::Memory& memory_c break; } case IR::Opcode::ReadMemory16: { + if (!inst.AreAllArgsImmediates()) + break; + u32 vaddr = inst.GetArg(0).GetU32(); if (memory_callbacks.IsReadOnlyMemory(vaddr)) { u16 value_from_memory = memory_callbacks.Read16(vaddr); @@ -36,6 +64,9 @@ void ConstantPropagation(IR::Block& block, const UserCallbacks::Memory& memory_c break; } case IR::Opcode::ReadMemory32: { + if (!inst.AreAllArgsImmediates()) + break; + u32 vaddr = inst.GetArg(0).GetU32(); if (memory_callbacks.IsReadOnlyMemory(vaddr)) { u32 value_from_memory = memory_callbacks.Read32(vaddr); @@ -44,6 +75,9 @@ void ConstantPropagation(IR::Block& block, const UserCallbacks::Memory& memory_c break; } case IR::Opcode::ReadMemory64: { + if (!inst.AreAllArgsImmediates()) + break; + u32 vaddr = inst.GetArg(0).GetU32(); if (memory_callbacks.IsReadOnlyMemory(vaddr)) { u64 value_from_memory = memory_callbacks.Read64(vaddr); @@ -52,12 +86,18 @@ void ConstantPropagation(IR::Block& block, const UserCallbacks::Memory& memory_c break; } case IR::Opcode::ZeroExtendByteToWord: { + if (!inst.AreAllArgsImmediates()) + break; + u8 byte = inst.GetArg(0).GetU8(); u32 value = static_cast(byte); inst.ReplaceUsesWith(IR::Value{value}); break; } case IR::Opcode::ZeroExtendHalfToWord: { + if (!inst.AreAllArgsImmediates()) + break; + u16 half = inst.GetArg(0).GetU16(); u32 value = static_cast(half); inst.ReplaceUsesWith(IR::Value{value});