[llvm] r194514 - Protect user-supplied runtime library functions in LTO
Justin Bogner
mail at justinbogner.com
Tue Nov 12 13:44:02 PST 2013
Author: bogner
Date: Tue Nov 12 15:44:01 2013
New Revision: 194514
URL: http://llvm.org/viewvc/llvm-project?rev=194514&view=rev
Log:
Protect user-supplied runtime library functions in LTO
Add user-supplied C runtime and compiler-rt library functions to
llvm.compiler.used to protect them from premature optimization by
passes like -globalopt and -ipsccp. Calls to (seemingly unused)
runtime library functions can be added by -instcombine and instruction
lowering.
Patch by Duncan Exon Smith, thanks!
Fixes <rdar://problem/14740087>
Added:
llvm/trunk/test/LTO/runtime-library.ll
Modified:
llvm/trunk/include/llvm/LTO/LTOCodeGenerator.h
llvm/trunk/lib/LTO/LTOCodeGenerator.cpp
Modified: llvm/trunk/include/llvm/LTO/LTOCodeGenerator.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/LTO/LTOCodeGenerator.h?rev=194514&r1=194513&r2=194514&view=diff
==============================================================================
--- llvm/trunk/include/llvm/LTO/LTOCodeGenerator.h (original)
+++ llvm/trunk/include/llvm/LTO/LTOCodeGenerator.h Tue Nov 12 15:44:01 2013
@@ -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);
Modified: llvm/trunk/lib/LTO/LTOCodeGenerator.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/LTO/LTOCodeGenerator.cpp?rev=194514&r1=194513&r2=194514&view=diff
==============================================================================
--- llvm/trunk/lib/LTO/LTOCodeGenerator.cpp (original)
+++ llvm/trunk/lib/LTO/LTOCodeGenerator.cpp Tue Nov 12 15:44:01 2013
@@ -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(s
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(GlobalVariabl
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::applyScopeRestric
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");
Added: llvm/trunk/test/LTO/runtime-library.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/LTO/runtime-library.ll?rev=194514&view=auto
==============================================================================
--- llvm/trunk/test/LTO/runtime-library.ll (added)
+++ llvm/trunk/test/LTO/runtime-library.ll Tue Nov 12 15:44:01 2013
@@ -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
+}
+
More information about the llvm-commits
mailing list