101095a5dSDimitry Andric //==-LTOInternalize.cpp - LLVM Link Time Optimizer Internalization Utility -==//
201095a5dSDimitry Andric //
3e6d15924SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4e6d15924SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5e6d15924SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
601095a5dSDimitry Andric //
701095a5dSDimitry Andric //===----------------------------------------------------------------------===//
801095a5dSDimitry Andric //
901095a5dSDimitry Andric // This file defines a helper to run the internalization part of LTO.
1001095a5dSDimitry Andric //
1101095a5dSDimitry Andric //===----------------------------------------------------------------------===//
1201095a5dSDimitry Andric
1301095a5dSDimitry Andric #include "llvm/LTO/legacy/UpdateCompilerUsed.h"
1401095a5dSDimitry Andric #include "llvm/Analysis/TargetLibraryInfo.h"
15044eb2f6SDimitry Andric #include "llvm/CodeGen/TargetLowering.h"
16044eb2f6SDimitry Andric #include "llvm/CodeGen/TargetSubtargetInfo.h"
1701095a5dSDimitry Andric #include "llvm/IR/Mangler.h"
18ac9a064cSDimitry Andric #include "llvm/IR/Module.h"
19cfca06d7SDimitry Andric #include "llvm/Target/TargetMachine.h"
20ac9a064cSDimitry Andric #include "llvm/Transforms/Utils/ModuleUtils.h"
2101095a5dSDimitry Andric
2201095a5dSDimitry Andric using namespace llvm;
2301095a5dSDimitry Andric
2401095a5dSDimitry Andric namespace {
2501095a5dSDimitry Andric
2601095a5dSDimitry Andric // Helper class that collects AsmUsed and user supplied libcalls.
2701095a5dSDimitry Andric class PreserveLibCallsAndAsmUsed {
2801095a5dSDimitry Andric public:
PreserveLibCallsAndAsmUsed(const StringSet<> & AsmUndefinedRefs,const TargetMachine & TM,std::vector<GlobalValue * > & LLVMUsed)2901095a5dSDimitry Andric PreserveLibCallsAndAsmUsed(const StringSet<> &AsmUndefinedRefs,
3001095a5dSDimitry Andric const TargetMachine &TM,
31b915e9e0SDimitry Andric std::vector<GlobalValue *> &LLVMUsed)
3201095a5dSDimitry Andric : AsmUndefinedRefs(AsmUndefinedRefs), TM(TM), LLVMUsed(LLVMUsed) {}
3301095a5dSDimitry Andric
findInModule(Module & TheModule)34b915e9e0SDimitry Andric void findInModule(Module &TheModule) {
3501095a5dSDimitry Andric initializeLibCalls(TheModule);
36b915e9e0SDimitry Andric for (Function &F : TheModule)
3701095a5dSDimitry Andric findLibCallsAndAsm(F);
38b915e9e0SDimitry Andric for (GlobalVariable &GV : TheModule.globals())
3901095a5dSDimitry Andric findLibCallsAndAsm(GV);
40b915e9e0SDimitry Andric for (GlobalAlias &GA : TheModule.aliases())
4101095a5dSDimitry Andric findLibCallsAndAsm(GA);
4201095a5dSDimitry Andric }
4301095a5dSDimitry Andric
4401095a5dSDimitry Andric private:
4501095a5dSDimitry Andric // Inputs
4601095a5dSDimitry Andric const StringSet<> &AsmUndefinedRefs;
4701095a5dSDimitry Andric const TargetMachine &TM;
4801095a5dSDimitry Andric
4901095a5dSDimitry Andric // Temps
5001095a5dSDimitry Andric llvm::Mangler Mangler;
5101095a5dSDimitry Andric StringSet<> Libcalls;
5201095a5dSDimitry Andric
5301095a5dSDimitry Andric // Output
54b915e9e0SDimitry Andric std::vector<GlobalValue *> &LLVMUsed;
5501095a5dSDimitry Andric
5601095a5dSDimitry Andric // Collect names of runtime library functions. User-defined functions with the
5701095a5dSDimitry Andric // same names are added to llvm.compiler.used to prevent them from being
5801095a5dSDimitry Andric // deleted by optimizations.
initializeLibCalls(const Module & TheModule)5901095a5dSDimitry Andric void initializeLibCalls(const Module &TheModule) {
6001095a5dSDimitry Andric TargetLibraryInfoImpl TLII(Triple(TM.getTargetTriple()));
6101095a5dSDimitry Andric TargetLibraryInfo TLI(TLII);
6201095a5dSDimitry Andric
6301095a5dSDimitry Andric // TargetLibraryInfo has info on C runtime library calls on the current
6401095a5dSDimitry Andric // target.
6501095a5dSDimitry Andric for (unsigned I = 0, E = static_cast<unsigned>(LibFunc::NumLibFuncs);
6601095a5dSDimitry Andric I != E; ++I) {
6771d5a254SDimitry Andric LibFunc F = static_cast<LibFunc>(I);
6801095a5dSDimitry Andric if (TLI.has(F))
6901095a5dSDimitry Andric Libcalls.insert(TLI.getName(F));
7001095a5dSDimitry Andric }
7101095a5dSDimitry Andric
7201095a5dSDimitry Andric SmallPtrSet<const TargetLowering *, 1> TLSet;
7301095a5dSDimitry Andric
7401095a5dSDimitry Andric for (const Function &F : TheModule) {
7501095a5dSDimitry Andric const TargetLowering *Lowering =
7601095a5dSDimitry Andric TM.getSubtargetImpl(F)->getTargetLowering();
7701095a5dSDimitry Andric
7801095a5dSDimitry Andric if (Lowering && TLSet.insert(Lowering).second)
7901095a5dSDimitry Andric // TargetLowering has info on library calls that CodeGen expects to be
8001095a5dSDimitry Andric // available, both from the C runtime and compiler-rt.
8101095a5dSDimitry Andric for (unsigned I = 0, E = static_cast<unsigned>(RTLIB::UNKNOWN_LIBCALL);
8201095a5dSDimitry Andric I != E; ++I)
8301095a5dSDimitry Andric if (const char *Name =
8401095a5dSDimitry Andric Lowering->getLibcallName(static_cast<RTLIB::Libcall>(I)))
8501095a5dSDimitry Andric Libcalls.insert(Name);
8601095a5dSDimitry Andric }
8701095a5dSDimitry Andric }
8801095a5dSDimitry Andric
findLibCallsAndAsm(GlobalValue & GV)89b915e9e0SDimitry Andric void findLibCallsAndAsm(GlobalValue &GV) {
9001095a5dSDimitry Andric // There are no restrictions to apply to declarations.
9101095a5dSDimitry Andric if (GV.isDeclaration())
9201095a5dSDimitry Andric return;
9301095a5dSDimitry Andric
9401095a5dSDimitry Andric // There is nothing more restrictive than private linkage.
9501095a5dSDimitry Andric if (GV.hasPrivateLinkage())
9601095a5dSDimitry Andric return;
9701095a5dSDimitry Andric
98d8e91e46SDimitry Andric // Conservatively append user-supplied runtime library functions (supplied
99d8e91e46SDimitry Andric // either directly, or via a function alias) to llvm.compiler.used. These
100d8e91e46SDimitry Andric // could be internalized and deleted by optimizations like -globalopt,
101d8e91e46SDimitry Andric // causing problems when later optimizations add new library calls (e.g.,
102d8e91e46SDimitry Andric // llvm.memset => memset and printf => puts).
10301095a5dSDimitry Andric // Leave it to the linker to remove any dead code (e.g. with -dead_strip).
104d8e91e46SDimitry Andric GlobalValue *FuncAliasee = nullptr;
105d8e91e46SDimitry Andric if (isa<GlobalAlias>(GV)) {
106d8e91e46SDimitry Andric auto *A = cast<GlobalAlias>(&GV);
107d8e91e46SDimitry Andric FuncAliasee = dyn_cast<Function>(A->getAliasee());
108d8e91e46SDimitry Andric }
109d8e91e46SDimitry Andric if ((isa<Function>(GV) || FuncAliasee) && Libcalls.count(GV.getName())) {
110b915e9e0SDimitry Andric LLVMUsed.push_back(&GV);
111b915e9e0SDimitry Andric return;
112b915e9e0SDimitry Andric }
11301095a5dSDimitry Andric
11401095a5dSDimitry Andric SmallString<64> Buffer;
11501095a5dSDimitry Andric TM.getNameWithPrefix(Buffer, &GV, Mangler);
11601095a5dSDimitry Andric if (AsmUndefinedRefs.count(Buffer))
117b915e9e0SDimitry Andric LLVMUsed.push_back(&GV);
11801095a5dSDimitry Andric }
11901095a5dSDimitry Andric };
12001095a5dSDimitry Andric
12101095a5dSDimitry Andric } // namespace anonymous
12201095a5dSDimitry Andric
updateCompilerUsed(Module & TheModule,const TargetMachine & TM,const StringSet<> & AsmUndefinedRefs)12301095a5dSDimitry Andric void llvm::updateCompilerUsed(Module &TheModule, const TargetMachine &TM,
12401095a5dSDimitry Andric const StringSet<> &AsmUndefinedRefs) {
125b915e9e0SDimitry Andric std::vector<GlobalValue *> UsedValues;
12601095a5dSDimitry Andric PreserveLibCallsAndAsmUsed(AsmUndefinedRefs, TM, UsedValues)
12701095a5dSDimitry Andric .findInModule(TheModule);
12801095a5dSDimitry Andric
12901095a5dSDimitry Andric if (UsedValues.empty())
13001095a5dSDimitry Andric return;
13101095a5dSDimitry Andric
132b915e9e0SDimitry Andric appendToCompilerUsed(TheModule, UsedValues);
13301095a5dSDimitry Andric }
134