aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNick Lewycky <nicholas@mxc.ca>2008-02-03 07:42:09 +0000
committerNick Lewycky <nicholas@mxc.ca>2008-02-03 07:42:09 +0000
commitb6eabff1699589dc8748c4b34706a3731cd43bfe (patch)
treee5bfb31fd45d7ee84b208907fe1e49de2658efa8
parent9d3e5d476c4478d2837760a9bf43fedb8a5a7e51 (diff)
Fold away one multiply in instcombine. This would normally be caught in
reassociate anyways, but they could be generated during instcombine's run. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@46683 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/Transforms/Scalar/InstructionCombining.cpp24
1 files changed, 24 insertions, 0 deletions
diff --git a/lib/Transforms/Scalar/InstructionCombining.cpp b/lib/Transforms/Scalar/InstructionCombining.cpp
index 1968f9b36e..761b57d2ec 100644
--- a/lib/Transforms/Scalar/InstructionCombining.cpp
+++ b/lib/Transforms/Scalar/InstructionCombining.cpp
@@ -2123,6 +2123,30 @@ Instruction *InstCombiner::visitAdd(BinaryOperator &I) {
if (Instruction *R = AssociativeOpt(I, AddMaskingAnd(C2)))
return R;
+ // W*X + Y*Z --> W * (X+Z) iff W == Y
+ if (I.getType()->isInteger()) {
+ Value *W, *X, *Y, *Z;
+ if (match(LHS, m_Mul(m_Value(W), m_Value(X))) &&
+ match(RHS, m_Mul(m_Value(Y), m_Value(Z)))) {
+ if (W != Y) {
+ if (W == Z) {
+ std::swap(Y, Z);
+ } else if (Y == X) {
+ std::swap(W, X);
+ } else if (X == Z) {
+ std::swap(Y, Z);
+ std::swap(W, X);
+ }
+ }
+
+ if (W == Y) {
+ Value *NewAdd = InsertNewInstBefore(BinaryOperator::createAdd(X, Z,
+ LHS->getName()), I);
+ return BinaryOperator::createMul(W, NewAdd);
+ }
+ }
+ }
+
if (ConstantInt *CRHS = dyn_cast<ConstantInt>(RHS)) {
Value *X = 0;
if (match(LHS, m_Not(m_Value(X)))) // ~X + C --> (C-1) - X