diff options
| author | Dimitry Andric <dim@FreeBSD.org> | 2014-11-24 09:08:18 +0000 | 
|---|---|---|
| committer | Dimitry Andric <dim@FreeBSD.org> | 2014-11-24 09:08:18 +0000 | 
| commit | 5ca98fd98791947eba83a1ed3f2c8191ef7afa6c (patch) | |
| tree | f5944309621cee4fe0976be6f9ac619b7ebfc4c2 /lib/Transforms/Utils/CloneFunction.cpp | |
| parent | 68bcb7db193e4bc81430063148253d30a791023e (diff) | |
Notes
Diffstat (limited to 'lib/Transforms/Utils/CloneFunction.cpp')
| -rw-r--r-- | lib/Transforms/Utils/CloneFunction.cpp | 106 | 
1 files changed, 80 insertions, 26 deletions
diff --git a/lib/Transforms/Utils/CloneFunction.cpp b/lib/Transforms/Utils/CloneFunction.cpp index d105f5e24a2b..5c8f20d5f884 100644 --- a/lib/Transforms/Utils/CloneFunction.cpp +++ b/lib/Transforms/Utils/CloneFunction.cpp @@ -17,8 +17,9 @@  #include "llvm/ADT/SmallVector.h"  #include "llvm/Analysis/ConstantFolding.h"  #include "llvm/Analysis/InstructionSimplify.h" -#include "llvm/DebugInfo.h" +#include "llvm/IR/CFG.h"  #include "llvm/IR/Constants.h" +#include "llvm/IR/DebugInfo.h"  #include "llvm/IR/DerivedTypes.h"  #include "llvm/IR/Function.h"  #include "llvm/IR/GlobalVariable.h" @@ -26,7 +27,7 @@  #include "llvm/IR/IntrinsicInst.h"  #include "llvm/IR/LLVMContext.h"  #include "llvm/IR/Metadata.h" -#include "llvm/Support/CFG.h" +#include "llvm/IR/Module.h"  #include "llvm/Transforms/Utils/BasicBlockUtils.h"  #include "llvm/Transforms/Utils/Local.h"  #include "llvm/Transforms/Utils/ValueMapper.h" @@ -88,26 +89,28 @@ void llvm::CloneFunctionInto(Function *NewFunc, const Function *OldFunc,      assert(VMap.count(I) && "No mapping from source argument specified!");  #endif +  // Copy all attributes other than those stored in the AttributeSet.  We need +  // to remap the parameter indices of the AttributeSet. +  AttributeSet NewAttrs = NewFunc->getAttributes(); +  NewFunc->copyAttributesFrom(OldFunc); +  NewFunc->setAttributes(NewAttrs); +    AttributeSet OldAttrs = OldFunc->getAttributes();    // Clone any argument attributes that are present in the VMap. -  for (Function::const_arg_iterator I = OldFunc->arg_begin(), -                                    E = OldFunc->arg_end(); -       I != E; ++I) -    if (Argument *Anew = dyn_cast<Argument>(VMap[I])) { +  for (const Argument &OldArg : OldFunc->args()) +    if (Argument *NewArg = dyn_cast<Argument>(VMap[&OldArg])) {        AttributeSet attrs = -          OldAttrs.getParamAttributes(I->getArgNo() + 1); +          OldAttrs.getParamAttributes(OldArg.getArgNo() + 1);        if (attrs.getNumSlots() > 0) -        Anew->addAttr(attrs); +        NewArg->addAttr(attrs);      } -  NewFunc->setAttributes(NewFunc->getAttributes() -                         .addAttributes(NewFunc->getContext(), -                                        AttributeSet::ReturnIndex, -                                        OldAttrs.getRetAttributes())); -  NewFunc->setAttributes(NewFunc->getAttributes() -                         .addAttributes(NewFunc->getContext(), -                                        AttributeSet::FunctionIndex, -                                        OldAttrs.getFnAttributes())); +  NewFunc->setAttributes( +      NewFunc->getAttributes() +          .addAttributes(NewFunc->getContext(), AttributeSet::ReturnIndex, +                         OldAttrs.getRetAttributes()) +          .addAttributes(NewFunc->getContext(), AttributeSet::FunctionIndex, +                         OldAttrs.getFnAttributes()));    // Loop over all of the basic blocks in the function, cloning them as    // appropriate.  Note that we save BE this way in order to handle cloning of @@ -151,6 +154,54 @@ void llvm::CloneFunctionInto(Function *NewFunc, const Function *OldFunc,                         TypeMapper, Materializer);  } +// Find the MDNode which corresponds to the DISubprogram data that described F. +static MDNode* FindSubprogram(const Function *F, DebugInfoFinder &Finder) { +  for (DISubprogram Subprogram : Finder.subprograms()) { +    if (Subprogram.describes(F)) return Subprogram; +  } +  return nullptr; +} + +// Add an operand to an existing MDNode. The new operand will be added at the +// back of the operand list. +static void AddOperand(MDNode *Node, Value *Operand) { +  SmallVector<Value*, 16> Operands; +  for (unsigned i = 0; i < Node->getNumOperands(); i++) { +    Operands.push_back(Node->getOperand(i)); +  } +  Operands.push_back(Operand); +  MDNode *NewNode = MDNode::get(Node->getContext(), Operands); +  Node->replaceAllUsesWith(NewNode); +} + +// Clone the module-level debug info associated with OldFunc. The cloned data +// will point to NewFunc instead. +static void CloneDebugInfoMetadata(Function *NewFunc, const Function *OldFunc, +                            ValueToValueMapTy &VMap) { +  DebugInfoFinder Finder; +  Finder.processModule(*OldFunc->getParent()); + +  const MDNode *OldSubprogramMDNode = FindSubprogram(OldFunc, Finder); +  if (!OldSubprogramMDNode) return; + +  // Ensure that OldFunc appears in the map. +  // (if it's already there it must point to NewFunc anyway) +  VMap[OldFunc] = NewFunc; +  DISubprogram NewSubprogram(MapValue(OldSubprogramMDNode, VMap)); + +  for (DICompileUnit CU : Finder.compile_units()) { +    DIArray Subprograms(CU.getSubprograms()); + +    // If the compile unit's function list contains the old function, it should +    // also contain the new one. +    for (unsigned i = 0; i < Subprograms.getNumElements(); i++) { +      if ((MDNode*)Subprograms.getElement(i) == OldSubprogramMDNode) { +        AddOperand(Subprograms, NewSubprogram); +      } +    } +  } +} +  /// CloneFunction - Return a copy of the specified function, but without  /// embedding the function into another module.  Also, any references specified  /// in the VMap are changed to refer to their mapped value instead of the @@ -188,6 +239,9 @@ Function *llvm::CloneFunction(const Function *F, ValueToValueMapTy &VMap,        VMap[I] = DestI++;        // Add mapping to VMap      } +  if (ModuleLevelChanges) +    CloneDebugInfoMetadata(NewF, F, VMap); +    SmallVector<ReturnInst*, 8> Returns;  // Ignore returns cloned.    CloneFunctionInto(NewF, F, VMap, ModuleLevelChanges, Returns, "", CodeInfo);    return NewF; @@ -205,17 +259,17 @@ namespace {      bool ModuleLevelChanges;      const char *NameSuffix;      ClonedCodeInfo *CodeInfo; -    const DataLayout *TD; +    const DataLayout *DL;    public:      PruningFunctionCloner(Function *newFunc, const Function *oldFunc,                            ValueToValueMapTy &valueMap,                            bool moduleLevelChanges,                            const char *nameSuffix,                             ClonedCodeInfo *codeInfo, -                          const DataLayout *td) +                          const DataLayout *DL)      : NewFunc(newFunc), OldFunc(oldFunc),        VMap(valueMap), ModuleLevelChanges(moduleLevelChanges), -      NameSuffix(nameSuffix), CodeInfo(codeInfo), TD(td) { +      NameSuffix(nameSuffix), CodeInfo(codeInfo), DL(DL) {      }      /// CloneBlock - The specified block is found to be reachable, clone it and @@ -272,7 +326,7 @@ void PruningFunctionCloner::CloneBlock(const BasicBlock *BB,        // If we can simplify this instruction to some other value, simply add        // a mapping to that value rather than inserting a new instruction into        // the basic block. -      if (Value *V = SimplifyInstruction(NewInst, TD)) { +      if (Value *V = SimplifyInstruction(NewInst, DL)) {          // On the off-chance that this simplifies to an instruction in the old          // function, map it back into the new function.          if (Value *MappedV = VMap.lookup(V)) @@ -305,7 +359,7 @@ void PruningFunctionCloner::CloneBlock(const BasicBlock *BB,        // If the condition was a known constant in the callee...        ConstantInt *Cond = dyn_cast<ConstantInt>(BI->getCondition());        // Or is a known constant in the caller... -      if (Cond == 0) { +      if (!Cond) {          Value *V = VMap[BI->getCondition()];          Cond = dyn_cast_or_null<ConstantInt>(V);        } @@ -321,7 +375,7 @@ void PruningFunctionCloner::CloneBlock(const BasicBlock *BB,    } else if (const SwitchInst *SI = dyn_cast<SwitchInst>(OldTI)) {      // If switching on a value known constant in the caller.      ConstantInt *Cond = dyn_cast<ConstantInt>(SI->getCondition()); -    if (Cond == 0) { // Or known constant after constant prop in the callee... +    if (!Cond) { // Or known constant after constant prop in the callee...        Value *V = VMap[SI->getCondition()];        Cond = dyn_cast_or_null<ConstantInt>(V);      } @@ -368,7 +422,7 @@ void llvm::CloneAndPruneFunctionInto(Function *NewFunc, const Function *OldFunc,                                       SmallVectorImpl<ReturnInst*> &Returns,                                       const char *NameSuffix,                                        ClonedCodeInfo *CodeInfo, -                                     const DataLayout *TD, +                                     const DataLayout *DL,                                       Instruction *TheCall) {    assert(NameSuffix && "NameSuffix cannot be null!"); @@ -379,7 +433,7 @@ void llvm::CloneAndPruneFunctionInto(Function *NewFunc, const Function *OldFunc,  #endif    PruningFunctionCloner PFC(NewFunc, OldFunc, VMap, ModuleLevelChanges, -                            NameSuffix, CodeInfo, TD); +                            NameSuffix, CodeInfo, DL);    // Clone the entry block, and anything recursively reachable from it.    std::vector<const BasicBlock*> CloneWorklist; @@ -400,7 +454,7 @@ void llvm::CloneAndPruneFunctionInto(Function *NewFunc, const Function *OldFunc,         BI != BE; ++BI) {      Value *V = VMap[BI];      BasicBlock *NewBB = cast_or_null<BasicBlock>(V); -    if (NewBB == 0) continue;  // Dead block. +    if (!NewBB) continue;  // Dead block.      // Add the new block to the new function.      NewFunc->getBasicBlockList().push_back(NewBB); @@ -509,7 +563,7 @@ void llvm::CloneAndPruneFunctionInto(Function *NewFunc, const Function *OldFunc,    // node).    for (unsigned Idx = 0, Size = PHIToResolve.size(); Idx != Size; ++Idx)      if (PHINode *PN = dyn_cast<PHINode>(VMap[PHIToResolve[Idx]])) -      recursivelySimplifyInstruction(PN, TD); +      recursivelySimplifyInstruction(PN, DL);    // Now that the inlined function body has been fully constructed, go through    // and zap unconditional fall-through branches.  This happen all the time when  | 
