forked from OSchip/llvm-project
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:
parent
baabda9317
commit
e5f8d643d4
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue