forked from OSchip/llvm-project
LTO: Hash the parts of the LTO configuration that affect code generation.
Most importantly, we need to hash the relocation model, otherwise we can end up trying to link non-PIC object files into PIEs or DSOs. Differential Revision: https://reviews.llvm.org/D27556 llvm-svn: 289024
This commit is contained in:
parent
b2979d8464
commit
f4257528e9
|
@ -232,6 +232,11 @@ UseCtors("use-ctors",
|
|||
cl::desc("Use .ctors instead of .init_array."),
|
||||
cl::init(false));
|
||||
|
||||
cl::opt<bool> RelaxELFRelocations(
|
||||
"relax-elf-relocations",
|
||||
cl::desc("Emit GOTPCRELX/REX_GOTPCRELX instead of GOTPCREL on x86-64 ELF"),
|
||||
cl::init(false));
|
||||
|
||||
cl::opt<bool> DataSections("data-sections",
|
||||
cl::desc("Emit data into separate sections"),
|
||||
cl::init(false));
|
||||
|
@ -288,6 +293,7 @@ static inline TargetOptions InitTargetOptionsFromCodeGenFlags() {
|
|||
Options.StackAlignmentOverride = OverrideStackAlignment;
|
||||
Options.StackSymbolOrdering = StackSymbolOrdering;
|
||||
Options.UseInitArray = !UseCtors;
|
||||
Options.RelaxELFRelocations = RelaxELFRelocations;
|
||||
Options.DataSections = DataSections;
|
||||
Options.FunctionSections = FunctionSections;
|
||||
Options.UniqueSectionNames = UniqueSectionNames;
|
||||
|
|
|
@ -33,6 +33,8 @@ namespace lto {
|
|||
/// LTO configuration. A linker can configure LTO by setting fields in this data
|
||||
/// structure and passing it to the lto::LTO constructor.
|
||||
struct Config {
|
||||
// Note: when adding fields here, consider whether they need to be added to
|
||||
// computeCacheKey in LTO.cpp.
|
||||
std::string CPU;
|
||||
TargetOptions Options;
|
||||
std::vector<std::string> MAttrs;
|
||||
|
|
|
@ -50,8 +50,8 @@ using namespace object;
|
|||
// export/import and other global analysis results.
|
||||
// The hash is produced in \p Key.
|
||||
static void computeCacheKey(
|
||||
SmallString<40> &Key, const ModuleSummaryIndex &Index, StringRef ModuleID,
|
||||
const FunctionImporter::ImportMapTy &ImportList,
|
||||
SmallString<40> &Key, const Config &Conf, const ModuleSummaryIndex &Index,
|
||||
StringRef ModuleID, const FunctionImporter::ImportMapTy &ImportList,
|
||||
const FunctionImporter::ExportSetTy &ExportList,
|
||||
const std::map<GlobalValue::GUID, GlobalValue::LinkageTypes> &ResolvedODR,
|
||||
const GVSummaryMapTy &DefinedGlobals) {
|
||||
|
@ -67,6 +67,39 @@ static void computeCacheKey(
|
|||
Hasher.update(LLVM_REVISION);
|
||||
#endif
|
||||
|
||||
// Include the parts of the LTO configuration that affect code generation.
|
||||
auto AddString = [&](StringRef Str) {
|
||||
Hasher.update(Str);
|
||||
Hasher.update(ArrayRef<uint8_t>{0});
|
||||
};
|
||||
auto AddUnsigned = [&](unsigned I) {
|
||||
uint8_t Data[4];
|
||||
Data[0] = I;
|
||||
Data[1] = I >> 8;
|
||||
Data[2] = I >> 16;
|
||||
Data[3] = I >> 24;
|
||||
Hasher.update(ArrayRef<uint8_t>{Data, 4});
|
||||
};
|
||||
AddString(Conf.CPU);
|
||||
// FIXME: Hash more of Options. For now all clients initialize Options from
|
||||
// command-line flags (which is unsupported in production), but may set
|
||||
// RelaxELFRelocations. The clang driver can also pass FunctionSections,
|
||||
// DataSections and DebuggerTuning via command line flags.
|
||||
AddUnsigned(Conf.Options.RelaxELFRelocations);
|
||||
AddUnsigned(Conf.Options.FunctionSections);
|
||||
AddUnsigned(Conf.Options.DataSections);
|
||||
AddUnsigned((unsigned)Conf.Options.DebuggerTuning);
|
||||
for (auto &A : Conf.MAttrs)
|
||||
AddString(A);
|
||||
AddUnsigned(Conf.RelocModel);
|
||||
AddUnsigned(Conf.CodeModel);
|
||||
AddUnsigned(Conf.CGOptLevel);
|
||||
AddUnsigned(Conf.OptLevel);
|
||||
AddString(Conf.OptPipeline);
|
||||
AddString(Conf.AAPipeline);
|
||||
AddString(Conf.OverrideTriple);
|
||||
AddString(Conf.DefaultTriple);
|
||||
|
||||
// Include the hash for the current module
|
||||
auto ModHash = Index.getModuleHash(ModuleID);
|
||||
Hasher.update(ArrayRef<uint8_t>((uint8_t *)&ModHash[0], sizeof(ModHash)));
|
||||
|
@ -562,7 +595,7 @@ public:
|
|||
|
||||
SmallString<40> Key;
|
||||
// The module may be cached, this helps handling it.
|
||||
computeCacheKey(Key, CombinedIndex, ModuleID, ImportList, ExportList,
|
||||
computeCacheKey(Key, Conf, CombinedIndex, ModuleID, ImportList, ExportList,
|
||||
ResolvedODR, DefinedGlobals);
|
||||
if (AddStreamFn CacheAddStream = Cache(Task, Key))
|
||||
return RunThinBackend(CacheAddStream);
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
; RUN: rm -rf %t.cache && mkdir %t.cache
|
||||
; RUN: opt -module-hash -module-summary %s -o %t.bc
|
||||
|
||||
; RUN: llvm-lto2 -o %t.o %t.bc -cache-dir %t.cache -r=%t.bc,globalfunc,plx
|
||||
; RUN: llvm-lto2 -o %t.o %t.bc -cache-dir %t.cache -r=%t.bc,globalfunc,plx -mcpu=yonah
|
||||
; RUN: llvm-lto2 -o %t.o %t.bc -cache-dir %t.cache -r=%t.bc,globalfunc,plx -relax-elf-relocations
|
||||
; RUN: llvm-lto2 -o %t.o %t.bc -cache-dir %t.cache -r=%t.bc,globalfunc,plx -function-sections
|
||||
; RUN: llvm-lto2 -o %t.o %t.bc -cache-dir %t.cache -r=%t.bc,globalfunc,plx -data-sections
|
||||
; RUN: llvm-lto2 -o %t.o %t.bc -cache-dir %t.cache -r=%t.bc,globalfunc,plx -debugger-tune=sce
|
||||
; RUN: llvm-lto2 -o %t.o %t.bc -cache-dir %t.cache -r=%t.bc,globalfunc,plx -mattr=+sse2
|
||||
; RUN: llvm-lto2 -o %t.o %t.bc -cache-dir %t.cache -r=%t.bc,globalfunc,plx -relocation-model=static
|
||||
; RUN: llvm-lto2 -o %t.o %t.bc -cache-dir %t.cache -r=%t.bc,globalfunc,plx -code-model=large
|
||||
; RUN: llvm-lto2 -o %t.o %t.bc -cache-dir %t.cache -r=%t.bc,globalfunc,plx -cg-opt-level=0
|
||||
; RUN: llvm-lto2 -o %t.o %t.bc -cache-dir %t.cache -r=%t.bc,globalfunc,plx -O1
|
||||
; RUN: llvm-lto2 -o %t.o %t.bc -cache-dir %t.cache -r=%t.bc,globalfunc,plx -opt-pipeline=loweratomic
|
||||
; RUN: llvm-lto2 -o %t.o %t.bc -cache-dir %t.cache -r=%t.bc,globalfunc,plx -aa-pipeline=basic-aa
|
||||
; RUN: llvm-lto2 -o %t.o %t.bc -cache-dir %t.cache -r=%t.bc,globalfunc,plx -override-triple=x86_64-unknown-linux-gnu
|
||||
; RUN: llvm-lto2 -o %t.o %t.bc -cache-dir %t.cache -r=%t.bc,globalfunc,plx -default-triple=x86_64-unknown-linux-gnu
|
||||
; RUN: ls %t.cache | count 15
|
||||
|
||||
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
|
||||
target triple = "x86_64-unknown-linux-gnu"
|
||||
|
||||
define void @globalfunc() {
|
||||
entry:
|
||||
ret void
|
||||
}
|
|
@ -17,6 +17,7 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "llvm/LTO/Caching.h"
|
||||
#include "llvm/CodeGen/CommandFlags.h"
|
||||
#include "llvm/LTO/LTO.h"
|
||||
#include "llvm/Support/CommandLine.h"
|
||||
#include "llvm/Support/TargetSelect.h"
|
||||
|
@ -31,6 +32,11 @@ static cl::opt<char>
|
|||
"(default = '-O2')"),
|
||||
cl::Prefix, cl::ZeroOrMore, cl::init('2'));
|
||||
|
||||
static cl::opt<char> CGOptLevel(
|
||||
"cg-opt-level",
|
||||
cl::desc("Codegen optimization level (0, 1, 2 or 3, default = '2')"),
|
||||
cl::init('2'));
|
||||
|
||||
static cl::list<std::string> InputFilenames(cl::Positional, cl::OneOrMore,
|
||||
cl::desc("<input bitcode files>"));
|
||||
|
||||
|
@ -74,6 +80,15 @@ static cl::list<std::string> SymbolResolutions(
|
|||
"A resolution for each symbol must be specified."),
|
||||
cl::ZeroOrMore);
|
||||
|
||||
static cl::opt<std::string> OverrideTriple(
|
||||
"override-triple",
|
||||
cl::desc("Replace target triples in input files with this triple"));
|
||||
|
||||
static cl::opt<std::string> DefaultTriple(
|
||||
"default-triple",
|
||||
cl::desc(
|
||||
"Replace unspecified target triples in input files with this triple"));
|
||||
|
||||
static void check(Error E, std::string Msg) {
|
||||
if (!E)
|
||||
return;
|
||||
|
@ -146,6 +161,13 @@ int main(int argc, char **argv) {
|
|||
exit(1);
|
||||
};
|
||||
|
||||
Conf.CPU = MCPU;
|
||||
Conf.Options = InitTargetOptionsFromCodeGenFlags();
|
||||
Conf.MAttrs = MAttrs;
|
||||
if (auto RM = getRelocModel())
|
||||
Conf.RelocModel = *RM;
|
||||
Conf.CodeModel = CMModel;
|
||||
|
||||
if (SaveTemps)
|
||||
check(Conf.addSaveTemps(OutputFilename + "."),
|
||||
"Config::addSaveTemps failed");
|
||||
|
@ -155,6 +177,26 @@ int main(int argc, char **argv) {
|
|||
Conf.AAPipeline = AAPipeline;
|
||||
|
||||
Conf.OptLevel = OptLevel - '0';
|
||||
switch (CGOptLevel) {
|
||||
case '0':
|
||||
Conf.CGOptLevel = CodeGenOpt::None;
|
||||
break;
|
||||
case '1':
|
||||
Conf.CGOptLevel = CodeGenOpt::Less;
|
||||
break;
|
||||
case '2':
|
||||
Conf.CGOptLevel = CodeGenOpt::Default;
|
||||
break;
|
||||
case '3':
|
||||
Conf.CGOptLevel = CodeGenOpt::Aggressive;
|
||||
break;
|
||||
default:
|
||||
llvm::errs() << "invalid cg optimization level: " << CGOptLevel << '\n';
|
||||
return 1;
|
||||
}
|
||||
|
||||
Conf.OverrideTriple = OverrideTriple;
|
||||
Conf.DefaultTriple = DefaultTriple;
|
||||
|
||||
ThinBackend Backend;
|
||||
if (ThinLTODistributedIndexes)
|
||||
|
|
Loading…
Reference in New Issue