1ce23e970SMehdi Amini //==-LTOInternalize.cpp - LLVM Link Time Optimizer Internalization Utility -==//
2ce23e970SMehdi Amini //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6ce23e970SMehdi Amini //
7ce23e970SMehdi Amini //===----------------------------------------------------------------------===//
8ce23e970SMehdi Amini //
9ce23e970SMehdi Amini // This file defines a helper to run the internalization part of LTO.
10ce23e970SMehdi Amini //
11ce23e970SMehdi Amini //===----------------------------------------------------------------------===//
12ce23e970SMehdi Amini
135c73220fSPeter Collingbourne #include "llvm/LTO/legacy/UpdateCompilerUsed.h"
14ce23e970SMehdi Amini #include "llvm/Analysis/TargetLibraryInfo.h"
15b3bde2eaSDavid Blaikie #include "llvm/CodeGen/TargetLowering.h"
16b3bde2eaSDavid Blaikie #include "llvm/CodeGen/TargetSubtargetInfo.h"
17ce23e970SMehdi Amini #include "llvm/IR/LegacyPassManager.h"
18ce23e970SMehdi Amini #include "llvm/IR/Mangler.h"
19ea6d49d3SEvgeniy Stepanov #include "llvm/Transforms/Utils/ModuleUtils.h"
20*fe0006c8SSimon Pilgrim #include "llvm/Target/TargetMachine.h"
21ce23e970SMehdi Amini
22ce23e970SMehdi Amini using namespace llvm;
23ce23e970SMehdi Amini
24ce23e970SMehdi Amini namespace {
25ce23e970SMehdi Amini
26ce23e970SMehdi Amini // Helper class that collects AsmUsed and user supplied libcalls.
27ce23e970SMehdi Amini class PreserveLibCallsAndAsmUsed {
28ce23e970SMehdi Amini public:
PreserveLibCallsAndAsmUsed(const StringSet<> & AsmUndefinedRefs,const TargetMachine & TM,std::vector<GlobalValue * > & LLVMUsed)29ce23e970SMehdi Amini PreserveLibCallsAndAsmUsed(const StringSet<> &AsmUndefinedRefs,
30ce23e970SMehdi Amini const TargetMachine &TM,
31ea6d49d3SEvgeniy Stepanov std::vector<GlobalValue *> &LLVMUsed)
32ce23e970SMehdi Amini : AsmUndefinedRefs(AsmUndefinedRefs), TM(TM), LLVMUsed(LLVMUsed) {}
33ce23e970SMehdi Amini
findInModule(Module & TheModule)34ea6d49d3SEvgeniy Stepanov void findInModule(Module &TheModule) {
35ce23e970SMehdi Amini initializeLibCalls(TheModule);
36ea6d49d3SEvgeniy Stepanov for (Function &F : TheModule)
37ce23e970SMehdi Amini findLibCallsAndAsm(F);
38ea6d49d3SEvgeniy Stepanov for (GlobalVariable &GV : TheModule.globals())
39ce23e970SMehdi Amini findLibCallsAndAsm(GV);
40ea6d49d3SEvgeniy Stepanov for (GlobalAlias &GA : TheModule.aliases())
41ce23e970SMehdi Amini findLibCallsAndAsm(GA);
42ce23e970SMehdi Amini }
43ce23e970SMehdi Amini
44ce23e970SMehdi Amini private:
45ce23e970SMehdi Amini // Inputs
46ce23e970SMehdi Amini const StringSet<> &AsmUndefinedRefs;
47ce23e970SMehdi Amini const TargetMachine &TM;
48ce23e970SMehdi Amini
49ce23e970SMehdi Amini // Temps
50ce23e970SMehdi Amini llvm::Mangler Mangler;
51ce23e970SMehdi Amini StringSet<> Libcalls;
52ce23e970SMehdi Amini
53ce23e970SMehdi Amini // Output
54ea6d49d3SEvgeniy Stepanov std::vector<GlobalValue *> &LLVMUsed;
55ce23e970SMehdi Amini
56ce23e970SMehdi Amini // Collect names of runtime library functions. User-defined functions with the
57ce23e970SMehdi Amini // same names are added to llvm.compiler.used to prevent them from being
58ce23e970SMehdi Amini // deleted by optimizations.
initializeLibCalls(const Module & TheModule)59ce23e970SMehdi Amini void initializeLibCalls(const Module &TheModule) {
60ce23e970SMehdi Amini TargetLibraryInfoImpl TLII(Triple(TM.getTargetTriple()));
61ce23e970SMehdi Amini TargetLibraryInfo TLI(TLII);
62ce23e970SMehdi Amini
63ce23e970SMehdi Amini // TargetLibraryInfo has info on C runtime library calls on the current
64ce23e970SMehdi Amini // target.
65ce23e970SMehdi Amini for (unsigned I = 0, E = static_cast<unsigned>(LibFunc::NumLibFuncs);
66ce23e970SMehdi Amini I != E; ++I) {
67d21529faSDavid L. Jones LibFunc F = static_cast<LibFunc>(I);
68ce23e970SMehdi Amini if (TLI.has(F))
69ce23e970SMehdi Amini Libcalls.insert(TLI.getName(F));
70ce23e970SMehdi Amini }
71ce23e970SMehdi Amini
72ce23e970SMehdi Amini SmallPtrSet<const TargetLowering *, 1> TLSet;
73ce23e970SMehdi Amini
74ce23e970SMehdi Amini for (const Function &F : TheModule) {
75ce23e970SMehdi Amini const TargetLowering *Lowering =
76ce23e970SMehdi Amini TM.getSubtargetImpl(F)->getTargetLowering();
77ce23e970SMehdi Amini
78ce23e970SMehdi Amini if (Lowering && TLSet.insert(Lowering).second)
79ce23e970SMehdi Amini // TargetLowering has info on library calls that CodeGen expects to be
80ce23e970SMehdi Amini // available, both from the C runtime and compiler-rt.
81ce23e970SMehdi Amini for (unsigned I = 0, E = static_cast<unsigned>(RTLIB::UNKNOWN_LIBCALL);
82ce23e970SMehdi Amini I != E; ++I)
83ce23e970SMehdi Amini if (const char *Name =
84ce23e970SMehdi Amini Lowering->getLibcallName(static_cast<RTLIB::Libcall>(I)))
85ce23e970SMehdi Amini Libcalls.insert(Name);
86ce23e970SMehdi Amini }
87ce23e970SMehdi Amini }
88ce23e970SMehdi Amini
findLibCallsAndAsm(GlobalValue & GV)89ea6d49d3SEvgeniy Stepanov void findLibCallsAndAsm(GlobalValue &GV) {
90ce23e970SMehdi Amini // There are no restrictions to apply to declarations.
91ce23e970SMehdi Amini if (GV.isDeclaration())
92ce23e970SMehdi Amini return;
93ce23e970SMehdi Amini
94ce23e970SMehdi Amini // There is nothing more restrictive than private linkage.
95ce23e970SMehdi Amini if (GV.hasPrivateLinkage())
96ce23e970SMehdi Amini return;
97ce23e970SMehdi Amini
98febfc4e8SWarren Ristow // Conservatively append user-supplied runtime library functions (supplied
99febfc4e8SWarren Ristow // either directly, or via a function alias) to llvm.compiler.used. These
100febfc4e8SWarren Ristow // could be internalized and deleted by optimizations like -globalopt,
101febfc4e8SWarren Ristow // causing problems when later optimizations add new library calls (e.g.,
102febfc4e8SWarren Ristow // llvm.memset => memset and printf => puts).
103ce23e970SMehdi Amini // Leave it to the linker to remove any dead code (e.g. with -dead_strip).
104febfc4e8SWarren Ristow GlobalValue *FuncAliasee = nullptr;
105febfc4e8SWarren Ristow if (isa<GlobalAlias>(GV)) {
106febfc4e8SWarren Ristow auto *A = cast<GlobalAlias>(&GV);
107febfc4e8SWarren Ristow FuncAliasee = dyn_cast<Function>(A->getAliasee());
108febfc4e8SWarren Ristow }
109febfc4e8SWarren Ristow if ((isa<Function>(GV) || FuncAliasee) && Libcalls.count(GV.getName())) {
110ea6d49d3SEvgeniy Stepanov LLVMUsed.push_back(&GV);
111ea6d49d3SEvgeniy Stepanov return;
112ea6d49d3SEvgeniy Stepanov }
113ce23e970SMehdi Amini
114ce23e970SMehdi Amini SmallString<64> Buffer;
115ce23e970SMehdi Amini TM.getNameWithPrefix(Buffer, &GV, Mangler);
116ce23e970SMehdi Amini if (AsmUndefinedRefs.count(Buffer))
117ea6d49d3SEvgeniy Stepanov LLVMUsed.push_back(&GV);
118ce23e970SMehdi Amini }
119ce23e970SMehdi Amini };
120ce23e970SMehdi Amini
121ce23e970SMehdi Amini } // namespace anonymous
122ce23e970SMehdi Amini
updateCompilerUsed(Module & TheModule,const TargetMachine & TM,const StringSet<> & AsmUndefinedRefs)12353d457c6SDavide Italiano void llvm::updateCompilerUsed(Module &TheModule, const TargetMachine &TM,
124ce23e970SMehdi Amini const StringSet<> &AsmUndefinedRefs) {
125ea6d49d3SEvgeniy Stepanov std::vector<GlobalValue *> UsedValues;
126ce23e970SMehdi Amini PreserveLibCallsAndAsmUsed(AsmUndefinedRefs, TM, UsedValues)
127ce23e970SMehdi Amini .findInModule(TheModule);
128ce23e970SMehdi Amini
129ce23e970SMehdi Amini if (UsedValues.empty())
130ce23e970SMehdi Amini return;
131ce23e970SMehdi Amini
132ea6d49d3SEvgeniy Stepanov appendToCompilerUsed(TheModule, UsedValues);
133ce23e970SMehdi Amini }
134