diff --git a/llvm/include/llvm/Transforms/IPO/Attributor.h b/llvm/include/llvm/Transforms/IPO/Attributor.h --- a/llvm/include/llvm/Transforms/IPO/Attributor.h +++ b/llvm/include/llvm/Transforms/IPO/Attributor.h @@ -1535,6 +1535,66 @@ bool checkForAllReadWriteInstructions(function_ref Pred, AbstractAttribute &QueryingAA); + /// Create a shallow wrapper for \p F such that \p F has internal linkage + /// afterwards. It also sets the original \p F 's name to anonymous + /// + /// A wrapper is a function with the same type (and attributes) as \p F + /// that will only call \p F and return the result, if any. + /// + /// Assuming the declaration of looks like: + /// rty F(aty0 arg0, ..., atyN argN); + /// + /// The wrapper will then look as follows: + /// rty wrapper(aty0 arg0, ..., atyN argN) { + /// return F(arg0, ..., argN); + /// } + /// + static void createShallowWrapper(Function &F) { + assert(!F.isDeclaration() && + "Cannot create a wrapper around a declaration!"); + + Module &M = *F.getParent(); + LLVMContext &Ctx = M.getContext(); + FunctionType *FnTy = F.getFunctionType(); + + Function *Wrapper = Function::Create(FnTy, F.getLinkage(), + F.getAddressSpace(), F.getName()); + F.setName(""); // set the inside function anonymous + M.getFunctionList().insert(F.getIterator(), Wrapper); + + F.setLinkage(GlobalValue::InternalLinkage); + + F.replaceAllUsesWith(Wrapper); + assert(F.use_empty() && "Uses remained after wrapper was created!"); + + // Move the COMDAT section to the wrapper. + // TODO: Check if we need to keep it for F as well. + Wrapper->setComdat(F.getComdat()); + F.setComdat(nullptr); + + // Copy all metadata and attributes but keep them on F as well. + SmallVector, 1> MDs; + F.getAllMetadata(MDs); + for (auto MDIt : MDs) + Wrapper->addMetadata(MDIt.first, *MDIt.second); + Wrapper->setAttributes(F.getAttributes()); + + // Create the call in the wrapper. + BasicBlock *EntryBB = BasicBlock::Create(Ctx, "entry", Wrapper); + + SmallVector Args; + Argument *FArgIt = F.arg_begin(); + for (Argument &Arg : Wrapper->args()) { + Args.push_back(&Arg); + Arg.setName((FArgIt++)->getName()); + } + + CallInst *CI = CallInst::Create(&F, Args, "", EntryBB); + CI->setTailCall(true); + CI->addAttribute(AttributeList::FunctionIndex, Attribute::NoInline); + ReturnInst::Create(Ctx, CI->getType()->isVoidTy() ? nullptr : CI, EntryBB); + } + /// Return the data layout associated with the anchor scope. const DataLayout &getDataLayout() const { return InfoCache.DL; } diff --git a/llvm/lib/Transforms/IPO/Attributor.cpp b/llvm/lib/Transforms/IPO/Attributor.cpp --- a/llvm/lib/Transforms/IPO/Attributor.cpp +++ b/llvm/lib/Transforms/IPO/Attributor.cpp @@ -51,7 +51,7 @@ "Number of functions with exact definitions"); STATISTIC(NumFnWithoutExactDefinition, "Number of functions without exact definitions"); -STATISTIC(NumFnShallowWrapperCreated, "Number of shallow wrappers created"); +STATISTIC(NumFnShallowWrappersCreated, "Number of shallow wrappers created"); STATISTIC(NumAttributesTimedOut, "Number of abstract attributes timed out before fixpoint"); STATISTIC(NumAttributesValidFixpoint, @@ -1415,69 +1415,6 @@ return CS; } -/// Create a shallow wrapper for \p F such that \p F has internal linkage -/// afterwards. It also sets the original \p F 's name to anonymous -/// -/// A wrapper is a function with the same type (and attributes) as \p F -/// that will only call \p F and return the result, if any. -/// -/// Assuming the declaration of looks like: -/// rty F(aty0 arg0, ..., atyN argN); -/// -/// The wrapper will then look as follows: -/// rty wrapper(aty0 arg0, ..., atyN argN) { -/// return F(arg0, ..., argN); -/// } -/// -static void createShallowWrapper(Function &F) { - assert(AllowShallowWrappers && - "Cannot create a wrapper if it is not allowed!"); - assert(!F.isDeclaration() && "Cannot create a wrapper around a declaration!"); - - Module &M = *F.getParent(); - LLVMContext &Ctx = M.getContext(); - FunctionType *FnTy = F.getFunctionType(); - - Function *Wrapper = - Function::Create(FnTy, F.getLinkage(), F.getAddressSpace(), F.getName()); - F.setName(""); // set the inside function anonymous - M.getFunctionList().insert(F.getIterator(), Wrapper); - - F.setLinkage(GlobalValue::InternalLinkage); - - F.replaceAllUsesWith(Wrapper); - assert(F.use_empty() && "Uses remained after wrapper was created!"); - - // Move the COMDAT section to the wrapper. - // TODO: Check if we need to keep it for F as well. - Wrapper->setComdat(F.getComdat()); - F.setComdat(nullptr); - - // Copy all metadata and attributes but keep them on F as well. - SmallVector, 1> MDs; - F.getAllMetadata(MDs); - for (auto MDIt : MDs) - Wrapper->addMetadata(MDIt.first, *MDIt.second); - Wrapper->setAttributes(F.getAttributes()); - - // Create the call in the wrapper. - BasicBlock *EntryBB = BasicBlock::Create(Ctx, "entry", Wrapper); - - SmallVector Args; - Argument *FArgIt = F.arg_begin(); - for (Argument &Arg : Wrapper->args()) { - Args.push_back(&Arg); - Arg.setName((FArgIt++)->getName()); - } - - CallInst *CI = CallInst::Create(&F, Args, "", EntryBB); - CI->setTailCall(true); - CI->addAttribute(AttributeList::FunctionIndex, Attribute::NoInline); - ReturnInst::Create(Ctx, CI->getType()->isVoidTy() ? nullptr : CI, EntryBB); - - NumFnShallowWrapperCreated++; -} - /// Make another copy of the function \p F such that the copied version has /// internal linkage afterwards and can be analysed. Then we replace all uses /// of the original function to the copied one @@ -2276,10 +2213,14 @@ Attributor A(Functions, InfoCache, CGUpdater); // Create shallow wrappers for all functions that are not IPO amendable - if (AllowShallowWrappers) - for (Function *F : Functions) - if (!A.isFunctionIPOAmendable(*F)) - createShallowWrapper(*F); + if (AllowShallowWrappers) { + for (Function *F : Functions) { + if (!A.isFunctionIPOAmendable(*F)) { + Attributor::createShallowWrapper(*F); + NumFnShallowWrappersCreated++; + } + } + } // Internalize non-exact functions // TODO: for now we eagerly internalize functions without calculating the