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 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);
|
||||||
|
|
Loading…
Reference in a new issue