1 //===- ElimAvailExtern.cpp - DCE unreachable internal functions -----------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // This transform is designed to eliminate available external global 10 // definitions from the program, turning them into declarations. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #include "llvm/Transforms/IPO/ElimAvailExtern.h" 15 #include "llvm/ADT/STLExtras.h" 16 #include "llvm/ADT/Statistic.h" 17 #include "llvm/Analysis/CtxProfAnalysis.h" 18 #include "llvm/IR/Constant.h" 19 #include "llvm/IR/DebugInfoMetadata.h" 20 #include "llvm/IR/Function.h" 21 #include "llvm/IR/GlobalValue.h" 22 #include "llvm/IR/GlobalVariable.h" 23 #include "llvm/IR/MDBuilder.h" 24 #include "llvm/IR/Module.h" 25 #include "llvm/Support/CommandLine.h" 26 #include "llvm/Transforms/Utils/GlobalStatus.h" 27 #include "llvm/Transforms/Utils/ModuleUtils.h" 28 29 using namespace llvm; 30 31 #define DEBUG_TYPE "elim-avail-extern" 32 33 static cl::opt<bool> ConvertToLocal( 34 "avail-extern-to-local", cl::Hidden, 35 cl::desc("Convert available_externally into locals, renaming them " 36 "to avoid link-time clashes.")); 37 38 // This option was originally introduced to correctly support the lowering of 39 // LDS variables for AMDGPU when ThinLTO is enabled. It can be utilized for 40 // other purposes, but make sure it is safe to do so, as privatizing global 41 // variables is generally not safe. 42 static cl::opt<unsigned> ConvertGlobalVariableInAddrSpace( 43 "avail-extern-gv-in-addrspace-to-local", cl::Hidden, 44 cl::desc( 45 "Convert available_externally global variables into locals if they are " 46 "in specificed addrspace, renaming them to avoid link-time clashes.")); 47 48 STATISTIC(NumRemovals, "Number of functions removed"); 49 STATISTIC(NumFunctionsConverted, "Number of functions converted"); 50 STATISTIC(NumGlobalVariablesConverted, "Number of global variables converted"); 51 STATISTIC(NumVariables, "Number of global variables removed"); 52 53 void deleteFunction(Function &F) { 54 // This will set the linkage to external 55 F.deleteBody(); 56 ++NumRemovals; 57 } 58 59 static std::string getNewName(Module &M, const GlobalValue &GV) { 60 return GV.getName().str() + ".__uniq" + getUniqueModuleId(&M); 61 } 62 63 /// Create a copy of the thinlto import, mark it local, and redirect direct 64 /// calls to the copy. Only direct calls are replaced, so that e.g. indirect 65 /// call function pointer tests would use the global identity of the function. 66 /// 67 /// Currently, Value Profiling ("VP") MD_prof data isn't updated to refer to the 68 /// clone's GUID (which will be different, because the name and linkage is 69 /// different), under the assumption that the last consumer of this data is 70 /// upstream the pipeline (e.g. ICP). 71 static void convertToLocalCopy(Module &M, Function &F) { 72 assert(F.hasAvailableExternallyLinkage()); 73 assert(!F.isDeclaration()); 74 // If we can't find a single use that's a call, just delete the function. 75 if (F.uses().end() == llvm::find_if(F.uses(), [&](Use &U) { 76 return isa<CallBase>(U.getUser()); 77 })) 78 return deleteFunction(F); 79 80 auto OrigName = F.getName().str(); 81 // Build a new name. We still need the old name (see below). 82 // We could just rely on internal linking allowing 2 modules have internal 83 // functions with the same name, but that just creates more trouble than 84 // necessary e.g. distinguishing profiles or debugging. Instead, we append the 85 // module identifier. 86 std::string NewName = getNewName(M, F); 87 F.setName(NewName); 88 if (auto *SP = F.getSubprogram()) 89 SP->replaceLinkageName(MDString::get(F.getParent()->getContext(), NewName)); 90 91 F.setLinkage(GlobalValue::InternalLinkage); 92 // Now make a declaration for the old name. We'll use it if there are non-call 93 // uses. For those, it would be incorrect to replace them with the local copy: 94 // for example, one such use could be taking the address of the function and 95 // passing it to an external function, which, in turn, might compare the 96 // function pointer to the original (non-local) function pointer, e.g. as part 97 // of indirect call promotion. 98 auto *Decl = 99 Function::Create(F.getFunctionType(), GlobalValue::ExternalLinkage, 100 F.getAddressSpace(), OrigName, F.getParent()); 101 F.replaceUsesWithIf(Decl, 102 [&](Use &U) { return !isa<CallBase>(U.getUser()); }); 103 ++NumFunctionsConverted; 104 } 105 106 /// Similar to the function above, this is to convert an externally available 107 /// global variable to local. 108 static void convertToLocalCopy(Module &M, GlobalVariable &GV) { 109 assert(GV.hasAvailableExternallyLinkage()); 110 GV.setName(getNewName(M, GV)); 111 GV.setLinkage(GlobalValue::InternalLinkage); 112 ++NumGlobalVariablesConverted; 113 } 114 115 static bool eliminateAvailableExternally(Module &M, bool Convert) { 116 bool Changed = false; 117 118 // If a global variable is available externally and in the specified address 119 // space, convert it to local linkage; otherwise, drop its initializer. 120 for (GlobalVariable &GV : M.globals()) { 121 if (!GV.hasAvailableExternallyLinkage()) 122 continue; 123 if (ConvertGlobalVariableInAddrSpace.getNumOccurrences() && 124 GV.getAddressSpace() == ConvertGlobalVariableInAddrSpace && 125 !GV.use_empty()) { 126 convertToLocalCopy(M, GV); 127 Changed = true; 128 continue; 129 } 130 if (GV.hasInitializer()) { 131 Constant *Init = GV.getInitializer(); 132 GV.setInitializer(nullptr); 133 if (isSafeToDestroyConstant(Init)) 134 Init->destroyConstant(); 135 } 136 GV.removeDeadConstantUsers(); 137 GV.setLinkage(GlobalValue::ExternalLinkage); 138 ++NumVariables; 139 Changed = true; 140 } 141 142 // Drop the bodies of available externally functions. 143 for (Function &F : llvm::make_early_inc_range(M)) { 144 if (F.isDeclaration() || !F.hasAvailableExternallyLinkage()) 145 continue; 146 147 if (Convert || ConvertToLocal) 148 convertToLocalCopy(M, F); 149 else 150 deleteFunction(F); 151 152 F.removeDeadConstantUsers(); 153 Changed = true; 154 } 155 156 return Changed; 157 } 158 159 PreservedAnalyses 160 EliminateAvailableExternallyPass::run(Module &M, ModuleAnalysisManager &MAM) { 161 auto *CtxProf = MAM.getCachedResult<CtxProfAnalysis>(M); 162 // Convert to local instead of eliding if we use contextual profiling in this 163 // module. This is because the IPO decisions performed with contextual 164 // information will likely differ from decisions made without. For a function 165 // that's imported, its optimizations will, thus, differ, and be specialized 166 // for this contextual information. Eliding it in favor of the original would 167 // undo these optimizations. 168 if (!eliminateAvailableExternally( 169 M, /*Convert=*/(CtxProf && CtxProf->isInSpecializedModule()))) 170 return PreservedAnalyses::all(); 171 return PreservedAnalyses::none(); 172 } 173