diff --git a/llvm/lib/Linker/IRMover.cpp b/llvm/lib/Linker/IRMover.cpp --- a/llvm/lib/Linker/IRMover.cpp +++ b/llvm/lib/Linker/IRMover.cpp @@ -20,6 +20,7 @@ #include "llvm/IR/TypeFinder.h" #include "llvm/Object/ModuleSymbolTable.h" #include "llvm/Support/Error.h" +#include "llvm/Support/Path.h" #include "llvm/Transforms/Utils/Cloning.h" #include using namespace llvm; @@ -1443,20 +1444,34 @@ if (DstM.getDataLayout().isDefault()) DstM.setDataLayout(SrcM->getDataLayout()); - if (SrcM->getDataLayout() != DstM.getDataLayout()) { - emitWarning("Linking two modules of different data layouts: '" + - SrcM->getModuleIdentifier() + "' is '" + - SrcM->getDataLayoutStr() + "' whereas '" + - DstM.getModuleIdentifier() + "' is '" + - DstM.getDataLayoutStr() + "'\n"); - } - // Copy the target triple from the source to dest if the dest's is empty. if (DstM.getTargetTriple().empty() && !SrcM->getTargetTriple().empty()) DstM.setTargetTriple(SrcM->getTargetTriple()); Triple SrcTriple(SrcM->getTargetTriple()), DstTriple(DstM.getTargetTriple()); + // NVIDIA supplies libdevice bitcode without data layout set (pre-CUDA-11), or + // with the layout that is different from the one used by us (it does not + // include i128). Issuing a warning for that is not very helpful as there's + // not much the user can do about that. + bool SuppressDLWarning = false; + if (SrcTriple.isNVPTX()) { + std::string ModuleId = SrcM->getModuleIdentifier(); + StringRef FileName = llvm::sys::path::filename(ModuleId); + SuppressDLWarning = + FileName.startswith("libdevice") && FileName.endswith(".10.bc") && + (SrcM->getDataLayoutStr().empty() || + SrcM->getDataLayoutStr() == "e-i64:64-v16:16-v32:32-n16:32:64"); + } + + if (!SuppressDLWarning && (SrcM->getDataLayout() != DstM.getDataLayout())) { + emitWarning("Linking two modules of different data layouts: '" + + SrcM->getModuleIdentifier() + "' is '" + + SrcM->getDataLayoutStr() + "' whereas '" + + DstM.getModuleIdentifier() + "' is '" + + DstM.getDataLayoutStr() + "'\n"); + } + if (!SrcM->getTargetTriple().empty()&& !SrcTriple.isCompatibleWith(DstTriple)) emitWarning("Linking two modules of different target triples: '" + diff --git a/llvm/lib/Support/Triple.cpp b/llvm/lib/Support/Triple.cpp --- a/llvm/lib/Support/Triple.cpp +++ b/llvm/lib/Support/Triple.cpp @@ -16,6 +16,7 @@ #include "llvm/Support/SwapByteOrder.h" #include "llvm/Support/TargetParser.h" #include "llvm/Support/VersionTuple.h" +#include "llvm/Support/raw_ostream.h" #include #include using namespace llvm; @@ -1639,6 +1640,25 @@ return getArch() == Other.getArch() && getSubArch() == Other.getSubArch() && getVendor() == Other.getVendor() && getOS() == Other.getOS(); + if (isNVPTX()) { + // libdevice bitcode uses nvptx64-nvidia-gpulibs or just + // 'nvptx-unknown-unknown' triple (before CUDA-10.x) and is compatible with + // all NVPTX variants. + auto IsLibDevice = [](const Triple &T) { + if (T.getVendor() == Triple::NVIDIA && T.getOSName() == "gpulibs") + return true; + // Compare unknown-unknown as strings, so we would not consider something + // intentionally different, but unknown to LLVM, as compatible. + if (T.getVendorName() == "unknown" && T.getOSName() == "unknown") + return true; + return false; + }; + + // If one of the modules appears to be a libdevice, consider it to be + // compatible as long as it is an nvptx variant. + if (IsLibDevice(*this) || IsLibDevice(Other)) + return Other.isNVPTX(); + } return *this == Other; }