[PATCH] D26299: Improving the efficiency of the Loop Unswitching pass
Abhilash Bhandari via llvm-commits
llvm-commits at lists.llvm.org
Fri Nov 4 11:07:28 PDT 2016
Abhilash created this revision.
Abhilash added reviewers: hfinkel, lattner, atrick.
Abhilash added a subscriber: llvm-commits.
Abhilash set the repository for this revision to rL LLVM.
Herald added a subscriber: mzolotukhin.
The existing Loop Unswitching Pass generates an exponential number of loops with respect to the number of unswitched branches.
For any loop, the number of generated loops are n^2 where n is the number of unswitched branches.
The exponential nature of the transformation is an obstacle in generating better unswitched code.
Consider the following testcase:
1: for(int i=0;i<100;i++){
2: if (m)
3: a[i]*=2;
4: else if (n)
5: a[i]*=3;
6:
7: a[i]*=4;
8: }
m and n are loop invariants.
The existing algorithm generates 4 unswitched loops for the following cases:
1. Condition at line 2 is true and Condition at line 4 is true.
2. Condition at line 2 is true and Condition at line 4 is false.
3. Condition at line 2 is false and Condition at line 4 is true.
4. Condition at line 2 is false and Condition at line 4 is false.
However, due to the very nature of the else-if chain, there exists a control dependency between Conditions at line 2 and 4. When the Condition at line 2 is true, the Condition at line 4 is never taken and hence the outcome of the Condition at line 4 is irrelevant (don't care scenario), in this case.
This has not been accounted for, in the existing infrastructure. Currently, two similar loops are generated for cases 1 and 2 leading to redundancy and inefficiency.
It is sufficient, if we handle the following three cases:
1. Condition at line 2 is true.
2. Condition at line 2 is false and Condition at line 4 is true.
3. Condition at line 2 is false and Condition at line 4 is false.
One of the possible solutions, is to find the unreachable branches and eliminate them before unswitching.
The attached patch has the solution implemented in the Loop Unswitching Pass. The choice of this solution (among other possible solutions) is for the following reasons:
1. Eliminating unreachable branches so that many other branches are unswitched out of their enclosing loops (probably, better code).
2. Difficult to handle in the existing CFG Simplification Pass.
Repository:
rL LLVM
https://reviews.llvm.org/D26299
Files:
lib/Transforms/Scalar/LoopUnswitch.cpp
Index: lib/Transforms/Scalar/LoopUnswitch.cpp
===================================================================
--- lib/Transforms/Scalar/LoopUnswitch.cpp
+++ lib/Transforms/Scalar/LoopUnswitch.cpp
@@ -593,6 +593,45 @@
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.
+ */
+ auto *Node = DT->getNode(*I)->getIDom();
+ BasicBlock *DomBB = Node->getBlock();
+ bool isUnreachable = false;
+ while (currentLoop->contains(DomBB)) {
+ BranchInst *BI = dyn_cast<BranchInst> (DomBB->getTerminator());
+
+ if (BI && BI->isConditional()) {
+ Value *Cond = BI->getCondition();
+ BasicBlock *Succ = NULL;
+ if (Cond == ConstantInt::getTrue(Cond->getContext())) {
+ Succ = BI->getSuccessor(1);
+ } else if (Cond == ConstantInt::getFalse(Cond->getContext())){
+ Succ = BI->getSuccessor(0);
+ }
+
+ if (Succ) {
+ BasicBlockEdge UnreachableEdge (BI->getParent(), Succ);
+ if (DT->dominates(UnreachableEdge, *I)) {
+ isUnreachable = true;
+ break;
+ }
+ }
+ }
+
+ if (isUnreachable) break;
+
+ Node = DT->getNode(DomBB)->getIDom();
+ DomBB = Node->getBlock();
+ }
+
+ if (isUnreachable) {
+ DEBUG (dbgs() << "Unreachable branch: " << *TI << " in Function " << (*I)->getParent()->getName() << "\n");
+ continue;
+ }
+
// If this isn't branching on an invariant condition, we can't unswitch
// it.
if (BI->isConditional()) {
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D26299.76914.patch
Type: text/x-patch
Size: 1807 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20161104/31adc4eb/attachment.bin>
More information about the llvm-commits
mailing list