]> granicus.if.org Git - llvm/commitdiff
Constant fold switch inst when looking for trivial conditions to unswitch on.
authorXin Tong <trent.xin.tong@gmail.com>
Fri, 27 Jan 2017 01:42:20 +0000 (01:42 +0000)
committerXin Tong <trent.xin.tong@gmail.com>
Fri, 27 Jan 2017 01:42:20 +0000 (01:42 +0000)
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

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@293250 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Transforms/Scalar/LoopUnswitch.cpp
test/Transforms/LoopUnswitch/trivial-unswitch.ll

index 76fe91884c7b8384229569c7359a44b31256d2b3..d7daab4c666a6182ae94292938d926d46e3c4814 100644 (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;
     }
 
index db3328278dae16d2734d29716a2aba4d0d394b44..2def5b6f03346fab28f1c842bd302800e5cddb9e 100644 (file)
@@ -44,4 +44,48 @@ loop_exit:
   ret i32 0
 }
 
-declare void @some_func() noreturn
\ No newline at end of file
+
+; 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