[llvm] r287925 - [Loop Unswitch] Patch to selective unswitch only the reachable branch instructions.

Abhilash Bhandari via llvm-commits llvm-commits at lists.llvm.org
Fri Nov 25 06:07:45 PST 2016


Author: abhandari
Date: Fri Nov 25 08:07:44 2016
New Revision: 287925

URL: http://llvm.org/viewvc/llvm-project?rev=287925&view=rev
Log:
[Loop Unswitch] Patch to selective unswitch only the reachable branch instructions.

Summary:
The iterative algorithm for Loop Unswitching may render some of the branches unreachable in the unswitched loops.
Given the exponential nature of the algorithm, this is quite an overhead.
This patch fixes this problem by selectively unswitching only those branches within a loop that are reachable from the loop header.

Reviewers: Michael Zolothukin, Anna Thomas, Weiming Zhao.
Subscribers: llvm-commits.

Differential Revision: http://reviews.llvm.org/D26299

Added:
    llvm/trunk/test/Transforms/LoopUnswitch/elseif-non-exponential-behavior.ll
Modified:
    llvm/trunk/lib/Transforms/Scalar/LoopUnswitch.cpp

Modified: llvm/trunk/lib/Transforms/Scalar/LoopUnswitch.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/LoopUnswitch.cpp?rev=287925&r1=287924&r2=287925&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/Scalar/LoopUnswitch.cpp (original)
+++ llvm/trunk/lib/Transforms/Scalar/LoopUnswitch.cpp Fri Nov 25 08:07:44 2016
@@ -210,7 +210,7 @@ namespace {
 
     bool runOnLoop(Loop *L, LPPassManager &LPM) override;
     bool processCurrentLoop();
-
+    bool isUnreachableDueToPreviousUnswitching(BasicBlock *);
     /// This transformation requires natural loop information & requires that
     /// loop preheaders be inserted into the CFG.
     ///
@@ -483,6 +483,35 @@ bool LoopUnswitch::runOnLoop(Loop *L, LP
   return Changed;
 }
 
+// Return true if the BasicBlock BB is unreachable from the loop header.
+// Return false, otherwise.
+bool LoopUnswitch::isUnreachableDueToPreviousUnswitching(BasicBlock *BB) {
+  auto *Node = DT->getNode(BB)->getIDom();
+  BasicBlock *DomBB = Node->getBlock();
+  while (currentLoop->contains(DomBB)) {
+    BranchInst *BInst = dyn_cast<BranchInst>(DomBB->getTerminator());
+
+    Node = DT->getNode(DomBB)->getIDom();
+    DomBB = Node->getBlock();
+
+    if (!BInst || !BInst->isConditional())
+      continue;
+
+    Value *Cond = BInst->getCondition();
+    if (!isa<ConstantInt>(Cond))
+      continue;
+
+    BasicBlock *UnreachableSucc =
+        Cond == ConstantInt::getTrue(Cond->getContext())
+            ? BInst->getSuccessor(1)
+            : BInst->getSuccessor(0);
+
+    if (DT->dominates(UnreachableSucc, BB))
+      return true;
+  }
+  return false;
+}
+
 /// Do actual work and unswitch loop if possible and profitable.
 bool LoopUnswitch::processCurrentLoop() {
   bool Changed = false;
@@ -593,6 +622,12 @@ bool LoopUnswitch::processCurrentLoop()
       continue;
 
     if (BranchInst *BI = dyn_cast<BranchInst>(TI)) {
+      // Some branches may be rendered unreachable because of previous
+      // unswitching.
+      // Unswitch only those branches that are reachable.
+      if (isUnreachableDueToPreviousUnswitching(*I))
+        continue;
+ 
       // If this isn't branching on an invariant condition, we can't unswitch
       // it.
       if (BI->isConditional()) {

Added: llvm/trunk/test/Transforms/LoopUnswitch/elseif-non-exponential-behavior.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/LoopUnswitch/elseif-non-exponential-behavior.ll?rev=287925&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/LoopUnswitch/elseif-non-exponential-behavior.ll (added)
+++ llvm/trunk/test/Transforms/LoopUnswitch/elseif-non-exponential-behavior.ll Fri Nov 25 08:07:44 2016
@@ -0,0 +1,62 @@
+; RUN: opt -loop-unswitch -S - < %s | FileCheck %s
+
+;CHECK-LABEL: @b
+;CHECK: [[Loop1:for\.end.*]]:                              ; preds = %for.cond.us
+;CHECK-NEXT:  %[[PhiVar1:pdt.*]] = phi i32 [ %pdt.0.us, %for.cond.us ]
+;CHECK: [[Loop2:for\.end.*]]:                     ; preds = %for.cond.us1
+;CHECK-NEXT:  %[[PhiVar2:pdt.*]] = phi i32 [ %pdt.0.us2, %for.cond.us1 ]
+;CHECK: [[Loop3:for\.end.*]]:                        ; preds = %for.cond
+;CHECK-NEXT:  %[[PhiVar3:pdt.*]] = phi i32 [ %pdt.0, %for.cond ]
+;CHECK: [[Join1:for\.end.*]]:                                 ; preds = %[[Loop2]], %[[Loop3]]
+;CHECK-NEXT:  %[[PhiRes1:pdt.*]] = phi i32 [ %[[PhiVar3]], %[[Loop3]] ], [ %[[PhiVar2]], %[[Loop2]] ]
+;CHECK: for.end:                                          ; preds = %[[Loop1]], %[[Join1]]
+;CHECK-NEXT:  %[[PhiRes2:pdt.*]] = phi i32 [ %[[PhiRes1]], %[[Join1]] ], [ %[[PhiVar1]], %[[Loop1]] ]
+;CHECK-NEXT:  ret i32 %[[PhiRes2]]
+
+; Function Attrs: nounwind uwtable
+define i32 @b(i32 %x, i32 %y) #0 {
+entry:
+  br label %for.cond
+
+for.cond:                                         ; preds = %for.inc, %entry
+  %pdt.0 = phi i32 [ 1, %entry ], [ %pdt.2, %for.inc ]
+  %i.0 = phi i32 [ 0, %entry ], [ %inc, %for.inc ]
+  %cmp = icmp slt i32 %i.0, 100
+  br i1 %cmp, label %for.body, label %for.end
+
+for.body:                                         ; preds = %for.cond
+  %tobool = icmp ne i32 %x, 0
+  br i1 %tobool, label %if.then, label %if.else
+
+if.then:                                          ; preds = %for.body
+  %mul = mul nsw i32 %pdt.0, 2
+  br label %if.end6
+
+if.else:                                          ; preds = %for.body
+  %tobool1 = icmp ne i32 %y, 0
+  br i1 %tobool1, label %if.then2, label %if.else4
+
+if.then2:                                         ; preds = %if.else
+  %mul3 = mul nsw i32 %pdt.0, 3
+  br label %if.end
+
+if.else4:                                         ; preds = %if.else
+  %mul5 = mul nsw i32 %pdt.0, 4
+  br label %if.end
+
+if.end:                                           ; preds = %if.else4, %if.then2
+  %pdt.1 = phi i32 [ %mul3, %if.then2 ], [ %mul5, %if.else4 ]
+  br label %if.end6
+
+if.end6:                                          ; preds = %if.end, %if.then
+  %pdt.2 = phi i32 [ %mul, %if.then ], [ %pdt.1, %if.end ]
+  br label %for.inc
+
+for.inc:                                          ; preds = %if.end6
+  %inc = add nsw i32 %i.0, 1
+  br label %for.cond
+
+for.end:                                          ; preds = %for.cond
+  ret i32 %pdt.0
+}
+




More information about the llvm-commits mailing list