[llvm-commits] CVS: llvm/lib/Transforms/Scalar/LoopUnswitch.cpp

Chris Lattner lattner at cs.uiuc.edu
Fri Feb 10 15:16:51 PST 2006



Changes in directory llvm/lib/Transforms/Scalar:

LoopUnswitch.cpp updated: 1.14 -> 1.15
---
Log message:

Reform the unswitching code in terms of edge splitting, not block splitting.


---
Diffs of the changes:  (+67 -49)

 LoopUnswitch.cpp |  116 +++++++++++++++++++++++++++++++------------------------
 1 files changed, 67 insertions(+), 49 deletions(-)


Index: llvm/lib/Transforms/Scalar/LoopUnswitch.cpp
diff -u llvm/lib/Transforms/Scalar/LoopUnswitch.cpp:1.14 llvm/lib/Transforms/Scalar/LoopUnswitch.cpp:1.15
--- llvm/lib/Transforms/Scalar/LoopUnswitch.cpp:1.14	Fri Feb 10 13:08:15 2006
+++ llvm/lib/Transforms/Scalar/LoopUnswitch.cpp	Fri Feb 10 17:16:39 2006
@@ -68,7 +68,7 @@
   private:
     unsigned getLoopUnswitchCost(Loop *L, Value *LIC);
     void VersionLoop(Value *LIC, Loop *L, Loop *&Out1, Loop *&Out2);
-    BasicBlock *SplitBlock(BasicBlock *BB, bool SplitAtTop);
+    BasicBlock *SplitEdge(BasicBlock *From, BasicBlock *To);
     void RewriteLoopBodyWithConditionConstant(Loop *L, Value *LIC, bool Val);
     void UnswitchTrivialCondition(Loop *L, Value *Cond, bool EntersLoopOnCond,
                                   BasicBlock *ExitBlock);
@@ -256,8 +256,6 @@
   // loop.
   for (Loop::block_iterator I = L->block_begin(), E = L->block_end();
        I != E; ++I) {
-    for (BasicBlock::iterator BBI = (*I)->begin(), E = (*I)->end(); 
-         BBI != E; ++BBI)
     TerminatorInst *TI = (*I)->getTerminator();
     // FIXME: Handle invariant select instructions.
     
@@ -329,31 +327,49 @@
   return Changed;
 }
 
