Index: lib/Transforms/Utils/LoopUtils.cpp =================================================================== --- lib/Transforms/Utils/LoopUtils.cpp +++ lib/Transforms/Utils/LoopUtils.cpp @@ -1356,6 +1356,32 @@ DT->deleteEdge(Preheader, L->getHeader()); } + // Strongly speaking any instruction in the loop at this moment should not + // have a user outside of this loop. However it is possible that there are + // some users in unreachable blocks and we want to remove these users 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 no one operation after dropping all + // references is valid except 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(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()) Index: test/Transforms/LoopDeletion/use-in-unreachable.ll =================================================================== --- /dev/null +++ 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 %badloop +; CHECK-LABEL-NOT: badloop +badloop: + %indvar1 = phi i64 [ 3, %entry ], [ %indvar2, %badloop_iter ] + %check = icmp ult i64 %indvar1, 400 + br i1 %check, label %badloop_iter, label %loopexit +badloop_iter: + %indvar2 = add i64 %indvar1, 1 + %baddef = add i64 0, 0 + br label %badloop +loopexit: + ret i64 0 +deadcode: +; CHECK-LABEL: deadcode +; CHECK: ret i64 undef + ret i64 %baddef +} \ No newline at end of file