forked from OSchip/llvm-project
[SimpleLoopUnswitch] Update DefaultExit condition to check unreachable is not empty.
Summary: Update the check for the default exit block to not only check that the terminator is not unreachable, but also check that unreachable block has *only* the unreachable instruction. Reviewers: chandlerc Subscribers: hiraditya, uabelho, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D78277
This commit is contained in:
parent
c9e6519d15
commit
6227f021ad
|
@ -598,6 +598,23 @@ static bool unswitchTrivialSwitch(Loop &L, SwitchInst &SI, DominatorTree &DT,
|
|||
|
||||
auto *ParentBB = SI.getParent();
|
||||
|
||||
auto IsTriviallyUnswitchableExitBlock = [&](BasicBlock &BBToCheck) {
|
||||
// BBToCheck is not an exit block if it is inside loop L.
|
||||
if (L.contains(&BBToCheck))
|
||||
return false;
|
||||
// BBToCheck is not trivial to unswitch if its phis aren't loop invariant.
|
||||
if (!areLoopExitPHIsLoopInvariant(L, *ParentBB, BBToCheck))
|
||||
return false;
|
||||
// We do not unswitch a block that only has an unreachable statement, as
|
||||
// it's possible this is a previously unswitched block. Only unswitch if
|
||||
// either the terminator is not unreachable, or, if it is, it's not the only
|
||||
// instruction in the block.
|
||||
auto *TI = BBToCheck.getTerminator();
|
||||
bool isUnreachable = isa<UnreachableInst>(TI);
|
||||
return !isUnreachable ||
|
||||
(isUnreachable && (BBToCheck.getFirstNonPHIOrDbg() != TI));
|
||||
};
|
||||
|
||||
SmallVector<int, 4> ExitCaseIndices;
|
||||
for (auto Case : SI.cases()) {
|
||||
auto *SuccBB = Case.getCaseSuccessor();
|
||||
|
@ -608,9 +625,7 @@ static bool unswitchTrivialSwitch(Loop &L, SwitchInst &SI, DominatorTree &DT,
|
|||
BasicBlock *DefaultExitBB = nullptr;
|
||||
SwitchInstProfUpdateWrapper::CaseWeightOpt DefaultCaseWeight =
|
||||
SwitchInstProfUpdateWrapper::getSuccessorWeight(SI, 0);
|
||||
if (!L.contains(SI.getDefaultDest()) &&
|
||||
areLoopExitPHIsLoopInvariant(L, *ParentBB, *SI.getDefaultDest()) &&
|
||||
!isa<UnreachableInst>(SI.getDefaultDest()->getTerminator())) {
|
||||
if (IsTriviallyUnswitchableExitBlock(*SI.getDefaultDest())) {
|
||||
DefaultExitBB = SI.getDefaultDest();
|
||||
} else if (ExitCaseIndices.empty())
|
||||
return false;
|
||||
|
|
|
@ -1243,3 +1243,52 @@ loopexit:
|
|||
; CHECK: loopexit:
|
||||
; CHECK-NEXT: ret
|
||||
}
|
||||
|
||||
declare void @f()
|
||||
declare void @g()
|
||||
define void @test_unswitch_switch_with_nonempty_unreachable() {
|
||||
; CHECK-LABEL: @test_unswitch_switch_with_nonempty_unreachable()
|
||||
entry:
|
||||
br label %loop
|
||||
|
||||
loop:
|
||||
%cleanup.dest.slot.0 = select i1 undef, i32 5, i32 undef
|
||||
br label %for.cond
|
||||
|
||||
for.cond:
|
||||
switch i32 %cleanup.dest.slot.0, label %NonEmptyUnreachableBlock [
|
||||
i32 0, label %for.cond
|
||||
i32 1, label %NonEmptyUnreachableBlock
|
||||
i32 2, label %loop.loopexit
|
||||
]
|
||||
|
||||
loop.loopexit:
|
||||
unreachable
|
||||
|
||||
NonEmptyUnreachableBlock:
|
||||
call void @f()
|
||||
call void @g()
|
||||
unreachable
|
||||
|
||||
; CHECK:loop:
|
||||
; CHECK-NEXT: %cleanup.dest.slot.0 = select i1 undef, i32 5, i32 undef
|
||||
; CHECK-NEXT: switch i32 %cleanup.dest.slot.0, label %NonEmptyUnreachableBlock [
|
||||
; CHECK-NEXT: i32 1, label %NonEmptyUnreachableBlock
|
||||
; CHECK-NEXT: i32 2, label %loop.loopexit
|
||||
; CHECK-NEXT: i32 0, label %loop.split
|
||||
; CHECK-NEXT: ]
|
||||
|
||||
; CHECK:loop.split:
|
||||
; CHECK-NEXT: br label %for.cond
|
||||
|
||||
; CHECK:for.cond:
|
||||
; CHECK-NEXT: br label %for.cond
|
||||
|
||||
; CHECK:loop.loopexit:
|
||||
; CHECK-NEXT: unreachable
|
||||
|
||||
; CHECK:NonEmptyUnreachableBlock:
|
||||
; CHECK-NEXT: call void @f()
|
||||
; CHECK-NEXT: call void @g()
|
||||
; CHECK-NEXT: unreachable
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue