From b10bff1183b8fcfe1a6625e353f9ebdef904ae7c Mon Sep 17 00:00:00 2001 From: Akira Hatanaka Date: Thu, 18 May 2017 03:52:29 +0000 Subject: [PATCH] [ThinLTO] Do not assert when adding a module with a different but compatible target triple Currently, an assertion fails in ThinLTOCodeGenerator::addModule when the target triple of the module being added doesn't match that of the one stored in TMBuilder. This patch relaxes the constraint and makes changes to allow target triples that only differ in their version numbers on Apple platforms, similarly to what r228999 did. rdar://problem/30133904 Differential Revision: https://reviews.llvm.org/D33291 llvm-svn: 303326 --- llvm/include/llvm/ADT/Triple.h | 10 ++++++++ llvm/lib/LTO/ThinLTOCodeGenerator.cpp | 38 +++++++++++++--------------- llvm/lib/Linker/IRMover.cpp | 26 +++---------------- llvm/lib/Support/Triple.cpp | 18 +++++++++++++ llvm/test/ThinLTO/X86/Inputs/merge-triple.ll | 1 + llvm/test/ThinLTO/X86/merge-triple.ll | 10 ++++++++ 6 files changed, 59 insertions(+), 44 deletions(-) create mode 100644 llvm/test/ThinLTO/X86/Inputs/merge-triple.ll create mode 100644 llvm/test/ThinLTO/X86/merge-triple.ll diff --git a/llvm/include/llvm/ADT/Triple.h b/llvm/include/llvm/ADT/Triple.h index e3a8a31..3a4a370 100644 --- a/llvm/include/llvm/ADT/Triple.h +++ b/llvm/include/llvm/ADT/Triple.h @@ -252,6 +252,10 @@ public: ObjectFormat == Other.ObjectFormat; } + bool operator!=(const Triple &Other) const { + return !(*this == Other); + } + /// @} /// @name Normalization /// @{ @@ -722,6 +726,12 @@ public: /// \returns true if the triple is little endian, false otherwise. bool isLittleEndian() const; + /// Test whether target triples are compatible. + bool isCompatibleWith(const Triple &Other) const; + + /// Merge target triples. + std::string merge(const Triple &Other) const; + /// @} /// @name Static helpers for IDs. /// @{ diff --git a/llvm/lib/LTO/ThinLTOCodeGenerator.cpp b/llvm/lib/LTO/ThinLTOCodeGenerator.cpp index 65a7994..327f237 100644 --- a/llvm/lib/LTO/ThinLTOCodeGenerator.cpp +++ b/llvm/lib/LTO/ThinLTOCodeGenerator.cpp @@ -505,29 +505,25 @@ static void initTMBuilder(TargetMachineBuilder &TMBuilder, void ThinLTOCodeGenerator::addModule(StringRef Identifier, StringRef Data) { ThinLTOBuffer Buffer(Data, Identifier); - if (Modules.empty()) { - // First module added, so initialize the triple and some options - LLVMContext Context; - StringRef TripleStr; - ErrorOr TripleOrErr = expectedToErrorOrAndEmitErrors( - Context, getBitcodeTargetTriple(Buffer.getMemBuffer())); - if (TripleOrErr) - TripleStr = *TripleOrErr; - Triple TheTriple(TripleStr); + LLVMContext Context; + StringRef TripleStr; + ErrorOr TripleOrErr = expectedToErrorOrAndEmitErrors( + Context, getBitcodeTargetTriple(Buffer.getMemBuffer())); + + if (TripleOrErr) + TripleStr = *TripleOrErr; + + Triple TheTriple(TripleStr); + + if (Modules.empty()) initTMBuilder(TMBuilder, Triple(TheTriple)); + else if (TMBuilder.TheTriple != TheTriple) { + if (!TMBuilder.TheTriple.isCompatibleWith(TheTriple)) + report_fatal_error("ThinLTO modules with incompatible triples not " + "supported"); + initTMBuilder(TMBuilder, Triple(TMBuilder.TheTriple.merge(TheTriple))); } -#ifndef NDEBUG - else { - LLVMContext Context; - StringRef TripleStr; - ErrorOr TripleOrErr = expectedToErrorOrAndEmitErrors( - Context, getBitcodeTargetTriple(Buffer.getMemBuffer())); - if (TripleOrErr) - TripleStr = *TripleOrErr; - assert(TMBuilder.TheTriple.str() == TripleStr && - "ThinLTO modules with different triple not supported"); - } -#endif + Modules.push_back(Buffer); } diff --git a/llvm/lib/Linker/IRMover.cpp b/llvm/lib/Linker/IRMover.cpp index ecef1ef..c0af21a 100644 --- a/llvm/lib/Linker/IRMover.cpp +++ b/llvm/lib/Linker/IRMover.cpp @@ -1243,27 +1243,6 @@ Error IRLinker::linkModuleFlagsMetadata() { return Error::success(); } -// This function returns true if the triples match. -static bool triplesMatch(const Triple &T0, const Triple &T1) { - // If vendor is apple, ignore the version number. - if (T0.getVendor() == Triple::Apple) - return T0.getArch() == T1.getArch() && T0.getSubArch() == T1.getSubArch() && - T0.getVendor() == T1.getVendor() && T0.getOS() == T1.getOS(); - - return T0 == T1; -} - -// This function returns the merged triple. -static std::string mergeTriples(const Triple &SrcTriple, - const Triple &DstTriple) { - // If vendor is apple, pick the triple with the larger version number. - if (SrcTriple.getVendor() == Triple::Apple) - if (DstTriple.isOSVersionLT(SrcTriple)) - return SrcTriple.str(); - - return DstTriple.str(); -} - Error IRLinker::run() { // Ensure metadata materialized before value mapping. if (SrcM->getMaterializer()) @@ -1289,14 +1268,15 @@ Error IRLinker::run() { Triple SrcTriple(SrcM->getTargetTriple()), DstTriple(DstM.getTargetTriple()); - if (!SrcM->getTargetTriple().empty() && !triplesMatch(SrcTriple, DstTriple)) + if (!SrcM->getTargetTriple().empty()&& + !SrcTriple.isCompatibleWith(DstTriple)) emitWarning("Linking two modules of different target triples: " + SrcM->getModuleIdentifier() + "' is '" + SrcM->getTargetTriple() + "' whereas '" + DstM.getModuleIdentifier() + "' is '" + DstM.getTargetTriple() + "'\n"); - DstM.setTargetTriple(mergeTriples(SrcTriple, DstTriple)); + DstM.setTargetTriple(SrcTriple.merge(DstTriple)); // Append the module inline asm string. if (!IsPerformingImport && !SrcM->getModuleInlineAsm().empty()) { diff --git a/llvm/lib/Support/Triple.cpp b/llvm/lib/Support/Triple.cpp index eb81089..b0e3d68 100644 --- a/llvm/lib/Support/Triple.cpp +++ b/llvm/lib/Support/Triple.cpp @@ -1472,6 +1472,24 @@ bool Triple::isLittleEndian() const { } } +bool Triple::isCompatibleWith(const Triple &Other) const { + // If vendor is apple, ignore the version number. + if (getVendor() == Triple::Apple) + return getArch() == Other.getArch() && getSubArch() == Other.getSubArch() && + getVendor() == Other.getVendor() && getOS() == Other.getOS(); + + return *this == Other; +} + +std::string Triple::merge(const Triple &Other) const { + // If vendor is apple, pick the triple with the larger version number. + if (getVendor() == Triple::Apple) + if (Other.isOSVersionLT(*this)) + return str(); + + return Other.str(); +} + StringRef Triple::getARMCPUForArch(StringRef MArch) const { if (MArch.empty()) MArch = getArchName(); diff --git a/llvm/test/ThinLTO/X86/Inputs/merge-triple.ll b/llvm/test/ThinLTO/X86/Inputs/merge-triple.ll new file mode 100644 index 0000000..ea644f5 --- /dev/null +++ b/llvm/test/ThinLTO/X86/Inputs/merge-triple.ll @@ -0,0 +1 @@ +target triple = "x86_64-apple-macosx10.11.0" diff --git a/llvm/test/ThinLTO/X86/merge-triple.ll b/llvm/test/ThinLTO/X86/merge-triple.ll new file mode 100644 index 0000000..8f099d12 --- /dev/null +++ b/llvm/test/ThinLTO/X86/merge-triple.ll @@ -0,0 +1,10 @@ +; RUN: opt -module-summary %s -o %t1.bc +; RUN: opt -module-summary %p/Inputs/merge-triple.ll -o %t2.bc +; RUN: llvm-lto -thinlto-action=optimize %t1.bc %t2.bc +; RUN: llvm-dis < %t1.bc.thinlto.imported.bc | FileCheck %s --check-prefix=CHECK1 +; RUN: llvm-dis < %t2.bc.thinlto.imported.bc | FileCheck %s --check-prefix=CHECK2 + +target triple = "x86_64-apple-macosx10.12.0" + +; CHECK1: target triple = "x86_64-apple-macosx10.12.0" +; CHECK2: target triple = "x86_64-apple-macosx10.11.0" -- 2.7.4