Merge pull request #406 from lioncash/mul

constant_propagation_pass: Fold Mul32 and Mul64 cases where applicable
This commit is contained in:
Merry 2018-10-09 15:11:36 +01:00 committed by MerryMage
commit d83eae2004

View file

@ -13,6 +13,16 @@
namespace Dynarmic::Optimization { namespace Dynarmic::Optimization {
namespace { namespace {
// Tiny helper to avoid the need to store based off the opcode
// bit size all over the place within folding functions.
void ReplaceUsesWith(IR::Inst& inst, bool is_32_bit, u64 value) {
if (is_32_bit) {
inst.ReplaceUsesWith(IR::Value{static_cast<u32>(value)});
} else {
inst.ReplaceUsesWith(IR::Value{value});
}
}
// Folds AND operations based on the following: // Folds AND operations based on the following:
// //
// 1. imm_x & imm_y -> result // 1. imm_x & imm_y -> result
@ -30,18 +40,9 @@ void FoldAND(IR::Inst& inst, bool is_32_bit) {
if (is_lhs_immediate && is_rhs_immediate) { if (is_lhs_immediate && is_rhs_immediate) {
const u64 result = lhs.GetImmediateAsU64() & rhs.GetImmediateAsU64(); const u64 result = lhs.GetImmediateAsU64() & rhs.GetImmediateAsU64();
ReplaceUsesWith(inst, is_32_bit, result);
if (is_32_bit) {
inst.ReplaceUsesWith(IR::Value{static_cast<u32>(result)});
} else {
inst.ReplaceUsesWith(IR::Value{result});
}
} else if (lhs.IsZero() || rhs.IsZero()) { } else if (lhs.IsZero() || rhs.IsZero()) {
if (is_32_bit) { ReplaceUsesWith(inst, is_32_bit, 0);
inst.ReplaceUsesWith(IR::Value{u32{0}});
} else {
inst.ReplaceUsesWith(IR::Value{u64{0}});
}
} else if (is_lhs_immediate && lhs.HasAllBitsSet()) { } else if (is_lhs_immediate && lhs.HasAllBitsSet()) {
inst.ReplaceUsesWith(rhs); inst.ReplaceUsesWith(rhs);
} else if (is_rhs_immediate && rhs.HasAllBitsSet()) { } else if (is_rhs_immediate && rhs.HasAllBitsSet()) {
@ -61,12 +62,7 @@ void FoldEOR(IR::Inst& inst, bool is_32_bit) {
if (lhs.IsImmediate() && rhs.IsImmediate()) { if (lhs.IsImmediate() && rhs.IsImmediate()) {
const u64 result = lhs.GetImmediateAsU64() ^ rhs.GetImmediateAsU64(); const u64 result = lhs.GetImmediateAsU64() ^ rhs.GetImmediateAsU64();
ReplaceUsesWith(inst, is_32_bit, result);
if (is_32_bit) {
inst.ReplaceUsesWith(IR::Value{static_cast<u32>(result)});
} else {
inst.ReplaceUsesWith(IR::Value{result});
}
} else if (lhs.IsZero()) { } else if (lhs.IsZero()) {
inst.ReplaceUsesWith(rhs); inst.ReplaceUsesWith(rhs);
} else if (rhs.IsZero()) { } else if (rhs.IsZero()) {
@ -74,19 +70,40 @@ void FoldEOR(IR::Inst& inst, bool is_32_bit) {
} }
} }
// Folds multiplication operations based on the following:
//
// 1. imm_x * imm_y -> result
// 2. x * 0 -> 0
// 3. 0 * y -> 0
// 4. x * 1 -> x
// 5. 1 * y -> y
//
void FoldMultiply(IR::Inst& inst, bool is_32_bit) {
const auto lhs = inst.GetArg(0);
const auto rhs = inst.GetArg(1);
if (lhs.IsImmediate() && rhs.IsImmediate()) {
const u64 result = lhs.GetImmediateAsU64() * rhs.GetImmediateAsU64();
ReplaceUsesWith(inst, is_32_bit, result);
} else if (lhs.IsZero() || rhs.IsZero()) {
ReplaceUsesWith(inst, is_32_bit, 0);
} else if (lhs.IsUnsignedImmediate(1)) {
inst.ReplaceUsesWith(rhs);
} else if (rhs.IsUnsignedImmediate(1)) {
inst.ReplaceUsesWith(lhs);
}
}
// Folds NOT operations if the contained value is an immediate. // Folds NOT operations if the contained value is an immediate.
void FoldNOT(IR::Inst& inst, bool is_32_bit) { void FoldNOT(IR::Inst& inst, bool is_32_bit) {
const auto operand = inst.GetArg(0); const auto operand = inst.GetArg(0);
if (operand.IsImmediate()) { if (!operand.IsImmediate()) {
const u64 result = ~operand.GetImmediateAsU64(); return;
if (is_32_bit) {
inst.ReplaceUsesWith(IR::Value{static_cast<u32>(result)});
} else {
inst.ReplaceUsesWith(IR::Value{result});
}
} }
const u64 result = ~operand.GetImmediateAsU64();
ReplaceUsesWith(inst, is_32_bit, result);
} }
// Folds OR operations based on the following: // Folds OR operations based on the following:
@ -101,12 +118,7 @@ void FoldOR(IR::Inst& inst, bool is_32_bit) {
if (lhs.IsImmediate() && rhs.IsImmediate()) { if (lhs.IsImmediate() && rhs.IsImmediate()) {
const u64 result = lhs.GetImmediateAsU64() | rhs.GetImmediateAsU64(); const u64 result = lhs.GetImmediateAsU64() | rhs.GetImmediateAsU64();
ReplaceUsesWith(inst, is_32_bit, result);
if (is_32_bit) {
inst.ReplaceUsesWith(IR::Value{static_cast<u32>(result)});
} else {
inst.ReplaceUsesWith(IR::Value{result});
}
} else if (lhs.IsZero()) { } else if (lhs.IsZero()) {
inst.ReplaceUsesWith(rhs); inst.ReplaceUsesWith(rhs);
} else if (rhs.IsZero()) { } else if (rhs.IsZero()) {
@ -174,6 +186,10 @@ void ConstantPropagation(IR::Block& block) {
} }
break; break;
} }
case IR::Opcode::Mul32:
case IR::Opcode::Mul64:
FoldMultiply(inst, opcode == IR::Opcode::Mul32);
break;
case IR::Opcode::And32: case IR::Opcode::And32:
case IR::Opcode::And64: case IR::Opcode::And64:
FoldAND(inst, opcode == IR::Opcode::And32); FoldAND(inst, opcode == IR::Opcode::And32);