LLVM 22.0.0git
ElimAvailExtern.cpp
Go to the documentation of this file.
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
15#include "llvm/ADT/STLExtras.h"
16#include "llvm/ADT/Statistic.h"
18#include "llvm/IR/Constant.h"
20#include "llvm/IR/Function.h"
21#include "llvm/IR/GlobalValue.h"
23#include "llvm/IR/MDBuilder.h"
24#include "llvm/IR/Module.h"
28
29using namespace llvm;
30
31#define DEBUG_TYPE "elim-avail-extern"
32
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.
43 "avail-extern-gv-in-addrspace-to-local", cl::Hidden,
45 "Convert available_externally global variables into locals if they are "
46 "in specificed addrspace, renaming them to avoid link-time clashes."));
47
48STATISTIC(NumRemovals, "Number of functions removed");
49STATISTIC(NumFunctionsConverted, "Number of functions converted");
50STATISTIC(NumGlobalVariablesConverted, "Number of global variables converted");
51STATISTIC(NumVariables, "Number of global variables removed");
52
54 // This will set the linkage to external
55 F.deleteBody();
56 ++NumRemovals;
57}
58
59static 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).
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
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 =
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.
110 GV.setName(getNewName(M, GV));
112 ++NumGlobalVariablesConverted;
113}
114
115static 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);
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.
144 if (F.isDeclaration() || !F.hasAvailableExternallyLinkage())
145 continue;
146
147 if (Convert || ConvertToLocal)
149 else
151
152 F.removeDeadConstantUsers();
153 Changed = true;
154 }
155
156 return Changed;
157}
158
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.
169 M, /*Convert=*/(CtxProf && CtxProf->isInSpecializedModule())))
170 return PreservedAnalyses::all();
172}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static std::string getNewName(Module &M, const GlobalValue &GV)
static void convertToLocalCopy(Module &M, Function &F)
Create a copy of the thinlto import, mark it local, and redirect direct calls to the copy.
static cl::opt< bool > ConvertToLocal("avail-extern-to-local", cl::Hidden, cl::desc("Convert available_externally into locals, renaming them " "to avoid link-time clashes."))
void deleteFunction(Function &F)
static cl::opt< unsigned > ConvertGlobalVariableInAddrSpace("avail-extern-gv-in-addrspace-to-local", cl::Hidden, cl::desc("Convert available_externally global variables into locals if they are " "in specificed addrspace, renaming them to avoid link-time clashes."))
static bool eliminateAvailableExternally(Module &M, bool Convert)
Module.h This file contains the declarations for the Module class.
#define F(x, y, z)
Definition: MD5.cpp:55
ModuleAnalysisManager MAM
This file contains some templates that are useful if you are working with the STL at all.
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
Definition: Statistic.h:167
A container for analyses that lazily runs them and caches their results.
Definition: PassManager.h:255
PassT::Result * getCachedResult(IRUnitT &IR) const
Get the cached result of an analysis pass for a given IR unit.
Definition: PassManager.h:431
This is an important base class in LLVM.
Definition: Constant.h:43
PreservedAnalyses run(Module &M, ModuleAnalysisManager &)
static Function * Create(FunctionType *Ty, LinkageTypes Linkage, unsigned AddrSpace, const Twine &N="", Module *M=nullptr)
Definition: Function.h:166
void setLinkage(LinkageTypes LT)
Definition: GlobalValue.h:539
bool hasAvailableExternallyLinkage() const
Definition: GlobalValue.h:514
@ InternalLinkage
Rename collisions when linking (static functions).
Definition: GlobalValue.h:60
@ ExternalLinkage
Externally visible function.
Definition: GlobalValue.h:53
static LLVM_ABI MDString * get(LLVMContext &Context, StringRef Str)
Definition: Metadata.cpp:607
A Module instance is used to store all the information related to an LLVM module.
Definition: Module.h:67
A set of analyses that are preserved following a run of a transformation pass.
Definition: Analysis.h:112
static PreservedAnalyses none()
Convenience factory function for the empty preserved set.
Definition: Analysis.h:115
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
Definition: Analysis.h:118
std::string str() const
str - Get the contents as an std::string.
Definition: StringRef.h:233
A Use represents the edge between a Value definition and its users.
Definition: Use.h:35
LLVM_ABI void setName(const Twine &Name)
Change the name of the value.
Definition: Value.cpp:390
LLVM_ABI StringRef getName() const
Return a constant reference to the value's name.
Definition: Value.cpp:322
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
iterator_range< early_inc_iterator_impl< detail::IterOfRange< RangeT > > > make_early_inc_range(RangeT &&Range)
Make a range that does early increment to allow mutation of the underlying range without disrupting i...
Definition: STLExtras.h:663
bool isSafeToDestroyConstant(const Constant *C)
It is safe to destroy a constant iff it is only used by constants itself.
LLVM_ABI std::string getUniqueModuleId(Module *M)
Produce a unique identifier for this module by taking the MD5 sum of the names of the module's strong...
auto find_if(R &&Range, UnaryPredicate P)
Provide wrappers to std::find_if which take ranges instead of having to pass begin/end explicitly.
Definition: STLExtras.h:1777