diff --git a/llvm/include/llvm/Analysis/LoopInfo.h b/llvm/include/llvm/Analysis/LoopInfo.h --- a/llvm/include/llvm/Analysis/LoopInfo.h +++ b/llvm/include/llvm/Analysis/LoopInfo.h @@ -583,7 +583,8 @@ /// bool makeLoopInvariant(Value *V, bool &Changed, Instruction *InsertPt = nullptr, - MemorySSAUpdater *MSSAU = nullptr) const; + MemorySSAUpdater *MSSAU = nullptr, + ScalarEvolution *SE = nullptr) const; /// If the given instruction is inside of the loop and it can be hoisted, do /// so to make it trivially loop-invariant. @@ -597,7 +598,8 @@ /// bool makeLoopInvariant(Instruction *I, bool &Changed, Instruction *InsertPt = nullptr, - MemorySSAUpdater *MSSAU = nullptr) const; + MemorySSAUpdater *MSSAU = nullptr, + ScalarEvolution *SE = nullptr) const; /// Check to see if the loop has a canonical induction variable: an integer /// recurrence that starts at 0 and increments by one each time through the diff --git a/llvm/lib/Analysis/LoopInfo.cpp b/llvm/lib/Analysis/LoopInfo.cpp --- a/llvm/lib/Analysis/LoopInfo.cpp +++ b/llvm/lib/Analysis/LoopInfo.cpp @@ -68,15 +68,16 @@ } bool Loop::makeLoopInvariant(Value *V, bool &Changed, Instruction *InsertPt, - MemorySSAUpdater *MSSAU) const { + MemorySSAUpdater *MSSAU, + ScalarEvolution *SE) const { if (Instruction *I = dyn_cast(V)) - return makeLoopInvariant(I, Changed, InsertPt, MSSAU); + return makeLoopInvariant(I, Changed, InsertPt, MSSAU, SE); return true; // All non-instructions are loop-invariant. } bool Loop::makeLoopInvariant(Instruction *I, bool &Changed, - Instruction *InsertPt, - MemorySSAUpdater *MSSAU) const { + Instruction *InsertPt, MemorySSAUpdater *MSSAU, + ScalarEvolution *SE) const { // Test if the value is already loop-invariant. if (isLoopInvariant(I)) return true; @@ -97,7 +98,7 @@ } // Don't hoist instructions with loop-variant operands. for (Value *Operand : I->operands()) - if (!makeLoopInvariant(Operand, Changed, InsertPt, MSSAU)) + if (!makeLoopInvariant(Operand, Changed, InsertPt, MSSAU, SE)) return false; // Hoist. @@ -113,6 +114,9 @@ // information to the optimizer. I->dropUnknownNonDebugMetadata(); + if (SE) + SE->forgetBlockAndLoopDispositions(I); + Changed = true; return true; } diff --git a/llvm/lib/Transforms/Scalar/LoopDeletion.cpp b/llvm/lib/Transforms/Scalar/LoopDeletion.cpp --- a/llvm/lib/Transforms/Scalar/LoopDeletion.cpp +++ b/llvm/lib/Transforms/Scalar/LoopDeletion.cpp @@ -90,17 +90,11 @@ break; if (Instruction *I = dyn_cast(incoming)) { - bool InstrMoved = false; - if (!L->makeLoopInvariant(I, InstrMoved, Preheader->getTerminator())) { + if (!L->makeLoopInvariant(I, Changed, Preheader->getTerminator(), + /*MSSAU=*/nullptr, &SE)) { AllEntriesInvariant = false; break; } - Changed |= InstrMoved; - if (InstrMoved) { - // Moving I to a different location may change its block disposition, - // so invalidate its SCEV. - SE.forgetBlockAndLoopDispositions(I); - } } } } diff --git a/llvm/lib/Transforms/Utils/LoopSimplify.cpp b/llvm/lib/Transforms/Utils/LoopSimplify.cpp --- a/llvm/lib/Transforms/Utils/LoopSimplify.cpp +++ b/llvm/lib/Transforms/Utils/LoopSimplify.cpp @@ -647,19 +647,12 @@ Instruction *Inst = &*I++; if (Inst == CI) continue; - bool InstInvariant = false; if (!L->makeLoopInvariant( - Inst, InstInvariant, - Preheader ? Preheader->getTerminator() : nullptr, MSSAU)) { + Inst, AnyInvariant, + Preheader ? Preheader->getTerminator() : nullptr, MSSAU, SE)) { AllInvariant = false; break; } - if (InstInvariant && SE) { - // The loop disposition of all SCEV expressions that depend on any - // hoisted values have also changed. - SE->forgetBlockAndLoopDispositions(Inst); - } - AnyInvariant |= InstInvariant; } if (AnyInvariant) Changed = true; diff --git a/llvm/test/Transforms/LoopDeletion/pr57837-invalidate-scev-after-hoisting.ll b/llvm/test/Transforms/LoopDeletion/invalidate-scev-after-hoisting.ll rename from llvm/test/Transforms/LoopDeletion/pr57837-invalidate-scev-after-hoisting.ll rename to llvm/test/Transforms/LoopDeletion/invalidate-scev-after-hoisting.ll --- a/llvm/test/Transforms/LoopDeletion/pr57837-invalidate-scev-after-hoisting.ll +++ b/llvm/test/Transforms/LoopDeletion/invalidate-scev-after-hoisting.ll @@ -9,8 +9,8 @@ ; CHECK-NEXT: Loop %inner: max backedge-taken count is 405 ; CHECK-NEXT: Loop %inner: Predicated backedge-taken count is (405 + %invar) -define void @test() { -; CHECK-LABEL: @test( +define void @test_pr57837() { +; CHECK-LABEL: @test_pr57837( ; CHECK-NEXT: bb: ; CHECK-NEXT: br label [[OUTER_HEADER:%.*]] ; CHECK: outer.header: @@ -126,3 +126,37 @@ %outer.iv.next = add nsw i32 %l, %trunc br label %outer.header } + +define void @test_pr58314() { +; CHECK-LABEL: @test_pr58314( +; CHECK-NEXT: entry: +; CHECK-NEXT: br label [[OUTER_HEADER:%.*]] +; CHECK: outer.header: +; CHECK-NEXT: [[C:%.*]] = icmp ne i16 0, 0 +; CHECK-NEXT: [[SEL:%.*]] = select i1 [[C]], i1 false, i1 true +; CHECK-NEXT: br label [[INNER:%.*]] +; CHECK: inner: +; CHECK-NEXT: br i1 true, label [[INNER]], label [[OUTER_LATCH:%.*]] +; CHECK: outer.latch: +; CHECK-NEXT: [[SEL_LCSSA:%.*]] = phi i1 [ [[SEL]], [[INNER]] ] +; CHECK-NEXT: br i1 [[SEL_LCSSA]], label [[OUTER_HEADER]], label [[EXIT:%.*]] +; CHECK: exit: +; CHECK-NEXT: ret void +; +entry: + br label %outer.header + +outer.header: + br label %inner + +inner: + %c = icmp ne i16 0, 0 + %sel = select i1 %c, i1 false, i1 true + br i1 true, label %inner, label %outer.latch + +outer.latch: + br i1 %sel, label %outer.header, label %exit + +exit: + ret void +}