#include "llvm/Transforms/Utils/Cloning.h"
#include "llvm/BasicBlock.h"
#include "llvm/Analysis/LoopPass.h"
#include "llvm/Analysis/Dominators.h"
using namespace llvm;
static void CloneDominatorInfo(BasicBlock *BB,
ValueToValueMapTy &VMap,
DominatorTree *DT) {
assert (DT && "DominatorTree is not available");
ValueToValueMapTy::iterator BI = VMap.find(BB);
assert (BI != VMap.end() && "BasicBlock clone is missing");
BasicBlock *NewBB = cast<BasicBlock>(BI->second);
if (DT->getNode(NewBB))
return;
assert (DT->getNode(BB) && "BasicBlock does not have dominator info");
assert (DT->getNode(BB)->getIDom() && "BasicBlock does not have immediate dominator");
BasicBlock *BBDom = DT->getNode(BB)->getIDom()->getBlock();
BasicBlock *NewBBDom = BBDom;
ValueToValueMapTy::iterator BBDomI = VMap.find(BBDom);
if (BBDomI != VMap.end()) {
NewBBDom = cast<BasicBlock>(BBDomI->second);
if (!DT->getNode(NewBBDom))
CloneDominatorInfo(BBDom, VMap, DT);
}
DT->addNewBlock(NewBB, NewBBDom);
}
Loop *llvm::CloneLoop(Loop *OrigL, LPPassManager *LPM, LoopInfo *LI,
ValueToValueMapTy &VMap, Pass *P) {
DominatorTree *DT = NULL;
if (P)
DT = P->getAnalysisIfAvailable<DominatorTree>();
SmallVector<BasicBlock *, 16> NewBlocks;
SmallVector<Loop *, 8> LoopNest;
LoopNest.push_back(OrigL);
Loop *NewParentLoop = NULL;
do {
Loop *L = LoopNest.pop_back_val();
Loop *NewLoop = new Loop();
if (!NewParentLoop)
NewParentLoop = NewLoop;
LPM->insertLoop(NewLoop, L->getParentLoop());
for (Loop::block_iterator I = L->block_begin(), E = L->block_end();
I != E; ++I) {
BasicBlock *BB = *I;
BasicBlock *NewBB = CloneBasicBlock(BB, VMap, ".clone");
VMap[BB] = NewBB;
if (P)
LPM->cloneBasicBlockSimpleAnalysis(BB, NewBB, L);
NewLoop->addBasicBlockToLoop(NewBB, LI->getBase());
NewBlocks.push_back(NewBB);
}
if (DT)
for (Loop::block_iterator I = L->block_begin(), E = L->block_end();
I != E; ++I) {
BasicBlock *BB = *I;
CloneDominatorInfo(BB, VMap, DT);
}
for (Loop::iterator I = L->begin(), E = L->end(); I != E; ++I)
LoopNest.push_back(*I);
} while (!LoopNest.empty());
for(SmallVector<BasicBlock *, 16>::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);
ValueToValueMapTy::iterator OpItr = VMap.find(Op);
if (OpItr != VMap.end())
Insn->setOperand(index, OpItr->second);
}
}
}
BasicBlock *Latch = OrigL->getLoopLatch();
Function *F = Latch->getParent();
F->getBasicBlockList().insert(OrigL->getHeader(),
NewBlocks.begin(), NewBlocks.end());
return NewParentLoop;
}