diff options
-rw-r--r-- | include/llvm/LTO/LTOCodeGenerator.h | 3 | ||||
-rw-r--r-- | lib/LTO/LTOCodeGenerator.cpp | 49 | ||||
-rw-r--r-- | test/LTO/runtime-library.ll | 27 |
3 files changed, 76 insertions, 3 deletions
diff --git a/include/llvm/LTO/LTOCodeGenerator.h b/include/llvm/LTO/LTOCodeGenerator.h index 97a5066..c478bd9 100644 --- a/include/llvm/LTO/LTOCodeGenerator.h +++ b/include/llvm/LTO/LTOCodeGenerator.h @@ -38,6 +38,7 @@ #include "llvm-c/lto.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/StringMap.h" +#include "llvm/ADT/ArrayRef.h" #include "llvm/Linker.h" #include "llvm/Target/TargetOptions.h" #include <string> @@ -48,6 +49,7 @@ namespace llvm { class GlobalValue; class Mangler; class MemoryBuffer; + class TargetLibraryInfo; class TargetMachine; class raw_ostream; } @@ -125,6 +127,7 @@ private: std::string &errMsg); void applyScopeRestrictions(); void applyRestriction(llvm::GlobalValue &GV, + const llvm::ArrayRef<llvm::StringRef> &Libcalls, std::vector<const char*> &MustPreserveList, llvm::SmallPtrSet<llvm::GlobalValue*, 8> &AsmUsed, llvm::Mangler &Mangler); diff --git a/lib/LTO/LTOCodeGenerator.cpp b/lib/LTO/LTOCodeGenerator.cpp index 3c9a378..02bb184 100644 --- a/lib/LTO/LTOCodeGenerator.cpp +++ b/lib/LTO/LTOCodeGenerator.cpp @@ -18,6 +18,7 @@ #include "llvm/Analysis/Passes.h" #include "llvm/Analysis/Verifier.h" #include "llvm/Bitcode/ReaderWriter.h" +#include "llvm/CodeGen/RuntimeLibcalls.h" #include "llvm/Config/config.h" #include "llvm/IR/Constants.h" #include "llvm/IR/DataLayout.h" @@ -40,6 +41,8 @@ #include "llvm/Support/TargetSelect.h" #include "llvm/Support/ToolOutputFile.h" #include "llvm/Support/system_error.h" +#include "llvm/Target/TargetLibraryInfo.h" +#include "llvm/Target/TargetLowering.h" #include "llvm/Target/TargetOptions.h" #include "llvm/Target/TargetRegisterInfo.h" #include "llvm/Target/Mangler.h" @@ -312,6 +315,7 @@ bool LTOCodeGenerator::determineTarget(std::string &errMsg) { void LTOCodeGenerator:: applyRestriction(GlobalValue &GV, + const ArrayRef<StringRef> &Libcalls, std::vector<const char*> &MustPreserveList, SmallPtrSet<GlobalValue*, 8> &AsmUsed, Mangler &Mangler) { @@ -324,6 +328,15 @@ applyRestriction(GlobalValue &GV, MustPreserveList.push_back(GV.getName().data()); if (AsmUndefinedRefs.count(Buffer)) AsmUsed.insert(&GV); + + // Conservatively append user-supplied runtime library functions to + // llvm.compiler.used. These could be internalized and deleted by + // optimizations like -globalopt, causing problems when later optimizations + // add new library calls (e.g., llvm.memset => memset and printf => puts). + // Leave it to the linker to remove any dead code (e.g. with -dead_strip). + if (isa<Function>(GV) && + std::binary_search(Libcalls.begin(), Libcalls.end(), GV.getName())) + AsmUsed.insert(&GV); } static void findUsedValues(GlobalVariable *LLVMUsed, @@ -337,6 +350,33 @@ static void findUsedValues(GlobalVariable *LLVMUsed, UsedValues.insert(GV); } +static void accumulateAndSortLibcalls(std::vector<StringRef> &Libcalls, + const TargetLibraryInfo& TLI, + const TargetLowering *Lowering) +{ + // TargetLibraryInfo has info on C runtime library calls on the current + // target. + for (unsigned I = 0, E = static_cast<unsigned>(LibFunc::NumLibFuncs); + I != E; ++I) { + LibFunc::Func F = static_cast<LibFunc::Func>(I); + if (TLI.has(F)) + Libcalls.push_back(TLI.getName(F)); + } + + // TargetLowering has info on library calls that CodeGen expects to be + // available, both from the C runtime and compiler-rt. + if (Lowering) + for (unsigned I = 0, E = static_cast<unsigned>(RTLIB::UNKNOWN_LIBCALL); + I != E; ++I) + if (const char *Name + = Lowering->getLibcallName(static_cast<RTLIB::Libcall>(I))) + Libcalls.push_back(Name); + + std::sort(Libcalls.begin(), Libcalls.end()); + Libcalls.erase(std::unique(Libcalls.begin(), Libcalls.end()), + Libcalls.end()); +} + void LTOCodeGenerator::applyScopeRestrictions() { if (ScopeRestrictionsDone) return; @@ -350,16 +390,19 @@ void LTOCodeGenerator::applyScopeRestrictions() { Mangler Mangler(TargetMach); std::vector<const char*> MustPreserveList; SmallPtrSet<GlobalValue*, 8> AsmUsed; + std::vector<StringRef> Libcalls; + TargetLibraryInfo TLI(Triple(TargetMach->getTargetTriple())); + accumulateAndSortLibcalls(Libcalls, TLI, TargetMach->getTargetLowering()); for (Module::iterator f = mergedModule->begin(), e = mergedModule->end(); f != e; ++f) - applyRestriction(*f, MustPreserveList, AsmUsed, Mangler); + applyRestriction(*f, Libcalls, MustPreserveList, AsmUsed, Mangler); for (Module::global_iterator v = mergedModule->global_begin(), e = mergedModule->global_end(); v != e; ++v) - applyRestriction(*v, MustPreserveList, AsmUsed, Mangler); + applyRestriction(*v, Libcalls, MustPreserveList, AsmUsed, Mangler); for (Module::alias_iterator a = mergedModule->alias_begin(), e = mergedModule->alias_end(); a != e; ++a) - applyRestriction(*a, MustPreserveList, AsmUsed, Mangler); + applyRestriction(*a, Libcalls, MustPreserveList, AsmUsed, Mangler); GlobalVariable *LLVMCompilerUsed = mergedModule->getGlobalVariable("llvm.compiler.used"); diff --git a/test/LTO/runtime-library.ll b/test/LTO/runtime-library.ll new file mode 100644 index 0000000..76fc6f0 --- /dev/null +++ b/test/LTO/runtime-library.ll @@ -0,0 +1,27 @@ +; runtime library implementations should be added to llvm.compiler.used +; RUN: llvm-as <%s >%t1 +; RUN: llvm-lto -o %t2 %t1 +; RUN: llvm-nm -no-sort %t2 | FileCheck %s -check-prefix=KEEP -check-prefix=LOSE + +target triple = "x86_64-apple-darwin9" + +; KEEP-LABEL: _puts +define void @puts() { + ret void +} + +; KEEP-LABEL: ___divti3 +define void @__divti3() { + ret void +} + +; KEEP-LABEL: _memset +define void @memset() { + ret void +} + +; LOSE-NOT: _myprintf +define void @myprintf() { + ret void +} + |