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/IR/Constant.h" 18 #include "llvm/IR/DebugInfoMetadata.h" 19 #include "llvm/IR/Function.h" 20 #include "llvm/IR/GlobalValue.h" 21 #include "llvm/IR/GlobalVariable.h" 22 #include "llvm/IR/MDBuilder.h" 23 #include "llvm/IR/Module.h" 24 #include "llvm/Support/CommandLine.h" 25 #include "llvm/Transforms/IPO.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 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 STATISTIC(NumRemovals, "Number of functions removed"); 39 STATISTIC(NumConversions, "Number of functions converted"); 40 STATISTIC(NumVariables, "Number of global variables removed"); 41 42 void deleteFunction(Function &F) { 43 // This will set the linkage to external 44 F.deleteBody(); 45 ++NumRemovals; 46 } 47 48 /// Create a copy of the thinlto import, mark it local, and redirect direct 49 /// calls to the copy. Only direct calls are replaced, so that e.g. indirect 50 /// call function pointer tests would use the global identity of the function. 51 /// 52 /// Currently, Value Profiling ("VP") MD_prof data isn't updated to refer to the 53 /// clone's GUID (which will be different, because the name and linkage is 54 /// different), under the assumption that the last consumer of this data is 55 /// upstream the pipeline (e.g. ICP). 56 static void convertToLocalCopy(Module &M, Function &F) { 57 assert(F.hasAvailableExternallyLinkage()); 58 assert(!F.isDeclaration()); 59 // If we can't find a single use that's a call, just delete the function. 60 if (F.uses().end() == llvm::find_if(F.uses(), [&](Use &U) { 61 return isa<CallBase>(U.getUser()); 62 })) 63 return deleteFunction(F); 64 65 auto OrigName = F.getName().str(); 66 // Build a new name. We still need the old name (see below). 67 // We could just rely on internal linking allowing 2 modules have internal 68 // functions with the same name, but that just creates more trouble than 69 // necessary e.g. distinguishing profiles or debugging. Instead, we append the 70 // module identifier. 71 auto NewName = OrigName + ".__uniq" + getUniqueModuleId(&M); 72 F.setName(NewName); 73 if (auto *SP = F.getSubprogram()) 74 SP->replaceLinkageName(MDString::get(F.getParent()->getContext(), NewName)); 75 76 F.setLinkage(GlobalValue::InternalLinkage); 77 // Now make a declaration for the old name. We'll use it if there are non-call 78 // uses. For those, it would be incorrect to replace them with the local copy: 79 // for example, one such use could be taking the address of the function and 80 // passing it to an external function, which, in turn, might compare the 81 // function pointer to the original (non-local) function pointer, e.g. as part 82 // of indirect call promotion. 83 auto *Decl = 84 Function::Create(F.getFunctionType(), GlobalValue::ExternalLinkage, 85 F.getAddressSpace(), OrigName, F.getParent()); 86 F.replaceUsesWithIf(Decl, 87 [&](Use &U) { return !isa<CallBase>(U.getUser()); }); 88 ++NumConversions; 89 } 90 91 static bool eliminateAvailableExternally(Module &M) { 92 bool Changed = false; 93 94 // Drop initializers of available externally global variables. 95 for (GlobalVariable &GV : M.globals()) { 96 if (!GV.hasAvailableExternallyLinkage()) 97 continue; 98 if (GV.hasInitializer()) { 99 Constant *Init = GV.getInitializer(); 100 GV.setInitializer(nullptr); 101 if (isSafeToDestroyConstant(Init)) 102 Init->destroyConstant(); 103 } 104 GV.removeDeadConstantUsers(); 105 GV.setLinkage(GlobalValue::ExternalLinkage); 106 ++NumVariables; 107 Changed = true; 108 } 109 110 // Drop the bodies of available externally functions. 111 for (Function &F : llvm::make_early_inc_range(M)) { 112 if (F.isDeclaration() || !F.hasAvailableExternallyLinkage()) 113 continue; 114 115 if (ConvertToLocal) 116 convertToLocalCopy(M, F); 117 else 118 deleteFunction(F); 119 120 F.removeDeadConstantUsers(); 121 Changed = true; 122 } 123 124 return Changed; 125 } 126 127 PreservedAnalyses 128 EliminateAvailableExternallyPass::run(Module &M, ModuleAnalysisManager &) { 129 if (!eliminateAvailableExternally(M)) 130 return PreservedAnalyses::all(); 131 return PreservedAnalyses::none(); 132 } 133