mirror of
https://github.com/RPCSX/llvm.git
synced 2024-11-28 14:10:41 +00:00
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> git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@194514 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
59e648e3c8
commit
dc6b4b4fc2
@ -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);
|
||||
|
@ -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");
|
||||
|
27
test/LTO/runtime-library.ll
Normal file
27
test/LTO/runtime-library.ll
Normal file
@ -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
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user