diff --git a/lib/Transforms/Utils/CloneTrace.cpp b/lib/Transforms/Utils/CloneTrace.cpp new file mode 100644 index 00000000000..e8578c512d2 --- /dev/null +++ b/lib/Transforms/Utils/CloneTrace.cpp @@ -0,0 +1,83 @@ +//===- CloneTrace.cpp - Clone a trace ---------===// +// +// This file implements the CloneTrace interface, which is used +// when writing runtime optimizations. It takes a vector of basic blocks +// removes internal phi nodes, clones the basic blocks, and returns the new +// vector of basic blocks. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Instruction.h" +#include "llvm/BasicBlock.h" +#include "llvm/iPHINode.h" +#include "llvm/Function.h" +#include "llvm/Transforms/Utils/Cloning.h" +#include + + +//Clones the trace (a vector of basic blocks) +std::vector CloneTrace(std::vector &origTrace) { + + std::vector clonedTrace; + std::map ValueMap; + + //First, loop over all the Basic Blocks in the trace and copy + //them using CloneBasicBlock. Also fix the phi nodes during + //this loop. To fix the phi nodes, we delete incoming branches + //that are not in the trace. + for(std::vector::const_iterator T = origTrace.begin(), + End = origTrace.end(); T != End; ++T) { + + //Clone Basic Block + BasicBlock *clonedBlock = CloneBasicBlock(*T, ValueMap); + + //Add it to our new trace + clonedTrace.push_back(clonedBlock); + + //Add this new mapping to our Value Map + ValueMap[*T] = clonedBlock; + + //Add this cloned BB to the old BB's function + (*T)->getParent()->getBasicBlockList().push_back(clonedBlock); + + //Loop over the phi instructions and delete operands + //that are from blocks not in the trace + //only do this if we are NOT the first block + if(T != origTrace.begin()) { + for (BasicBlock::iterator I = clonedBlock->begin(); + PHINode *PN = dyn_cast(I); ++I) { + //get incoming value for the previous BB + Value *V = PN->getIncomingValueForBlock(*(T-1)); + assert(V && "No incoming value from a BasicBlock in our trace!"); + + //remap our phi node to point to incoming value + ValueMap[*&I] = V; + + //remove phi node + clonedBlock->getInstList().erase(PN); + } + } + } + + //Second loop to do the remapping + for(std::vector::const_iterator BB = clonedTrace.begin(), + BE = clonedTrace.end(); BB != BE; ++BB) { + for(BasicBlock::iterator I = (*BB)->begin(); I != (*BB)->end(); ++I) { + + //Loop over all the operands of the instruction + for(unsigned op=0, E = I->getNumOperands(); op != E; ++op) { + const Value *Op = I->getOperand(op); + + //Get it out of the value map + Value *V = ValueMap[Op]; + + //If not in the value map, then its outside our trace so ignore + if(V != 0) + I->setOperand(op,V); + } + } + } + + //return new vector of basic blocks + return clonedTrace; +}