aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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