const SCEV *MaxBECount = getCouldNotCompute();
bool CouldComputeBECount = true;
BasicBlock *Latch = L->getLoopLatch(); // may be NULL.
- const SCEV *LatchMaxCount = nullptr;
+ bool LatchMustExit = false;
SmallVector<std::pair<BasicBlock *, const SCEV *>, 4> ExitCounts;
for (unsigned i = 0, e = ExitingBlocks.size(); i != e; ++i) {
ExitLimit EL = ComputeExitLimit(L, ExitingBlocks[i]);
// skip some loop tests. Taking the max over the exits is sufficiently
// conservative. TODO: We could do better taking into consideration
// non-latch exits that dominate the latch.
- if (EL.MustExit && ExitingBlocks[i] == Latch)
- LatchMaxCount = EL.Max;
- else
+ if (EL.MustExit && ExitingBlocks[i] == Latch) {
+ MaxBECount = EL.Max;
+ LatchMustExit = true;
+ }
+ else if (!LatchMustExit)
MaxBECount = getUMaxFromMismatchedTypes(MaxBECount, EL.Max);
}
}
- // Be more precise in the easy case of a loop latch that must exit.
- if (LatchMaxCount) {
- MaxBECount = getUMinFromMismatchedTypes(MaxBECount, LatchMaxCount);
- }
return BackedgeTakenInfo(ExitCounts, CouldComputeBECount, MaxBECount);
}
; CHECK: Determining loop execution counts for: @test
; CHECK-NEXT: backedge-taken count is
; CHECK-NEXT: max backedge-taken count is -1
+
+; PR19799: Indvars miscompile due to an incorrect max backedge taken count from SCEV.
+; CHECK-LABEL: @pr19799
+; CHECK: Loop %for.body.i: <multiple exits> Unpredictable backedge-taken count.
+; CHECK: Loop %for.body.i: max backedge-taken count is 1
+@a = common global i32 0, align 4
+
+define i32 @pr19799() {
+entry:
+ store i32 -1, i32* @a, align 4
+ br label %for.body.i
+
+for.body.i: ; preds = %for.cond.i, %entry
+ %storemerge1.i = phi i32 [ -1, %entry ], [ %add.i.i, %for.cond.i ]
+ %tobool.i = icmp eq i32 %storemerge1.i, 0
+ %add.i.i = add nsw i32 %storemerge1.i, 2
+ br i1 %tobool.i, label %bar.exit, label %for.cond.i
+
+for.cond.i: ; preds = %for.body.i
+ store i32 %add.i.i, i32* @a, align 4
+ %cmp.i = icmp slt i32 %storemerge1.i, 0
+ br i1 %cmp.i, label %for.body.i, label %bar.exit
+
+bar.exit: ; preds = %for.cond.i, %for.body.i
+ ret i32 0
+}