LLVM 20.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"
17#include "llvm/IR/Constant.h"
19#include "llvm/IR/Function.h"
20#include "llvm/IR/GlobalValue.h"
22#include "llvm/IR/MDBuilder.h"
23#include "llvm/IR/Module.h"
25#include "llvm/Transforms/IPO.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
38STATISTIC(NumRemovals, "Number of functions removed");
39STATISTIC(NumConversions, "Number of functions converted");
40STATISTIC(NumVariables, "Number of global variables removed");
41
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).
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
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 =
85 F.getAddressSpace(), OrigName, F.getParent());
86 F.replaceUsesWithIf(Decl,
87 [&](Use &U) { return !isa<CallBase>(U.getUser()); });
88 ++NumConversions;
89}
90
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);
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.
112 if (F.isDeclaration() || !F.hasAvailableExternallyLinkage())
113 continue;
114
115 if (ConvertToLocal)
117 else
119
120 F.removeDeadConstantUsers();
121 Changed = true;
122 }
123
124 return Changed;
125}
126
130 return PreservedAnalyses::all();
132}
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 bool eliminateAvailableExternally(Module &M)
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)
#define F(x, y, z)
Definition: MD5.cpp:55
Module.h This file contains the declarations for the Module class.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
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:166
A container for analyses that lazily runs them and caches their results.
Definition: PassManager.h:253
This is an important base class in LLVM.
Definition: Constant.h:42
PreservedAnalyses run(Module &M, ModuleAnalysisManager &)
static Function * Create(FunctionType *Ty, LinkageTypes Linkage, unsigned AddrSpace, const Twine &N="", Module *M=nullptr)
Definition: Function.h:172
@ InternalLinkage
Rename collisions when linking (static functions).
Definition: GlobalValue.h:59
@ ExternalLinkage
Externally visible function.
Definition: GlobalValue.h:52
static MDString * get(LLVMContext &Context, StringRef Str)
Definition: Metadata.cpp:606
A Module instance is used to store all the information related to an LLVM module.
Definition: Module.h:65
A set of analyses that are preserved following a run of a transformation pass.
Definition: Analysis.h:111
static PreservedAnalyses none()
Convenience factory function for the empty preserved set.
Definition: Analysis.h:114
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
Definition: Analysis.h:117
A Use represents the edge between a Value definition and its users.
Definition: Use.h:43
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:656
bool isSafeToDestroyConstant(const Constant *C)
It is safe to destroy a constant iff it is only used by constants itself.
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:1749