1 //===-- AMDGPUAlwaysInlinePass.cpp - Promote Allocas ----------------------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 /// \file 11 /// This pass marks all internal functions as always_inline and creates 12 /// duplicates of all other functions and marks the duplicates as always_inline. 13 // 14 //===----------------------------------------------------------------------===// 15 16 #include "AMDGPU.h" 17 #include "llvm/IR/Module.h" 18 #include "llvm/Transforms/Utils/Cloning.h" 19 20 using namespace llvm; 21 22 namespace { 23 24 static cl::opt<bool> StressCalls( 25 "amdgpu-stress-function-calls", 26 cl::Hidden, 27 cl::desc("Force all functions to be noinline"), 28 cl::init(false)); 29 30 class AMDGPUAlwaysInline : public ModulePass { 31 bool GlobalOpt; 32 33 public: 34 static char ID; 35 36 AMDGPUAlwaysInline(bool GlobalOpt = false) : 37 ModulePass(ID), GlobalOpt(GlobalOpt) { } 38 bool runOnModule(Module &M) override; 39 StringRef getPassName() const override { return "AMDGPU Always Inline Pass"; } 40 }; 41 42 } // End anonymous namespace 43 44 INITIALIZE_PASS(AMDGPUAlwaysInline, "amdgpu-always-inline", 45 "AMDGPU Inline All Functions", false, false) 46 47 char AMDGPUAlwaysInline::ID = 0; 48 49 bool AMDGPUAlwaysInline::runOnModule(Module &M) { 50 std::vector<GlobalAlias*> AliasesToRemove; 51 std::vector<Function *> FuncsToClone; 52 53 for (GlobalAlias &A : M.aliases()) { 54 if (Function* F = dyn_cast<Function>(A.getAliasee())) { 55 A.replaceAllUsesWith(F); 56 AliasesToRemove.push_back(&A); 57 } 58 } 59 60 if (GlobalOpt) { 61 for (GlobalAlias* A : AliasesToRemove) { 62 A->eraseFromParent(); 63 } 64 } 65 66 auto NewAttr = StressCalls ? Attribute::NoInline : Attribute::AlwaysInline; 67 auto IncompatAttr 68 = StressCalls ? Attribute::AlwaysInline : Attribute::NoInline; 69 70 for (Function &F : M) { 71 if (!F.hasLocalLinkage() && !F.isDeclaration() && !F.use_empty() && 72 !F.hasFnAttribute(IncompatAttr)) 73 FuncsToClone.push_back(&F); 74 } 75 76 for (Function *F : FuncsToClone) { 77 ValueToValueMapTy VMap; 78 Function *NewFunc = CloneFunction(F, VMap); 79 NewFunc->setLinkage(GlobalValue::InternalLinkage); 80 F->replaceAllUsesWith(NewFunc); 81 } 82 83 for (Function &F : M) { 84 if (F.hasLocalLinkage() && !F.hasFnAttribute(IncompatAttr)) { 85 F.addFnAttr(NewAttr); 86 } 87 } 88 return false; 89 } 90 91 ModulePass *llvm::createAMDGPUAlwaysInlinePass(bool GlobalOpt) { 92 return new AMDGPUAlwaysInline(GlobalOpt); 93 } 94