diff --git a/llvm/include/llvm/Analysis/ScalarEvolution.h b/llvm/include/llvm/Analysis/ScalarEvolution.h --- a/llvm/include/llvm/Analysis/ScalarEvolution.h +++ b/llvm/include/llvm/Analysis/ScalarEvolution.h @@ -939,6 +939,13 @@ /// recompute is simpler. void forgetLoopDispositions(); + /// Called when the client has changed the disposition of values in + /// a loop or block. + /// + /// We don't have a way to invalidate per-loop/per-block dispositions. Clear and + /// recompute is simpler. + void forgetBlockAndLoopDispositions(); + /// Determine the minimum number of zero bits that S is guaranteed to end in /// (at every loop iteration). It is, at the same time, the minimum number /// of times S is divisible by 2. For example, given {4,+,8} it returns 2. 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 @@ -8384,6 +8384,8 @@ void ScalarEvolution::forgetLoopDispositions() { LoopDispositions.clear(); } +void ScalarEvolution::forgetBlockAndLoopDispositions() { BlockDispositions.clear(); LoopDispositions.clear();} + /// Get the exact loop backedge taken count considering all loop exits. A /// computable result can only be returned for loops with all exiting blocks /// dominating the latch. howFarToZero assumes that the limit of each loop test diff --git a/llvm/lib/Transforms/Utils/LoopUnroll.cpp b/llvm/lib/Transforms/Utils/LoopUnroll.cpp --- a/llvm/lib/Transforms/Utils/LoopUnroll.cpp +++ b/llvm/lib/Transforms/Utils/LoopUnroll.cpp @@ -467,6 +467,7 @@ SE->forgetAllLoops(); else SE->forgetTopmostLoop(L); + SE->forgetBlockAndLoopDispositions(); } if (!LatchIsExiting) diff --git a/llvm/test/Transforms/LoopUnroll/loop-block-disposition-after-full-unroll.ll b/llvm/test/Transforms/LoopUnroll/loop-block-disposition-after-full-unroll.ll --- a/llvm/test/Transforms/LoopUnroll/loop-block-disposition-after-full-unroll.ll +++ b/llvm/test/Transforms/LoopUnroll/loop-block-disposition-after-full-unroll.ll @@ -1,9 +1,28 @@ -; RUN: opt -passes='loop(indvars,loop-deletion,loop-unroll-full),verify' -S %s - -; XFAIL: * -; FIXME: currently fails verification. +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; RUN: opt -passes='loop(indvars,loop-deletion,loop-unroll-full),verify' -S %s | FileCheck %s define void @test(i1 %c.0, ptr %A) { +; CHECK-LABEL: @test( +; CHECK-NEXT: entry: +; CHECK-NEXT: br i1 [[C_0:%.*]], label [[LOOP_1_HEADER_PREHEADER:%.*]], label [[OUTER_HEADER_PREHEADER:%.*]] +; CHECK: outer.header.preheader: +; CHECK-NEXT: br label [[OUTER_HEADER:%.*]] +; CHECK: loop.1.header.preheader: +; CHECK-NEXT: br label [[LOOP_1_HEADER:%.*]] +; CHECK: loop.1.header: +; CHECK-NEXT: store i32 0, ptr [[A:%.*]], align 4 +; CHECK-NEXT: br label [[LOOP_1_LATCH:%.*]] +; CHECK: loop.1.latch: +; CHECK-NEXT: store i32 0, ptr [[A]], align 4 +; CHECK-NEXT: br label [[LOOP_1_LATCH_1:%.*]] +; CHECK: loop.1.latch.1: +; CHECK-NEXT: ret void +; CHECK: outer.header.loopexit: +; CHECK-NEXT: br label [[OUTER_HEADER]] +; CHECK: outer.header: +; CHECK-NEXT: [[L:%.*]] = load i32, ptr [[A]], align 4 +; CHECK-NEXT: br label [[OUTER_HEADER_LOOPEXIT:%.*]] +; entry: br i1 %c.0, label %loop.1.header, label %outer.header