From 72daf372081813904ee9906f03c14204ef3c23cf Mon Sep 17 00:00:00 2001 From: Lioncash Date: Sun, 7 Oct 2018 21:48:42 -0400 Subject: [PATCH] constant_propagation_pass: Fold Mul32 and Mul64 cases where applicable Multiplication operations can currently be folded if: 1. Both arguments are known constant values 2. Either operand is zero (in which case the result is also zero) 3. Either operand is one (in which case the result is the non-one operand). --- src/ir_opt/constant_propagation_pass.cpp | 37 ++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/src/ir_opt/constant_propagation_pass.cpp b/src/ir_opt/constant_propagation_pass.cpp index a8018711..c18f31cd 100644 --- a/src/ir_opt/constant_propagation_pass.cpp +++ b/src/ir_opt/constant_propagation_pass.cpp @@ -74,6 +74,39 @@ 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(); + + if (is_32_bit) { + inst.ReplaceUsesWith(IR::Value{static_cast(result)}); + } else { + inst.ReplaceUsesWith(IR::Value{result}); + } + } else if (lhs.IsZero() || rhs.IsZero()) { + if (is_32_bit) { + inst.ReplaceUsesWith(IR::Value{u32{0}}); + } else { + inst.ReplaceUsesWith(IR::Value{u64{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); @@ -174,6 +207,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);