diff --git a/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp b/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp --- a/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp @@ -424,6 +424,14 @@ I.setHasNoUnsignedWrap(true); } + // Optimise loop multiplication when the inital accumulator value is zero. + // When we have a PHINode initalised to zero and we repeatedly multiply it + // with array elements we can remove the loop. + PHINode *PN = nullptr; + Value *Start = nullptr, *Step = nullptr; + if (matchSimpleRecurrence(&I, PN, Start, Step) && match(Start, m_Zero())) + return replaceInstUsesWith(I, Start); + return Changed ? &I : nullptr; } diff --git a/llvm/test/Transforms/InstCombine/remove-loop-phi-multiply-by-zero.ll b/llvm/test/Transforms/InstCombine/remove-loop-phi-multiply-by-zero.ll --- a/llvm/test/Transforms/InstCombine/remove-loop-phi-multiply-by-zero.ll +++ b/llvm/test/Transforms/InstCombine/remove-loop-phi-multiply-by-zero.ll @@ -280,15 +280,11 @@ ; CHECK-NEXT: br label [[FOR_BODY:%.*]] ; CHECK: for.body: ; CHECK-NEXT: [[I_02:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INC:%.*]], [[FOR_BODY]] ] -; CHECK-NEXT: [[F_PROD_01:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[MUL:%.*]], [[FOR_BODY]] ] -; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[ARR_D:%.*]], i64 [[I_02]] -; CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[ARRAYIDX]], align 4 -; CHECK-NEXT: [[MUL]] = mul nsw i32 [[F_PROD_01]], [[TMP0]] ; CHECK-NEXT: [[INC]] = add i64 [[I_02]], 1 ; CHECK-NEXT: [[CMP:%.*]] = icmp ult i64 [[INC]], 1000 ; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[END:%.*]] ; CHECK: end: -; CHECK-NEXT: ret i32 [[MUL]] +; CHECK-NEXT: ret i32 0 ; entry: br label %for.body