diff --git a/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp --- a/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp @@ -1390,6 +1390,13 @@ } Value *A, *B; + + // A - B + B << 1 -> A + B + if (match(LHS, m_Sub(m_Value(A), m_Value(B))) && + match(RHS, m_Shl(m_Value(B), m_One())) && + LHS->hasOneUse() && RHS->hasOneUse()) + return BinaryOperator::CreateAdd(A, B); + if (match(LHS, m_Neg(m_Value(A)))) { // -A + -B --> -(A + B) if (match(RHS, m_Neg(m_Value(B)))) diff --git a/llvm/test/Transforms/InstCombine/add.ll b/llvm/test/Transforms/InstCombine/add.ll --- a/llvm/test/Transforms/InstCombine/add.ll +++ b/llvm/test/Transforms/InstCombine/add.ll @@ -2943,4 +2943,14 @@ ret <2 x i32> %c } +define i32 @add_shl_sub(i32 %a, i32 %b) { +; CHECK-LABEL: @add_shl_sub +; CHECK-NEXT: %add = add i32 %a, %b +; CHECK-NEXT: ret i32 %add + %sub = sub i32 %a, %b + %mul = shl nsw i32 %b, 1 + %add = add nsw i32 %sub, %mul + ret i32 %add +} + declare void @llvm.assume(i1)