LLVM API Documentation

LoopRotation.cpp

Go to the documentation of this file.
00001 //===- LoopRotation.cpp - Loop Rotation Pass ------------------------------===//
00002 //
00003 //                     The LLVM Compiler Infrastructure
00004 //
00005 // This file is distributed under the University of Illinois Open Source
00006 // License. See LICENSE.TXT for details.
00007 //
00008 //===----------------------------------------------------------------------===//
00009 //
00010 // This file implements Loop Rotation Pass.
00011 //
00012 //===----------------------------------------------------------------------===//
00013 
00014 #define DEBUG_TYPE "loop-rotate"
00015 
00016 #include "llvm/Transforms/Scalar.h"
00017 #include "llvm/Function.h"
00018 #include "llvm/Instructions.h"
00019 #include "llvm/Analysis/LoopInfo.h"
00020 #include "llvm/Analysis/LoopPass.h"
00021 #include "llvm/Analysis/Dominators.h"
00022 #include "llvm/Analysis/ScalarEvolution.h"
00023 #include "llvm/Transforms/Utils/Local.h"
00024 #include "llvm/Transforms/Utils/BasicBlockUtils.h"
00025 #include "llvm/Support/CommandLine.h"
00026 #include "llvm/Support/Debug.h"
00027 #include "llvm/ADT/Statistic.h"
00028 #include "llvm/ADT/SmallVector.h"
00029 
00030 using namespace llvm;
00031 
00032 #define MAX_HEADER_SIZE 16
00033 
00034 STATISTIC(NumRotated, "Number of loops rotated");
00035 namespace {
00036 
00037   class VISIBILITY_HIDDEN RenameData {
00038   public:
00039     RenameData(Instruction *O, Value *P, Instruction *H) 
00040       : Original(O), PreHeader(P), Header(H) { }
00041   public:
00042     Instruction *Original; // Original instruction
00043     Value *PreHeader; // Original pre-header replacement
00044     Instruction *Header; // New header replacement
00045   };
00046   
00047   class VISIBILITY_HIDDEN LoopRotate : public LoopPass {
00048 
00049   public:
00050     static char ID; // Pass ID, replacement for typeid
00051     LoopRotate() : LoopPass(&ID) {}
00052 
00053     // Rotate Loop L as many times as possible. Return true if
00054     // loop is rotated at least once.
00055     bool runOnLoop(Loop *L, LPPassManager &LPM);
00056 
00057     // LCSSA form makes instruction renaming easier.
00058     virtual void getAnalysisUsage(AnalysisUsage &AU) const {
00059       AU.addRequiredID(LoopSimplifyID);
00060       AU.addPreservedID(LoopSimplifyID);
00061       AU.addRequiredID(LCSSAID);
00062       AU.addPreservedID(LCSSAID);
00063       AU.addPreserved<ScalarEvolution>();
00064       AU.addPreserved<LoopInfo>();
00065       AU.addPreserved<DominatorTree>();
00066       AU.addPreserved<DominanceFrontier>();
00067     }
00068 
00069     // Helper functions
00070 
00071     /// Do actual work
00072     bool rotateLoop(Loop *L, LPPassManager &LPM);
00073     
00074     /// Initialize local data
00075     void initialize();
00076 
00077     /// Make sure all Exit block PHINodes have required incoming values.
00078     /// If incoming value is constant or defined outside the loop then
00079     /// PHINode may not have an entry for original pre-header. 
00080     void  updateExitBlock();
00081 
00082     /// Return true if this instruction is used outside original header.
00083     bool usedOutsideOriginalHeader(Instruction *In);
00084 
00085     /// Find Replacement information for instruction. Return NULL if it is
00086     /// not available.
00087     const RenameData *findReplacementData(Instruction *I);
00088 
00089     /// After loop rotation, loop pre-header has multiple sucessors.
00090     /// Insert one forwarding basic block to ensure that loop pre-header
00091     /// has only one successor.
00092     void preserveCanonicalLoopForm(LPPassManager &LPM);
00093 
00094   private:
00095 
00096     Loop *L;
00097     BasicBlock *OrigHeader;
00098     BasicBlock *OrigPreHeader;
00099     BasicBlock *OrigLatch;
00100     BasicBlock *NewHeader;
00101     BasicBlock *Exit;
00102     LPPassManager *LPM_Ptr;
00103     SmallVector<RenameData, MAX_HEADER_SIZE> LoopHeaderInfo;
00104   };
00105 }
00106   
00107 char LoopRotate::ID = 0;
00108 static RegisterPass<LoopRotate> X("loop-rotate", "Rotate Loops");
00109 
00110 LoopPass *llvm::createLoopRotatePass() { return new LoopRotate(); }
00111 
00112 /// Rotate Loop L as many times as possible. Return true if
00113 /// loop is rotated at least once.
00114 bool LoopRotate::runOnLoop(Loop *Lp, LPPassManager &LPM) {
00115 
00116   bool RotatedOneLoop = false;
00117   initialize();
00118   LPM_Ptr = &LPM;
00119 
00120   // One loop can be rotated multiple times.
00121   while (rotateLoop(Lp,LPM)) {
00122     RotatedOneLoop = true;
00123     initialize();
00124   }
00125 
00126   return RotatedOneLoop;
00127 }
00128 
00129 /// Rotate loop LP. Return true if the loop is rotated.
00130 bool LoopRotate::rotateLoop(Loop *Lp, LPPassManager &LPM) {
00131 
00132   L = Lp;
00133 
00134   OrigHeader =  L->getHeader();
00135   OrigPreHeader = L->getLoopPreheader();
00136   OrigLatch = L->getLoopLatch();
00137 
00138   // If loop has only one block then there is not much to rotate.
00139   if (L->getBlocks().size() == 1)
00140     return false;
00141 
00142   assert (OrigHeader && OrigLatch && OrigPreHeader &&
00143           "Loop is not in canonical form");
00144 
00145   // If loop header is not one of the loop exit block then
00146   // either this loop is already rotated or it is not 
00147   // suitable for loop rotation transformations.
00148   if (!L->isLoopExit(OrigHeader))
00149     return false;
00150 
00151   BranchInst *BI = dyn_cast<BranchInst>(OrigHeader->getTerminator());
00152   if (!BI)
00153     return false;
00154   assert (BI->isConditional() && "Branch Instruction is not conditional");
00155 
00156   // Updating PHInodes in loops with multiple exits adds complexity. 
00157   // Keep it simple, and restrict loop rotation to loops with one exit only.
00158   // In future, lift this restriction and support for multiple exits if
00159   // required.
00160   SmallVector<BasicBlock*, 8> ExitBlocks;
00161   L->getExitBlocks(ExitBlocks);
00162   if (ExitBlocks.size() > 1)
00163     return false;
00164 
00165   // Check size of original header and reject
00166   // loop if it is very big.
00167   if (OrigHeader->size() > MAX_HEADER_SIZE)
00168     return false;
00169 
00170   // Now, this loop is suitable for rotation.
00171 
00172   // Find new Loop header. NewHeader is a Header's one and only successor
00173   // that is inside loop.  Header's other successor is out side the
00174   // loop. Otherwise loop is not suitable for rotation.
00175   Exit = BI->getSuccessor(0);
00176   NewHeader = BI->getSuccessor(1);
00177   if (L->contains(Exit))
00178     std::swap(Exit, NewHeader);
00179   assert (NewHeader && "Unable to determine new loop header");
00180   assert(L->contains(NewHeader) && !L->contains(Exit) && 
00181          "Unable to determine loop header and exit blocks");
00182 
00183   // Copy PHI nodes and other instructions from original header
00184   // into original pre-header. Unlike original header, original pre-header is
00185   // not a member of loop. 
00186   //
00187   // New loop header is one and only successor of original header that 
00188   // is inside the loop. All other original header successors are outside 
00189   // the loop. Copy PHI Nodes from original header into new loop header. 
00190   // Add second incoming value, from original loop pre-header into these phi 
00191   // nodes. If a value defined in original header is used outside original 
00192   // header then new loop header will need new phi nodes with two incoming 
00193   // values, one definition from original header and second definition is 
00194   // from original loop pre-header.
00195 
00196   // Remove terminator from Original pre-header. Original pre-header will
00197   // receive a clone of original header terminator as a new terminator.
00198   OrigPreHeader->getInstList().pop_back();
00199   BasicBlock::iterator I = OrigHeader->begin(), E = OrigHeader->end();
00200   PHINode *PN = NULL;
00201   for (; (PN = dyn_cast<PHINode>(I)); ++I) {
00202     Instruction *In = I;
00203 
00204     // PHI nodes are not copied into original pre-header. Instead their values
00205     // are directly propagated.
00206     Value * NPV = PN->getIncomingValueForBlock(OrigPreHeader);
00207 
00208     // Create new PHI node with two incoming values for NewHeader.
00209     // One incoming value is from OrigLatch (through OrigHeader) and 
00210     // second incoming value is from original pre-header.
00211     PHINode *NH = PHINode::Create(In->getType(), In->getName(),
00212                                   NewHeader->begin());
00213     NH->addIncoming(PN->getIncomingValueForBlock(OrigLatch), OrigHeader);
00214     NH->addIncoming(NPV, OrigPreHeader);
00215     
00216     // "In" can be replaced by NH at various places.
00217     LoopHeaderInfo.push_back(RenameData(In, NPV, NH));
00218   }
00219 
00220   // Now, handle non-phi instructions.
00221   for (; I != E; ++I) {
00222     Instruction *In = I;
00223 
00224     assert (!isa<PHINode>(In) && "PHINode is not expected here");
00225     // This is not a PHI instruction. Insert its clone into original pre-header.
00226     // If this instruction is using a value from same basic block then
00227     // update it to use value from cloned instruction.
00228     Instruction *C = In->clone();
00229     C->setName(In->getName());
00230     OrigPreHeader->getInstList().push_back(C);
00231 
00232     for (unsigned opi = 0, e = In->getNumOperands(); opi != e; ++opi) {
00233       if (Instruction *OpPhi = dyn_cast<PHINode>(In->getOperand(opi))) {
00234         if (const RenameData *D = findReplacementData(OpPhi)) {
00235           // This is using values from original header PHI node.
00236           // Here, directly used incoming value from original pre-header.
00237           C->setOperand(opi, D->PreHeader);
00238         }
00239       }
00240       else if (Instruction *OpInsn = 
00241                dyn_cast<Instruction>(In->getOperand(opi))) {
00242         if (const RenameData *D = findReplacementData(OpInsn))
00243           C->setOperand(opi, D->PreHeader);
00244       }
00245     }
00246 
00247 
00248     // If this instruction is used outside this basic block then
00249     // create new PHINode for this instruction.
00250     Instruction *NewHeaderReplacement = NULL;
00251     if (usedOutsideOriginalHeader(In)) {
00252       PHINode *PN = PHINode::Create(In->getType(), In->getName(),
00253                                     NewHeader->begin());
00254       PN->addIncoming(In, OrigHeader);
00255       PN->addIncoming(C, OrigPreHeader);
00256       NewHeaderReplacement = PN;
00257     }
00258     LoopHeaderInfo.push_back(RenameData(In, C, NewHeaderReplacement));
00259   }
00260 
00261   // Rename uses of original header instructions to reflect their new
00262   // definitions (either from original pre-header node or from newly created
00263   // new header PHINodes.
00264   //
00265   // Original header instructions are used in
00266   // 1) Original header:
00267   //
00268   //    If instruction is used in non-phi instructions then it is using
00269   //    defintion from original heder iteself. Do not replace this use
00270   //    with definition from new header or original pre-header.
00271   //
00272   //    If instruction is used in phi node then it is an incoming 
00273   //    value. Rename its use to reflect new definition from new-preheader
00274   //    or new header.
00275   //
00276   // 2) Inside loop but not in original header
00277   //
00278   //    Replace this use to reflect definition from new header.
00279   for(unsigned LHI = 0, LHI_E = LoopHeaderInfo.size(); LHI != LHI_E; ++LHI) {
00280     const RenameData &ILoopHeaderInfo = LoopHeaderInfo[LHI];
00281 
00282     if (!ILoopHeaderInfo.Header)
00283       continue;
00284 
00285     Instruction *OldPhi = ILoopHeaderInfo.Original;
00286     Instruction *NewPhi = ILoopHeaderInfo.Header;
00287 
00288     // Before replacing uses, collect them first, so that iterator is
00289     // not invalidated.
00290     SmallVector<Instruction *, 16> AllUses;
00291     for (Value::use_iterator UI = OldPhi->use_begin(), UE = OldPhi->use_end();
00292          UI != UE; ++UI) {
00293       Instruction *U = cast<Instruction>(UI);
00294       AllUses.push_back(U);
00295     }
00296 
00297     for (SmallVector<Instruction *, 16>::iterator UI = AllUses.begin(), 
00298            UE = AllUses.end(); UI != UE; ++UI) {
00299       Instruction *U = *UI;
00300       BasicBlock *Parent = U->getParent();
00301 
00302       // Used inside original header
00303       if (Parent == OrigHeader) {
00304         // Do not rename uses inside original header non-phi instructions.
00305         PHINode *PU = dyn_cast<PHINode>(U);
00306         if (!PU)
00307           continue;
00308 
00309         // Do not rename uses inside original header phi nodes, if the
00310         // incoming value is for new header.
00311         if (PU->getBasicBlockIndex(NewHeader) != -1
00312             && PU->getIncomingValueForBlock(NewHeader) == U)
00313           continue;
00314         
00315        U->replaceUsesOfWith(OldPhi, NewPhi);
00316        continue;
00317       }
00318 
00319       // Used inside loop, but not in original header.
00320       if (L->contains(U->getParent())) {
00321         if (U != NewPhi)
00322           U->replaceUsesOfWith(OldPhi, NewPhi);
00323         continue;
00324       }
00325       
00326       // Used inside Exit Block. Since we are in LCSSA form, U must be PHINode.
00327       if (U->getParent() == Exit) {
00328         assert (isa<PHINode>(U) && "Use in Exit Block that is not PHINode");
00329         
00330         PHINode *UPhi = cast<PHINode>(U);
00331         // UPhi already has one incoming argument from original header. 
00332         // Add second incoming argument from new Pre header.
00333         UPhi->addIncoming(ILoopHeaderInfo.PreHeader, OrigPreHeader);
00334       } else {
00335         // Used outside Exit block. Create a new PHI node from exit block
00336         // to receive value from ne new header ane pre header.
00337         PHINode *PN = PHINode::Create(U->getType(), U->getName(),
00338                                       Exit->begin());
00339         PN->addIncoming(ILoopHeaderInfo.PreHeader, OrigPreHeader);
00340         PN->addIncoming(OldPhi, OrigHeader);
00341         U->replaceUsesOfWith(OldPhi, PN);
00342       }
00343     }
00344   }
00345   
00346   /// Make sure all Exit block PHINodes have required incoming values.
00347   updateExitBlock();
00348 
00349   // Update CFG
00350 
00351   // Removing incoming branch from loop preheader to original header.
00352   // Now original header is inside the loop.
00353   for (BasicBlock::iterator I = OrigHeader->begin(), E = OrigHeader->end();
00354        I != E; ++I) {
00355     Instruction *In = I;
00356     PHINode *PN = dyn_cast<PHINode>(In);
00357     if (!PN)
00358       break;
00359 
00360     PN->removeIncomingValue(OrigPreHeader);
00361   }
00362 
00363   // Make NewHeader as the new header for the loop.
00364   L->moveToHeader(NewHeader);
00365 
00366   preserveCanonicalLoopForm(LPM);
00367 
00368   NumRotated++;
00369   return true;
00370 }
00371 
00372 /// Make sure all Exit block PHINodes have required incoming values.
00373 /// If incoming value is constant or defined outside the loop then
00374 /// PHINode may not have an entry for original pre-header. 
00375 void LoopRotate::updateExitBlock() {
00376 
00377   for (BasicBlock::iterator I = Exit->begin(), E = Exit->end();
00378        I != E; ++I) {
00379 
00380     PHINode *PN = dyn_cast<PHINode>(I);
00381     if (!PN)
00382       break;
00383 
00384     // There is already one incoming value from original pre-header block.
00385     if (PN->getBasicBlockIndex(OrigPreHeader) != -1)
00386       continue;
00387 
00388     const RenameData *ILoopHeaderInfo;
00389     Value *V = PN->getIncomingValueForBlock(OrigHeader);
00390     if (isa<Instruction>(V) && 
00391         (ILoopHeaderInfo = findReplacementData(cast<Instruction>(V)))) {
00392       assert(ILoopHeaderInfo->PreHeader && "Missing New Preheader Instruction");
00393       PN->addIncoming(ILoopHeaderInfo->PreHeader, OrigPreHeader);
00394     } else {
00395       PN->addIncoming(V, OrigPreHeader);
00396     }
00397   }
00398 }
00399 
00400 /// Initialize local data
00401 void LoopRotate::initialize() {
00402   L = NULL;
00403   OrigHeader = NULL;
00404   OrigPreHeader = NULL;
00405   NewHeader = NULL;
00406   Exit = NULL;
00407 
00408   LoopHeaderInfo.clear();
00409 }
00410 
00411 /// Return true if this instruction is used by any instructions in the loop that
00412 /// aren't in original header.
00413 bool LoopRotate::usedOutsideOriginalHeader(Instruction *In) {
00414 
00415   for (Value::use_iterator UI = In->use_begin(), UE = In->use_end();
00416        UI != UE; ++UI) {
00417     Instruction *U = cast<Instruction>(UI);
00418     if (U->getParent() != OrigHeader) {
00419       if (L->contains(U->getParent()))
00420         return true;
00421     }
00422   }
00423 
00424   return false;
00425 }
00426 
00427 /// Find Replacement information for instruction. Return NULL if it is
00428 /// not available.
00429 const RenameData *LoopRotate::findReplacementData(Instruction *In) {
00430 
00431   // Since LoopHeaderInfo is small, linear walk is OK.
00432   for(unsigned LHI = 0, LHI_E = LoopHeaderInfo.size(); LHI != LHI_E; ++LHI) {
00433     const RenameData &ILoopHeaderInfo = LoopHeaderInfo[LHI];
00434     if (ILoopHeaderInfo.Original == In)
00435       return &ILoopHeaderInfo;
00436   }
00437   return NULL;
00438 }
00439 
00440 /// After loop rotation, loop pre-header has multiple sucessors.
00441 /// Insert one forwarding basic block to ensure that loop pre-header
00442 /// has only one successor.
00443 void LoopRotate::preserveCanonicalLoopForm(LPPassManager &LPM) {
00444 
00445   // Right now original pre-header has two successors, new header and
00446   // exit block. Insert new block between original pre-header and
00447   // new header such that loop's new pre-header has only one successor.
00448   BasicBlock *NewPreHeader = BasicBlock::Create("bb.nph",
00449                                                 OrigHeader->getParent(), 
00450                                                 NewHeader);
00451   LoopInfo &LI = LPM.getAnalysis<LoopInfo>();
00452   if (Loop *PL = LI.getLoopFor(OrigPreHeader))
00453     PL->addBasicBlockToLoop(NewPreHeader, LI.getBase());
00454   BranchInst::Create(NewHeader, NewPreHeader);
00455   
00456   BranchInst *OrigPH_BI = cast<BranchInst>(OrigPreHeader->getTerminator());
00457   if (OrigPH_BI->getSuccessor(0) == NewHeader)
00458     OrigPH_BI->setSuccessor(0, NewPreHeader);
00459   else {
00460     assert (OrigPH_BI->getSuccessor(1) == NewHeader &&
00461             "Unexpected original pre-header terminator");
00462     OrigPH_BI->setSuccessor(1, NewPreHeader);
00463   }
00464   
00465   for (BasicBlock::iterator I = NewHeader->begin(), E = NewHeader->end();
00466        I != E; ++I) {
00467     Instruction *In = I;
00468     PHINode *PN = dyn_cast<PHINode>(In);
00469     if (!PN)
00470       break;
00471 
00472     int index = PN->getBasicBlockIndex(OrigPreHeader);
00473     assert (index != -1 && "Expected incoming value from Original PreHeader");
00474     PN->setIncomingBlock(index, NewPreHeader);
00475     assert (PN->getBasicBlockIndex(OrigPreHeader) == -1 && 
00476             "Expected only one incoming value from Original PreHeader");
00477   }
00478 
00479   if (DominatorTree *DT = getAnalysisToUpdate<DominatorTree>()) {
00480     DT->addNewBlock(NewPreHeader, OrigPreHeader);
00481     DT->changeImmediateDominator(L->getHeader(), NewPreHeader);
00482     DT->changeImmediateDominator(Exit, OrigPreHeader);
00483     for (Loop::block_iterator BI = L->block_begin(), BE = L->block_end();
00484          BI != BE; ++BI) {
00485       BasicBlock *B = *BI;
00486       if (L->getHeader() != B) {
00487         DomTreeNode *Node = DT->getNode(B);
00488         if (Node && Node->getBlock() == OrigHeader)
00489           DT->changeImmediateDominator(*BI, L->getHeader());
00490       }
00491     }
00492     DT->changeImmediateDominator(OrigHeader, OrigLatch);
00493   }
00494 
00495   if(DominanceFrontier *DF = getAnalysisToUpdate<DominanceFrontier>()) {
00496 
00497     // New Preheader's dominance frontier is Exit block.
00498     DominanceFrontier::DomSetType NewPHSet;
00499     NewPHSet.insert(Exit);
00500     DF->addBasicBlock(NewPreHeader, NewPHSet);
00501 
00502     // New Header's dominance frontier now includes itself and Exit block
00503     DominanceFrontier::iterator HeadI = DF->find(L->getHeader());
00504     if (HeadI != DF->end()) {
00505       DominanceFrontier::DomSetType & HeaderSet = HeadI->second;
00506       HeaderSet.clear();
00507       HeaderSet.insert(L->getHeader());
00508       HeaderSet.insert(Exit);
00509     } else {
00510       DominanceFrontier::DomSetType HeaderSet;
00511       HeaderSet.insert(L->getHeader());
00512       HeaderSet.insert(Exit);
00513       DF->addBasicBlock(L->getHeader(), HeaderSet);
00514     }
00515 
00516     // Original header (new Loop Latch)'s dominance frontier is Exit.
00517     DominanceFrontier::iterator LatchI = DF->find(L->getLoopLatch());
00518     if (LatchI != DF->end()) {
00519       DominanceFrontier::DomSetType &LatchSet = LatchI->second;
00520       LatchSet = LatchI->second;
00521       LatchSet.clear();
00522       LatchSet.insert(Exit);
00523     } else {
00524       DominanceFrontier::DomSetType LatchSet;
00525       LatchSet.insert(Exit);
00526       DF->addBasicBlock(L->getHeader(), LatchSet);
00527     }
00528 
00529     // If a loop block dominates new loop latch then its frontier is
00530     // new header and Exit.
00531     BasicBlock *NewLatch = L->getLoopLatch();
00532     DominatorTree *DT = getAnalysisToUpdate<DominatorTree>();
00533     for (Loop::block_iterator BI = L->block_begin(), BE = L->block_end();
00534          BI != BE; ++BI) {
00535       BasicBlock *B = *BI;
00536       if (DT->dominates(B, NewLatch)) {
00537         DominanceFrontier::iterator BDFI = DF->find(B);
00538         if (BDFI != DF->end()) {
00539           DominanceFrontier::DomSetType &BSet = BDFI->second;
00540           BSet = BDFI->second;
00541           BSet.clear();
00542           BSet.insert(L->getHeader());
00543           BSet.insert(Exit);
00544         } else {
00545           DominanceFrontier::DomSetType BSet;
00546           BSet.insert(L->getHeader());
00547           BSet.insert(Exit);
00548           DF->addBasicBlock(B, BSet);
00549         }
00550       }
00551     }
00552   }
00553 
00554   // Preserve canonical loop form, which means Exit block should
00555   // have only one predecessor.
00556   BasicBlock *NExit = SplitEdge(L->getLoopLatch(), Exit, this);
00557 
00558   // Preserve LCSSA.
00559   BasicBlock::iterator I = Exit->begin(), E = Exit->end();
00560   PHINode *PN = NULL;
00561   for (; (PN = dyn_cast<PHINode>(I)); ++I) {
00562     unsigned N = PN->getNumIncomingValues();
00563     for (unsigned index = 0; index < N; ++index)
00564       if (PN->getIncomingBlock(index) == NExit) {
00565         PHINode *NewPN = PHINode::Create(PN->getType(), PN->getName(),
00566                                          NExit->begin());
00567         NewPN->addIncoming(PN->getIncomingValue(index), L->getLoopLatch());
00568         PN->setIncomingValue(index, NewPN);
00569         PN->setIncomingBlock(index, NExit);
00570         break;
00571       }
00572   }
00573 
00574   assert (NewHeader && L->getHeader() == NewHeader 
00575           && "Invalid loop header after loop rotation");
00576   assert (NewPreHeader && L->getLoopPreheader() == NewPreHeader
00577           && "Invalid loop preheader after loop rotation");
00578   assert (L->getLoopLatch() 
00579           && "Invalid loop latch after loop rotation");
00580 
00581 }



This web site is hosted by the Computer Science Department at the University of Illinois at Urbana-Champaign.