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-exception 6 // 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/LegacyPassManager.h" 18 #include "llvm/IR/Mangler.h" 19 #include "llvm/Transforms/Utils/ModuleUtils.h" 20 #include "llvm/Target/TargetMachine.h" 21 22 using namespace llvm; 23 24 namespace { 25 26 // Helper class that collects AsmUsed and user supplied libcalls. 27 class PreserveLibCallsAndAsmUsed { 28 public: 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 44 private: 45 // Inputs 46 const StringSet<> &AsmUndefinedRefs; 47 const TargetMachine &TM; 48 49 // Temps 50 llvm::Mangler Mangler; 51 StringSet<> Libcalls; 52 53 // Output 54 std::vector<GlobalValue *> &LLVMUsed; 55 56 // Collect names of runtime library functions. User-defined functions with the 57 // same names are added to llvm.compiler.used to prevent them from being 58 // deleted by optimizations. 59 void initializeLibCalls(const Module &TheModule) { 60 TargetLibraryInfoImpl TLII(Triple(TM.getTargetTriple())); 61 TargetLibraryInfo TLI(TLII); 62 63 // TargetLibraryInfo has info on C runtime library calls on the current 64 // target. 65 for (unsigned I = 0, E = static_cast<unsigned>(LibFunc::NumLibFuncs); 66 I != E; ++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 be 80 // 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 (supplied 99 // either directly, or via a function alias) to llvm.compiler.used. These 100 // 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 anonymous 122 123 void 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