Merge pull request #406 from lioncash/mul
constant_propagation_pass: Fold Mul32 and Mul64 cases where applicable
This commit is contained in:
commit
d83eae2004
1 changed files with 47 additions and 31 deletions
|
@ -13,6 +13,16 @@
|
|||
namespace Dynarmic::Optimization {
|
||||
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:
|
||||
//
|
||||
// 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) {
|
||||
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});
|
||||
}
|
||||
ReplaceUsesWith(inst, is_32_bit, result);
|
||||
} else if (lhs.IsZero() || rhs.IsZero()) {
|
||||
if (is_32_bit) {
|
||||
inst.ReplaceUsesWith(IR::Value{u32{0}});
|
||||
} else {
|
||||
inst.ReplaceUsesWith(IR::Value{u64{0}});
|
||||
}
|
||||
ReplaceUsesWith(inst, is_32_bit, 0);
|
||||
} else if (is_lhs_immediate && lhs.HasAllBitsSet()) {
|
||||
inst.ReplaceUsesWith(rhs);
|
||||
} 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()) {
|
||||
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});
|
||||
}
|
||||
ReplaceUsesWith(inst, is_32_bit, result);
|
||||
} else if (lhs.IsZero()) {
|
||||
inst.ReplaceUsesWith(rhs);
|
||||
} 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.
|
||||
void FoldNOT(IR::Inst& inst, bool is_32_bit) {
|
||||
const auto operand = inst.GetArg(0);
|
||||
|
||||
if (operand.IsImmediate()) {
|
||||
const u64 result = ~operand.GetImmediateAsU64();
|
||||
|
||||
if (is_32_bit) {
|
||||
inst.ReplaceUsesWith(IR::Value{static_cast<u32>(result)});
|
||||
} else {
|
||||
inst.ReplaceUsesWith(IR::Value{result});
|
||||
}
|
||||
if (!operand.IsImmediate()) {
|
||||
return;
|
||||
}
|
||||
|
||||
const u64 result = ~operand.GetImmediateAsU64();
|
||||
ReplaceUsesWith(inst, is_32_bit, result);
|
||||
}
|
||||
|
||||
// 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()) {
|
||||
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});
|
||||
}
|
||||
ReplaceUsesWith(inst, is_32_bit, result);
|
||||
} else if (lhs.IsZero()) {
|
||||
inst.ReplaceUsesWith(rhs);
|
||||
} else if (rhs.IsZero()) {
|
||||
|
@ -174,6 +186,10 @@ void ConstantPropagation(IR::Block& block) {
|
|||
}
|
||||
break;
|
||||
}
|
||||
case IR::Opcode::Mul32:
|
||||
case IR::Opcode::Mul64:
|
||||
FoldMultiply(inst, opcode == IR::Opcode::Mul32);
|
||||
break;
|
||||
case IR::Opcode::And32:
|
||||
case IR::Opcode::And64:
|
||||
FoldAND(inst, opcode == IR::Opcode::And32);
|
||||
|
|
Loading…
Reference in a new issue