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.
This commit is contained in:
Lioncash 2018-09-28 17:42:34 -04:00
parent 41ba9fd7bc
commit f5233bfc69
No known key found for this signature in database
GPG Key ID: 4E3C3CC1031BA9C7

View File

@ -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<u32>(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;