]> granicus.if.org Git - llvm/commitdiff
[ThinLTO] Do not assert when adding a module with a different but
authorAkira Hatanaka <ahatanaka@apple.com>
Thu, 18 May 2017 03:52:29 +0000 (03:52 +0000)
committerAkira Hatanaka <ahatanaka@apple.com>
Thu, 18 May 2017 03:52:29 +0000 (03:52 +0000)
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

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@303326 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/ADT/Triple.h
lib/LTO/ThinLTOCodeGenerator.cpp
lib/Linker/IRMover.cpp
lib/Support/Triple.cpp
test/ThinLTO/X86/Inputs/merge-triple.ll [new file with mode: 0644]
test/ThinLTO/X86/merge-triple.ll [new file with mode: 0644]

index e3a8a31ba9bc3fca19f44c8576b198aa06af1aa0..3a4a37017d61c131094d14fe49c68bfc5c62a8f3 100644 (file)
@@ -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.
   /// @{
index 65a7994325bcd5a181654cb20fa67db6c580a04d..327f2377d91b820913c4f89296df68eae2b81d14 100644 (file)
@@ -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<std::string> TripleOrErr = expectedToErrorOrAndEmitErrors(
-        Context, getBitcodeTargetTriple(Buffer.getMemBuffer()));
-    if (TripleOrErr)
-      TripleStr = *TripleOrErr;
-    Triple TheTriple(TripleStr);
+  LLVMContext Context;
+  StringRef TripleStr;
+  ErrorOr<std::string> 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<std::string> 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);
 }
 
index ecef1efda1a2cf5826908a60584110721cef839d..c0af21aa148c302d1ee7cc28637d5c53aafbec60 100644 (file)
@@ -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()) {
index eb8108908ac5fee86d240cd5c36a2b6d69adc336..b0e3d6898cae0df7c62fd1d8bd0aeb4f830768c7 100644 (file)
@@ -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/test/ThinLTO/X86/Inputs/merge-triple.ll b/test/ThinLTO/X86/Inputs/merge-triple.ll
new file mode 100644 (file)
index 0000000..ea644f5
--- /dev/null
@@ -0,0 +1 @@
+target triple = "x86_64-apple-macosx10.11.0"
diff --git a/test/ThinLTO/X86/merge-triple.ll b/test/ThinLTO/X86/merge-triple.ll
new file mode 100644 (file)
index 0000000..8f099d1
--- /dev/null
@@ -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"