ir_opt: Remove redundant shift instructions
This commit is contained in:
parent
f9e7e85308
commit
bbeea72eba
4 changed files with 48 additions and 7 deletions
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -305,6 +305,7 @@ void Inst::Invalidate() {
|
||||||
}
|
}
|
||||||
value = {};
|
value = {};
|
||||||
}
|
}
|
||||||
|
op = Opcode::Void;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Inst::ReplaceUsesWith(Value replacement) {
|
void Inst::ReplaceUsesWith(Value replacement) {
|
||||||
|
|
|
@ -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, )
|
||||||
|
|
||||||
|
|
|
@ -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});
|
||||||
|
|
Loading…
Reference in a new issue