1 //==-LTOInternalize.cpp - LLVM Link Time Optimizer Internalization Utility -==// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // This file defines a helper to run the internalization part of LTO. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #include "llvm/LTO/legacy/UpdateCompilerUsed.h" 15 #include "llvm/Analysis/TargetLibraryInfo.h" 16 #include "llvm/CodeGen/TargetLowering.h" 17 #include "llvm/CodeGen/TargetSubtargetInfo.h" 18 #include "llvm/IR/LegacyPassManager.h" 19 #include "llvm/IR/Mangler.h" 20 #include "llvm/Transforms/Utils/ModuleUtils.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 to 99 // llvm.compiler.used. These could be internalized and deleted by 100 // optimizations like -globalopt, causing problems when later optimizations 101 // add new library calls (e.g., llvm.memset => memset and printf => puts). 102 // Leave it to the linker to remove any dead code (e.g. with -dead_strip). 103 if (isa<Function>(GV) && Libcalls.count(GV.getName())) { 104 LLVMUsed.push_back(&GV); 105 return; 106 } 107 108 SmallString<64> Buffer; 109 TM.getNameWithPrefix(Buffer, &GV, Mangler); 110 if (AsmUndefinedRefs.count(Buffer)) 111 LLVMUsed.push_back(&GV); 112 } 113 }; 114 115 } // namespace anonymous 116 117 void llvm::updateCompilerUsed(Module &TheModule, const TargetMachine &TM, 118 const StringSet<> &AsmUndefinedRefs) { 119 std::vector<GlobalValue *> UsedValues; 120 PreserveLibCallsAndAsmUsed(AsmUndefinedRefs, TM, UsedValues) 121 .findInModule(TheModule); 122 123 if (UsedValues.empty()) 124 return; 125 126 appendToCompilerUsed(TheModule, UsedValues); 127 } 128