1 //==-LTOInternalize.cpp - LLVM Link Time Optimizer Internalization Utility -==//
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 file defines a helper to run the internalization part of LTO.
11 //===----------------------------------------------------------------------===//
13 #include "llvm/LTO/legacy/UpdateCompilerUsed.h"
14 #include "llvm/Analysis/TargetLibraryInfo.h"
15 #include "llvm/CodeGen/TargetLowering.h"
16 #include "llvm/CodeGen/TargetSubtargetInfo.h"
17 #include "llvm/IR/LegacyPassManager.h"
18 #include "llvm/IR/Mangler.h"
19 #include "llvm/Transforms/Utils/ModuleUtils.h"
25 // Helper class that collects AsmUsed and user supplied libcalls.
26 class PreserveLibCallsAndAsmUsed
{
28 PreserveLibCallsAndAsmUsed(const StringSet
<> &AsmUndefinedRefs
,
29 const TargetMachine
&TM
,
30 std::vector
<GlobalValue
*> &LLVMUsed
)
31 : AsmUndefinedRefs(AsmUndefinedRefs
), TM(TM
), LLVMUsed(LLVMUsed
) {}
33 void findInModule(Module
&TheModule
) {
34 initializeLibCalls(TheModule
);
35 for (Function
&F
: TheModule
)
36 findLibCallsAndAsm(F
);
37 for (GlobalVariable
&GV
: TheModule
.globals())
38 findLibCallsAndAsm(GV
);
39 for (GlobalAlias
&GA
: TheModule
.aliases())
40 findLibCallsAndAsm(GA
);
45 const StringSet
<> &AsmUndefinedRefs
;
46 const TargetMachine
&TM
;
49 llvm::Mangler Mangler
;
53 std::vector
<GlobalValue
*> &LLVMUsed
;
55 // Collect names of runtime library functions. User-defined functions with the
56 // same names are added to llvm.compiler.used to prevent them from being
57 // deleted by optimizations.
58 void initializeLibCalls(const Module
&TheModule
) {
59 TargetLibraryInfoImpl
TLII(Triple(TM
.getTargetTriple()));
60 TargetLibraryInfo
TLI(TLII
);
62 // TargetLibraryInfo has info on C runtime library calls on the current
64 for (unsigned I
= 0, E
= static_cast<unsigned>(LibFunc::NumLibFuncs
);
66 LibFunc F
= static_cast<LibFunc
>(I
);
68 Libcalls
.insert(TLI
.getName(F
));
71 SmallPtrSet
<const TargetLowering
*, 1> TLSet
;
73 for (const Function
&F
: TheModule
) {
74 const TargetLowering
*Lowering
=
75 TM
.getSubtargetImpl(F
)->getTargetLowering();
77 if (Lowering
&& TLSet
.insert(Lowering
).second
)
78 // TargetLowering has info on library calls that CodeGen expects to be
79 // available, both from the C runtime and compiler-rt.
80 for (unsigned I
= 0, E
= static_cast<unsigned>(RTLIB::UNKNOWN_LIBCALL
);
82 if (const char *Name
=
83 Lowering
->getLibcallName(static_cast<RTLIB::Libcall
>(I
)))
84 Libcalls
.insert(Name
);
88 void findLibCallsAndAsm(GlobalValue
&GV
) {
89 // There are no restrictions to apply to declarations.
90 if (GV
.isDeclaration())
93 // There is nothing more restrictive than private linkage.
94 if (GV
.hasPrivateLinkage())
97 // Conservatively append user-supplied runtime library functions (supplied
98 // either directly, or via a function alias) to llvm.compiler.used. These
99 // could be internalized and deleted by optimizations like -globalopt,
100 // causing problems when later optimizations add new library calls (e.g.,
101 // llvm.memset => memset and printf => puts).
102 // Leave it to the linker to remove any dead code (e.g. with -dead_strip).
103 GlobalValue
*FuncAliasee
= nullptr;
104 if (isa
<GlobalAlias
>(GV
)) {
105 auto *A
= cast
<GlobalAlias
>(&GV
);
106 FuncAliasee
= dyn_cast
<Function
>(A
->getAliasee());
108 if ((isa
<Function
>(GV
) || FuncAliasee
) && Libcalls
.count(GV
.getName())) {
109 LLVMUsed
.push_back(&GV
);
113 SmallString
<64> Buffer
;
114 TM
.getNameWithPrefix(Buffer
, &GV
, Mangler
);
115 if (AsmUndefinedRefs
.count(Buffer
))
116 LLVMUsed
.push_back(&GV
);
120 } // namespace anonymous
122 void llvm::updateCompilerUsed(Module
&TheModule
, const TargetMachine
&TM
,
123 const StringSet
<> &AsmUndefinedRefs
) {
124 std::vector
<GlobalValue
*> UsedValues
;
125 PreserveLibCallsAndAsmUsed(AsmUndefinedRefs
, TM
, UsedValues
)
126 .findInModule(TheModule
);
128 if (UsedValues
.empty())
131 appendToCompilerUsed(TheModule
, UsedValues
);