ir_opt: Remove redundant shift instructions

This commit is contained in:
MerryMage 2017-02-18 21:46:36 +00:00
parent f9e7e85308
commit bbeea72eba
4 changed files with 48 additions and 7 deletions

View file

@ -110,6 +110,9 @@ boost::optional<EmitX64::BlockDescriptor> EmitX64::GetBasicBlock(IR::LocationDes
return boost::make_optional<BlockDescriptor>(iter->second); return boost::make_optional<BlockDescriptor>(iter->second);
} }
void EmitX64::EmitVoid(RegAlloc&, IR::Block&, IR::Inst*) {
}
void EmitX64::EmitBreakpoint(RegAlloc&, IR::Block&, IR::Inst*) { void EmitX64::EmitBreakpoint(RegAlloc&, IR::Block&, IR::Inst*) {
code->int3(); code->int3();
} }
@ -546,7 +549,6 @@ void EmitX64::EmitLogicalShiftLeft(RegAlloc& reg_alloc, IR::Block& block, IR::In
if (!carry_inst) { if (!carry_inst) {
if (!inst->GetArg(2).IsImmediate()) { if (!inst->GetArg(2).IsImmediate()) {
// TODO: Remove redundant argument.
inst->GetArg(2).GetInst()->DecrementRemainingUses(); inst->GetArg(2).GetInst()->DecrementRemainingUses();
} }
@ -638,7 +640,6 @@ void EmitX64::EmitLogicalShiftRight(RegAlloc& reg_alloc, IR::Block& block, IR::I
if (!carry_inst) { if (!carry_inst) {
if (!inst->GetArg(2).IsImmediate()) { if (!inst->GetArg(2).IsImmediate()) {
// TODO: Remove redundant argument.
inst->GetArg(2).GetInst()->DecrementRemainingUses(); inst->GetArg(2).GetInst()->DecrementRemainingUses();
} }
@ -742,7 +743,6 @@ void EmitX64::EmitArithmeticShiftRight(RegAlloc& reg_alloc, IR::Block& block, IR
if (!carry_inst) { if (!carry_inst) {
if (!inst->GetArg(2).IsImmediate()) { if (!inst->GetArg(2).IsImmediate()) {
// TODO: Remove redundant argument.
inst->GetArg(2).GetInst()->DecrementRemainingUses(); 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 (!carry_inst) {
if (!inst->GetArg(2).IsImmediate()) { if (!inst->GetArg(2).IsImmediate()) {
// TODO: Remove redundant argument.
inst->GetArg(2).GetInst()->DecrementRemainingUses(); inst->GetArg(2).GetInst()->DecrementRemainingUses();
} }

View file

@ -305,6 +305,7 @@ void Inst::Invalidate() {
} }
value = {}; value = {};
} }
op = Opcode::Void;
} }
void Inst::ReplaceUsesWith(Value replacement) { void Inst::ReplaceUsesWith(Value replacement) {

View file

@ -1,5 +1,6 @@
// opcode name, return type, arg1 type, arg2 type, arg3 type, ... // opcode name, return type, arg1 type, arg2 type, arg3 type, ...
OPCODE(Void, T::Void, )
OPCODE(Identity, T::Opaque, T::Opaque ) OPCODE(Identity, T::Opaque, T::Opaque )
OPCODE(Breakpoint, T::Void, ) OPCODE(Breakpoint, T::Void, )

View file

@ -15,11 +15,36 @@ namespace Optimization {
void ConstantPropagation(IR::Block& block, const UserCallbacks::Memory& memory_callbacks) { void ConstantPropagation(IR::Block& block, const UserCallbacks::Memory& memory_callbacks) {
for (auto& inst : block) { for (auto& inst : block) {
if (!inst.AreAllArgsImmediates())
continue;
switch (inst.GetOpcode()) { 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: { case IR::Opcode::ReadMemory8: {
if (!inst.AreAllArgsImmediates())
break;
u32 vaddr = inst.GetArg(0).GetU32(); u32 vaddr = inst.GetArg(0).GetU32();
if (memory_callbacks.IsReadOnlyMemory(vaddr)) { if (memory_callbacks.IsReadOnlyMemory(vaddr)) {
u8 value_from_memory = memory_callbacks.Read8(vaddr); u8 value_from_memory = memory_callbacks.Read8(vaddr);
@ -28,6 +53,9 @@ void ConstantPropagation(IR::Block& block, const UserCallbacks::Memory& memory_c
break; break;
} }
case IR::Opcode::ReadMemory16: { case IR::Opcode::ReadMemory16: {
if (!inst.AreAllArgsImmediates())
break;
u32 vaddr = inst.GetArg(0).GetU32(); u32 vaddr = inst.GetArg(0).GetU32();
if (memory_callbacks.IsReadOnlyMemory(vaddr)) { if (memory_callbacks.IsReadOnlyMemory(vaddr)) {
u16 value_from_memory = memory_callbacks.Read16(vaddr); u16 value_from_memory = memory_callbacks.Read16(vaddr);
@ -36,6 +64,9 @@ void ConstantPropagation(IR::Block& block, const UserCallbacks::Memory& memory_c
break; break;
} }
case IR::Opcode::ReadMemory32: { case IR::Opcode::ReadMemory32: {
if (!inst.AreAllArgsImmediates())
break;
u32 vaddr = inst.GetArg(0).GetU32(); u32 vaddr = inst.GetArg(0).GetU32();
if (memory_callbacks.IsReadOnlyMemory(vaddr)) { if (memory_callbacks.IsReadOnlyMemory(vaddr)) {
u32 value_from_memory = memory_callbacks.Read32(vaddr); u32 value_from_memory = memory_callbacks.Read32(vaddr);
@ -44,6 +75,9 @@ void ConstantPropagation(IR::Block& block, const UserCallbacks::Memory& memory_c
break; break;
} }
case IR::Opcode::ReadMemory64: { case IR::Opcode::ReadMemory64: {
if (!inst.AreAllArgsImmediates())
break;
u32 vaddr = inst.GetArg(0).GetU32(); u32 vaddr = inst.GetArg(0).GetU32();
if (memory_callbacks.IsReadOnlyMemory(vaddr)) { if (memory_callbacks.IsReadOnlyMemory(vaddr)) {
u64 value_from_memory = memory_callbacks.Read64(vaddr); u64 value_from_memory = memory_callbacks.Read64(vaddr);
@ -52,12 +86,18 @@ void ConstantPropagation(IR::Block& block, const UserCallbacks::Memory& memory_c
break; break;
} }
case IR::Opcode::ZeroExtendByteToWord: { case IR::Opcode::ZeroExtendByteToWord: {
if (!inst.AreAllArgsImmediates())
break;
u8 byte = inst.GetArg(0).GetU8(); u8 byte = inst.GetArg(0).GetU8();
u32 value = static_cast<u32>(byte); u32 value = static_cast<u32>(byte);
inst.ReplaceUsesWith(IR::Value{value}); inst.ReplaceUsesWith(IR::Value{value});
break; break;
} }
case IR::Opcode::ZeroExtendHalfToWord: { case IR::Opcode::ZeroExtendHalfToWord: {
if (!inst.AreAllArgsImmediates())
break;
u16 half = inst.GetArg(0).GetU16(); u16 half = inst.GetArg(0).GetU16();
u32 value = static_cast<u32>(half); u32 value = static_cast<u32>(half);
inst.ReplaceUsesWith(IR::Value{value}); inst.ReplaceUsesWith(IR::Value{value});