Skip to content

Commit

Permalink
[Loop] Move block and loop dispo invalidation to makeLoopInvariant.
Browse files Browse the repository at this point in the history
makeLoopInvariant may recursively move its operands to make them
invariant, before moving the passed in instruction. Those recursively
moved instructions are currently missed when invalidating block and loop
dispositions.

To address this, move the invalidation code to Loop::makeLoopInvariant.

Fixes #58314.

Reviewed By: nikic

Differential Revision: https://reviews.llvm.org/D135909
  • Loading branch information
fhahn committed Oct 14, 2022
1 parent adf2972 commit 16cf666
Show file tree
Hide file tree
Showing 5 changed files with 53 additions and 26 deletions.
6 changes: 4 additions & 2 deletions llvm/include/llvm/Analysis/LoopInfo.h
Expand Up @@ -583,7 +583,8 @@ class LLVM_EXTERNAL_VISIBILITY Loop : public LoopBase<BasicBlock, Loop> {
///
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.
Expand All @@ -597,7 +598,8 @@ class LLVM_EXTERNAL_VISIBILITY Loop : public LoopBase<BasicBlock, Loop> {
///
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
Expand Down
14 changes: 9 additions & 5 deletions llvm/lib/Analysis/LoopInfo.cpp
Expand Up @@ -68,15 +68,16 @@ bool Loop::hasLoopInvariantOperands(const Instruction *I) const {
}

bool Loop::makeLoopInvariant(Value *V, bool &Changed, Instruction *InsertPt,
MemorySSAUpdater *MSSAU) const {
MemorySSAUpdater *MSSAU,
ScalarEvolution *SE) const {
if (Instruction *I = dyn_cast<Instruction>(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;
Expand All @@ -97,7 +98,7 @@ bool Loop::makeLoopInvariant(Instruction *I, bool &Changed,
}
// 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.
Expand All @@ -113,6 +114,9 @@ bool Loop::makeLoopInvariant(Instruction *I, bool &Changed,
// information to the optimizer.
I->dropUnknownNonDebugMetadata();

if (SE)
SE->forgetBlockAndLoopDispositions(I);

Changed = true;
return true;
}
Expand Down
10 changes: 2 additions & 8 deletions llvm/lib/Transforms/Scalar/LoopDeletion.cpp
Expand Up @@ -90,17 +90,11 @@ static bool isLoopDead(Loop *L, ScalarEvolution &SE,
break;

if (Instruction *I = dyn_cast<Instruction>(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);
}
}
}
}
Expand Down
11 changes: 2 additions & 9 deletions llvm/lib/Transforms/Utils/LoopSimplify.cpp
Expand Up @@ -647,19 +647,12 @@ static bool simplifyOneLoop(Loop *L, SmallVectorImpl<Loop *> &Worklist,
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;
Expand Down
Expand Up @@ -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)<nuw><nsw>

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:
Expand Down Expand Up @@ -126,3 +126,37 @@ outer.latch:
%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
}

0 comments on commit 16cf666

Please sign in to comment.