Constant fold switch inst when looking for trivial conditions to unswitch on.

Summary: Constant fold switch inst when looking for trivial conditions to unswitch on.

Reviewers: sanjoy, chenli, hfinkel, efriedma

Subscribers: llvm-commits, mzolotukhin

Differential Revision: https://reviews.llvm.org/D29037

llvm-svn: 293250
This commit is contained in:
Xin Tong 2017-01-27 01:42:20 +00:00
parent baabda9317
commit e5f8d643d4
2 changed files with 55 additions and 3 deletions

View File

@ -899,7 +899,6 @@ bool LoopUnswitch::TryTrivialLoopUnswitch(bool &Changed) {
if (I.mayHaveSideEffects())
return false;
// FIXME: add check for constant foldable switch instructions.
if (BranchInst *BI = dyn_cast<BranchInst>(CurrentTerm)) {
if (BI->isUnconditional()) {
CurrentBB = BI->getSuccessor(0);
@ -911,7 +910,16 @@ bool LoopUnswitch::TryTrivialLoopUnswitch(bool &Changed) {
// Found a trivial condition candidate: non-foldable conditional branch.
break;
}
} else {
} else if (SwitchInst *SI = dyn_cast<SwitchInst>(CurrentTerm)) {
// At this point, any constant-foldable instructions should have probably
// been folded.
ConstantInt *Cond = dyn_cast<ConstantInt>(SI->getCondition());
if (!Cond)
break;
// Find the target block we are definitely going to.
CurrentBB = SI->findCaseValue(Cond).getCaseSuccessor();
} else {
// We do not understand these terminator instructions.
break;
}

View File

@ -44,4 +44,48 @@ loop_exit:
ret i32 0
}
declare void @some_func() noreturn
; We will not be able trivially unswitch on the SwitchInst, as its input
; is a constant. However, since its a constant we should be able to figure
; out that the switch can be folded into a unconditional branch to %continue.
; Then we unswitch on the br inst in %continue.
;
; CHECK: define i32 @test2(
; This is an indication that the loop has been unswitched on %cond1.
; CHECK: br i1 %cond1, label %..split_crit_edge, label %.loop_exit.split_crit_edge
; CHECK: ..split_crit_edge: ; preds = %0
; CHECK: br label %.split
; CHECK: .split: ; preds = %..split_crit_edge
; CHECK: br label %loop_begin
; CHECK: loop_begin: ; preds = %do_something, %.split
; CHECK: switch i32
; CHECK: continue: ; preds = %loop_begin
; CHECK: %var_val = load i32, i32* %var
; CHECK: br i1 true, label %do_something, label %loop_exit
define i32 @test2(i32* %var, i1 %cond1) {
br label %loop_begin
loop_begin:
switch i32 1, label %continue [
i32 0, label %loop_exit
i32 1, label %continue
]
continue:
%var_val = load i32, i32* %var
br i1 %cond1, label %do_something, label %loop_exit
do_something:
call void @some_func() noreturn nounwind
br label %loop_begin
loop_exit:
ret i32 0
}
declare void @some_func() noreturn