Index: llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp =================================================================== --- llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp +++ llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp @@ -1415,6 +1415,14 @@ return &I; } + // (X * Y) + X --> (Y + 1) * X + Value *X, *Y; + if (match(&I, m_c_Add(m_Value(X), + m_OneUse(m_c_Mul(m_Deferred(X), m_Value(Y)))))) { + Value *IncY = Builder.CreateAdd(Y, ConstantInt::get(I.getType(), 1)); + return BinaryOperator::CreateMul(IncY, X); + } + // TODO(jingyue): Consider willNotOverflowSignedAdd and // willNotOverflowUnsignedAdd to reduce the number of invocations of // computeKnownBits. Index: llvm/test/Transforms/InstCombine/add.ll =================================================================== --- llvm/test/Transforms/InstCombine/add.ll +++ llvm/test/Transforms/InstCombine/add.ll @@ -1756,10 +1756,12 @@ ret i32 %G } +; (x * y) + x --> (y + 1) * x + define i8 @mul_add_common_factor_commute1(i8 %x, i8 %y) { ; CHECK-LABEL: @mul_add_common_factor_commute1( -; CHECK-NEXT: [[M:%.*]] = mul i8 [[X:%.*]], [[Y:%.*]] -; CHECK-NEXT: [[A:%.*]] = add i8 [[M]], [[X]] +; CHECK-NEXT: [[TMP1:%.*]] = add i8 [[Y:%.*]], 1 +; CHECK-NEXT: [[A:%.*]] = mul i8 [[TMP1]], [[X:%.*]] ; CHECK-NEXT: ret i8 [[A]] ; %m = mul i8 %x, %y @@ -1769,8 +1771,8 @@ define <2 x i8> @mul_add_common_factor_commute2(<2 x i8> %x, <2 x i8> %y) { ; CHECK-LABEL: @mul_add_common_factor_commute2( -; CHECK-NEXT: [[M:%.*]] = mul <2 x i8> [[Y:%.*]], [[X:%.*]] -; CHECK-NEXT: [[A:%.*]] = add <2 x i8> [[M]], [[X]] +; CHECK-NEXT: [[TMP1:%.*]] = add <2 x i8> [[Y:%.*]], +; CHECK-NEXT: [[A:%.*]] = mul <2 x i8> [[TMP1]], [[X:%.*]] ; CHECK-NEXT: ret <2 x i8> [[A]] ; %m = mul <2 x i8> %y, %x @@ -1781,8 +1783,8 @@ define i8 @mul_add_common_factor_commute3(i8 %p, i8 %y) { ; CHECK-LABEL: @mul_add_common_factor_commute3( ; CHECK-NEXT: [[X:%.*]] = mul i8 [[P:%.*]], [[P]] -; CHECK-NEXT: [[M:%.*]] = mul i8 [[X]], [[Y:%.*]] -; CHECK-NEXT: [[A:%.*]] = add i8 [[X]], [[M]] +; CHECK-NEXT: [[TMP1:%.*]] = add i8 [[Y:%.*]], 1 +; CHECK-NEXT: [[A:%.*]] = mul i8 [[TMP1]], [[X]] ; CHECK-NEXT: ret i8 [[A]] ; %x = mul i8 %p, %p ; thwart complexity-based canonicalization @@ -1795,8 +1797,8 @@ ; CHECK-LABEL: @mul_add_common_factor_commute4( ; CHECK-NEXT: [[X:%.*]] = mul i8 [[P:%.*]], [[P]] ; CHECK-NEXT: [[Y:%.*]] = mul i8 [[Q:%.*]], [[Q]] -; CHECK-NEXT: [[M:%.*]] = mul i8 [[Y]], [[X]] -; CHECK-NEXT: [[A:%.*]] = add i8 [[X]], [[M]] +; CHECK-NEXT: [[TMP1:%.*]] = add i8 [[Y]], 1 +; CHECK-NEXT: [[A:%.*]] = mul i8 [[TMP1]], [[X]] ; CHECK-NEXT: ret i8 [[A]] ; %x = mul i8 %p, %p ; thwart complexity-based canonicalization @@ -1806,6 +1808,8 @@ ret i8 %a } +; negative test - extra use + define i8 @mul_add_common_factor_use(i8 %x, i8 %y) { ; CHECK-LABEL: @mul_add_common_factor_use( ; CHECK-NEXT: [[M:%.*]] = mul i8 [[X:%.*]], [[Y:%.*]]