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 @@ -1344,6 +1344,21 @@ if (match(RHS, m_OneUse(m_c_Add(m_Value(A), m_Specific(LHS))))) return BinaryOperator::CreateAdd(A, Builder.CreateShl(LHS, 1, "reass.add")); + { + // ((A + B) + C) + A --> (A << 1) + (B + C) + // ((A + B) + C) + B --> (B << 1) + (A + C) + Value *A, *B, *C; + if (match(LHS, m_OneUse(m_c_Add(m_OneUse(m_c_Add(m_Value(A), m_Value(B))), + m_Value(C))))) { + if (RHS == A || RHS == B) { + Value *SHL = Builder.CreateShl(RHS, 1, "reass.add"); + Value *ADD = RHS == A ? Builder.CreateAdd(B, C, "reass.add") + : Builder.CreateAdd(A, C, "reass.add"); + return BinaryOperator::CreateAdd(SHL, ADD); + } + } + } + { // (A + C1) + (C2 - B) --> (A - B) + (C1 + C2) Constant *C1, *C2; 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 @@ -295,12 +295,11 @@ ret i8 %r } -;; TODO: shl A, 1? define i32 @test13(i32 %A, i32 %B, i32 %C) { ; CHECK-LABEL: @test13( -; CHECK-NEXT: [[D_OK:%.*]] = add i32 [[A:%.*]], [[B:%.*]] -; CHECK-NEXT: [[E_OK:%.*]] = add i32 [[D_OK]], [[C:%.*]] -; CHECK-NEXT: [[F:%.*]] = add i32 [[E_OK]], [[A]] +; CHECK-NEXT: [[REASS_ADD:%.*]] = shl i32 [[A:%.*]], 1 +; CHECK-NEXT: [[REASS_ADD1:%.*]] = add i32 [[B:%.*]], [[C:%.*]] +; CHECK-NEXT: [[F:%.*]] = add i32 [[REASS_ADD]], [[REASS_ADD1]] ; CHECK-NEXT: ret i32 [[F]] ; %D_OK = add i32 %A, %B @@ -1691,54 +1690,41 @@ ret i8 %add } -define i32 @add_add_add(i32 %A, i32 %B, i32 %C, i32 %D) { +define i32 @add_add_add(i32 %A, i32 %B, i32 %C) { ; CHECK-LABEL: @add_add_add( -; CHECK-NEXT: [[E:%.*]] = add i32 [[A:%.*]], [[B:%.*]] -; CHECK-NEXT: [[F:%.*]] = add i32 [[E]], [[C:%.*]] -; CHECK-NEXT: [[G:%.*]] = add i32 [[F]], [[D:%.*]] +; CHECK-NEXT: [[REASS_ADD:%.*]] = shl i32 [[B:%.*]], 1 +; CHECK-NEXT: [[REASS_ADD1:%.*]] = add i32 [[A:%.*]], [[C:%.*]] +; CHECK-NEXT: [[G:%.*]] = add i32 [[REASS_ADD]], [[REASS_ADD1]] ; CHECK-NEXT: ret i32 [[G]] ; %E = add i32 %A, %B %F = add i32 %E, %C - %G = add i32 %F, %D + %G = add i32 %F, %B ret i32 %G } -define i32 @add_add_add_commute1(i32 %A, i32 %B, i32 %C, i32 %D) { +define i32 @add_add_add_commute1(i32 %A, i32 %B, i32 %C) { ; CHECK-LABEL: @add_add_add_commute1( -; CHECK-NEXT: [[E:%.*]] = add i32 [[B:%.*]], [[A:%.*]] -; CHECK-NEXT: [[F:%.*]] = add i32 [[E]], [[C:%.*]] -; CHECK-NEXT: [[G:%.*]] = add i32 [[F]], [[D:%.*]] +; CHECK-NEXT: [[REASS_ADD:%.*]] = shl i32 [[B:%.*]], 1 +; CHECK-NEXT: [[REASS_ADD1:%.*]] = add i32 [[A:%.*]], [[C:%.*]] +; CHECK-NEXT: [[G:%.*]] = add i32 [[REASS_ADD]], [[REASS_ADD1]] ; CHECK-NEXT: ret i32 [[G]] ; %E = add i32 %B, %A %F = add i32 %E, %C - %G = add i32 %F, %D + %G = add i32 %B, %F ret i32 %G } -define i32 @add_add_add_commute2(i32 %A, i32 %B, i32 %C, i32 %D) { +define i32 @add_add_add_commute2(i32 %A, i32 %B, i32 %C) { ; CHECK-LABEL: @add_add_add_commute2( -; CHECK-NEXT: [[E:%.*]] = add i32 [[B:%.*]], [[A:%.*]] -; CHECK-NEXT: [[F:%.*]] = add i32 [[E]], [[C:%.*]] -; CHECK-NEXT: [[G:%.*]] = add i32 [[F]], [[D:%.*]] +; CHECK-NEXT: [[REASS_ADD:%.*]] = shl i32 [[A:%.*]], 1 +; CHECK-NEXT: [[REASS_ADD1:%.*]] = add i32 [[B:%.*]], [[C:%.*]] +; CHECK-NEXT: [[G:%.*]] = add i32 [[REASS_ADD]], [[REASS_ADD1]] ; CHECK-NEXT: ret i32 [[G]] ; %E = add i32 %B, %A %F = add i32 %C, %E - %G = add i32 %F, %D - ret i32 %G -} - -define i32 @add_add_add_commute3(i32 %A, i32 %B, i32 %C, i32 %D) { -; CHECK-LABEL: @add_add_add_commute3( -; CHECK-NEXT: [[E:%.*]] = add i32 [[B:%.*]], [[A:%.*]] -; CHECK-NEXT: [[F:%.*]] = add i32 [[E]], [[C:%.*]] -; CHECK-NEXT: [[G:%.*]] = add i32 [[F]], [[D:%.*]] -; CHECK-NEXT: ret i32 [[G]] -; - %E = add i32 %B, %A - %F = add i32 %C, %E - %G = add i32 %D, %F + %G = add i32 %A, %F ret i32 %G }