-/// SplitBlock - Split the specified basic block into two pieces.  If SplitAtTop
-/// is false, this splits the block so the second half only has an unconditional
-/// branch.  If SplitAtTop is true, it makes it so the first half of the block
-/// only has an unconditional branch in it.
-///
-/// This method updates the LoopInfo for this function to correctly reflect the
-/// CFG changes made.
-///
-/// This routine returns the new basic block that was inserted, which is always
-/// the later part of the block.
-BasicBlock *LoopUnswitch::SplitBlock(BasicBlock *BB, bool SplitAtTop) {
+BasicBlock *LoopUnswitch::SplitEdge(BasicBlock *BB, BasicBlock *Succ) {
+  TerminatorInst *LatchTerm = BB->getTerminator();
+  unsigned SuccNum = 0;
+  for (unsigned i = 0, e = LatchTerm->getNumSuccessors(); ; ++i) {
+    assert(i != e && "Didn't find edge?");
+    if (LatchTerm->getSuccessor(i) == Succ) {
+      SuccNum = i;
+      break;
+    }
+  }
+  
+  // If this is a critical edge, let SplitCriticalEdge do it.
+  if (SplitCriticalEdge(BB->getTerminator(), SuccNum, this))
+    return LatchTerm->getSuccessor(SuccNum);
+
+  // If the edge isn't critical, then BB has a single successor or Succ has a
+  // single pred.  Split the block.
+  BasicBlock *BlockToSplit;
   BasicBlock::iterator SplitPoint;
-  if (!SplitAtTop)
+  if (BasicBlock *SP = Succ->getSinglePredecessor()) {
+    // If the successor only has a single pred, split the top of the successor
+    // block.
+    assert(SP == BB && "CFG broken");
+    BlockToSplit = Succ;
+    SplitPoint = Succ->begin();
+  } else {
+    // Otherwise, if BB has a single successor, split it at the bottom of the
+    // block.
+    assert(BB->getTerminator()->getNumSuccessors() == 1 &&
+           "Should have a single succ!"); 
+    BlockToSplit = BB;
     SplitPoint = BB->getTerminator();
-  else {
-    SplitPoint = BB->begin();
-    while (isa<PHINode>(SplitPoint)) ++SplitPoint;
   }
-  
-  BasicBlock *New = BB->splitBasicBlock(SplitPoint, BB->getName()+".tail");
+
+  BasicBlock *New =
+    BlockToSplit->splitBasicBlock(SplitPoint, 
+                                  BlockToSplit->getName()+".tail");
   // New now lives in whichever loop that BB used to.
-  if (Loop *L = LI->getLoopFor(BB))
+  if (Loop *L = LI->getLoopFor(BlockToSplit))
     L->addBasicBlockToLoop(New, *LI);
   return New;
 }
+  
 
 
 // RemapInstruction - Convert the instruction operands from referencing the
@@ -406,40 +422,21 @@
         << " blocks] in Function " << L->getHeader()->getParent()->getName()
         << " on cond:" << *Cond << "\n");
   
-  // First step, split the preahder, so that we know that there is a safe place
+  // First step, split the preheader, so that we know that there is a safe place
   // to insert the conditional branch.  We will change 'OrigPH' to have a
   // conditional branch on Cond.
   BasicBlock *OrigPH = L->getLoopPreheader();
-  BasicBlock *NewPH = SplitBlock(OrigPH, false);
+  BasicBlock *NewPH = SplitEdge(OrigPH, L->getHeader());
 
   // Now that we have a place to insert the conditional branch, create a place
   // to branch to: this is the exit block out of the loop that we should
   // short-circuit to.
   
-  // Split this block now, so that the loop maintains its exit block.
+  // Split this edge now, so that the loop maintains its exit block.
   assert(!L->contains(ExitBlock) && "Exit block is in the loop?");
-  BasicBlock *NewExit;
-  if (BasicBlock *SinglePred = ExitBlock->getSinglePredecessor()) {
-    assert(SinglePred == L->getLoopLatch() && "Unexpected case");
-    NewExit = SplitBlock(ExitBlock, true);
-  } else {
-    // Otherwise, this is a critical edge.  Split block would split the wrong
-    // edge here, so we use SplitCriticalEdge, which allows us to specify the
-    // edge to split, not just the block.
-    TerminatorInst *LatchTerm = L->getLoopLatch()->getTerminator();
-    unsigned SuccNum = 0;
-    for (unsigned i = 0, e = LatchTerm->getNumSuccessors(); ; ++i) {
-      assert(i != e && "Didn't find edge?");
-      if (LatchTerm->getSuccessor(i) == ExitBlock) {
-        SuccNum = i;
-        break;
-      }
-    }
-    SplitCriticalEdge(LatchTerm, SuccNum, this);
-    NewExit = LatchTerm->getSuccessor(SuccNum);
-    assert(NewExit != ExitBlock && "Edge not split!");
-  }
-  
+  BasicBlock *NewExit = SplitEdge(L->getLoopLatch(), ExitBlock);
+  assert(NewExit != ExitBlock && "Edge not split!");
+    
   // Okay, now we have a position to branch from and a position to branch to, 
   // insert the new conditional branch.
   new BranchInst(EnterOnCond ? NewPH : NewExit, EnterOnCond ? NewExit : NewPH,
@@ -467,12 +464,15 @@
         << " blocks] in Function " << F->getName()
         << " on cond:" << *LIC << "\n");
 
+  // LoopBlocks contains all of the basic blocks of the loop, including the
+  // preheader of the loop, the body of the loop, and the exit blocks of the 
+  // loop, in that order.
   std::vector<BasicBlock*> LoopBlocks;
 
   // First step, split the preheader and exit blocks, and add these blocks to
   // the LoopBlocks list.
   BasicBlock *OrigPreheader = L->getLoopPreheader();
-  LoopBlocks.push_back(SplitBlock(OrigPreheader, false));
+  LoopBlocks.push_back(SplitEdge(OrigPreheader, L->getHeader()));
 
   // We want the loop to come after the preheader, but before the exit blocks.
   LoopBlocks.insert(LoopBlocks.end(), L->block_begin(), L->block_end());
@@ -482,10 +482,28 @@
   std::sort(ExitBlocks.begin(), ExitBlocks.end());
   ExitBlocks.erase(std::unique(ExitBlocks.begin(), ExitBlocks.end()),
                    ExitBlocks.end());
+  // Split all of the edges from inside the loop to their exit blocks.  This
+  // unswitching trivial: no phi nodes to update.
   for (unsigned i = 0, e = ExitBlocks.size(); i != e; ++i) {
-    SplitBlock(ExitBlocks[i], true);
-    LoopBlocks.push_back(ExitBlocks[i]);
+    BasicBlock *ExitBlock = ExitBlocks[i];
+    std::vector<BasicBlock*> Preds(pred_begin(ExitBlock), pred_end(ExitBlock));
+
+    for (unsigned j = 0, e = Preds.size(); j != e; ++j) {
+      assert(L->contains(Preds[j]) &&
+             "All preds of loop exit blocks must be the same loop!");
+      SplitEdge(Preds[j], ExitBlock);
+    }
   }
+  
+  // The exit blocks may have been changed due to edge splitting, recompute.
+  ExitBlocks.clear();
+  L->getExitBlocks(ExitBlocks);
+  std::sort(ExitBlocks.begin(), ExitBlocks.end());
+  ExitBlocks.erase(std::unique(ExitBlocks.begin(), ExitBlocks.end()),
+                   ExitBlocks.end());
+  
+  // Add exit blocks to the loop blocks.
+  LoopBlocks.insert(LoopBlocks.end(), ExitBlocks.begin(), ExitBlocks.end());
 
   // Next step, clone all of the basic blocks that make up the loop (including
   // the loop preheader and exit blocks), keeping track of the mapping between






More information about the llvm-commits mailing list