1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-10-19 02:52:53 +02:00

[LoopDeletion] Handle users in unreachable block

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
This commit is contained in:
Serguei Katkov 2018-01-12 07:24:43 +00:00
parent 46f6d0692f
commit 444df39ddc
2 changed files with 50 additions and 0 deletions

View File

@ -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())

View File

@ -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
}