Skip to content

Commit

Permalink
[LoopDeletion] Handle users in unreachable block
Browse files Browse the repository at this point in the history
This is a fix for PR35884.

When we want to delete dead loop we must clean uses in unreachable blocks
otherwise we'll get an assert during deletion of instructions from the loop.

Reviewers: anna, davide
Reviewed By: anna
Subscribers: llvm-commits, lebedev.ri
Differential Revision: https://reviews.llvm.org/D41943

llvm-svn: 322357
  • Loading branch information
Serguei Katkov committed Jan 12, 2018
1 parent 72001f4 commit a757d65
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 0 deletions.
26 changes: 26 additions & 0 deletions llvm/lib/Transforms/Utils/LoopUtils.cpp
Expand Up @@ -1356,6 +1356,32 @@ void llvm::deleteDeadLoop(Loop *L, DominatorTree *DT = nullptr,
DT->deleteEdge(Preheader, L->getHeader());
}

// Given LCSSA form is satisfied, we should not have users of instructions
// within the dead loop outside of the loop. However, LCSSA doesn't take
// unreachable uses into account. We handle them here.
// We could do it after drop all references (in this case all users in the
// loop will be already eliminated and we have less work to do but according
// to API doc of User::dropAllReferences only valid operation after dropping
// references, is deletion. So let's substitute all usages of
// instruction from the loop with undef value of corresponding type first.
for (auto *Block : L->blocks())
for (Instruction &I : *Block) {
auto *Undef = UndefValue::get(I.getType());
for (Value::use_iterator UI = I.use_begin(), E = I.use_end(); UI != E;) {
Use &U = *UI;
++UI;
if (auto *Usr = dyn_cast<Instruction>(U.getUser()))
if (L->contains(Usr->getParent()))
continue;
// If we have a DT then we can check that uses outside a loop only in
// unreachable block.
if (DT)
assert(!DT->isReachableFromEntry(U) &&
"Unexpected user in reachable block");
U.set(Undef);
}
}

// Remove the block from the reference counting scheme, so that we can
// delete it freely later.
for (auto *Block : L->blocks())
Expand Down
24 changes: 24 additions & 0 deletions llvm/test/Transforms/LoopDeletion/use-in-unreachable.ll
@@ -0,0 +1,24 @@
; RUN: opt < %s -loop-deletion -S | FileCheck %s

; Checking that possible users of instruction from the loop in
; unreachable blocks are handled.

define i64 @foo() {
entry:
br label %invloop
; CHECK-LABEL-NOT: invloop
invloop:
%indvar1 = phi i64 [ 3, %entry ], [ %indvar2, %invloop_iter ]
%check = icmp ult i64 %indvar1, 400
br i1 %check, label %invloop_iter, label %loopexit
invloop_iter:
%indvar2 = add i64 %indvar1, 1
%baddef = add i64 0, 0
br label %invloop
loopexit:
ret i64 0
deadcode:
; CHECK-LABEL: deadcode
; CHECK: ret i64 undef
ret i64 %baddef
}

0 comments on commit a757d65

Please sign in to comment.