diff --git a/include/llvm/Transforms/Utils/Cloning.h b/include/llvm/Transforms/Utils/Cloning.h index 49b5e330423..d2dcc3d5910 100644 --- a/include/llvm/Transforms/Utils/Cloning.h +++ b/include/llvm/Transforms/Utils/Cloning.h @@ -37,6 +37,31 @@ class Trace; /// Module *CloneModule(const Module *M); +/// ClonedCodeInfo - This struct can be used to capture information about code +/// being cloned, while it is being cloned. +struct ClonedCodeInfo { + /// ContainsCalls - This is set to true if the cloned code contains a normal + /// call instruction. + bool ContainsCalls; + + /// ContainsUnwinds - This is set to true if the cloned code contains an + /// unwind instruction. + bool ContainsUnwinds; + + /// ContainsDynamicAllocas - This is set to true if the cloned code contains + /// a 'dynamic' alloca. Dynamic allocas are allocas that are either not in + /// the entry block or they are in the entry block but are not a constant + /// size. + bool ContainsDynamicAllocas; + + ClonedCodeInfo() { + ContainsCalls = false; + ContainsUnwinds = false; + ContainsDynamicAllocas = false; + } +}; + + /// CloneBasicBlock - Return a copy of the specified basic block, but without /// embedding the block into a particular function. The block returned is an /// exact copy of the specified basic block, without any remapping having been @@ -61,9 +86,14 @@ Module *CloneModule(const Module *M); /// If you would like the basic block to be auto-inserted into the end of a /// function, you can specify it as the optional fourth parameter. /// +/// If you would like to collect additional information about the cloned +/// function, you can specify a ClonedCodeInfo object with the optional fifth +/// parameter. +/// BasicBlock *CloneBasicBlock(const BasicBlock *BB, std::map &ValueMap, - const char *NameSuffix = "", Function *F = 0); + const char *NameSuffix = "", Function *F = 0, + ClonedCodeInfo *CodeInfo = 0); /// CloneFunction - Return a copy of the specified function, but without @@ -72,16 +102,18 @@ BasicBlock *CloneBasicBlock(const BasicBlock *BB, /// original one. If any of the arguments to the function are in the ValueMap, /// the arguments are deleted from the resultant function. The ValueMap is /// updated to include mappings from all of the instructions and basicblocks in -/// the function from their old to new values. +/// the function from their old to new values. The final argument captures +/// information about the cloned code if non-null. /// Function *CloneFunction(const Function *F, - std::map &ValueMap); + std::map &ValueMap, + ClonedCodeInfo *CodeInfo = 0); /// CloneFunction - Version of the function that doesn't need the ValueMap. /// -inline Function *CloneFunction(const Function *F) { +inline Function *CloneFunction(const Function *F, ClonedCodeInfo *CodeInfo = 0){ std::map ValueMap; - return CloneFunction(F, ValueMap); + return CloneFunction(F, ValueMap, CodeInfo); } /// Clone OldFunc into NewFunc, transforming the old arguments into references @@ -93,7 +125,8 @@ inline Function *CloneFunction(const Function *F) { void CloneFunctionInto(Function *NewFunc, const Function *OldFunc, std::map &ValueMap, std::vector &Returns, - const char *NameSuffix = ""); + const char *NameSuffix = "", + ClonedCodeInfo *CodeInfo = 0); /// CloneTraceInto - Clone T into NewFunc. Original<->clone mapping is diff --git a/lib/Transforms/Utils/CloneFunction.cpp b/lib/Transforms/Utils/CloneFunction.cpp index 7eaf147dc69..f6341fa3cf1 100644 --- a/lib/Transforms/Utils/CloneFunction.cpp +++ b/lib/Transforms/Utils/CloneFunction.cpp @@ -14,8 +14,9 @@ //===----------------------------------------------------------------------===// #include "llvm/Transforms/Utils/Cloning.h" -#include "llvm/Instructions.h" +#include "llvm/Constants.h" #include "llvm/DerivedTypes.h" +#include "llvm/Instructions.h" #include "llvm/Function.h" #include "ValueMapper.h" using namespace llvm; @@ -23,11 +24,14 @@ using namespace llvm; // CloneBasicBlock - See comments in Cloning.h BasicBlock *llvm::CloneBasicBlock(const BasicBlock *BB, std::map &ValueMap, - const char *NameSuffix, Function *F) { + const char *NameSuffix, Function *F, + ClonedCodeInfo *CodeInfo) { BasicBlock *NewBB = new BasicBlock("", F); if (BB->hasName()) NewBB->setName(BB->getName()+NameSuffix); - // Loop over all instructions copying them over... + bool hasCalls = false, hasDynamicAllocas = false, hasStaticAllocas = false; + + // Loop over all instructions, and copy them over. for (BasicBlock::const_iterator II = BB->begin(), IE = BB->end(); II != IE; ++II) { Instruction *NewInst = II->clone(); @@ -35,6 +39,22 @@ BasicBlock *llvm::CloneBasicBlock(const BasicBlock *BB, NewInst->setName(II->getName()+NameSuffix); NewBB->getInstList().push_back(NewInst); ValueMap[II] = NewInst; // Add instruction map to value. + + hasCalls |= isa(II); + if (const AllocaInst *AI = dyn_cast(II)) { + if (isa(AI->getArraySize())) + hasStaticAllocas = true; + else + hasDynamicAllocas = true; + } + } + + if (CodeInfo) { + CodeInfo->ContainsCalls |= hasCalls; + CodeInfo->ContainsUnwinds |= isa(BB->getTerminator()); + CodeInfo->ContainsDynamicAllocas |= hasDynamicAllocas; + CodeInfo->ContainsDynamicAllocas |= hasStaticAllocas && + BB != &BB->getParent()->front(); } return NewBB; } @@ -45,12 +65,12 @@ BasicBlock *llvm::CloneBasicBlock(const BasicBlock *BB, void llvm::CloneFunctionInto(Function *NewFunc, const Function *OldFunc, std::map &ValueMap, std::vector &Returns, - const char *NameSuffix) { + const char *NameSuffix, ClonedCodeInfo *CodeInfo) { assert(NameSuffix && "NameSuffix cannot be null!"); #ifndef NDEBUG - for (Function::const_arg_iterator I = OldFunc->arg_begin(), E = OldFunc->arg_end(); - I != E; ++I) + for (Function::const_arg_iterator I = OldFunc->arg_begin(), + E = OldFunc->arg_end(); I != E; ++I) assert(ValueMap.count(I) && "No mapping from source argument specified!"); #endif @@ -63,7 +83,8 @@ void llvm::CloneFunctionInto(Function *NewFunc, const Function *OldFunc, const BasicBlock &BB = *BI; // Create a new basic block and copy instructions into it! - BasicBlock *CBB = CloneBasicBlock(&BB, ValueMap, NameSuffix, NewFunc); + BasicBlock *CBB = CloneBasicBlock(&BB, ValueMap, NameSuffix, NewFunc, + CodeInfo); ValueMap[&BB] = CBB; // Add basic block mapping. if (ReturnInst *RI = dyn_cast(CBB->getTerminator())) @@ -89,13 +110,15 @@ void llvm::CloneFunctionInto(Function *NewFunc, const Function *OldFunc, /// the function from their old to new values. /// Function *llvm::CloneFunction(const Function *F, - std::map &ValueMap) { + std::map &ValueMap, + ClonedCodeInfo *CodeInfo) { std::vector ArgTypes; // The user might be deleting arguments to the function by specifying them in // the ValueMap. If so, we need to not add the arguments to the arg ty vector // - for (Function::const_arg_iterator I = F->arg_begin(), E = F->arg_end(); I != E; ++I) + for (Function::const_arg_iterator I = F->arg_begin(), E = F->arg_end(); + I != E; ++I) if (ValueMap.count(I) == 0) // Haven't mapped the argument to anything yet? ArgTypes.push_back(I->getType()); @@ -108,14 +131,15 @@ Function *llvm::CloneFunction(const Function *F, // Loop over the arguments, copying the names of the mapped arguments over... Function::arg_iterator DestI = NewF->arg_begin(); - for (Function::const_arg_iterator I = F->arg_begin(), E = F->arg_end(); I != E; ++I) + for (Function::const_arg_iterator I = F->arg_begin(), E = F->arg_end(); + I != E; ++I) if (ValueMap.count(I) == 0) { // Is this argument preserved? DestI->setName(I->getName()); // Copy the name over... ValueMap[I] = DestI++; // Add mapping to ValueMap } std::vector Returns; // Ignore returns cloned... - CloneFunctionInto(NewF, F, ValueMap, Returns); + CloneFunctionInto(NewF, F, ValueMap, Returns, "", CodeInfo); return NewF; }