diff --git a/llvm/include/llvm/TargetParser/Triple.h b/llvm/include/llvm/TargetParser/Triple.h --- a/llvm/include/llvm/TargetParser/Triple.h +++ b/llvm/include/llvm/TargetParser/Triple.h @@ -288,6 +288,13 @@ Wasm, XCOFF, }; + enum RTLibType { + UnknownRTLib, + + COMPILER_RT, + LIB_GCC, + WINDOWS_RT, + }; private: std::string Data; @@ -363,6 +370,9 @@ /// Get the parsed operating system type of this triple. OSType getOS() const { return OS; } + /// Get the rtlib implied by this triple. + RTLibType getRTLib() const; + /// Does this triple have the optional environment (fourth) component? bool hasEnvironment() const { return getEnvironmentName() != ""; diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp --- a/llvm/lib/Target/X86/X86ISelLowering.cpp +++ b/llvm/lib/Target/X86/X86ISelLowering.cpp @@ -2307,10 +2307,12 @@ setLibcallName(RTLIB::SRA_I128, nullptr); setLibcallName(RTLIB::MUL_I128, nullptr); // The MULO libcall is not part of libgcc, only compiler-rt. - setLibcallName(RTLIB::MULO_I64, nullptr); + if (Subtarget.getTargetTriple().getRTLib() != Triple::COMPILER_RT) + setLibcallName(RTLIB::MULO_I64, nullptr); } // The MULO libcall is not part of libgcc, only compiler-rt. - setLibcallName(RTLIB::MULO_I128, nullptr); + if (Subtarget.getTargetTriple().getRTLib() != Triple::COMPILER_RT) + setLibcallName(RTLIB::MULO_I128, nullptr); // Combine sin / cos into _sincos_stret if it is available. if (getLibcallName(RTLIB::SINCOS_STRET_F32) != nullptr && diff --git a/llvm/lib/TargetParser/Triple.cpp b/llvm/lib/TargetParser/Triple.cpp --- a/llvm/lib/TargetParser/Triple.cpp +++ b/llvm/lib/TargetParser/Triple.cpp @@ -1225,6 +1225,29 @@ return parseVersionFromName(OSName); } +Triple::RTLibType Triple::getRTLib() const { + if (isAndroid() || isOSDarwin() || isOSFuchsia()) + return COMPILER_RT; + + if (isGNUEnvironment()) { + if (isOSWindows()) + return UnknownRTLib; + return LIB_GCC; + } + + if (isOSWindows()) + return WINDOWS_RT; + + // TODO: more conditions, look at GetDefaultRuntimeLibType in clang for + // inspiration. + // Looks like AIX uses compiler-rt. + // "bare metal" uses compiler-rt. + // Fuchsia uses compiler-rt. + // openbsd uses compiler-rt. + // wasm uses compiler-rt. + return UnknownRTLib; +} + bool Triple::getMacOSXVersion(VersionTuple &Version) const { Version = getOSVersion(); diff --git a/llvm/test/CodeGen/X86/overflow-intrinsic-optimizations.ll b/llvm/test/CodeGen/X86/overflow-intrinsic-optimizations.ll --- a/llvm/test/CodeGen/X86/overflow-intrinsic-optimizations.ll +++ b/llvm/test/CodeGen/X86/overflow-intrinsic-optimizations.ll @@ -1,8 +1,10 @@ -; RUN: llc %s -mtriple=i386 -o - | FileCheck %s +; RUN: llc %s -mtriple=i386-linux-gnu -o - | FileCheck %s --check-prefix=CHECK-LIBGCC +; RUN: llc %s -mtriple=i386 -o - | FileCheck %s --check-prefix=CHECK-COMPILERRT define i1 @no__mulodi4(i32 %a, i64 %b, ptr %c) { ; CHECK-LABEL: no__mulodi4: -; CHECK-NOT: calll __mulodi4 +; CHECK-LIBGCC-NOT: calll __mulodi4 +; CHECK-COMPILERRT: calll __mulodi4 entry: %0 = sext i32 %a to i64 %1 = call { i64, i1 } @llvm.smul.with.overflow.i64(i64 %0, i64 %b) diff --git a/llvm/unittests/TargetParser/TargetParserTest.cpp b/llvm/unittests/TargetParser/TargetParserTest.cpp --- a/llvm/unittests/TargetParser/TargetParserTest.cpp +++ b/llvm/unittests/TargetParser/TargetParserTest.cpp @@ -1803,4 +1803,33 @@ } } +static Triple::RTLibType RT(const char* triple) { + llvm::Triple Triple(llvm::Triple::normalize(triple)); + return Triple.getRTLib(); +} + +TEST(TargetParserTest, getRTLib) { + const char* compiler_rt_triples [] = { + "aarch64-linux-android", "aarch64-apple-ios", "x86_64-fuchsia", + }; + const char* lib_gcc_triples [] = { + "x86_64-linux-gnu", + }; + const char* windows_rt_triples [] = { + "x86_64-pc-windows-msvc" + }; + const char* unknown_rt_triples [] = { + "x86_64-w64-mingw32", "x86_64-pc-mingw32", "i386-pc-mingw32", + "i686-pc-mingw32", "x86_64-w64-windows-gnu", "i686-w64-windows-gnu" + }; + for (const char* T : compiler_rt_triples) + EXPECT_EQ(RT(T), Triple::COMPILER_RT); + for (const char* T : lib_gcc_triples) + EXPECT_EQ(RT(T), Triple::LIB_GCC); + for (const char* T : windows_rt_triples) + EXPECT_EQ(RT(T), Triple::WINDOWS_RT); + for (const char* T : unknown_rt_triples) + EXPECT_EQ(RT(T), Triple::UnknownRTLib); +} + } // namespace