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/Mangler.h"
18 #include "llvm/IR/Module.h"
19 #include "llvm/Target/TargetMachine.h"
20 #include "llvm/Transforms/Utils/ModuleUtils.h"
26 // Helper class that collects AsmUsed and user supplied libcalls.
27 class PreserveLibCallsAndAsmUsed
{
29 PreserveLibCallsAndAsmUsed(const StringSet
<> &AsmUndefinedRefs
,
30 const TargetMachine
&TM
,
31 std::vector
<GlobalValue
*> &LLVMUsed
)
32 : AsmUndefinedRefs(AsmUndefinedRefs
), TM(TM
), LLVMUsed(LLVMUsed
) {}
34 void findInModule(Module
&TheModule
) {
35 initializeLibCalls(TheModule
);
36 for (Function
&F
: TheModule
)
37 findLibCallsAndAsm(F
);
38 for (GlobalVariable
&GV
: TheModule
.globals())
39 findLibCallsAndAsm(GV
);
40 for (GlobalAlias
&GA
: TheModule
.aliases())
41 findLibCallsAndAsm(GA
);
46 const StringSet
<> &AsmUndefinedRefs
;
47 const TargetMachine
&TM
;
50 llvm::Mangler Mangler
;
54 std::vector
<GlobalValue
*> &LLVMUsed
;
56 // Collect names of runtime library functions. User-defined functions with the
57 // same names are added to llvm.compiler.used to prevent them from being
58 // deleted by optimizations.
59 void initializeLibCalls(const Module
&TheModule
) {
60 TargetLibraryInfoImpl
TLII(Triple(TM
.getTargetTriple()));
61 TargetLibraryInfo
TLI(TLII
);
63 // TargetLibraryInfo has info on C runtime library calls on the current
65 for (unsigned I
= 0, E
= static_cast<unsigned>(LibFunc::NumLibFuncs
);
67 LibFunc F
= static_cast<LibFunc
>(I
);
69 Libcalls
.insert(TLI
.getName(F
));
72 SmallPtrSet
<const TargetLowering
*, 1> TLSet
;
74 for (const Function
&F
: TheModule
) {
75 const TargetLowering
*Lowering
=
76 TM
.getSubtargetImpl(F
)->getTargetLowering();
78 if (Lowering
&& TLSet
.insert(Lowering
).second
)
79 // TargetLowering has info on library calls that CodeGen expects to be
80 // available, both from the C runtime and compiler-rt.
81 for (unsigned I
= 0, E
= static_cast<unsigned>(RTLIB::UNKNOWN_LIBCALL
);
83 if (const char *Name
=
84 Lowering
->getLibcallName(static_cast<RTLIB::Libcall
>(I
)))
85 Libcalls
.insert(Name
);
89 void findLibCallsAndAsm(GlobalValue
&GV
) {
90 // There are no restrictions to apply to declarations.
91 if (GV
.isDeclaration())
94 // There is nothing more restrictive than private linkage.
95 if (GV
.hasPrivateLinkage())
98 // Conservatively append user-supplied runtime library functions (supplied
99 // either directly, or via a function alias) to llvm.compiler.used. These
100 // could be internalized and deleted by optimizations like -globalopt,
101 // causing problems when later optimizations add new library calls (e.g.,
102 // llvm.memset => memset and printf => puts).
103 // Leave it to the linker to remove any dead code (e.g. with -dead_strip).
104 GlobalValue
*FuncAliasee
= nullptr;
105 if (isa
<GlobalAlias
>(GV
)) {
106 auto *A
= cast
<GlobalAlias
>(&GV
);
107 FuncAliasee
= dyn_cast
<Function
>(A
->getAliasee());
109 if ((isa
<Function
>(GV
) || FuncAliasee
) && Libcalls
.count(GV
.getName())) {
110 LLVMUsed
.push_back(&GV
);
114 SmallString
<64> Buffer
;
115 TM
.getNameWithPrefix(Buffer
, &GV
, Mangler
);
116 if (AsmUndefinedRefs
.count(Buffer
))
117 LLVMUsed
.push_back(&GV
);
121 } // namespace anonymous
123 void llvm::updateCompilerUsed(Module
&TheModule
, const TargetMachine
&TM
,
124 const StringSet
<> &AsmUndefinedRefs
) {
125 std::vector
<GlobalValue
*> UsedValues
;
126 PreserveLibCallsAndAsmUsed(AsmUndefinedRefs
, TM
, UsedValues
)
127 .findInModule(TheModule
);
129 if (UsedValues
.empty())
132 appendToCompilerUsed(TheModule
, UsedValues
);