diff --git a/llvm/lib/Analysis/ScalarEvolution.cpp b/llvm/lib/Analysis/ScalarEvolution.cpp --- a/llvm/lib/Analysis/ScalarEvolution.cpp +++ b/llvm/lib/Analysis/ScalarEvolution.cpp @@ -13989,6 +13989,22 @@ } } } + + // Verify integrity of the block disposition cache. + for (const auto &It : BlockDispositions) { + const SCEV *S = It.first; + auto &Values = It.second; + for (auto &V : Values) { + auto CachedDisposition = V.getInt(); + const BasicBlock *BB = V.getPointer(); + const auto RecomputedDisposition = SE2.getBlockDisposition(S, BB); + if (CachedDisposition != RecomputedDisposition) { + dbgs() << "Cached disposition of " << *S << " for block %" + << BB->getName() << " is incorrect! \n"; + std::abort(); + } + } + } } bool ScalarEvolution::invalidate( diff --git a/llvm/test/Transforms/LoopDeletion/pr57837-invalidate-scev-after-hoisting.ll b/llvm/test/Transforms/LoopDeletion/pr57837-invalidate-scev-after-hoisting.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Transforms/LoopDeletion/pr57837-invalidate-scev-after-hoisting.ll @@ -0,0 +1,45 @@ +; RUN: opt -passes='loop(indvars,loop-deletion),verify' -S %s + +; XFAIL: * +; FIXME: Currently fails verification. + +; Make sure the SCEV for %invar is invalidated properly when the instruction is +; moved by LoopDeletion. + +define void @test() { +bb: + br label %outer.header + +outer.header: ; preds = %bb19, %bb + %outer.iv = phi i32 [ 0, %bb ], [ %tmp21, %outer.latch ] + %outer.cmp = icmp ult i32 %outer.iv, 400 + br i1 %outer.cmp, label %inner.ph, label %outer.latch + +inner.ph: + br label %inner + +inner: + %p = phi i32 [ poison, %inner.ph ], [ %invar, %inner ] + %inner.iv = phi i32 [ 1, %inner.ph ], [ %inner.iv.next , %inner ] + %add.1 = add i32 %p, 30586 + call void @use(i32 %add.1) + %invar = ashr i32 0, 3 + %inner.iv.next = add nuw nsw i32 %inner.iv, 1 + %invar.add = add i32 %invar, 407 + %inner.cmp = icmp slt i32 %inner.iv.next, %invar.add + br i1 %inner.cmp, label %inner, label %inner.exit + +inner.exit: + br label %outer.latch + +outer.latch: + %merge = phi i32 [ 0, %outer.header ], [ %invar, %inner.exit ] + call void @use(i32 %merge) + %tmp21 = add i32 %outer.iv, 1 + br i1 true, label %exit, label %outer.header + +exit: + ret void +} + +declare void @use(i32)