1 //===- ElimAvailExtern.cpp - DCE unreachable internal functions -----------===//
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
7 //===----------------------------------------------------------------------===//
9 // This transform is designed to eliminate available external global
10 // definitions from the program, turning them into declarations.
12 //===----------------------------------------------------------------------===//
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"
31 #define DEBUG_TYPE "elim-avail-extern"
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."));
38 STATISTIC(NumRemovals
, "Number of functions removed");
39 STATISTIC(NumConversions
, "Number of functions converted");
40 STATISTIC(NumVariables
, "Number of global variables removed");
42 void deleteFunction(Function
&F
) {
43 // This will set the linkage to external
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.
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());
63 return deleteFunction(F
);
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
71 auto NewName
= OrigName
+ ".__uniq" + getUniqueModuleId(&M
);
73 if (auto *SP
= F
.getSubprogram())
74 SP
->replaceLinkageName(MDString::get(F
.getParent()->getContext(), NewName
));
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.
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()); });
91 static bool eliminateAvailableExternally(Module
&M
) {
94 // Drop initializers of available externally global variables.
95 for (GlobalVariable
&GV
: M
.globals()) {
96 if (!GV
.hasAvailableExternallyLinkage())
98 if (GV
.hasInitializer()) {
99 Constant
*Init
= GV
.getInitializer();
100 GV
.setInitializer(nullptr);
101 if (isSafeToDestroyConstant(Init
))
102 Init
->destroyConstant();
104 GV
.removeDeadConstantUsers();
105 GV
.setLinkage(GlobalValue::ExternalLinkage
);
110 // Drop the bodies of available externally functions.
111 for (Function
&F
: llvm::make_early_inc_range(M
)) {
112 if (F
.isDeclaration() || !F
.hasAvailableExternallyLinkage())
116 convertToLocalCopy(M
, F
);
120 F
.removeDeadConstantUsers();
128 EliminateAvailableExternallyPass::run(Module
&M
, ModuleAnalysisManager
&) {
129 if (!eliminateAvailableExternally(M
))
130 return PreservedAnalyses::all();
131 return PreservedAnalyses::none();