Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/llvm/lib/Transforms/IPO/ElimAvailExtern.cpp
35269 views
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
134