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