//===-- AMDGPUAlwaysInlinePass.cpp - Promote Allocas ----------------------===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // /// \file /// This pass marks all internal functions as always_inline and creates /// duplicates of all other functions and marks the duplicates as always_inline. // //===----------------------------------------------------------------------===// #include "AMDGPU.h" #include "llvm/IR/Module.h" #include "llvm/Transforms/Utils/Cloning.h" using namespace llvm; namespace { static cl::opt StressCalls( "amdgpu-stress-function-calls", cl::Hidden, cl::desc("Force all functions to be noinline"), cl::init(false)); class AMDGPUAlwaysInline : public ModulePass { bool GlobalOpt; public: static char ID; AMDGPUAlwaysInline(bool GlobalOpt = false) : ModulePass(ID), GlobalOpt(GlobalOpt) { } bool runOnModule(Module &M) override; StringRef getPassName() const override { return "AMDGPU Always Inline Pass"; } }; } // End anonymous namespace INITIALIZE_PASS(AMDGPUAlwaysInline, "amdgpu-always-inline", "AMDGPU Inline All Functions", false, false) char AMDGPUAlwaysInline::ID = 0; bool AMDGPUAlwaysInline::runOnModule(Module &M) { std::vector AliasesToRemove; std::vector FuncsToClone; for (GlobalAlias &A : M.aliases()) { if (Function* F = dyn_cast(A.getAliasee())) { A.replaceAllUsesWith(F); AliasesToRemove.push_back(&A); } } if (GlobalOpt) { for (GlobalAlias* A : AliasesToRemove) { A->eraseFromParent(); } } auto NewAttr = StressCalls ? Attribute::NoInline : Attribute::AlwaysInline; auto IncompatAttr = StressCalls ? Attribute::AlwaysInline : Attribute::NoInline; for (Function &F : M) { if (!F.hasLocalLinkage() && !F.isDeclaration() && !F.use_empty() && !F.hasFnAttribute(IncompatAttr)) FuncsToClone.push_back(&F); } for (Function *F : FuncsToClone) { ValueToValueMapTy VMap; Function *NewFunc = CloneFunction(F, VMap); NewFunc->setLinkage(GlobalValue::InternalLinkage); F->replaceAllUsesWith(NewFunc); } for (Function &F : M) { if (F.hasLocalLinkage() && !F.hasFnAttribute(IncompatAttr)) { F.addFnAttr(NewAttr); } } return false; } ModulePass *llvm::createAMDGPUAlwaysInlinePass(bool GlobalOpt) { return new AMDGPUAlwaysInline(GlobalOpt); }