134 lines · cpp
1//==-LTOInternalize.cpp - LLVM Link Time Optimizer Internalization Utility -==//2//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-exception6//7//===----------------------------------------------------------------------===//8//9// This file defines a helper to run the internalization part of LTO.10//11//===----------------------------------------------------------------------===//12 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"21 22using namespace llvm;23 24namespace {25 26// Helper class that collects AsmUsed and user supplied libcalls.27class PreserveLibCallsAndAsmUsed {28public:29 PreserveLibCallsAndAsmUsed(const StringSet<> &AsmUndefinedRefs,30 const TargetMachine &TM,31 std::vector<GlobalValue *> &LLVMUsed)32 : AsmUndefinedRefs(AsmUndefinedRefs), TM(TM), LLVMUsed(LLVMUsed) {}33 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);42 }43 44private:45 // Inputs46 const StringSet<> &AsmUndefinedRefs;47 const TargetMachine &TM;48 49 // Temps50 llvm::Mangler Mangler;51 StringSet<> Libcalls;52 53 // Output54 std::vector<GlobalValue *> &LLVMUsed;55 56 // Collect names of runtime library functions. User-defined functions with the57 // same names are added to llvm.compiler.used to prevent them from being58 // deleted by optimizations.59 void initializeLibCalls(const Module &TheModule) {60 TargetLibraryInfoImpl TLII(TM.getTargetTriple());61 TargetLibraryInfo TLI(TLII);62 63 // TargetLibraryInfo has info on C runtime library calls on the current64 // target.65 for (unsigned I = LibFunc::Begin_LibFunc, E = LibFunc::End_LibFunc; I != E;66 ++I) {67 LibFunc F = static_cast<LibFunc>(I);68 if (TLI.has(F))69 Libcalls.insert(TLI.getName(F));70 }71 72 SmallPtrSet<const TargetLowering *, 1> TLSet;73 74 for (const Function &F : TheModule) {75 const TargetLowering *Lowering =76 TM.getSubtargetImpl(F)->getTargetLowering();77 78 if (Lowering && TLSet.insert(Lowering).second)79 // TargetLowering has info on library calls that CodeGen expects to be80 // available, both from the C runtime and compiler-rt.81 for (unsigned I = 0, E = static_cast<unsigned>(RTLIB::UNKNOWN_LIBCALL);82 I != E; ++I)83 if (const char *Name =84 Lowering->getLibcallName(static_cast<RTLIB::Libcall>(I)))85 Libcalls.insert(Name);86 }87 }88 89 void findLibCallsAndAsm(GlobalValue &GV) {90 // There are no restrictions to apply to declarations.91 if (GV.isDeclaration())92 return;93 94 // There is nothing more restrictive than private linkage.95 if (GV.hasPrivateLinkage())96 return;97 98 // Conservatively append user-supplied runtime library functions (supplied99 // either directly, or via a function alias) to llvm.compiler.used. These100 // 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());108 }109 if ((isa<Function>(GV) || FuncAliasee) && Libcalls.count(GV.getName())) {110 LLVMUsed.push_back(&GV);111 return;112 }113 114 SmallString<64> Buffer;115 TM.getNameWithPrefix(Buffer, &GV, Mangler);116 if (AsmUndefinedRefs.count(Buffer))117 LLVMUsed.push_back(&GV);118 }119};120 121} // namespace anonymous122 123void llvm::updateCompilerUsed(Module &TheModule, const TargetMachine &TM,124 const StringSet<> &AsmUndefinedRefs) {125 std::vector<GlobalValue *> UsedValues;126 PreserveLibCallsAndAsmUsed(AsmUndefinedRefs, TM, UsedValues)127 .findInModule(TheModule);128 129 if (UsedValues.empty())130 return;131 132 appendToCompilerUsed(TheModule, UsedValues);133}134