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