From f5233bfc69aa343ad7cec4d5f2a1c27876f9c785 Mon Sep 17 00:00:00 2001 From: Lioncash Date: Fri, 28 Sep 2018 17:42:34 -0400 Subject: [PATCH] constant_propagation_pass: Fold EOR operations It's possible to fold cases of exclusive OR operations if they can be known to be an identity operation, or if both operands happen to be known immediates, in which case we can just store the result of the exclusive-OR directly. --- src/ir_opt/constant_propagation_pass.cpp | 38 +++++++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-) diff --git a/src/ir_opt/constant_propagation_pass.cpp b/src/ir_opt/constant_propagation_pass.cpp index 62d9bf01..5b9f7ac5 100644 --- a/src/ir_opt/constant_propagation_pass.cpp +++ b/src/ir_opt/constant_propagation_pass.cpp @@ -11,10 +11,42 @@ #include "ir_opt/passes.h" namespace Dynarmic::Optimization { +namespace { + +// Folds EOR operations based on: +// +// 1. imm_x ^ imm_y -> result +// 2. x ^ 0 -> x +// 3. 0 ^ y -> y +// +void FoldEOR(IR::Inst& inst, bool is_32_bit) { + const auto lhs = inst.GetArg(0); + const auto rhs = inst.GetArg(1); + + const bool is_lhs_immediate = lhs.IsImmediate(); + const bool is_rhs_immediate = rhs.IsImmediate(); + + if (is_lhs_immediate && is_rhs_immediate) { + const u64 result = lhs.GetImmediateAsU64() ^ rhs.GetImmediateAsU64(); + + if (is_32_bit) { + inst.ReplaceUsesWith(IR::Value{static_cast(result)}); + } else { + inst.ReplaceUsesWith(IR::Value{result}); + } + } else if (is_lhs_immediate && lhs.GetImmediateAsU64() == 0) { + inst.ReplaceUsesWith(rhs); + } else if (is_rhs_immediate && rhs.GetImmediateAsU64() == 0) { + inst.ReplaceUsesWith(lhs); + } +} +} // Anonymous namespace void ConstantPropagation(IR::Block& block) { for (auto& inst : block) { - switch (inst.GetOpcode()) { + const auto opcode = inst.GetOpcode(); + + switch (opcode) { case IR::Opcode::LogicalShiftLeft32: case IR::Opcode::LogicalShiftRight32: case IR::Opcode::ArithmeticShiftRight32: @@ -33,6 +65,10 @@ void ConstantPropagation(IR::Block& block) { } break; } + case IR::Opcode::Eor32: + case IR::Opcode::Eor64: + FoldEOR(inst, opcode == IR::Opcode::Eor32); + break; case IR::Opcode::ZeroExtendByteToWord: { if (!inst.AreAllArgsImmediates()) break;