From 4bc2a0b420c728e77a852bad9721e4edfd4b3f79 Mon Sep 17 00:00:00 2001 From: Devang Patel Date: Fri, 10 Aug 2007 17:59:47 +0000 Subject: [PATCH] Add utility to clone loops. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@40997 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Transforms/Utils/Cloning.h | 9 ++ lib/Transforms/Utils/CloneLoop.cpp | 149 ++++++++++++++++++++++++ 2 files changed, 158 insertions(+) create mode 100644 lib/Transforms/Utils/CloneLoop.cpp diff --git a/include/llvm/Transforms/Utils/Cloning.h b/include/llvm/Transforms/Utils/Cloning.h index 9f1aad7db82..53e47a3c195 100644 --- a/include/llvm/Transforms/Utils/Cloning.h +++ b/include/llvm/Transforms/Utils/Cloning.h @@ -25,6 +25,10 @@ namespace llvm { class Module; class Function; +class Loop; +class LoopInfo; +class Pass; +class LPPassManager; class BasicBlock; class Value; class CallInst; @@ -99,6 +103,11 @@ BasicBlock *CloneBasicBlock(const BasicBlock *BB, ClonedCodeInfo *CodeInfo = 0); +/// CloneLoop - Clone Loop. Clone dominator info for loop insiders. Populate ValueMap +/// using old blocks to new blocks mapping. +Loop *CloneLoop(Loop *L, LPPassManager *LPM, LoopInfo *LI, + DenseMap &ValueMap, Pass *P); + /// CloneFunction - Return a copy of the specified function, but without /// embedding the function into another module. Also, any references specified /// in the ValueMap are changed to refer to their mapped value instead of the diff --git a/lib/Transforms/Utils/CloneLoop.cpp b/lib/Transforms/Utils/CloneLoop.cpp new file mode 100644 index 00000000000..02278b6d282 --- /dev/null +++ b/lib/Transforms/Utils/CloneLoop.cpp @@ -0,0 +1,149 @@ +//===- CloneLoop.cpp - Clone loop nest ------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by Devang Patel and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the CloneLoop interface which makes a copy of a loop. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Transforms/Utils/Cloning.h" +#include "llvm/BasicBlock.h" +#include "llvm/Analysis/LoopPass.h" +#include "llvm/Analysis/Dominators.h" +#include "llvm/ADT/DenseMap.h" + + +using namespace llvm; + +/// CloneDominatorInfo - Clone basicblock's dominator tree and, if available, +/// dominance info. It is expected that basic block is already cloned. +static void CloneDominatorInfo(BasicBlock *BB, + DenseMap &ValueMap, + DominatorTree *DT, + DominanceFrontier *DF) { + + assert (DT && "DominatorTree is not available"); + DenseMap::iterator BI = ValueMap.find(BB); + assert (BI != ValueMap.end() && "BasicBlock clone is missing"); + BasicBlock *NewBB = cast(BI->second); + + // NewBB already got dominator info. + if (DT->getNode(NewBB)) + return; + + assert (DT->getNode(BB) && "BasicBlock does not have dominator info"); + // Entry block is not expected here. Infinite loops are not to cloned. + assert (DT->getNode(BB)->getIDom() && "BasicBlock does not have immediate dominator"); + BasicBlock *BBDom = DT->getNode(BB)->getIDom()->getBlock(); + + // NewBB's dominator is either BB's dominator or BB's dominator's clone. + BasicBlock *NewBBDom = BBDom; + DenseMap::iterator BBDomI = ValueMap.find(BBDom); + if (BBDomI != ValueMap.end()) { + NewBBDom = cast(BBDomI->second); + if (!DT->getNode(NewBBDom)) + CloneDominatorInfo(BBDom, ValueMap, DT, DF); + } + DT->addNewBlock(NewBB, NewBBDom); + + // Copy cloned dominance frontiner set + if (DF) { + DominanceFrontier::DomSetType NewDFSet; + DominanceFrontier::iterator DFI = DF->find(BB); + if ( DFI != DF->end()) { + DominanceFrontier::DomSetType S = DFI->second; + for (DominanceFrontier::DomSetType::iterator I = S.begin(), E = S.end(); + I != E; ++I) { + BasicBlock *DB = *I; + DenseMap::iterator IDM = ValueMap.find(DB); + if (IDM != ValueMap.end()) + NewDFSet.insert(cast(IDM->second)); + else + NewDFSet.insert(DB); + } + } + DF->addBasicBlock(NewBB, NewDFSet); + } +} + +/// CloneLoop - Clone Loop. Clone dominator info. Populate ValueMap +/// using old blocks to new blocks mapping. +Loop *llvm::CloneLoop(Loop *OrigL, LPPassManager *LPM, LoopInfo *LI, + DenseMap &ValueMap, Pass *P) { + + DominatorTree *DT = NULL; + DominanceFrontier *DF = NULL; + if (P) { + DT = P->getAnalysisToUpdate(); + DF = P->getAnalysisToUpdate(); + } + + SmallVector NewBlocks; + SmallVector, 8> LoopNest; + LoopNest.push_back(std::make_pair(OrigL, OrigL->begin())); + + Loop *NewLoop = NULL; + while (!LoopNest.empty()) { + Loop *L = LoopNest.back().first; + Loop::iterator SubLoop = LoopNest.back().second; + + // Handle sub loops. + if (SubLoop != L->end()) { + Loop *SL = *SubLoop; + LoopNest.push_back(std::make_pair(SL, SL->begin())); + } + + LoopNest.pop_back(); + NewLoop = new Loop(); + LPM->insertLoop(NewLoop, L->getParentLoop()); + + // Clone Basic Blocks. + for (Loop::block_iterator I = L->block_begin(), E = L->block_end(); + I != E; ++I) { + BasicBlock *BB = *I; + BasicBlock *NewBB = CloneBasicBlock(BB, ValueMap, ".clone"); + ValueMap[BB] = NewBB; + if (P) + LPM->cloneBasicBlockSimpleAnalysis(BB, NewBB, L); + NewLoop->addBasicBlockToLoop(NewBB, *LI); + NewBlocks.push_back(NewBB); + } + + // Clone dominator info. + if (DT) + for (Loop::block_iterator I = L->block_begin(), E = L->block_end(); + I != E; ++I) { + BasicBlock *BB = *I; + CloneDominatorInfo(BB, ValueMap, DT, DF); + } + + } + + // Remap instructions to reference operands from ValueMap. + for(SmallVector::iterator NBItr = NewBlocks.begin(), + NBE = NewBlocks.end(); NBItr != NBE; ++NBItr) { + BasicBlock *NB = *NBItr; + for(BasicBlock::iterator BI = NB->begin(), BE = NB->end(); + BI != BE; ++BI) { + Instruction *Insn = BI; + for (unsigned index = 0, num_ops = Insn->getNumOperands(); + index != num_ops; ++index) { + Value *Op = Insn->getOperand(index); + DenseMap::iterator OpItr = ValueMap.find(Op); + if (OpItr != ValueMap.end()) + Insn->setOperand(index, OpItr->second); + } + } + } + + BasicBlock *Latch = OrigL->getLoopLatch(); + Function *F = Latch->getParent(); + F->getBasicBlockList().insert(Latch, NewBlocks.begin(), NewBlocks.end()); + + return NewLoop; +}