diff --git a/src/ir_opt/constant_propagation_pass.cpp b/src/ir_opt/constant_propagation_pass.cpp index f7b8601f..8dc94c0d 100644 --- a/src/ir_opt/constant_propagation_pass.cpp +++ b/src/ir_opt/constant_propagation_pass.cpp @@ -6,6 +6,7 @@ #include +#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(operand.GetImmediateAsU64())); + inst.ReplaceUsesWith(IR::Value{result}); + } else if (op == IR::Opcode::ByteReverseHalf) { + const u16 result = Common::Swap16(static_cast(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; }