constant_propagation_pass: Fold byte reversal opcodes where applicable

These are reasonably trivial to fold away when applicable. We just
perform the swap and replace the instruction with the constant value.
This commit is contained in:
Lioncash 2018-11-24 10:32:10 -05:00 committed by MerryMage
parent 2c53f354ab
commit 575ae852a9

View file

@ -6,6 +6,7 @@
#include <dynarmic/A32/config.h>
#include "common/bit_util.h"
#include "frontend/ir/basic_block.h"
#include "frontend/ir/opcodes.h"
#include "ir_opt/passes.h"
@ -50,6 +51,29 @@ void FoldAND(IR::Inst& inst, bool is_32_bit) {
}
}
// Folds byte reversal opcodes based on the following:
//
// 1. imm -> swap(imm)
//
void FoldByteReverse(IR::Inst& inst, IR::Opcode op) {
const auto operand = inst.GetArg(0);
if (!operand.IsImmediate()) {
return;
}
if (op == IR::Opcode::ByteReverseWord) {
const u32 result = Common::Swap32(static_cast<u32>(operand.GetImmediateAsU64()));
inst.ReplaceUsesWith(IR::Value{result});
} else if (op == IR::Opcode::ByteReverseHalf) {
const u16 result = Common::Swap16(static_cast<u16>(operand.GetImmediateAsU64()));
inst.ReplaceUsesWith(IR::Value{result});
} else {
const u64 result = Common::Swap64(operand.GetImmediateAsU64());
inst.ReplaceUsesWith(IR::Value{result});
}
}
// Folds division operations based on the following:
//
// 1. x / 0 -> 0 (NOTE: This is an ARM-specific behavior defined in the architecture reference manual)
@ -332,6 +356,11 @@ void ConstantPropagation(IR::Block& block) {
case IR::Opcode::ZeroExtendWordToLong:
FoldZeroExtendXToLong(inst);
break;
case IR::Opcode::ByteReverseWord:
case IR::Opcode::ByteReverseHalf:
case IR::Opcode::ByteReverseDual:
FoldByteReverse(inst, opcode);
break;
default:
break;
}