[llvm-branch-commits] [llvm] TableGen: Generate enum for runtime libcall implementations (PR #144973)

Matt Arsenault via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Fri Jun 27 00:32:06 PDT 2025


https://github.com/arsenm updated https://github.com/llvm/llvm-project/pull/144973

>From d5ea33f8d0507288abdb04b7981f109c9268a87d Mon Sep 17 00:00:00 2001
From: Matt Arsenault <Matthew.Arsenault at amd.com>
Date: Sat, 7 Jun 2025 00:20:34 +0900
Subject: [PATCH] TableGen: Generate enum for runtime libcall implementations

Work towards separating the ABI existence of libcalls vs. the
lowering selection. Set libcall selection through enums, rather
than through raw string names.
---
 llvm/include/llvm/CodeGen/TargetLowering.h    |   9 +-
 llvm/include/llvm/IR/RuntimeLibcalls.h        |  55 +-
 llvm/include/llvm/IR/RuntimeLibcalls.td       | 560 ++++++++++++++++++
 llvm/lib/IR/RuntimeLibcalls.cpp               | 519 ++++++++--------
 llvm/lib/LTO/LTO.cpp                          |  10 +-
 llvm/lib/Object/IRSymtab.cpp                  |   6 +-
 llvm/lib/Target/ARM/ARMISelLowering.cpp       | 210 +++----
 llvm/lib/Target/MSP430/MSP430ISelLowering.cpp |  64 +-
 llvm/lib/Target/Mips/Mips16ISelLowering.cpp   |  89 +--
 llvm/lib/Target/Sparc/SparcISelLowering.cpp   |  86 +--
 llvm/test/TableGen/RuntimeLibcallEmitter.td   |  53 +-
 .../TableGen/Basic/RuntimeLibcallsEmitter.cpp |  80 ++-
 12 files changed, 1210 insertions(+), 531 deletions(-)

diff --git a/llvm/include/llvm/CodeGen/TargetLowering.h b/llvm/include/llvm/CodeGen/TargetLowering.h
index 727526055e592..69ae4f80297d5 100644
--- a/llvm/include/llvm/CodeGen/TargetLowering.h
+++ b/llvm/include/llvm/CodeGen/TargetLowering.h
@@ -3558,13 +3558,8 @@ class LLVM_ABI TargetLoweringBase {
     return nullptr;
   }
 
-  /// Rename the default libcall routine name for the specified libcall.
-  void setLibcallName(RTLIB::Libcall Call, const char *Name) {
-    Libcalls.setLibcallName(Call, Name);
-  }
-
-  void setLibcallName(ArrayRef<RTLIB::Libcall> Calls, const char *Name) {
-    Libcalls.setLibcallName(Calls, Name);
+  void setLibcallImpl(RTLIB::Libcall Call, RTLIB::LibcallImpl Impl) {
+    Libcalls.setLibcallImpl(Call, Impl);
   }
 
   /// Get the libcall routine name for the specified libcall.
diff --git a/llvm/include/llvm/IR/RuntimeLibcalls.h b/llvm/include/llvm/IR/RuntimeLibcalls.h
index 79707a7475511..50b9791111ce2 100644
--- a/llvm/include/llvm/IR/RuntimeLibcalls.h
+++ b/llvm/include/llvm/IR/RuntimeLibcalls.h
@@ -23,6 +23,10 @@
 #include "llvm/Support/Compiler.h"
 #include "llvm/TargetParser/Triple.h"
 
+/// TableGen will produce 2 enums, RTLIB::Libcall and
+/// RTLIB::LibcallImpl. RTLIB::Libcall describes abstract functionality the
+/// compiler may choose to access, RTLIB::LibcallImpl describes a particular ABI
+/// implementation, which includes a name and type signature.
 #define GET_RUNTIME_LIBCALL_ENUM
 #include "llvm/IR/RuntimeLibcalls.inc"
 #undef GET_RUNTIME_LIBCALL_ENUM
@@ -48,38 +52,46 @@ struct RuntimeLibcallsInfo {
       FloatABI::ABIType FloatABI = FloatABI::Default,
       EABI EABIVersion = EABI::Default, StringRef ABIName = "") {
     initSoftFloatCmpLibcallPredicates();
-    initDefaultLibCallNames();
+    initDefaultLibCallImpls();
     initLibcalls(TT, ExceptionModel, FloatABI, EABIVersion, ABIName);
   }
 
   /// Rename the default libcall routine name for the specified libcall.
-  void setLibcallName(RTLIB::Libcall Call, const char *Name) {
-    LibcallRoutineNames[Call] = Name;
-  }
-
-  void setLibcallName(ArrayRef<RTLIB::Libcall> Calls, const char *Name) {
-    for (auto Call : Calls)
-      setLibcallName(Call, Name);
+  void setLibcallImpl(RTLIB::Libcall Call, RTLIB::LibcallImpl Impl) {
+    LibcallImpls[Call] = Impl;
   }
 
   /// Get the libcall routine name for the specified libcall.
+  // FIXME: This should be removed. Only LibcallImpl should have a name.
   const char *getLibcallName(RTLIB::Libcall Call) const {
-    return LibcallRoutineNames[Call];
+    return LibCallImplNames[LibcallImpls[Call]];
+  }
+
+  /// Get the libcall routine name for the specified libcall implementation.
+  const char *getLibcallImplName(RTLIB::LibcallImpl CallImpl) const {
+    return LibCallImplNames[CallImpl];
+  }
+
+  /// Return the lowering's selection of implementation call for \p Call
+  RTLIB::LibcallImpl getLibcallImpl(RTLIB::Libcall Call) const {
+    return LibcallImpls[Call];
   }
 
   /// Set the CallingConv that should be used for the specified libcall.
+  // FIXME: This should be a function of RTLIB::LibcallImpl
   void setLibcallCallingConv(RTLIB::Libcall Call, CallingConv::ID CC) {
     LibcallCallingConvs[Call] = CC;
   }
 
   /// Get the CallingConv that should be used for the specified libcall.
+  // FIXME: This should be a function of RTLIB::LibcallImpl
   CallingConv::ID getLibcallCallingConv(RTLIB::Libcall Call) const {
     return LibcallCallingConvs[Call];
   }
 
-  ArrayRef<const char *> getLibcallNames() const {
-    // Trim UNKNOWN_LIBCALL from the end
-    return ArrayRef(LibcallRoutineNames).drop_back();
+  ArrayRef<RTLIB::LibcallImpl> getLibcallImpls() const {
+    // Trim Unsupported from the start
+    return ArrayRef(LibcallImpls).drop_front();
   }
 
   /// Get the comparison predicate that's to be used to test the result of the
@@ -91,6 +103,7 @@ struct RuntimeLibcallsInfo {
   }
 
   // FIXME: This should be removed. This should be private constant.
+  // FIXME: This should be a function of RTLIB::LibcallImpl
   void setSoftFloatCmpLibcallPredicate(RTLIB::Libcall Call,
                                        CmpInst::Predicate Pred) {
     SoftFloatCompareLibcallPredicates[Call] = Pred;
@@ -107,11 +120,12 @@ struct RuntimeLibcallsInfo {
   }
 
 private:
-  static const char
-      *const DefaultLibcallRoutineNames[RTLIB::UNKNOWN_LIBCALL + 1];
+  static const RTLIB::LibcallImpl
+      DefaultLibcallImpls[RTLIB::UNKNOWN_LIBCALL + 1];
 
-  /// Stores the name each libcall.
-  const char *LibcallRoutineNames[RTLIB::UNKNOWN_LIBCALL + 1] = {nullptr};
+  /// Stores the implementation choice for each each libcall.
+  RTLIB::LibcallImpl LibcallImpls[RTLIB::UNKNOWN_LIBCALL + 1] = {
+      RTLIB::Unsupported};
 
   static_assert(static_cast<int>(CallingConv::C) == 0,
                 "default calling conv should be encoded as 0");
@@ -127,6 +141,13 @@ struct RuntimeLibcallsInfo {
   // opcode.
   CmpInst::Predicate SoftFloatCompareLibcallPredicates[RTLIB::UNKNOWN_LIBCALL];
 
+  /// Names of concrete implementations of runtime calls. e.g. __ashlsi3 for
+  /// SHL_I32
+  static const char *const LibCallImplNames[RTLIB::NumLibcallImpls];
+
+  /// Map from a concrete LibcallImpl implementation to its RTLIB::Libcall kind.
+  static const RTLIB::Libcall ImplToLibcall[RTLIB::NumLibcallImpls];
+
   static bool darwinHasSinCosStret(const Triple &TT) {
     assert(TT.isOSDarwin() && "should be called with darwin triple");
     // Don't bother with 32 bit x86.
@@ -150,7 +171,7 @@ struct RuntimeLibcallsInfo {
            (TT.isAndroid() && !TT.isAndroidVersionLT(9));
   }
 
-  void initDefaultLibCallNames();
+  void initDefaultLibCallImpls();
 
   /// Generated by tablegen.
   void setPPCLibCallNameOverrides();
diff --git a/llvm/include/llvm/IR/RuntimeLibcalls.td b/llvm/include/llvm/IR/RuntimeLibcalls.td
index 396dad6354ae2..b2fcb32cf5edd 100644
--- a/llvm/include/llvm/IR/RuntimeLibcalls.td
+++ b/llvm/include/llvm/IR/RuntimeLibcalls.td
@@ -8,6 +8,13 @@
 
 include "llvm/IR/RuntimeLibcallsImpl.td"
 
+//--------------------------------------------------------------------
+// Utility classes
+//--------------------------------------------------------------------
+
+class DuplicateLibcallImplWithPrefix<RuntimeLibcallImpl Impl, string prefix>
+    : RuntimeLibcallImpl<Impl.Provides, prefix#Impl.LibCallFuncName>;
+
 //--------------------------------------------------------------------
 // Declare all kinds of used libcalls
 //--------------------------------------------------------------------
@@ -299,6 +306,13 @@ multiclass AtomicOrderSizeLibcall {
   def _ACQ_REL : RuntimeLibcall;
 }
 
+multiclass AtomicOrderSizeLibcallImpl<string ProvidesBase> {
+  def _relax : RuntimeLibcallImpl<!cast<RuntimeLibcall>(ProvidesBase#"_RELAX")>;
+  def _acq : RuntimeLibcallImpl<!cast<RuntimeLibcall>(ProvidesBase#"_ACQ")>;
+  def _rel : RuntimeLibcallImpl<!cast<RuntimeLibcall>(ProvidesBase#"_REL")>;
+  def _acq_rel : RuntimeLibcallImpl<!cast<RuntimeLibcall>(ProvidesBase#"_ACQ_REL")>;
+}
+
 // Out-of-line atomics libcalls
 defset list<RuntimeLibcall> LibCalls__OutOfLineAtomic = {
   foreach MemSize = [1, 2, 4, 8, 16] in {
@@ -324,6 +338,12 @@ def RETURN_ADDRESS : RuntimeLibcall;
 def CLEAR_CACHE : RuntimeLibcall;
 def RISCV_FLUSH_ICACHE : RuntimeLibcall;
 
+// Mips16 calls
+def MIPS16_RET_DC : RuntimeLibcall;
+def MIPS16_RET_DF : RuntimeLibcall;
+def MIPS16_RET_SC : RuntimeLibcall;
+def MIPS16_RET_SF : RuntimeLibcall;
+
 multiclass LibmLongDoubleLibCall<string libcall_basename = !toupper(NAME),
                                  string rtbasename = NAME> {
   def NAME#"_f128"
@@ -926,6 +946,465 @@ def __exp2f128_finite : RuntimeLibcallImpl<EXP2_FINITE_F128>;
 def __exp10f128_finite : RuntimeLibcallImpl<EXP10_FINITE_F128>;
 def __powf128_finite : RuntimeLibcallImpl<POW_FINITE_F128>;
 
+//===----------------------------------------------------------------------===//
+// AArch64 Runtime Libcalls
+//===----------------------------------------------------------------------===//
+
+defset list<RuntimeLibcallImpl> AArch64LibcallImpls = {
+  foreach MemSize = [1, 2, 4, 8, 16] in {
+    defm __aarch64_cas#MemSize
+        : AtomicOrderSizeLibcallImpl<"OUTLINE_ATOMIC_CAS"#MemSize>;
+  }
+
+  foreach MemSize = [1, 2, 4, 8] in {
+    defm __aarch64_swp#MemSize
+        : AtomicOrderSizeLibcallImpl<"OUTLINE_ATOMIC_SWP"#MemSize>;
+    defm __aarch64_ldadd#MemSize
+        : AtomicOrderSizeLibcallImpl<"OUTLINE_ATOMIC_LDADD"#MemSize>;
+    defm __aarch64_ldset#MemSize
+        : AtomicOrderSizeLibcallImpl<"OUTLINE_ATOMIC_LDSET"#MemSize>;
+    defm __aarch64_ldclr#MemSize
+        : AtomicOrderSizeLibcallImpl<"OUTLINE_ATOMIC_LDCLR"#MemSize>;
+    defm __aarch64_ldeor#MemSize
+        : AtomicOrderSizeLibcallImpl<"OUTLINE_ATOMIC_LDEOR"#MemSize>;
+  }
+}
+
+foreach libcall = AArch64LibcallImpls in {
+  def arm64ec_#libcall : DuplicateLibcallImplWithPrefix<libcall, "#">;
+}
+
+foreach libcall = DefaultRuntimeLibcallImpls in {
+  def arm64ec_#libcall : DuplicateLibcallImplWithPrefix<libcall, "#">;
+}
+
+//===----------------------------------------------------------------------===//
+// ARM Runtime Libcalls
+//===----------------------------------------------------------------------===//
+
+// if (isTargetMachO()) {
+// if (Subtarget->isThumb() && Subtarget->hasVFP2Base() &&
+//  Subtarget->hasARMOps() && !Subtarget->useSoftFloat()) {
+
+def __addsf3vfp : RuntimeLibcallImpl<ADD_F32>;
+def __subsf3vfp : RuntimeLibcallImpl<SUB_F32>;
+def __mulsf3vfp : RuntimeLibcallImpl<MUL_F32>;
+def __divsf3vfp : RuntimeLibcallImpl<DIV_F32>;
+
+// Double-precision floating-point arithmetic.
+def __adddf3vfp : RuntimeLibcallImpl<ADD_F64>;
+def __subdf3vfp : RuntimeLibcallImpl<SUB_F64>;
+def __muldf3vfp : RuntimeLibcallImpl<MUL_F64>;
+def __divdf3vfp : RuntimeLibcallImpl<DIV_F64>;
+
+// Single-precision comparisons.
+
+// TODO: Track setcc type
+def __eqsf2vfp : RuntimeLibcallImpl<OEQ_F32>; // CmpInst::ICMP_NE
+def __nesf2vfp : RuntimeLibcallImpl<UNE_F32>; // CmpInst::ICMP_NE
+def __ltsf2vfp : RuntimeLibcallImpl<OLT_F32>; // CmpInst::ICMP_NE
+def __lesf2vfp : RuntimeLibcallImpl<OLE_F32>; // CmpInst::ICMP_NE
+def __gesf2vfp : RuntimeLibcallImpl<OGE_F32>; // CmpInst::ICMP_NE
+def __gtsf2vfp : RuntimeLibcallImpl<OGT_F32>; // CmpInst::ICMP_NE
+def __unordsf2vfp : RuntimeLibcallImpl<UO_F32>; // CmpInst::ICMP_NE
+
+// Double-precision comparisons.
+def __eqdf2vfp : RuntimeLibcallImpl<OEQ_F64>; // CmpInst::ICMP_NE
+def __nedf2vfp : RuntimeLibcallImpl<UNE_F64>; // CmpInst::ICMP_NE
+def __ltdf2vfp : RuntimeLibcallImpl<OLT_F64>; // CmpInst::ICMP_NE
+def __ledf2vfp : RuntimeLibcallImpl<OLE_F64>; // CmpInst::ICMP_NE
+def __gedf2vfp : RuntimeLibcallImpl<OGE_F64>; // CmpInst::ICMP_NE
+def __gtdf2vfp : RuntimeLibcallImpl<OGT_F64>; // CmpInst::ICMP_NE
+def __unorddf2vfp : RuntimeLibcallImpl<UO_F64>; // CmpInst::ICMP_NE
+
+// Floating-point to integer conversions.
+// i64 conversions are done via library routines even when generating VFP
+// instructions, so use the same ones.
+def __fixdfsivfp : RuntimeLibcallImpl<FPTOSINT_F64_I32>;
+def __fixunsdfsivfp : RuntimeLibcallImpl<FPTOUINT_F64_I32>;
+def __fixsfsivfp : RuntimeLibcallImpl<FPTOSINT_F32_I32>;
+def __fixunssfsivfp : RuntimeLibcallImpl<FPTOUINT_F32_I32>;
+
+// Conversions between floating types.
+def __truncdfsf2vfp : RuntimeLibcallImpl<FPROUND_F64_F32>;
+def __extendsfdf2vfp : RuntimeLibcallImpl<FPEXT_F32_F64>;
+
+// Integer to floating-point conversions.
+// i64 conversions are done via library routines even when generating VFP
+// instructions, so use the same ones.
+// FIXME: There appears to be some naming inconsistency in ARM libgcc:
+// e.g., __floatunsidf vs. __floatunssidfvfp.
+def __floatsidfvfp : RuntimeLibcallImpl<SINTTOFP_I32_F64>;
+def __floatunssidfvfp : RuntimeLibcallImpl<UINTTOFP_I32_F64>;
+def __floatsisfvfp : RuntimeLibcallImpl<SINTTOFP_I32_F32>;
+def __floatunssisfvfp : RuntimeLibcallImpl<UINTTOFP_I32_F32>;
+
+//  // RTLIB
+//  if (isAAPCS_ABI() &&
+//      (isTargetAEABI() || isTargetGNUAEABI() ||
+//       isTargetMuslAEABI() || isTargetAndroid())) {
+
+// TODO: Set CallingConv = ARM_AAPCS
+
+// Double-precision floating-point arithmetic helper functions
+// RTABI chapter 4.1.2, Table 2
+def __aeabi_dadd : RuntimeLibcallImpl<ADD_F64>; // CallingConv::ARM_AAPCS
+def __aeabi_ddiv : RuntimeLibcallImpl<DIV_F64>; // CallingConv::ARM_AAPCS
+def __aeabi_dmul : RuntimeLibcallImpl<MUL_F64>; // CallingConv::ARM_AAPCS
+def __aeabi_dsub : RuntimeLibcallImpl<SUB_F64>; // CallingConv::ARM_AAPCS
+
+// Double-precision floating-point comparison helper functions
+// RTABI chapter 4.1.2, Table 3
+def __aeabi_dcmpeq__ne : RuntimeLibcallImpl<OEQ_F64, "__aeabi_dcmpeq">; // CallingConv::ARM_AAPCS, CmpInst::ICMP_NE
+def __aeabi_dcmpeq__eq : RuntimeLibcallImpl<UNE_F64, "__aeabi_dcmpeq">; // CallingConv::ARM_AAPCS, CmpInst::ICMP_EQ
+def __aeabi_dcmplt : RuntimeLibcallImpl<OLT_F64>; // CallingConv::ARM_AAPCS, CmpInst::ICMP_NE
+def __aeabi_dcmple : RuntimeLibcallImpl<OLE_F64>; // CallingConv::ARM_AAPCS, CmpInst::ICMP_NE
+def __aeabi_dcmpge : RuntimeLibcallImpl<OGE_F64>; // CallingConv::ARM_AAPCS, CmpInst::ICMP_NE
+def __aeabi_dcmpgt : RuntimeLibcallImpl<OGT_F64>; // CallingConv::ARM_AAPCS, CmpInst::ICMP_NE
+def __aeabi_dcmpun : RuntimeLibcallImpl<UO_F64>; // CallingConv::ARM_AAPCS
+
+// Single-precision floating-point arithmetic helper functions
+// RTABI chapter 4.1.2, Table 4
+def __aeabi_fadd : RuntimeLibcallImpl<ADD_F32>; // CallingConv::ARM_AAPCS
+def __aeabi_fdiv : RuntimeLibcallImpl<DIV_F32>; // CallingConv::ARM_AAPCS
+def __aeabi_fmul : RuntimeLibcallImpl<MUL_F32>; // CallingConv::ARM_AAPCS
+def __aeabi_fsub : RuntimeLibcallImpl<SUB_F32>; // CallingConv::ARM_AAPCS
+
+// Single-precision floating-point comparison helper functions
+// RTABI chapter 4.1.2, Table 5
+def __aeabi_fcmpeq__ne : RuntimeLibcallImpl<OEQ_F32, "__aeabi_fcmpeq">; // CallingConv::ARM_AAPCS, CmpInst::ICMP_NE
+def __aeabi_fcmpeq__eq : RuntimeLibcallImpl<UNE_F32, "__aeabi_fcmpeq">; // CallingConv::ARM_AAPCS, CmpInst::ICMP_EQ
+def __aeabi_fcmplt : RuntimeLibcallImpl<OLT_F32>; // CallingConv::ARM_AAPCS, CmpInst::ICMP_NE
+def __aeabi_fcmple : RuntimeLibcallImpl<OLE_F32>; // CallingConv::ARM_AAPCS, CmpInst::ICMP_NE
+def __aeabi_fcmpge : RuntimeLibcallImpl<OGE_F32>; // CallingConv::ARM_AAPCS, CmpInst::ICMP_NE
+def __aeabi_fcmpgt : RuntimeLibcallImpl<OGT_F32>; // CallingConv::ARM_AAPCS, CmpInst::ICMP_NE
+def __aeabi_fcmpun : RuntimeLibcallImpl<UO_F32>; // CallingConv::ARM_AAPCS
+
+// Floating-point to integer conversions.
+// RTABI chapter 4.1.2, Table 6
+def __aeabi_d2iz : RuntimeLibcallImpl<FPTOSINT_F64_I32>; //  CallingConv::ARM_AAPCS
+def __aeabi_d2uiz : RuntimeLibcallImpl<FPTOUINT_F64_I32>; // CallingConv::ARM_AAPCS
+def __aeabi_d2lz : RuntimeLibcallImpl<FPTOSINT_F64_I64>; //  CallingConv::ARM_AAPCS
+def __aeabi_d2ulz : RuntimeLibcallImpl<FPTOUINT_F64_I64>; // CallingConv::ARM_AAPCS
+def __aeabi_f2iz : RuntimeLibcallImpl<FPTOSINT_F32_I32>; //  CallingConv::ARM_AAPCS
+def __aeabi_f2uiz : RuntimeLibcallImpl<FPTOUINT_F32_I32>; // CallingConv::ARM_AAPCS
+def __aeabi_f2lz : RuntimeLibcallImpl<FPTOSINT_F32_I64>; //  CallingConv::ARM_AAPCS
+def __aeabi_f2ulz : RuntimeLibcallImpl<FPTOUINT_F32_I64>; // CallingConv::ARM_AAPCS
+
+// Conversions between floating types.
+// RTABI chapter 4.1.2, Table 7
+def __aeabi_d2f : RuntimeLibcallImpl<FPROUND_F64_F32>; // CallingConv::ARM_AAPCS
+def __aeabi_d2h : RuntimeLibcallImpl<FPROUND_F64_F16>; // CallingConv::ARM_AAPCS
+def  __aeabi_f2d : RuntimeLibcallImpl<FPEXT_F32_F64>; // CallingConv::ARM_AAPCS
+
+// Integer to floating-point conversions.
+// RTABI chapter 4.1.2, Table 8
+def __aeabi_i2d : RuntimeLibcallImpl<SINTTOFP_I32_F64>; //  CallingConv::ARM_AAPCS
+def __aeabi_ui2d : RuntimeLibcallImpl<UINTTOFP_I32_F64>; // CallingConv::ARM_AAPCS
+def __aeabi_l2d : RuntimeLibcallImpl<SINTTOFP_I64_F64>; //  CallingConv::ARM_AAPCS
+def __aeabi_ul2d : RuntimeLibcallImpl<UINTTOFP_I64_F64>; // CallingConv::ARM_AAPCS
+def __aeabi_i2f : RuntimeLibcallImpl<SINTTOFP_I32_F32>; //  CallingConv::ARM_AAPCS
+def __aeabi_ui2f : RuntimeLibcallImpl<UINTTOFP_I32_F32>; // CallingConv::ARM_AAPCS
+def __aeabi_l2f : RuntimeLibcallImpl<SINTTOFP_I64_F32>; //  CallingConv::ARM_AAPCS
+def __aeabi_ul2f : RuntimeLibcallImpl<UINTTOFP_I64_F32>; // CallingConv::ARM_AAPCS
+
+// Long long helper functions
+// RTABI chapter 4.2, Table 9
+def __aeabi_lmul : RuntimeLibcallImpl<MUL_I64>; // CallingConv::ARM_AAPCS
+def __aeabi_llsl : RuntimeLibcallImpl<SHL_I64>; // CallingConv::ARM_AAPCS
+def __aeabi_llsr : RuntimeLibcallImpl<SRL_I64>; // CallingConv::ARM_AAPCS
+def __aeabi_lasr : RuntimeLibcallImpl<SRA_I64>; // CallingConv::ARM_AAPCS
+
+// Integer division functions
+// RTABI chapter 4.3.1
+def __aeabi_idiv__i8 : RuntimeLibcallImpl<SDIV_I8, "__aeabi_idiv">; // CallingConv::ARM_AAPCS
+def __aeabi_idiv__i16 : RuntimeLibcallImpl<SDIV_I16, "__aeabi_idiv">; // CallingConv::ARM_AAPCS
+def __aeabi_idiv__i32 : RuntimeLibcallImpl<SDIV_I32, "__aeabi_idiv">; // CallingConv::ARM_AAPCS
+def __aeabi_ldivmod : RuntimeLibcallImpl<SDIVREM_I64>; //  CallingConv::ARM_AAPCS
+def __aeabi_uidiv__i8 : RuntimeLibcallImpl<UDIV_I8, "__aeabi_uidiv">; // CallingConv::ARM_AAPCS
+def __aeabi_uidiv__i16 : RuntimeLibcallImpl<UDIV_I16, "__aeabi_uidiv">; // CallingConv::ARM_AAPCS
+def __aeabi_uidiv__i32 : RuntimeLibcallImpl<UDIV_I32, "__aeabi_uidiv">; // CallingConv::ARM_AAPCS
+def __aeabi_uldivmod : RuntimeLibcallImpl<UDIVREM_I64>; // CallingConv::ARM_AAPCS
+
+def __aeabi_idivmod : RuntimeLibcallImpl<SDIVREM_I32>; //  CallingConv::ARM_AAPCS
+def __aeabi_uidivmod : RuntimeLibcallImpl<UDIVREM_I32>; //  CallingConv::ARM_AAPCS
+
+// EABI dependent RTLIB
+
+// Memory operations
+// RTABI chapter 4.3.4
+def __aeabi_memcpy : RuntimeLibcallImpl<MEMCPY>; // CallingConv::ARM_AAPCS
+def __aeabi_memmove : RuntimeLibcallImpl<MEMMOVE>; // CallingConv::ARM_AAPCS
+def __aeabi_memset : RuntimeLibcallImpl<MEMSET>; // CallingConv::ARM_AAPCS
+
+// isTargetWindows()
+def __stoi64 : RuntimeLibcallImpl<FPTOSINT_F32_I64>; // CallingConv::ARM_AAPCS_VFP
+def __dtoi64 : RuntimeLibcallImpl<FPTOSINT_F64_I64>; // CallingConv::ARM_AAPCS_VFP
+def __stou64 : RuntimeLibcallImpl<FPTOUINT_F32_I64>; // CallingConv::ARM_AAPCS_VFP
+def __dtou64 : RuntimeLibcallImpl<FPTOUINT_F64_I64>; // CallingConv::ARM_AAPCS_VFP
+def __i64tos : RuntimeLibcallImpl<SINTTOFP_I64_F32>; // CallingConv::ARM_AAPCS_VFP
+def __i64tod : RuntimeLibcallImpl<SINTTOFP_I64_F64>; // CallingConv::ARM_AAPCS_VFP
+def __u64tos : RuntimeLibcallImpl<UINTTOFP_I64_F32>; // CallingConv::ARM_AAPCS_VFP
+def __u64tod : RuntimeLibcallImpl<UINTTOFP_I64_F64>; // CallingConv::ARM_AAPCS_VFP
+
+def __rt_sdiv : RuntimeLibcallImpl<SDIVREM_I32>; // CallingConv::ARM_AAPCS
+def __rt_sdiv64 : RuntimeLibcallImpl<SDIVREM_I64>; // CallingConv::ARM_AAPCS
+def __rt_udiv : RuntimeLibcallImpl<UDIVREM_I32>; // CallingConv::ARM_AAPCS
+def __rt_udiv64 : RuntimeLibcallImpl<UDIVREM_I64>; // CallingConv::ARM_AAPCS
+
+// Use divmod compiler-rt calls for iOS 5.0 and later.
+//  isTargetMachO() &&
+// !(isTargetIOS() && isOSVersionLT(5, 0))
+def __divmodsi4 : RuntimeLibcallImpl<SDIVREM_I32>;
+def __udivmodsi4 : RuntimeLibcallImpl<UDIVREM_I32>;
+
+// FIXME: Change calling convention of FPROUND_F32_F16,
+// RTLIB::FPROUND_F64_F16, FPEXT_F16_F32 for !Subtarget->isTargetWatchABI())
+
+// In EABI, these functions have an __aeabi_ prefix, but in GNUEABI they have
+// a __gnu_ prefix (which is the default).
+// isTargetAEABI()
+def __aeabi_f2h : RuntimeLibcallImpl<FPROUND_F32_F16>; // CallingConv::ARM_AAPCS
+//def __aeabi_d2h : RuntimeLibcallImpl<FPROUND_F64_F16>; // CallingConv::ARM_AAPCS
+def __aeabi_h2f : RuntimeLibcallImpl<FPEXT_F16_F32>; // CallingConv::ARM_AAPCS
+
+// !isTargetMachO()
+def __gnu_f2h_ieee : RuntimeLibcallImpl<FPROUND_F32_F16>;
+def __gnu_h2f_ieee : RuntimeLibcallImpl<FPEXT_F16_F32>;
+
+//===----------------------------------------------------------------------===//
+// AVR Runtime Libcalls
+//===----------------------------------------------------------------------===//
+
+// Several of the runtime library functions use a special calling conv
+def __divmodqi4 : RuntimeLibcallImpl<SDIVREM_I8>; // CallingConv::AVR_BUILTIN
+def __divmodhi4 : RuntimeLibcallImpl<SDIVREM_I16>; // CallingConv::AVR_BUILTIN
+//def __divmodsi4 : RuntimeLibcallImpl<SDIVREM_I32>;
+def __udivmodqi4 : RuntimeLibcallImpl<UDIVREM_I8>; // CallingConv::AVR_BUILTIN
+def __udivmodhi4 : RuntimeLibcallImpl<UDIVREM_I16>; // CallingConv::AVR_BUILTIN
+//def __udivmodsi4 : RuntimeLibcallImpl<UDIVREM_I32>;
+
+// Standard sinf/cosf name replaced with "sin" and "cos". Define a
+// separate Impl so we can set a different type signature.
+def avr_sin : RuntimeLibcallImpl<SIN_F32, "sin">;
+def avr_cos : RuntimeLibcallImpl<COS_F32, "cos">;
+
+//===----------------------------------------------------------------------===//
+// Hexagon Runtime Libcalls
+//===----------------------------------------------------------------------===//
+
+def __hexagon_divsi3 : RuntimeLibcallImpl<SDIV_I32>;
+def __hexagon_divdi3 : RuntimeLibcallImpl<SDIV_I64>;
+def __hexagon_udivsi3 : RuntimeLibcallImpl<UDIV_I32>;
+def __hexagon_udivdi3 : RuntimeLibcallImpl<UDIV_I64>;
+def __hexagon_modsi3 : RuntimeLibcallImpl<SREM_I32>;
+def __hexagon_moddi3 : RuntimeLibcallImpl<SREM_I64>;
+def __hexagon_umodsi3 : RuntimeLibcallImpl<UREM_I32>;
+def __hexagon_umoddi3 : RuntimeLibcallImpl<UREM_I64>;
+
+// FIXME: "Fast" versions should be treated as a separate RTLIB::FAST_* function
+def __hexagon_adddf3 : RuntimeLibcallImpl<ADD_F64>;
+def __hexagon_fast_adddf3 : RuntimeLibcallImpl<ADD_F64>;
+
+def __hexagon_subdf3 : RuntimeLibcallImpl<SUB_F64>;
+def __hexagon_fast_subdf3 : RuntimeLibcallImpl<SUB_F64>;
+
+def __hexagon_muldf3 : RuntimeLibcallImpl<MUL_F64>;
+def __hexagon_fast_muldf3 : RuntimeLibcallImpl<MUL_F64>;
+
+def __hexagon_divdf3 : RuntimeLibcallImpl<DIV_F64>;
+def __hexagon_fast_divdf3 : RuntimeLibcallImpl<DIV_F64>;
+
+def __hexagon_divsf3 : RuntimeLibcallImpl<DIV_F32>;
+def __hexagon_fast_divsf3 : RuntimeLibcallImpl<DIV_F32>;
+
+def __hexagon_sqrtf : RuntimeLibcallImpl<SQRT_F32>;
+def __hexagon_fast2_sqrtf : RuntimeLibcallImpl<SQRT_F32>;
+
+// This is the only fast library function for sqrtd.
+def __hexagon_fast2_sqrtdf2 : RuntimeLibcallImpl<SQRT_F64>;
+
+//===----------------------------------------------------------------------===//
+// Mips16 Runtime Libcalls
+//===----------------------------------------------------------------------===//
+
+// Hard float libcalls
+def __mips16_adddf3 : RuntimeLibcallImpl<ADD_F64>;
+def __mips16_addsf3 : RuntimeLibcallImpl<ADD_F32>;
+def __mips16_divdf3 : RuntimeLibcallImpl<DIV_F64>;
+def __mips16_divsf3 : RuntimeLibcallImpl<DIV_F32>;
+def __mips16_eqdf2 : RuntimeLibcallImpl<OEQ_F64>;
+def __mips16_eqsf2 : RuntimeLibcallImpl<OEQ_F32>;
+def __mips16_extendsfdf2 : RuntimeLibcallImpl<FPEXT_F32_F64>;
+def __mips16_fix_truncdfsi : RuntimeLibcallImpl<FPTOSINT_F64_I32>;
+def __mips16_fix_truncsfsi : RuntimeLibcallImpl<FPTOSINT_F32_I32>;
+def __mips16_floatsidf : RuntimeLibcallImpl<SINTTOFP_I32_F64>;
+def __mips16_floatsisf : RuntimeLibcallImpl<SINTTOFP_I32_F32>;
+def __mips16_floatunsidf : RuntimeLibcallImpl<UINTTOFP_I32_F64>;
+def __mips16_floatunsisf : RuntimeLibcallImpl<UINTTOFP_I32_F32>;
+def __mips16_gedf2 : RuntimeLibcallImpl<OGE_F64>;
+def __mips16_gesf2 : RuntimeLibcallImpl<OGE_F32>;
+def __mips16_gtdf2 : RuntimeLibcallImpl<OGT_F64>;
+def __mips16_gtsf2 : RuntimeLibcallImpl<OGT_F32>;
+def __mips16_ledf2 : RuntimeLibcallImpl<OLE_F64>;
+def __mips16_lesf2 : RuntimeLibcallImpl<OLE_F32>;
+def __mips16_ltdf2 : RuntimeLibcallImpl<OLT_F64>;
+def __mips16_ltsf2 : RuntimeLibcallImpl<OLT_F32>;
+def __mips16_muldf3 : RuntimeLibcallImpl<MUL_F64>;
+def __mips16_mulsf3 : RuntimeLibcallImpl<MUL_F32>;
+def __mips16_nedf2 : RuntimeLibcallImpl<UNE_F64>;
+def __mips16_nesf2 : RuntimeLibcallImpl<UNE_F32>;
+def __mips16_ret_dc : RuntimeLibcallImpl<MIPS16_RET_DC>;
+def __mips16_ret_df : RuntimeLibcallImpl<MIPS16_RET_DF>;
+def __mips16_ret_sc : RuntimeLibcallImpl<MIPS16_RET_SC>;
+def __mips16_ret_sf : RuntimeLibcallImpl<MIPS16_RET_SF>;
+def __mips16_subdf3 : RuntimeLibcallImpl<SUB_F64>;
+def __mips16_subsf3 : RuntimeLibcallImpl<SUB_F32>;
+def __mips16_truncdfsf2 : RuntimeLibcallImpl<FPROUND_F64_F32>;
+def __mips16_unorddf2 : RuntimeLibcallImpl<UO_F64>;
+def __mips16_unordsf2 : RuntimeLibcallImpl<UO_F32>;
+
+//===----------------------------------------------------------------------===//
+// MSP430 Runtime Libcalls
+//===----------------------------------------------------------------------===//
+
+// EABI Libcalls - EABI Section 6.2
+
+// Floating point conversions - EABI Table 6
+def __mspabi_cvtdf : RuntimeLibcallImpl<FPROUND_F64_F32>;
+def __mspabi_cvtfd : RuntimeLibcallImpl<FPEXT_F32_F64>;
+
+// The following is NOT implemented in libgcc
+//def __mspabi_fixdi : RuntimeLibcallImpl<FPTOSINT_F64_I16>;
+def __mspabi_fixdli : RuntimeLibcallImpl<FPTOSINT_F64_I32>;
+def __mspabi_fixdlli : RuntimeLibcallImpl<FPTOSINT_F64_I64>;
+
+// The following is NOT implemented in libgcc
+//def __mspabi_fixdu : RuntimeLibcallImpl<FPTOUINT_F64_I16>;
+def __mspabi_fixdul : RuntimeLibcallImpl<FPTOUINT_F64_I32>;
+def __mspabi_fixdull : RuntimeLibcallImpl<FPTOUINT_F64_I64>;
+
+// The following is NOT implemented in libgcc
+//def __mspabi_fixfi : RuntimeLibcallImpl<FPTOSINT_F32_I16>;
+def __mspabi_fixfli : RuntimeLibcallImpl<FPTOSINT_F32_I32>;
+def __mspabi_fixflli : RuntimeLibcallImpl<FPTOSINT_F32_I64>;
+
+// The following is NOT implemented in libgcc
+//def __mspabi_fixfu : RuntimeLibcallImpl<FPTOUINT_F32_I16>;
+def __mspabi_fixful : RuntimeLibcallImpl<FPTOUINT_F32_I32>;
+def __mspabi_fixfull : RuntimeLibcallImpl<FPTOUINT_F32_I64>;
+
+// TODO The following IS implemented in libgcc
+//def __mspabi_fltid : RuntimeLibcallImpl<SINTTOFP_I16_F64>;
+def __mspabi_fltlid : RuntimeLibcallImpl<SINTTOFP_I32_F64>;
+
+// TODO The following IS implemented in libgcc but is not in the EABI
+def __mspabi_fltllid : RuntimeLibcallImpl<SINTTOFP_I64_F64>;
+
+// TODO The following IS implemented in libgcc
+//def __mspabi_fltud : RuntimeLibcallImpl<UINTTOFP_I16_F64>;
+def __mspabi_fltuld : RuntimeLibcallImpl<UINTTOFP_I32_F64>;
+
+// The following IS implemented in libgcc but is not in the EABI
+def __mspabi_fltulld : RuntimeLibcallImpl<UINTTOFP_I64_F64>;
+
+// TODO The following IS implemented in libgcc
+//def __mspabi_fltif : RuntimeLibcallImpl<SINTTOFP_I16_F32>;
+def __mspabi_fltlif : RuntimeLibcallImpl<SINTTOFP_I32_F32>;
+
+// TODO The following IS implemented in libgcc but is not in the EABI
+def __mspabi_fltllif : RuntimeLibcallImpl<SINTTOFP_I64_F32>;
+
+// TODO The following IS implemented in libgcc
+//def __mspabi_fltuf : RuntimeLibcallImpl<UINTTOFP_I16_F32>;
+def __mspabi_fltulf : RuntimeLibcallImpl<UINTTOFP_I32_F32>;
+
+// The following IS implemented in libgcc but is not in the EABI
+def __mspabi_fltullf : RuntimeLibcallImpl<UINTTOFP_I64_F32>;
+
+// Floating point comparisons - EABI Table 7
+def __mspabi_cmpd__oeq : RuntimeLibcallImpl<OEQ_F64, "__mspabi_cmpd">;
+def __mspabi_cmpd__une : RuntimeLibcallImpl<UNE_F64, "__mspabi_cmpd">;
+def __mspabi_cmpd__oge : RuntimeLibcallImpl<OGE_F64, "__mspabi_cmpd">;
+def __mspabi_cmpd__olt : RuntimeLibcallImpl<OLT_F64, "__mspabi_cmpd">;
+def __mspabi_cmpd__ole : RuntimeLibcallImpl<OLE_F64, "__mspabi_cmpd">;
+def __mspabi_cmpd__ogt : RuntimeLibcallImpl<OGT_F64, "__mspabi_cmpd">;
+def __mspabi_cmpf__oeq : RuntimeLibcallImpl<OEQ_F32, "__mspabi_cmpf">;
+def __mspabi_cmpf__une : RuntimeLibcallImpl<UNE_F32, "__mspabi_cmpf">;
+def __mspabi_cmpf__oge : RuntimeLibcallImpl<OGE_F32, "__mspabi_cmpf">;
+def __mspabi_cmpf__olt : RuntimeLibcallImpl<OLT_F32, "__mspabi_cmpf">;
+def __mspabi_cmpf__ole : RuntimeLibcallImpl<OLE_F32, "__mspabi_cmpf">;
+def __mspabi_cmpf__ogt : RuntimeLibcallImpl<OGT_F32, "__mspabi_cmpf">;
+
+// Floating point arithmetic - EABI Table 8
+def __mspabi_addd : RuntimeLibcallImpl<ADD_F64>;
+def __mspabi_addf : RuntimeLibcallImpl<ADD_F32>;
+def __mspabi_divd : RuntimeLibcallImpl<DIV_F64>;
+def __mspabi_divf : RuntimeLibcallImpl<DIV_F32>;
+def __mspabi_mpyd : RuntimeLibcallImpl<MUL_F64>;
+def __mspabi_mpyf : RuntimeLibcallImpl<MUL_F32>;
+def __mspabi_subd : RuntimeLibcallImpl<SUB_F64>;
+def __mspabi_subf : RuntimeLibcallImpl<SUB_F32>;
+
+// The following are NOT implemented in libgcc
+// def __mspabi_negd : RuntimeLibcallImpl<NEG_F64>;
+// def __mspabi_negf : RuntimeLibcallImpl<NEG_F32>;
+
+// Universal Integer Operations - EABI Table 9
+def __mspabi_divi : RuntimeLibcallImpl<SDIV_I16>;
+def __mspabi_divli : RuntimeLibcallImpl<SDIV_I32>;
+def __mspabi_divlli : RuntimeLibcallImpl<SDIV_I64>;
+def __mspabi_divu : RuntimeLibcallImpl<UDIV_I16>;
+def __mspabi_divul : RuntimeLibcallImpl<UDIV_I32>;
+def __mspabi_divull : RuntimeLibcallImpl<UDIV_I64>;
+def __mspabi_remi : RuntimeLibcallImpl<SREM_I16>;
+def __mspabi_remli : RuntimeLibcallImpl<SREM_I32>;
+def __mspabi_remlli : RuntimeLibcallImpl<SREM_I64>;
+def __mspabi_remu : RuntimeLibcallImpl<UREM_I16>;
+def __mspabi_remul : RuntimeLibcallImpl<UREM_I32>;
+def __mspabi_remull : RuntimeLibcallImpl<UREM_I64>;
+
+// Bitwise Operations - EABI Table 10
+// TODO: __mspabi_[srli/srai/slli] ARE implemented in libgcc
+def __mspabi_srll : RuntimeLibcallImpl<SRL_I32>;
+def __mspabi_sral : RuntimeLibcallImpl<SRA_I32>;
+def __mspabi_slll : RuntimeLibcallImpl<SHL_I32>;
+// __mspabi_[srlll/srall/sllll/rlli/rlll] are NOT implemented in libgcc
+
+// hasHWMult16()
+// Integer Multiply - EABI Table 9
+//def __mspabi_mpyi_hw : RuntimeLibcallImpl<MUL_I16>;
+def __mspabi_mpyl_hw : RuntimeLibcallImpl<MUL_I32>;
+def __mspabi_mpyll_hw : RuntimeLibcallImpl<MUL_I64>;
+// TODO The __mspabi_mpysl*_hw functions ARE implemented in libgcc
+// TODO The __mspabi_mpyul*_hw functions ARE implemented in libgcc
+
+// hasHWMult32()
+// Integer Multiply - EABI Table 9
+def __mspabi_mpyi_hw : RuntimeLibcallImpl<MUL_I16>;
+def __mspabi_mpyl_hw32 : RuntimeLibcallImpl<MUL_I32>;
+def __mspabi_mpyll_hw32 : RuntimeLibcallImpl<MUL_I64>;
+// TODO The __mspabi_mpysl*_hw32 functions ARE implemented in libgcc
+// TODO The __mspabi_mpyul*_hw32 functions ARE implemented in libgcc
+
+// hasHWMultF5()
+// Integer Multiply - EABI Table 9
+def __mspabi_mpyi_f5hw : RuntimeLibcallImpl<MUL_I16>;
+def __mspabi_mpyl_f5hw : RuntimeLibcallImpl<MUL_I32>;
+def __mspabi_mpyll_f5hw : RuntimeLibcallImpl<MUL_I64>;
+// TODO The __mspabi_mpysl*_f5hw functions ARE implemented in libgcc
+// TODO The __mspabi_mpyul*_f5hw functions ARE implemented in libgcc
+
+// NoHWMult
+// Integer Multiply - EABI Table 9
+def __mspabi_mpyi : RuntimeLibcallImpl<MUL_I16>;
+def __mspabi_mpyl : RuntimeLibcallImpl<MUL_I32>;
+def __mspabi_mpyll : RuntimeLibcallImpl<MUL_I64>;
+// The __mspabi_mpysl* functions are NOT implemented in libgcc
+// The __mspabi_mpyul* functions are NOT implemented in libgcc
+
+// setLibcallCallingConv(MUL_I64, CallingConv::MSP430_BUILTIN);
+
 //===----------------------------------------------------------------------===//
 // PPC Runtime Libcalls
 //===----------------------------------------------------------------------===//
@@ -964,6 +1443,78 @@ def __lekf2 : PPCRuntimeLibcallImpl<OLE_F128>;
 def __gtkf2 : PPCRuntimeLibcallImpl<OGT_F128>;
 def __unordkf2 : PPCRuntimeLibcallImpl<UO_F128>;
 
+// PPC64 && Subtarget.isAIXABI()
+def ___memmove64 : RuntimeLibcallImpl<MEMCPY>;
+def ___memset64 : RuntimeLibcallImpl<MEMSET>;
+def ___bzero64 : RuntimeLibcallImpl<BZERO>;
+
+// !PPC64 && Subtarget.isAIXABI()
+def ___memmove : RuntimeLibcallImpl<MEMMOVE>;
+def ___memset : RuntimeLibcallImpl<MEMSET>;
+def ___bzero : RuntimeLibcallImpl<BZERO>;
+
+//===----------------------------------------------------------------------===//
+// SPARC Runtime Libcalls
+//===----------------------------------------------------------------------===//
+
+// Subtarget->useSoftMulDiv()
+def sparc_umul : RuntimeLibcallImpl<MUL_I32, ".umul">;
+def sparc_div : RuntimeLibcallImpl<SDIV_I32, ".div">;
+def sparc_udiv : RuntimeLibcallImpl<UDIV_I32, ".udiv">;
+def sparc_rem : RuntimeLibcallImpl<SREM_I32, ".rem">;
+def sparc_urem : RuntimeLibcallImpl<UREM_I32, ".urem">;
+
+// SPARC64 && !Subtarget->useSoftFloat()
+def _Qp_add : RuntimeLibcallImpl<ADD_F128>;
+def _Qp_sub : RuntimeLibcallImpl<SUB_F128>;
+def _Qp_mul : RuntimeLibcallImpl<MUL_F128>;
+def _Qp_div : RuntimeLibcallImpl<DIV_F128>;
+def _Qp_sqrt : RuntimeLibcallImpl<SQRT_F128>;
+def _Qp_qtoi : RuntimeLibcallImpl<FPTOSINT_F128_I32>;
+def _Qp_qtoui : RuntimeLibcallImpl<FPTOUINT_F128_I32>;
+def _Qp_itoq : RuntimeLibcallImpl<SINTTOFP_I32_F128>;
+def _Qp_uitoq : RuntimeLibcallImpl<UINTTOFP_I32_F128>;
+def _Qp_qtox : RuntimeLibcallImpl<FPTOSINT_F128_I64>;
+def _Qp_qtoux : RuntimeLibcallImpl<FPTOUINT_F128_I64>;
+def _Qp_xtoq : RuntimeLibcallImpl<SINTTOFP_I64_F128>;
+def _Qp_uxtoq : RuntimeLibcallImpl<UINTTOFP_I64_F128>;
+def _Qp_stoq : RuntimeLibcallImpl<FPEXT_F32_F128>;
+def _Qp_dtoq : RuntimeLibcallImpl<FPEXT_F64_F128>;
+def _Qp_qtos : RuntimeLibcallImpl<FPROUND_F128_F32>;
+def _Qp_qtod : RuntimeLibcallImpl<FPROUND_F128_F64>;
+
+// SPARC32 && !Subtarget->useSoftFloat()
+def _Q_add : RuntimeLibcallImpl<ADD_F128>;
+def _Q_sub : RuntimeLibcallImpl<SUB_F128>;
+def _Q_mul : RuntimeLibcallImpl<MUL_F128>;
+def _Q_div : RuntimeLibcallImpl<DIV_F128>;
+def _Q_sqrt : RuntimeLibcallImpl<SQRT_F128>;
+def _Q_qtoi : RuntimeLibcallImpl<FPTOSINT_F128_I32>;
+def _Q_qtou : RuntimeLibcallImpl<FPTOUINT_F128_I32>;
+def _Q_itoq : RuntimeLibcallImpl<SINTTOFP_I32_F128>;
+def _Q_utoq : RuntimeLibcallImpl<UINTTOFP_I32_F128>;
+def _Q_stoq : RuntimeLibcallImpl<FPEXT_F32_F128>;
+def _Q_dtoq : RuntimeLibcallImpl<FPEXT_F64_F128>;
+def _Q_qtos : RuntimeLibcallImpl<FPROUND_F128_F32>;
+def _Q_qtod : RuntimeLibcallImpl<FPROUND_F128_F64>;
+
+// SPARC32 && (Subtarget->hasHardQuad() || !Subtarget->useSoftFloat())
+def _Q_qtoll : RuntimeLibcallImpl<FPTOSINT_F128_I64>;
+def _Q_qtoull : RuntimeLibcallImpl<FPTOUINT_F128_I64>;
+def _Q_lltoq : RuntimeLibcallImpl<SINTTOFP_I64_F128>;
+def _Q_ulltoq : RuntimeLibcallImpl<UINTTOFP_I64_F128>;
+
+//===----------------------------------------------------------------------===//
+// Windows Runtime Libcalls
+//===----------------------------------------------------------------------===//
+
+// TT.isWindowsMSVCEnvironment() || TT.isWindowsItaniumEnvironment()
+def _alldiv : RuntimeLibcallImpl<SDIV_I64>; // CallingConv::X86_StdCall
+def _aulldiv : RuntimeLibcallImpl<UDIV_I64>; // CallingConv::X86_StdCall
+def _allrem : RuntimeLibcallImpl<SREM_I64>; // CallingConv::X86_StdCall
+def _aullrem : RuntimeLibcallImpl<UREM_I64>; // CallingConv::X86_StdCall
+def _allmul : RuntimeLibcallImpl<MUL_I64>; // CallingConv::X86_StdCall
+
 //===----------------------------------------------------------------------===//
 // ZOS Runtime Libcalls
 //===----------------------------------------------------------------------===//
@@ -1052,3 +1603,12 @@ def zos___LCEL_B : ZOSRuntimeLibcallImpl<CEIL_F128, "@@LCEL at B">;
 def zos___SCRT_B : ZOSRuntimeLibcallImpl<CBRT_F64, "@@SCRT at B">;
 def zos___FCBT_B : ZOSRuntimeLibcallImpl<CBRT_F32, "@@FCBT at B">;
 def zos___LCBT_B : ZOSRuntimeLibcallImpl<CBRT_F128, "@@LCBT at B">;
+
+//===----------------------------------------------------------------------===//
+// WebAssembly Runtime Libcalls
+//===----------------------------------------------------------------------===//
+
+// Define the emscripten name for return address helper.
+// TODO: when implementing other Wasm backends, make this generic or only do
+// this on emscripten depending on what they end up doing.
+def emscripten_return_address : RuntimeLibcallImpl<RETURN_ADDRESS>;
diff --git a/llvm/lib/IR/RuntimeLibcalls.cpp b/llvm/lib/IR/RuntimeLibcalls.cpp
index 645f9ed2360be..a3c021d7cf0f9 100644
--- a/llvm/lib/IR/RuntimeLibcalls.cpp
+++ b/llvm/lib/IR/RuntimeLibcalls.cpp
@@ -25,10 +25,10 @@ static cl::opt<bool>
 static void setAArch64LibcallNames(RuntimeLibcallsInfo &Info,
                                    const Triple &TT) {
 #define LCALLNAMES(A, B, N)                                                    \
-  Info.setLibcallName(A##N##_RELAX, #B #N "_relax");                           \
-  Info.setLibcallName(A##N##_ACQ, #B #N "_acq");                               \
-  Info.setLibcallName(A##N##_REL, #B #N "_rel");                               \
-  Info.setLibcallName(A##N##_ACQ_REL, #B #N "_acq_rel");
+  Info.setLibcallImpl(A##N##_RELAX, B##N##_relax);                             \
+  Info.setLibcallImpl(A##N##_ACQ, B##N##_acq);                                 \
+  Info.setLibcallImpl(A##N##_REL, B##N##_rel);                                 \
+  Info.setLibcallImpl(A##N##_ACQ_REL, B##N##_acq_rel);
 #define LCALLNAME4(A, B)                                                       \
   LCALLNAMES(A, B, 1)                                                          \
   LCALLNAMES(A, B, 2) LCALLNAMES(A, B, 4) LCALLNAMES(A, B, 8)
@@ -38,21 +38,20 @@ static void setAArch64LibcallNames(RuntimeLibcallsInfo &Info,
   LCALLNAMES(A, B, 4) LCALLNAMES(A, B, 8) LCALLNAMES(A, B, 16)
 
   if (TT.isWindowsArm64EC()) {
-    LCALLNAME5(RTLIB::OUTLINE_ATOMIC_CAS, #__aarch64_cas)
-    LCALLNAME4(RTLIB::OUTLINE_ATOMIC_SWP, #__aarch64_swp)
-    LCALLNAME4(RTLIB::OUTLINE_ATOMIC_LDADD, #__aarch64_ldadd)
-    LCALLNAME4(RTLIB::OUTLINE_ATOMIC_LDSET, #__aarch64_ldset)
-    LCALLNAME4(RTLIB::OUTLINE_ATOMIC_LDCLR, #__aarch64_ldclr)
-    LCALLNAME4(RTLIB::OUTLINE_ATOMIC_LDEOR, #__aarch64_ldeor)
+    LCALLNAME5(RTLIB::OUTLINE_ATOMIC_CAS, RTLIB::arm64ec___aarch64_cas)
+    LCALLNAME4(RTLIB::OUTLINE_ATOMIC_SWP, RTLIB::arm64ec___aarch64_swp)
+    LCALLNAME4(RTLIB::OUTLINE_ATOMIC_LDADD, RTLIB::arm64ec___aarch64_ldadd)
+    LCALLNAME4(RTLIB::OUTLINE_ATOMIC_LDSET, RTLIB::arm64ec___aarch64_ldset)
+    LCALLNAME4(RTLIB::OUTLINE_ATOMIC_LDCLR, RTLIB::arm64ec___aarch64_ldclr)
+    LCALLNAME4(RTLIB::OUTLINE_ATOMIC_LDEOR, RTLIB::arm64ec___aarch64_ldeor)
   } else {
-    LCALLNAME5(RTLIB::OUTLINE_ATOMIC_CAS, __aarch64_cas)
-    LCALLNAME4(RTLIB::OUTLINE_ATOMIC_SWP, __aarch64_swp)
-    LCALLNAME4(RTLIB::OUTLINE_ATOMIC_LDADD, __aarch64_ldadd)
-    LCALLNAME4(RTLIB::OUTLINE_ATOMIC_LDSET, __aarch64_ldset)
-    LCALLNAME4(RTLIB::OUTLINE_ATOMIC_LDCLR, __aarch64_ldclr)
-    LCALLNAME4(RTLIB::OUTLINE_ATOMIC_LDEOR, __aarch64_ldeor)
+    LCALLNAME5(RTLIB::OUTLINE_ATOMIC_CAS, RTLIB::__aarch64_cas)
+    LCALLNAME4(RTLIB::OUTLINE_ATOMIC_SWP, RTLIB::__aarch64_swp)
+    LCALLNAME4(RTLIB::OUTLINE_ATOMIC_LDADD, RTLIB::__aarch64_ldadd)
+    LCALLNAME4(RTLIB::OUTLINE_ATOMIC_LDSET, RTLIB::__aarch64_ldset)
+    LCALLNAME4(RTLIB::OUTLINE_ATOMIC_LDCLR, RTLIB::__aarch64_ldclr)
+    LCALLNAME4(RTLIB::OUTLINE_ATOMIC_LDEOR, RTLIB::__aarch64_ldeor)
   }
-
 #undef LCALLNAMES
 #undef LCALLNAME4
 #undef LCALLNAME5
@@ -75,33 +74,33 @@ static void setARMLibcallNames(RuntimeLibcallsInfo &Info, const Triple &TT,
     if (TT.isOSWindows()) {
       const struct {
         const RTLIB::Libcall Op;
-        const char *const Name;
+        const RTLIB::LibcallImpl Impl;
         const CallingConv::ID CC;
       } LibraryCalls[] = {
-          {RTLIB::SDIVREM_I32, "__rt_sdiv", CallingConv::ARM_AAPCS},
-          {RTLIB::SDIVREM_I64, "__rt_sdiv64", CallingConv::ARM_AAPCS},
-          {RTLIB::UDIVREM_I32, "__rt_udiv", CallingConv::ARM_AAPCS},
-          {RTLIB::UDIVREM_I64, "__rt_udiv64", CallingConv::ARM_AAPCS},
+          {RTLIB::SDIVREM_I32, RTLIB::__rt_sdiv, CallingConv::ARM_AAPCS},
+          {RTLIB::SDIVREM_I64, RTLIB::__rt_sdiv64, CallingConv::ARM_AAPCS},
+          {RTLIB::UDIVREM_I32, RTLIB::__rt_udiv, CallingConv::ARM_AAPCS},
+          {RTLIB::UDIVREM_I64, RTLIB::__rt_udiv64, CallingConv::ARM_AAPCS},
       };
 
       for (const auto &LC : LibraryCalls) {
-        Info.setLibcallName(LC.Op, LC.Name);
+        Info.setLibcallImpl(LC.Op, LC.Impl);
         Info.setLibcallCallingConv(LC.Op, LC.CC);
       }
     } else {
       const struct {
         const RTLIB::Libcall Op;
-        const char *const Name;
+        const RTLIB::LibcallImpl Impl;
         const CallingConv::ID CC;
       } LibraryCalls[] = {
-          {RTLIB::SDIVREM_I32, "__aeabi_idivmod", CallingConv::ARM_AAPCS},
-          {RTLIB::SDIVREM_I64, "__aeabi_ldivmod", CallingConv::ARM_AAPCS},
-          {RTLIB::UDIVREM_I32, "__aeabi_uidivmod", CallingConv::ARM_AAPCS},
-          {RTLIB::UDIVREM_I64, "__aeabi_uldivmod", CallingConv::ARM_AAPCS},
+          {RTLIB::SDIVREM_I32, RTLIB::__aeabi_idivmod, CallingConv::ARM_AAPCS},
+          {RTLIB::SDIVREM_I64, RTLIB::__aeabi_ldivmod, CallingConv::ARM_AAPCS},
+          {RTLIB::UDIVREM_I32, RTLIB::__aeabi_uidivmod, CallingConv::ARM_AAPCS},
+          {RTLIB::UDIVREM_I64, RTLIB::__aeabi_uldivmod, CallingConv::ARM_AAPCS},
       };
 
       for (const auto &LC : LibraryCalls) {
-        Info.setLibcallName(LC.Op, LC.Name);
+        Info.setLibcallImpl(LC.Op, LC.Impl);
         Info.setLibcallCallingConv(LC.Op, LC.CC);
       }
     }
@@ -110,29 +109,29 @@ static void setARMLibcallNames(RuntimeLibcallsInfo &Info, const Triple &TT,
   if (TT.isOSWindows()) {
     static const struct {
       const RTLIB::Libcall Op;
-      const char *const Name;
+      const RTLIB::LibcallImpl Impl;
       const CallingConv::ID CC;
     } LibraryCalls[] = {
-        {RTLIB::FPTOSINT_F32_I64, "__stoi64", CallingConv::ARM_AAPCS_VFP},
-        {RTLIB::FPTOSINT_F64_I64, "__dtoi64", CallingConv::ARM_AAPCS_VFP},
-        {RTLIB::FPTOUINT_F32_I64, "__stou64", CallingConv::ARM_AAPCS_VFP},
-        {RTLIB::FPTOUINT_F64_I64, "__dtou64", CallingConv::ARM_AAPCS_VFP},
-        {RTLIB::SINTTOFP_I64_F32, "__i64tos", CallingConv::ARM_AAPCS_VFP},
-        {RTLIB::SINTTOFP_I64_F64, "__i64tod", CallingConv::ARM_AAPCS_VFP},
-        {RTLIB::UINTTOFP_I64_F32, "__u64tos", CallingConv::ARM_AAPCS_VFP},
-        {RTLIB::UINTTOFP_I64_F64, "__u64tod", CallingConv::ARM_AAPCS_VFP},
+        {RTLIB::FPTOSINT_F32_I64, RTLIB::__stoi64, CallingConv::ARM_AAPCS_VFP},
+        {RTLIB::FPTOSINT_F64_I64, RTLIB::__dtoi64, CallingConv::ARM_AAPCS_VFP},
+        {RTLIB::FPTOUINT_F32_I64, RTLIB::__stou64, CallingConv::ARM_AAPCS_VFP},
+        {RTLIB::FPTOUINT_F64_I64, RTLIB::__dtou64, CallingConv::ARM_AAPCS_VFP},
+        {RTLIB::SINTTOFP_I64_F32, RTLIB::__i64tos, CallingConv::ARM_AAPCS_VFP},
+        {RTLIB::SINTTOFP_I64_F64, RTLIB::__i64tod, CallingConv::ARM_AAPCS_VFP},
+        {RTLIB::UINTTOFP_I64_F32, RTLIB::__u64tos, CallingConv::ARM_AAPCS_VFP},
+        {RTLIB::UINTTOFP_I64_F64, RTLIB::__u64tod, CallingConv::ARM_AAPCS_VFP},
     };
 
     for (const auto &LC : LibraryCalls) {
-      Info.setLibcallName(LC.Op, LC.Name);
+      Info.setLibcallImpl(LC.Op, LC.Impl);
       Info.setLibcallCallingConv(LC.Op, LC.CC);
     }
   }
 
   // Use divmod compiler-rt calls for iOS 5.0 and later.
   if (TT.isOSBinFormatMachO() && (!TT.isiOS() || !TT.isOSVersionLT(5, 0))) {
-    Info.setLibcallName(RTLIB::SDIVREM_I32, "__divmodsi4");
-    Info.setLibcallName(RTLIB::UDIVREM_I32, "__udivmodsi4");
+    Info.setLibcallImpl(RTLIB::SDIVREM_I32, RTLIB::__divmodsi4);
+    Info.setLibcallImpl(RTLIB::UDIVREM_I32, RTLIB::__udivmodsi4);
   }
 }
 
@@ -140,99 +139,99 @@ static void setMSP430Libcalls(RuntimeLibcallsInfo &Info, const Triple &TT) {
   // EABI Libcalls - EABI Section 6.2
   const struct {
     const RTLIB::Libcall Op;
-    const char *const Name;
+    const RTLIB::LibcallImpl Impl;
   } LibraryCalls[] = {
       // Floating point conversions - EABI Table 6
-      {RTLIB::FPROUND_F64_F32, "__mspabi_cvtdf"},
-      {RTLIB::FPEXT_F32_F64, "__mspabi_cvtfd"},
+      {RTLIB::FPROUND_F64_F32, RTLIB::__mspabi_cvtdf},
+      {RTLIB::FPEXT_F32_F64, RTLIB::__mspabi_cvtfd},
       // The following is NOT implemented in libgcc
-      //{ RTLIB::FPTOSINT_F64_I16,  "__mspabi_fixdi" },
-      {RTLIB::FPTOSINT_F64_I32, "__mspabi_fixdli"},
-      {RTLIB::FPTOSINT_F64_I64, "__mspabi_fixdlli"},
+      //{ RTLIB::FPTOSINT_F64_I16,  RTLIB::__mspabi_fixdi },
+      {RTLIB::FPTOSINT_F64_I32, RTLIB::__mspabi_fixdli},
+      {RTLIB::FPTOSINT_F64_I64, RTLIB::__mspabi_fixdlli},
       // The following is NOT implemented in libgcc
-      //{ RTLIB::FPTOUINT_F64_I16,  "__mspabi_fixdu" },
-      {RTLIB::FPTOUINT_F64_I32, "__mspabi_fixdul"},
-      {RTLIB::FPTOUINT_F64_I64, "__mspabi_fixdull"},
+      //{ RTLIB::FPTOUINT_F64_I16,  RTLIB::__mspabi_fixdu },
+      {RTLIB::FPTOUINT_F64_I32, RTLIB::__mspabi_fixdul},
+      {RTLIB::FPTOUINT_F64_I64, RTLIB::__mspabi_fixdull},
       // The following is NOT implemented in libgcc
-      //{ RTLIB::FPTOSINT_F32_I16,  "__mspabi_fixfi" },
-      {RTLIB::FPTOSINT_F32_I32, "__mspabi_fixfli"},
-      {RTLIB::FPTOSINT_F32_I64, "__mspabi_fixflli"},
+      //{ RTLIB::FPTOSINT_F32_I16,  RTLIB::__mspabi_fixfi },
+      {RTLIB::FPTOSINT_F32_I32, RTLIB::__mspabi_fixfli},
+      {RTLIB::FPTOSINT_F32_I64, RTLIB::__mspabi_fixflli},
       // The following is NOT implemented in libgcc
-      //{ RTLIB::FPTOUINT_F32_I16,  "__mspabi_fixfu" },
-      {RTLIB::FPTOUINT_F32_I32, "__mspabi_fixful"},
-      {RTLIB::FPTOUINT_F32_I64, "__mspabi_fixfull"},
+      //{ RTLIB::FPTOUINT_F32_I16,  RTLIB::__mspabi_fixfu },
+      {RTLIB::FPTOUINT_F32_I32, RTLIB::__mspabi_fixful},
+      {RTLIB::FPTOUINT_F32_I64, RTLIB::__mspabi_fixfull},
       // TODO The following IS implemented in libgcc
-      //{ RTLIB::SINTTOFP_I16_F64,  "__mspabi_fltid" },
-      {RTLIB::SINTTOFP_I32_F64, "__mspabi_fltlid"},
+      //{ RTLIB::SINTTOFP_I16_F64,  RTLIB::__mspabi_fltid },
+      {RTLIB::SINTTOFP_I32_F64, RTLIB::__mspabi_fltlid},
       // TODO The following IS implemented in libgcc but is not in the EABI
-      {RTLIB::SINTTOFP_I64_F64, "__mspabi_fltllid"},
+      {RTLIB::SINTTOFP_I64_F64, RTLIB::__mspabi_fltllid},
       // TODO The following IS implemented in libgcc
-      //{ RTLIB::UINTTOFP_I16_F64,  "__mspabi_fltud" },
-      {RTLIB::UINTTOFP_I32_F64, "__mspabi_fltuld"},
+      //{ RTLIB::UINTTOFP_I16_F64,  RTLIB::__mspabi_fltud },
+      {RTLIB::UINTTOFP_I32_F64, RTLIB::__mspabi_fltuld},
       // The following IS implemented in libgcc but is not in the EABI
-      {RTLIB::UINTTOFP_I64_F64, "__mspabi_fltulld"},
+      {RTLIB::UINTTOFP_I64_F64, RTLIB::__mspabi_fltulld},
       // TODO The following IS implemented in libgcc
-      //{ RTLIB::SINTTOFP_I16_F32,  "__mspabi_fltif" },
-      {RTLIB::SINTTOFP_I32_F32, "__mspabi_fltlif"},
+      //{ RTLIB::SINTTOFP_I16_F32,  RTLIB::__mspabi_fltif },
+      {RTLIB::SINTTOFP_I32_F32, RTLIB::__mspabi_fltlif},
       // TODO The following IS implemented in libgcc but is not in the EABI
-      {RTLIB::SINTTOFP_I64_F32, "__mspabi_fltllif"},
+      {RTLIB::SINTTOFP_I64_F32, RTLIB::__mspabi_fltllif},
       // TODO The following IS implemented in libgcc
-      //{ RTLIB::UINTTOFP_I16_F32,  "__mspabi_fltuf" },
-      {RTLIB::UINTTOFP_I32_F32, "__mspabi_fltulf"},
+      //{ RTLIB::UINTTOFP_I16_F32,  RTLIB::__mspabi_fltuf },
+      {RTLIB::UINTTOFP_I32_F32, RTLIB::__mspabi_fltulf},
       // The following IS implemented in libgcc but is not in the EABI
-      {RTLIB::UINTTOFP_I64_F32, "__mspabi_fltullf"},
+      {RTLIB::UINTTOFP_I64_F32, RTLIB::__mspabi_fltullf},
 
       // Floating point comparisons - EABI Table 7
-      {RTLIB::OEQ_F64, "__mspabi_cmpd"},
-      {RTLIB::UNE_F64, "__mspabi_cmpd"},
-      {RTLIB::OGE_F64, "__mspabi_cmpd"},
-      {RTLIB::OLT_F64, "__mspabi_cmpd"},
-      {RTLIB::OLE_F64, "__mspabi_cmpd"},
-      {RTLIB::OGT_F64, "__mspabi_cmpd"},
-      {RTLIB::OEQ_F32, "__mspabi_cmpf"},
-      {RTLIB::UNE_F32, "__mspabi_cmpf"},
-      {RTLIB::OGE_F32, "__mspabi_cmpf"},
-      {RTLIB::OLT_F32, "__mspabi_cmpf"},
-      {RTLIB::OLE_F32, "__mspabi_cmpf"},
-      {RTLIB::OGT_F32, "__mspabi_cmpf"},
+      {RTLIB::OEQ_F64, RTLIB::__mspabi_cmpd__oeq},
+      {RTLIB::UNE_F64, RTLIB::__mspabi_cmpd__une},
+      {RTLIB::OGE_F64, RTLIB::__mspabi_cmpd__oge},
+      {RTLIB::OLT_F64, RTLIB::__mspabi_cmpd__olt},
+      {RTLIB::OLE_F64, RTLIB::__mspabi_cmpd__ole},
+      {RTLIB::OGT_F64, RTLIB::__mspabi_cmpd__ogt},
+      {RTLIB::OEQ_F32, RTLIB::__mspabi_cmpf__oeq},
+      {RTLIB::UNE_F32, RTLIB::__mspabi_cmpf__une},
+      {RTLIB::OGE_F32, RTLIB::__mspabi_cmpf__oge},
+      {RTLIB::OLT_F32, RTLIB::__mspabi_cmpf__olt},
+      {RTLIB::OLE_F32, RTLIB::__mspabi_cmpf__ole},
+      {RTLIB::OGT_F32, RTLIB::__mspabi_cmpf__ogt},
 
       // Floating point arithmetic - EABI Table 8
-      {RTLIB::ADD_F64, "__mspabi_addd"},
-      {RTLIB::ADD_F32, "__mspabi_addf"},
-      {RTLIB::DIV_F64, "__mspabi_divd"},
-      {RTLIB::DIV_F32, "__mspabi_divf"},
-      {RTLIB::MUL_F64, "__mspabi_mpyd"},
-      {RTLIB::MUL_F32, "__mspabi_mpyf"},
-      {RTLIB::SUB_F64, "__mspabi_subd"},
-      {RTLIB::SUB_F32, "__mspabi_subf"},
+      {RTLIB::ADD_F64, RTLIB::__mspabi_addd},
+      {RTLIB::ADD_F32, RTLIB::__mspabi_addf},
+      {RTLIB::DIV_F64, RTLIB::__mspabi_divd},
+      {RTLIB::DIV_F32, RTLIB::__mspabi_divf},
+      {RTLIB::MUL_F64, RTLIB::__mspabi_mpyd},
+      {RTLIB::MUL_F32, RTLIB::__mspabi_mpyf},
+      {RTLIB::SUB_F64, RTLIB::__mspabi_subd},
+      {RTLIB::SUB_F32, RTLIB::__mspabi_subf},
       // The following are NOT implemented in libgcc
-      // { RTLIB::NEG_F64,  "__mspabi_negd" },
-      // { RTLIB::NEG_F32,  "__mspabi_negf" },
+      // { RTLIB::NEG_F64,  RTLIB::__mspabi_negd },
+      // { RTLIB::NEG_F32,  RTLIB::__mspabi_negf },
 
       // Universal Integer Operations - EABI Table 9
-      {RTLIB::SDIV_I16, "__mspabi_divi"},
-      {RTLIB::SDIV_I32, "__mspabi_divli"},
-      {RTLIB::SDIV_I64, "__mspabi_divlli"},
-      {RTLIB::UDIV_I16, "__mspabi_divu"},
-      {RTLIB::UDIV_I32, "__mspabi_divul"},
-      {RTLIB::UDIV_I64, "__mspabi_divull"},
-      {RTLIB::SREM_I16, "__mspabi_remi"},
-      {RTLIB::SREM_I32, "__mspabi_remli"},
-      {RTLIB::SREM_I64, "__mspabi_remlli"},
-      {RTLIB::UREM_I16, "__mspabi_remu"},
-      {RTLIB::UREM_I32, "__mspabi_remul"},
-      {RTLIB::UREM_I64, "__mspabi_remull"},
+      {RTLIB::SDIV_I16, RTLIB::__mspabi_divi},
+      {RTLIB::SDIV_I32, RTLIB::__mspabi_divli},
+      {RTLIB::SDIV_I64, RTLIB::__mspabi_divlli},
+      {RTLIB::UDIV_I16, RTLIB::__mspabi_divu},
+      {RTLIB::UDIV_I32, RTLIB::__mspabi_divul},
+      {RTLIB::UDIV_I64, RTLIB::__mspabi_divull},
+      {RTLIB::SREM_I16, RTLIB::__mspabi_remi},
+      {RTLIB::SREM_I32, RTLIB::__mspabi_remli},
+      {RTLIB::SREM_I64, RTLIB::__mspabi_remlli},
+      {RTLIB::UREM_I16, RTLIB::__mspabi_remu},
+      {RTLIB::UREM_I32, RTLIB::__mspabi_remul},
+      {RTLIB::UREM_I64, RTLIB::__mspabi_remull},
 
       // Bitwise Operations - EABI Table 10
       // TODO: __mspabi_[srli/srai/slli] ARE implemented in libgcc
-      {RTLIB::SRL_I32, "__mspabi_srll"},
-      {RTLIB::SRA_I32, "__mspabi_sral"},
-      {RTLIB::SHL_I32, "__mspabi_slll"},
+      {RTLIB::SRL_I32, RTLIB::__mspabi_srll},
+      {RTLIB::SRA_I32, RTLIB::__mspabi_sral},
+      {RTLIB::SHL_I32, RTLIB::__mspabi_slll},
       // __mspabi_[srlll/srall/sllll/rlli/rlll] are NOT implemented in libgcc
   };
 
   for (const auto &LC : LibraryCalls)
-    Info.setLibcallName(LC.Op, LC.Name);
+    Info.setLibcallImpl(LC.Op, LC.Impl);
 
   // Several of the runtime library functions use a special calling conv
   Info.setLibcallCallingConv(RTLIB::UDIV_I64, CallingConv::MSP430_BUILTIN);
@@ -286,72 +285,70 @@ void RuntimeLibcallsInfo::initSoftFloatCmpLibcallPredicates() {
 
 static void setLongDoubleIsF128Libm(RuntimeLibcallsInfo &Info,
                                     bool FiniteOnlyFuncs = false) {
-  Info.setLibcallName(RTLIB::REM_F128, "fmodf128");
-  Info.setLibcallName(RTLIB::FMA_F128, "fmaf128");
-  Info.setLibcallName(RTLIB::SQRT_F128, "sqrtf128");
-  Info.setLibcallName(RTLIB::CBRT_F128, "cbrtf128");
-  Info.setLibcallName(RTLIB::LOG_F128, "logf128");
-  Info.setLibcallName(RTLIB::LOG2_F128, "log2f128");
-  Info.setLibcallName(RTLIB::LOG10_F128, "log10f128");
-  Info.setLibcallName(RTLIB::EXP_F128, "expf128");
-  Info.setLibcallName(RTLIB::EXP2_F128, "exp2f128");
-  Info.setLibcallName(RTLIB::EXP10_F128, "exp10f128");
-  Info.setLibcallName(RTLIB::SIN_F128, "sinf128");
-  Info.setLibcallName(RTLIB::COS_F128, "cosf128");
-  Info.setLibcallName(RTLIB::TAN_F128, "tanf128");
-  Info.setLibcallName(RTLIB::SINCOS_F128, "sincosf128");
-  Info.setLibcallName(RTLIB::ASIN_F128, "asinf128");
-  Info.setLibcallName(RTLIB::ACOS_F128, "acosf128");
-  Info.setLibcallName(RTLIB::ATAN_F128, "atanf128");
-  Info.setLibcallName(RTLIB::ATAN2_F128, "atan2f128");
-  Info.setLibcallName(RTLIB::SINH_F128, "sinhf128");
-  Info.setLibcallName(RTLIB::COSH_F128, "coshf128");
-  Info.setLibcallName(RTLIB::TANH_F128, "tanhf128");
-  Info.setLibcallName(RTLIB::POW_F128, "powf128");
-  Info.setLibcallName(RTLIB::CEIL_F128, "ceilf128");
-  Info.setLibcallName(RTLIB::TRUNC_F128, "truncf128");
-  Info.setLibcallName(RTLIB::RINT_F128, "rintf128");
-  Info.setLibcallName(RTLIB::NEARBYINT_F128, "nearbyintf128");
-  Info.setLibcallName(RTLIB::ROUND_F128, "roundf128");
-  Info.setLibcallName(RTLIB::ROUNDEVEN_F128, "roundevenf128");
-  Info.setLibcallName(RTLIB::FLOOR_F128, "floorf128");
-  Info.setLibcallName(RTLIB::COPYSIGN_F128, "copysignf128");
-  Info.setLibcallName(RTLIB::FMIN_F128, "fminf128");
-  Info.setLibcallName(RTLIB::FMAX_F128, "fmaxf128");
-  Info.setLibcallName(RTLIB::FMINIMUM_F128, "fminimumf128");
-  Info.setLibcallName(RTLIB::FMAXIMUM_F128, "fmaximumf128");
-  Info.setLibcallName(RTLIB::FMINIMUM_NUM_F128, "fminimum_numf128");
-  Info.setLibcallName(RTLIB::FMAXIMUM_NUM_F128, "fmaximum_numf128");
-  Info.setLibcallName(RTLIB::LROUND_F128, "lroundf128");
-  Info.setLibcallName(RTLIB::LLROUND_F128, "llroundf128");
-  Info.setLibcallName(RTLIB::LRINT_F128, "lrintf128");
-  Info.setLibcallName(RTLIB::LLRINT_F128, "llrintf128");
-  Info.setLibcallName(RTLIB::LDEXP_F128, "ldexpf128");
-  Info.setLibcallName(RTLIB::FREXP_F128, "frexpf128");
-  Info.setLibcallName(RTLIB::MODF_F128, "modff128");
+  Info.setLibcallImpl(RTLIB::REM_F128, RTLIB::fmodf128);
+  Info.setLibcallImpl(RTLIB::FMA_F128, RTLIB::fmaf128);
+  Info.setLibcallImpl(RTLIB::SQRT_F128, RTLIB::sqrtf128);
+  Info.setLibcallImpl(RTLIB::CBRT_F128, RTLIB::cbrtf128);
+  Info.setLibcallImpl(RTLIB::LOG_F128, RTLIB::logf128);
+  Info.setLibcallImpl(RTLIB::LOG2_F128, RTLIB::log2f128);
+  Info.setLibcallImpl(RTLIB::LOG10_F128, RTLIB::log10f128);
+  Info.setLibcallImpl(RTLIB::EXP_F128, RTLIB::expf128);
+  Info.setLibcallImpl(RTLIB::EXP2_F128, RTLIB::exp2f128);
+  Info.setLibcallImpl(RTLIB::EXP10_F128, RTLIB::exp10f128);
+  Info.setLibcallImpl(RTLIB::SIN_F128, RTLIB::sinf128);
+  Info.setLibcallImpl(RTLIB::COS_F128, RTLIB::cosf128);
+  Info.setLibcallImpl(RTLIB::TAN_F128, RTLIB::tanf128);
+  Info.setLibcallImpl(RTLIB::SINCOS_F128, RTLIB::sincosf128);
+  Info.setLibcallImpl(RTLIB::ASIN_F128, RTLIB::asinf128);
+  Info.setLibcallImpl(RTLIB::ACOS_F128, RTLIB::acosf128);
+  Info.setLibcallImpl(RTLIB::ATAN_F128, RTLIB::atanf128);
+  Info.setLibcallImpl(RTLIB::ATAN2_F128, RTLIB::atan2f128);
+  Info.setLibcallImpl(RTLIB::SINH_F128, RTLIB::sinhf128);
+  Info.setLibcallImpl(RTLIB::COSH_F128, RTLIB::coshf128);
+  Info.setLibcallImpl(RTLIB::TANH_F128, RTLIB::tanhf128);
+  Info.setLibcallImpl(RTLIB::POW_F128, RTLIB::powf128);
+  Info.setLibcallImpl(RTLIB::CEIL_F128, RTLIB::ceilf128);
+  Info.setLibcallImpl(RTLIB::TRUNC_F128, RTLIB::truncf128);
+  Info.setLibcallImpl(RTLIB::RINT_F128, RTLIB::rintf128);
+  Info.setLibcallImpl(RTLIB::NEARBYINT_F128, RTLIB::nearbyintf128);
+  Info.setLibcallImpl(RTLIB::ROUND_F128, RTLIB::roundf128);
+  Info.setLibcallImpl(RTLIB::ROUNDEVEN_F128, RTLIB::roundevenf128);
+  Info.setLibcallImpl(RTLIB::FLOOR_F128, RTLIB::floorf128);
+  Info.setLibcallImpl(RTLIB::COPYSIGN_F128, RTLIB::copysignf128);
+  Info.setLibcallImpl(RTLIB::FMIN_F128, RTLIB::fminf128);
+  Info.setLibcallImpl(RTLIB::FMAX_F128, RTLIB::fmaxf128);
+  Info.setLibcallImpl(RTLIB::FMINIMUM_F128, RTLIB::fminimumf128);
+  Info.setLibcallImpl(RTLIB::FMAXIMUM_F128, RTLIB::fmaximumf128);
+  Info.setLibcallImpl(RTLIB::FMINIMUM_NUM_F128, RTLIB::fminimum_numf128);
+  Info.setLibcallImpl(RTLIB::FMAXIMUM_NUM_F128, RTLIB::fmaximum_numf128);
+  Info.setLibcallImpl(RTLIB::LROUND_F128, RTLIB::lroundf128);
+  Info.setLibcallImpl(RTLIB::LLROUND_F128, RTLIB::llroundf128);
+  Info.setLibcallImpl(RTLIB::LRINT_F128, RTLIB::lrintf128);
+  Info.setLibcallImpl(RTLIB::LLRINT_F128, RTLIB::llrintf128);
+  Info.setLibcallImpl(RTLIB::LDEXP_F128, RTLIB::ldexpf128);
+  Info.setLibcallImpl(RTLIB::FREXP_F128, RTLIB::frexpf128);
+  Info.setLibcallImpl(RTLIB::MODF_F128, RTLIB::modff128);
 
   if (FiniteOnlyFuncs) {
-    Info.setLibcallName(RTLIB::LOG_FINITE_F128, "__logf128_finite");
-    Info.setLibcallName(RTLIB::LOG2_FINITE_F128, "__log2f128_finite");
-    Info.setLibcallName(RTLIB::LOG10_FINITE_F128, "__log10f128_finite");
-    Info.setLibcallName(RTLIB::EXP_FINITE_F128, "__expf128_finite");
-    Info.setLibcallName(RTLIB::EXP2_FINITE_F128, "__exp2f128_finite");
-    Info.setLibcallName(RTLIB::POW_FINITE_F128, "__powf128_finite");
+    Info.setLibcallImpl(RTLIB::LOG_FINITE_F128, RTLIB::__logf128_finite);
+    Info.setLibcallImpl(RTLIB::LOG2_FINITE_F128, RTLIB::__log2f128_finite);
+    Info.setLibcallImpl(RTLIB::LOG10_FINITE_F128, RTLIB::__log10f128_finite);
+    Info.setLibcallImpl(RTLIB::EXP_FINITE_F128, RTLIB::__expf128_finite);
+    Info.setLibcallImpl(RTLIB::EXP2_FINITE_F128, RTLIB::__exp2f128_finite);
+    Info.setLibcallImpl(RTLIB::POW_FINITE_F128, RTLIB::__powf128_finite);
   } else {
-    Info.setLibcallName(RTLIB::LOG_FINITE_F128, nullptr);
-    Info.setLibcallName(RTLIB::LOG2_FINITE_F128, nullptr);
-    Info.setLibcallName(RTLIB::LOG10_FINITE_F128, nullptr);
-    Info.setLibcallName(RTLIB::EXP_FINITE_F128, nullptr);
-    Info.setLibcallName(RTLIB::EXP2_FINITE_F128, nullptr);
-    Info.setLibcallName(RTLIB::POW_FINITE_F128, nullptr);
+    Info.setLibcallImpl(RTLIB::LOG_FINITE_F128, RTLIB::Unsupported);
+    Info.setLibcallImpl(RTLIB::LOG2_FINITE_F128, RTLIB::Unsupported);
+    Info.setLibcallImpl(RTLIB::LOG10_FINITE_F128, RTLIB::Unsupported);
+    Info.setLibcallImpl(RTLIB::EXP_FINITE_F128, RTLIB::Unsupported);
+    Info.setLibcallImpl(RTLIB::EXP2_FINITE_F128, RTLIB::Unsupported);
+    Info.setLibcallImpl(RTLIB::POW_FINITE_F128, RTLIB::Unsupported);
   }
 }
 
-void RuntimeLibcallsInfo::initDefaultLibCallNames() {
-  std::memcpy(LibcallRoutineNames, DefaultLibcallRoutineNames,
-              sizeof(LibcallRoutineNames));
-  static_assert(sizeof(LibcallRoutineNames) ==
-                    sizeof(DefaultLibcallRoutineNames),
+void RTLIB::RuntimeLibcallsInfo::initDefaultLibCallImpls() {
+  std::memcpy(LibcallImpls, DefaultLibcallImpls, sizeof(LibcallImpls));
+  static_assert(sizeof(LibcallImpls) == sizeof(DefaultLibcallImpls),
                 "libcall array size should match");
 }
 
@@ -367,7 +364,7 @@ void RuntimeLibcallsInfo::initLibcalls(const Triple &TT,
 
   if (TT.isX86() || TT.isVE()) {
     if (ExceptionModel == ExceptionHandling::SjLj)
-      setLibcallName(RTLIB::UNWIND_RESUME, "_Unwind_SjLj_Resume");
+      setLibcallImpl(RTLIB::UNWIND_RESUME, RTLIB::_Unwind_SjLj_Resume);
   }
 
   if (TT.isPPC()) {
@@ -376,12 +373,19 @@ void RuntimeLibcallsInfo::initLibcalls(const Triple &TT,
     // TODO: Do the finite only functions exist?
     setLongDoubleIsF128Libm(*this, /*FiniteOnlyFuncs=*/false);
 
+    // TODO: Tablegen predicate support
     if (TT.isOSAIX()) {
-      bool isPPC64 = TT.isPPC64();
-      setLibcallName(RTLIB::MEMCPY, nullptr);
-      setLibcallName(RTLIB::MEMMOVE, isPPC64 ? "___memmove64" : "___memmove");
-      setLibcallName(RTLIB::MEMSET, isPPC64 ? "___memset64" : "___memset");
-      setLibcallName(RTLIB::BZERO, isPPC64 ? "___bzero64" : "___bzero");
+      if (TT.isPPC64()) {
+        setLibcallImpl(RTLIB::MEMCPY, RTLIB::Unsupported);
+        setLibcallImpl(RTLIB::MEMMOVE, RTLIB::___memmove64);
+        setLibcallImpl(RTLIB::MEMSET, RTLIB::___memset64);
+        setLibcallImpl(RTLIB::BZERO, RTLIB::___bzero64);
+      } else {
+        setLibcallImpl(RTLIB::MEMCPY, RTLIB::Unsupported);
+        setLibcallImpl(RTLIB::MEMMOVE, RTLIB::___memmove);
+        setLibcallImpl(RTLIB::MEMSET, RTLIB::___memset);
+        setLibcallImpl(RTLIB::BZERO, RTLIB::___bzero);
+      }
     }
   }
 
@@ -390,19 +394,19 @@ void RuntimeLibcallsInfo::initLibcalls(const Triple &TT,
     // For f16/f32 conversions, Darwin uses the standard naming scheme,
     // instead of the gnueabi-style __gnu_*_ieee.
     // FIXME: What about other targets?
-    setLibcallName(RTLIB::FPEXT_F16_F32, "__extendhfsf2");
-    setLibcallName(RTLIB::FPROUND_F32_F16, "__truncsfhf2");
+    setLibcallImpl(RTLIB::FPEXT_F16_F32, RTLIB::__extendhfsf2);
+    setLibcallImpl(RTLIB::FPROUND_F32_F16, RTLIB::__truncsfhf2);
 
     // Some darwins have an optimized __bzero/bzero function.
     if (TT.isX86()) {
       if (TT.isMacOSX() && !TT.isMacOSXVersionLT(10, 6))
-        setLibcallName(RTLIB::BZERO, "__bzero");
+        setLibcallImpl(RTLIB::BZERO, RTLIB::__bzero);
     } else if (TT.isAArch64())
-      setLibcallName(RTLIB::BZERO, "bzero");
+      setLibcallImpl(RTLIB::BZERO, RTLIB::bzero);
 
     if (darwinHasSinCosStret(TT)) {
-      setLibcallName(RTLIB::SINCOS_STRET_F32, "__sincosf_stret");
-      setLibcallName(RTLIB::SINCOS_STRET_F64, "__sincos_stret");
+      setLibcallImpl(RTLIB::SINCOS_STRET_F32, RTLIB::__sincosf_stret);
+      setLibcallImpl(RTLIB::SINCOS_STRET_F64, RTLIB::__sincos_stret);
       if (TT.isWatchABI()) {
         setLibcallCallingConv(RTLIB::SINCOS_STRET_F32,
                               CallingConv::ARM_AAPCS_VFP);
@@ -412,55 +416,55 @@ void RuntimeLibcallsInfo::initLibcalls(const Triple &TT,
     }
 
     if (darwinHasExp10(TT)) {
-      setLibcallName(RTLIB::EXP10_F32, "__exp10f");
-      setLibcallName(RTLIB::EXP10_F64, "__exp10");
+      setLibcallImpl(RTLIB::EXP10_F32, RTLIB::__exp10f);
+      setLibcallImpl(RTLIB::EXP10_F64, RTLIB::__exp10);
     } else {
-      setLibcallName(RTLIB::EXP10_F32, nullptr);
-      setLibcallName(RTLIB::EXP10_F64, nullptr);
+      setLibcallImpl(RTLIB::EXP10_F32, RTLIB::Unsupported);
+      setLibcallImpl(RTLIB::EXP10_F64, RTLIB::Unsupported);
     }
   }
 
   if (hasSinCos(TT)) {
-    setLibcallName(RTLIB::SINCOS_F32, "sincosf");
-    setLibcallName(RTLIB::SINCOS_F64, "sincos");
-    setLibcallName(RTLIB::SINCOS_F80, "sincosl");
-    setLibcallName(RTLIB::SINCOS_F128, "sincosl");
-    setLibcallName(RTLIB::SINCOS_PPCF128, "sincosl");
+    setLibcallImpl(RTLIB::SINCOS_F32, RTLIB::sincosf);
+    setLibcallImpl(RTLIB::SINCOS_F64, RTLIB::sincos);
+    setLibcallImpl(RTLIB::SINCOS_F80, RTLIB::sincos_f80);
+    setLibcallImpl(RTLIB::SINCOS_F128, RTLIB::sincos_f128);
+    setLibcallImpl(RTLIB::SINCOS_PPCF128, RTLIB::sincos_ppcf128);
   }
 
   if (TT.isPS()) {
-    setLibcallName(RTLIB::SINCOS_F32, "sincosf");
-    setLibcallName(RTLIB::SINCOS_F64, "sincos");
+    setLibcallImpl(RTLIB::SINCOS_F32, RTLIB::sincosf);
+    setLibcallImpl(RTLIB::SINCOS_F64, RTLIB::sincos);
   }
 
   if (TT.isOSOpenBSD()) {
-    setLibcallName(RTLIB::STACKPROTECTOR_CHECK_FAIL, nullptr);
+    setLibcallImpl(RTLIB::STACKPROTECTOR_CHECK_FAIL, RTLIB::Unsupported);
   }
 
   if (TT.isOSWindows() && !TT.isOSCygMing()) {
-    setLibcallName(RTLIB::LDEXP_F32, nullptr);
-    setLibcallName(RTLIB::LDEXP_F80, nullptr);
-    setLibcallName(RTLIB::LDEXP_F128, nullptr);
-    setLibcallName(RTLIB::LDEXP_PPCF128, nullptr);
-
-    setLibcallName(RTLIB::FREXP_F32, nullptr);
-    setLibcallName(RTLIB::FREXP_F80, nullptr);
-    setLibcallName(RTLIB::FREXP_F128, nullptr);
-    setLibcallName(RTLIB::FREXP_PPCF128, nullptr);
+    setLibcallImpl(RTLIB::LDEXP_F32, RTLIB::Unsupported);
+    setLibcallImpl(RTLIB::LDEXP_F80, RTLIB::Unsupported);
+    setLibcallImpl(RTLIB::LDEXP_F128, RTLIB::Unsupported);
+    setLibcallImpl(RTLIB::LDEXP_PPCF128, RTLIB::Unsupported);
+
+    setLibcallImpl(RTLIB::FREXP_F32, RTLIB::Unsupported);
+    setLibcallImpl(RTLIB::FREXP_F80, RTLIB::Unsupported);
+    setLibcallImpl(RTLIB::FREXP_F128, RTLIB::Unsupported);
+    setLibcallImpl(RTLIB::FREXP_PPCF128, RTLIB::Unsupported);
   }
 
   // Disable most libcalls on AMDGPU and NVPTX.
   if (TT.isAMDGPU() || TT.isNVPTX()) {
     for (RTLIB::Libcall LC : RTLIB::libcalls()) {
       if (!isAtomicLibCall(LC))
-        setLibcallName(LC, nullptr);
+        setLibcallImpl(LC, RTLIB::Unsupported);
     }
   }
 
   if (TT.isOSMSVCRT()) {
     // MSVCRT doesn't have powi; fall back to pow
-    setLibcallName(RTLIB::POWI_F32, nullptr);
-    setLibcallName(RTLIB::POWI_F64, nullptr);
+    setLibcallImpl(RTLIB::POWI_F32, RTLIB::Unsupported);
+    setLibcallImpl(RTLIB::POWI_F64, RTLIB::Unsupported);
   }
 
   // Setup Windows compiler runtime calls.
@@ -468,18 +472,18 @@ void RuntimeLibcallsInfo::initLibcalls(const Triple &TT,
       (TT.isWindowsMSVCEnvironment() || TT.isWindowsItaniumEnvironment())) {
     static const struct {
       const RTLIB::Libcall Op;
-      const char *const Name;
+      const RTLIB::LibcallImpl Impl;
       const CallingConv::ID CC;
     } LibraryCalls[] = {
-        {RTLIB::SDIV_I64, "_alldiv", CallingConv::X86_StdCall},
-        {RTLIB::UDIV_I64, "_aulldiv", CallingConv::X86_StdCall},
-        {RTLIB::SREM_I64, "_allrem", CallingConv::X86_StdCall},
-        {RTLIB::UREM_I64, "_aullrem", CallingConv::X86_StdCall},
-        {RTLIB::MUL_I64, "_allmul", CallingConv::X86_StdCall},
+        {RTLIB::SDIV_I64, RTLIB::_alldiv, CallingConv::X86_StdCall},
+        {RTLIB::UDIV_I64, RTLIB::_aulldiv, CallingConv::X86_StdCall},
+        {RTLIB::SREM_I64, RTLIB::_allrem, CallingConv::X86_StdCall},
+        {RTLIB::UREM_I64, RTLIB::_aullrem, CallingConv::X86_StdCall},
+        {RTLIB::MUL_I64, RTLIB::_allmul, CallingConv::X86_StdCall},
     };
 
     for (const auto &LC : LibraryCalls) {
-      setLibcallName(LC.Op, LC.Name);
+      setLibcallImpl(LC.Op, LC.Impl);
       setLibcallCallingConv(LC.Op, LC.CC);
     }
   }
@@ -492,28 +496,28 @@ void RuntimeLibcallsInfo::initLibcalls(const Triple &TT,
     setARMLibcallNames(*this, TT, FloatABI, EABIVersion);
   } else if (TT.getArch() == Triple::ArchType::avr) {
     // Division rtlib functions (not supported), use divmod functions instead
-    setLibcallName(RTLIB::SDIV_I8, nullptr);
-    setLibcallName(RTLIB::SDIV_I16, nullptr);
-    setLibcallName(RTLIB::SDIV_I32, nullptr);
-    setLibcallName(RTLIB::UDIV_I8, nullptr);
-    setLibcallName(RTLIB::UDIV_I16, nullptr);
-    setLibcallName(RTLIB::UDIV_I32, nullptr);
+    setLibcallImpl(RTLIB::SDIV_I8, RTLIB::Unsupported);
+    setLibcallImpl(RTLIB::SDIV_I16, RTLIB::Unsupported);
+    setLibcallImpl(RTLIB::SDIV_I32, RTLIB::Unsupported);
+    setLibcallImpl(RTLIB::UDIV_I8, RTLIB::Unsupported);
+    setLibcallImpl(RTLIB::UDIV_I16, RTLIB::Unsupported);
+    setLibcallImpl(RTLIB::UDIV_I32, RTLIB::Unsupported);
 
     // Modulus rtlib functions (not supported), use divmod functions instead
-    setLibcallName(RTLIB::SREM_I8, nullptr);
-    setLibcallName(RTLIB::SREM_I16, nullptr);
-    setLibcallName(RTLIB::SREM_I32, nullptr);
-    setLibcallName(RTLIB::UREM_I8, nullptr);
-    setLibcallName(RTLIB::UREM_I16, nullptr);
-    setLibcallName(RTLIB::UREM_I32, nullptr);
+    setLibcallImpl(RTLIB::SREM_I8, RTLIB::Unsupported);
+    setLibcallImpl(RTLIB::SREM_I16, RTLIB::Unsupported);
+    setLibcallImpl(RTLIB::SREM_I32, RTLIB::Unsupported);
+    setLibcallImpl(RTLIB::UREM_I8, RTLIB::Unsupported);
+    setLibcallImpl(RTLIB::UREM_I16, RTLIB::Unsupported);
+    setLibcallImpl(RTLIB::UREM_I32, RTLIB::Unsupported);
 
     // Division and modulus rtlib functions
-    setLibcallName(RTLIB::SDIVREM_I8, "__divmodqi4");
-    setLibcallName(RTLIB::SDIVREM_I16, "__divmodhi4");
-    setLibcallName(RTLIB::SDIVREM_I32, "__divmodsi4");
-    setLibcallName(RTLIB::UDIVREM_I8, "__udivmodqi4");
-    setLibcallName(RTLIB::UDIVREM_I16, "__udivmodhi4");
-    setLibcallName(RTLIB::UDIVREM_I32, "__udivmodsi4");
+    setLibcallImpl(RTLIB::SDIVREM_I8, RTLIB::__divmodqi4);
+    setLibcallImpl(RTLIB::SDIVREM_I16, RTLIB::__divmodhi4);
+    setLibcallImpl(RTLIB::SDIVREM_I32, RTLIB::__divmodsi4);
+    setLibcallImpl(RTLIB::UDIVREM_I8, RTLIB::__udivmodqi4);
+    setLibcallImpl(RTLIB::UDIVREM_I16, RTLIB::__udivmodhi4);
+    setLibcallImpl(RTLIB::UDIVREM_I32, RTLIB::__udivmodsi4);
 
     // Several of the runtime library functions use a special calling conv
     setLibcallCallingConv(RTLIB::SDIVREM_I8, CallingConv::AVR_BUILTIN);
@@ -522,63 +526,64 @@ void RuntimeLibcallsInfo::initLibcalls(const Triple &TT,
     setLibcallCallingConv(RTLIB::UDIVREM_I16, CallingConv::AVR_BUILTIN);
 
     // Trigonometric rtlib functions
-    setLibcallName(RTLIB::SIN_F32, "sin");
-    setLibcallName(RTLIB::COS_F32, "cos");
+    setLibcallImpl(RTLIB::SIN_F32, RTLIB::avr_sin);
+    setLibcallImpl(RTLIB::COS_F32, RTLIB::avr_cos);
   }
 
   if (!TT.isWasm()) {
     // These libcalls are only available in compiler-rt, not libgcc.
     if (TT.isArch32Bit()) {
-      setLibcallName(RTLIB::SHL_I128, nullptr);
-      setLibcallName(RTLIB::SRL_I128, nullptr);
-      setLibcallName(RTLIB::SRA_I128, nullptr);
-      setLibcallName(RTLIB::MUL_I128, nullptr);
-      setLibcallName(RTLIB::MULO_I64, nullptr);
+      setLibcallImpl(RTLIB::SHL_I128, RTLIB::Unsupported);
+      setLibcallImpl(RTLIB::SRL_I128, RTLIB::Unsupported);
+      setLibcallImpl(RTLIB::SRA_I128, RTLIB::Unsupported);
+      setLibcallImpl(RTLIB::MUL_I128, RTLIB::Unsupported);
+      setLibcallImpl(RTLIB::MULO_I64, RTLIB::Unsupported);
     }
-    setLibcallName(RTLIB::MULO_I128, nullptr);
+
+    setLibcallImpl(RTLIB::MULO_I128, RTLIB::Unsupported);
   } else {
     // Define the emscripten name for return address helper.
     // TODO: when implementing other Wasm backends, make this generic or only do
     // this on emscripten depending on what they end up doing.
-    setLibcallName(RTLIB::RETURN_ADDRESS, "emscripten_return_address");
+    setLibcallImpl(RTLIB::RETURN_ADDRESS, RTLIB::emscripten_return_address);
   }
 
   if (TT.getArch() == Triple::ArchType::hexagon) {
-    setLibcallName(RTLIB::SDIV_I32, "__hexagon_divsi3");
-    setLibcallName(RTLIB::SDIV_I64, "__hexagon_divdi3");
-    setLibcallName(RTLIB::UDIV_I32, "__hexagon_udivsi3");
-    setLibcallName(RTLIB::UDIV_I64, "__hexagon_udivdi3");
-    setLibcallName(RTLIB::SREM_I32, "__hexagon_modsi3");
-    setLibcallName(RTLIB::SREM_I64, "__hexagon_moddi3");
-    setLibcallName(RTLIB::UREM_I32, "__hexagon_umodsi3");
-    setLibcallName(RTLIB::UREM_I64, "__hexagon_umoddi3");
+    setLibcallImpl(RTLIB::SDIV_I32, RTLIB::__hexagon_divsi3);
+    setLibcallImpl(RTLIB::SDIV_I64, RTLIB::__hexagon_divdi3);
+    setLibcallImpl(RTLIB::UDIV_I32, RTLIB::__hexagon_udivsi3);
+    setLibcallImpl(RTLIB::UDIV_I64, RTLIB::__hexagon_udivdi3);
+    setLibcallImpl(RTLIB::SREM_I32, RTLIB::__hexagon_modsi3);
+    setLibcallImpl(RTLIB::SREM_I64, RTLIB::__hexagon_moddi3);
+    setLibcallImpl(RTLIB::UREM_I32, RTLIB::__hexagon_umodsi3);
+    setLibcallImpl(RTLIB::UREM_I64, RTLIB::__hexagon_umoddi3);
 
     const bool FastMath = HexagonEnableFastMathRuntimeCalls;
     // This is the only fast library function for sqrtd.
     if (FastMath)
-      setLibcallName(RTLIB::SQRT_F64, "__hexagon_fast2_sqrtdf2");
+      setLibcallImpl(RTLIB::SQRT_F64, RTLIB::__hexagon_fast2_sqrtdf2);
 
     // Prefix is: nothing  for "slow-math",
     //            "fast2_" for V5+ fast-math double-precision
     // (actually, keep fast-math and fast-math2 separate for now)
     if (FastMath) {
-      setLibcallName(RTLIB::ADD_F64, "__hexagon_fast_adddf3");
-      setLibcallName(RTLIB::SUB_F64, "__hexagon_fast_subdf3");
-      setLibcallName(RTLIB::MUL_F64, "__hexagon_fast_muldf3");
-      setLibcallName(RTLIB::DIV_F64, "__hexagon_fast_divdf3");
-      setLibcallName(RTLIB::DIV_F32, "__hexagon_fast_divsf3");
+      setLibcallImpl(RTLIB::ADD_F64, RTLIB::__hexagon_fast_adddf3);
+      setLibcallImpl(RTLIB::SUB_F64, RTLIB::__hexagon_fast_subdf3);
+      setLibcallImpl(RTLIB::MUL_F64, RTLIB::__hexagon_fast_muldf3);
+      setLibcallImpl(RTLIB::DIV_F64, RTLIB::__hexagon_fast_divdf3);
+      setLibcallImpl(RTLIB::DIV_F32, RTLIB::__hexagon_fast_divsf3);
     } else {
-      setLibcallName(RTLIB::ADD_F64, "__hexagon_adddf3");
-      setLibcallName(RTLIB::SUB_F64, "__hexagon_subdf3");
-      setLibcallName(RTLIB::MUL_F64, "__hexagon_muldf3");
-      setLibcallName(RTLIB::DIV_F64, "__hexagon_divdf3");
-      setLibcallName(RTLIB::DIV_F32, "__hexagon_divsf3");
+      setLibcallImpl(RTLIB::ADD_F64, RTLIB::__hexagon_adddf3);
+      setLibcallImpl(RTLIB::SUB_F64, RTLIB::__hexagon_subdf3);
+      setLibcallImpl(RTLIB::MUL_F64, RTLIB::__hexagon_muldf3);
+      setLibcallImpl(RTLIB::DIV_F64, RTLIB::__hexagon_divdf3);
+      setLibcallImpl(RTLIB::DIV_F32, RTLIB::__hexagon_divsf3);
     }
 
     if (FastMath)
-      setLibcallName(RTLIB::SQRT_F32, "__hexagon_fast2_sqrtf");
+      setLibcallImpl(RTLIB::SQRT_F32, RTLIB::__hexagon_fast2_sqrtf);
     else
-      setLibcallName(RTLIB::SQRT_F32, "__hexagon_sqrtf");
+      setLibcallImpl(RTLIB::SQRT_F32, RTLIB::__hexagon_sqrtf);
   }
 
   if (TT.getArch() == Triple::ArchType::msp430)
diff --git a/llvm/lib/LTO/LTO.cpp b/llvm/lib/LTO/LTO.cpp
index adf995cbc9b18..779c98ee4441e 100644
--- a/llvm/lib/LTO/LTO.cpp
+++ b/llvm/lib/LTO/LTO.cpp
@@ -1389,8 +1389,14 @@ Error LTO::runRegularLTO(AddStreamFn AddStream) {
 SmallVector<const char *> LTO::getRuntimeLibcallSymbols(const Triple &TT) {
   RTLIB::RuntimeLibcallsInfo Libcalls(TT);
   SmallVector<const char *> LibcallSymbols;
-  copy_if(Libcalls.getLibcallNames(), std::back_inserter(LibcallSymbols),
-          [](const char *Name) { return Name; });
+  ArrayRef<RTLIB::LibcallImpl> LibcallImpls = Libcalls.getLibcallImpls();
+  LibcallSymbols.reserve(LibcallImpls.size());
+
+  for (RTLIB::LibcallImpl Impl : LibcallImpls) {
+    if (Impl != RTLIB::Unsupported)
+      LibcallSymbols.push_back(Libcalls.getLibcallImplName(Impl));
+  }
+
   return LibcallSymbols;
 }
 
diff --git a/llvm/lib/Object/IRSymtab.cpp b/llvm/lib/Object/IRSymtab.cpp
index 2f25c771a93fa..2579fa37935f0 100644
--- a/llvm/lib/Object/IRSymtab.cpp
+++ b/llvm/lib/Object/IRSymtab.cpp
@@ -218,9 +218,9 @@ static DenseSet<StringRef> buildPreservedSymbolsSet(const Triple &TT) {
                                          std::end(PreservedSymbols));
   // FIXME: Do we need to pass in ABI fields from TargetOptions?
   RTLIB::RuntimeLibcallsInfo Libcalls(TT);
-  for (const char *Name : Libcalls.getLibcallNames()) {
-    if (Name)
-      PreservedSymbolSet.insert(Name);
+  for (RTLIB::LibcallImpl Impl : Libcalls.getLibcallImpls()) {
+    if (Impl != RTLIB::Unsupported)
+      PreservedSymbolSet.insert(Libcalls.getLibcallImplName(Impl));
   }
   return PreservedSymbolSet;
 }
diff --git a/llvm/lib/Target/ARM/ARMISelLowering.cpp b/llvm/lib/Target/ARM/ARMISelLowering.cpp
index c106835bdf3a8..3e536472b9898 100644
--- a/llvm/lib/Target/ARM/ARMISelLowering.cpp
+++ b/llvm/lib/Target/ARM/ARMISelLowering.cpp
@@ -522,65 +522,65 @@ ARMTargetLowering::ARMTargetLowering(const TargetMachine &TM_,
       // clang-format off
       static const struct {
         const RTLIB::Libcall Op;
-        const char * const Name;
+        const RTLIB::LibcallImpl Impl;
         const CmpInst::Predicate Cond;
       } LibraryCalls[] = {
         // Single-precision floating-point arithmetic.
-        { RTLIB::ADD_F32, "__addsf3vfp", CmpInst::BAD_ICMP_PREDICATE },
-        { RTLIB::SUB_F32, "__subsf3vfp", CmpInst::BAD_ICMP_PREDICATE },
-        { RTLIB::MUL_F32, "__mulsf3vfp", CmpInst::BAD_ICMP_PREDICATE },
-        { RTLIB::DIV_F32, "__divsf3vfp", CmpInst::BAD_ICMP_PREDICATE },
+        { RTLIB::ADD_F32, RTLIB::__addsf3vfp, CmpInst::BAD_ICMP_PREDICATE },
+        { RTLIB::SUB_F32, RTLIB::__subsf3vfp, CmpInst::BAD_ICMP_PREDICATE },
+        { RTLIB::MUL_F32, RTLIB::__mulsf3vfp, CmpInst::BAD_ICMP_PREDICATE },
+        { RTLIB::DIV_F32, RTLIB::__divsf3vfp, CmpInst::BAD_ICMP_PREDICATE },
 
         // Double-precision floating-point arithmetic.
-        { RTLIB::ADD_F64, "__adddf3vfp", CmpInst::BAD_ICMP_PREDICATE },
-        { RTLIB::SUB_F64, "__subdf3vfp", CmpInst::BAD_ICMP_PREDICATE },
-        { RTLIB::MUL_F64, "__muldf3vfp", CmpInst::BAD_ICMP_PREDICATE },
-        { RTLIB::DIV_F64, "__divdf3vfp", CmpInst::BAD_ICMP_PREDICATE },
+        { RTLIB::ADD_F64, RTLIB::__adddf3vfp, CmpInst::BAD_ICMP_PREDICATE },
+        { RTLIB::SUB_F64, RTLIB::__subdf3vfp, CmpInst::BAD_ICMP_PREDICATE },
+        { RTLIB::MUL_F64, RTLIB::__muldf3vfp, CmpInst::BAD_ICMP_PREDICATE },
+        { RTLIB::DIV_F64, RTLIB::__divdf3vfp, CmpInst::BAD_ICMP_PREDICATE },
 
         // Single-precision comparisons.
-        { RTLIB::OEQ_F32, "__eqsf2vfp",    CmpInst::ICMP_NE },
-        { RTLIB::UNE_F32, "__nesf2vfp",    CmpInst::ICMP_NE },
-        { RTLIB::OLT_F32, "__ltsf2vfp",    CmpInst::ICMP_NE },
-        { RTLIB::OLE_F32, "__lesf2vfp",    CmpInst::ICMP_NE },
-        { RTLIB::OGE_F32, "__gesf2vfp",    CmpInst::ICMP_NE },
-        { RTLIB::OGT_F32, "__gtsf2vfp",    CmpInst::ICMP_NE },
-        { RTLIB::UO_F32,  "__unordsf2vfp", CmpInst::ICMP_NE },
+        { RTLIB::OEQ_F32, RTLIB::__eqsf2vfp,    CmpInst::ICMP_NE },
+        { RTLIB::UNE_F32, RTLIB::__nesf2vfp,    CmpInst::ICMP_NE },
+        { RTLIB::OLT_F32, RTLIB::__ltsf2vfp,    CmpInst::ICMP_NE },
+        { RTLIB::OLE_F32, RTLIB::__lesf2vfp,    CmpInst::ICMP_NE },
+        { RTLIB::OGE_F32, RTLIB::__gesf2vfp,    CmpInst::ICMP_NE },
+        { RTLIB::OGT_F32, RTLIB::__gtsf2vfp,    CmpInst::ICMP_NE },
+        { RTLIB::UO_F32,  RTLIB::__unordsf2vfp, CmpInst::ICMP_NE },
 
         // Double-precision comparisons.
-        { RTLIB::OEQ_F64, "__eqdf2vfp",    CmpInst::ICMP_NE },
-        { RTLIB::UNE_F64, "__nedf2vfp",    CmpInst::ICMP_NE },
-        { RTLIB::OLT_F64, "__ltdf2vfp",    CmpInst::ICMP_NE },
-        { RTLIB::OLE_F64, "__ledf2vfp",    CmpInst::ICMP_NE },
-        { RTLIB::OGE_F64, "__gedf2vfp",    CmpInst::ICMP_NE },
-        { RTLIB::OGT_F64, "__gtdf2vfp",    CmpInst::ICMP_NE },
-        { RTLIB::UO_F64,  "__unorddf2vfp", CmpInst::ICMP_NE },
+        { RTLIB::OEQ_F64, RTLIB::__eqdf2vfp,    CmpInst::ICMP_NE },
+        { RTLIB::UNE_F64, RTLIB::__nedf2vfp,    CmpInst::ICMP_NE },
+        { RTLIB::OLT_F64, RTLIB::__ltdf2vfp,    CmpInst::ICMP_NE },
+        { RTLIB::OLE_F64, RTLIB::__ledf2vfp,    CmpInst::ICMP_NE },
+        { RTLIB::OGE_F64, RTLIB::__gedf2vfp,    CmpInst::ICMP_NE },
+        { RTLIB::OGT_F64, RTLIB::__gtdf2vfp,    CmpInst::ICMP_NE },
+        { RTLIB::UO_F64,  RTLIB::__unorddf2vfp, CmpInst::ICMP_NE },
 
         // Floating-point to integer conversions.
         // i64 conversions are done via library routines even when generating VFP
         // instructions, so use the same ones.
-        { RTLIB::FPTOSINT_F64_I32, "__fixdfsivfp",    CmpInst::BAD_ICMP_PREDICATE },
-        { RTLIB::FPTOUINT_F64_I32, "__fixunsdfsivfp", CmpInst::BAD_ICMP_PREDICATE },
-        { RTLIB::FPTOSINT_F32_I32, "__fixsfsivfp",    CmpInst::BAD_ICMP_PREDICATE },
-        { RTLIB::FPTOUINT_F32_I32, "__fixunssfsivfp", CmpInst::BAD_ICMP_PREDICATE },
+        { RTLIB::FPTOSINT_F64_I32, RTLIB::__fixdfsivfp,    CmpInst::BAD_ICMP_PREDICATE },
+        { RTLIB::FPTOUINT_F64_I32, RTLIB::__fixunsdfsivfp, CmpInst::BAD_ICMP_PREDICATE },
+        { RTLIB::FPTOSINT_F32_I32, RTLIB::__fixsfsivfp,    CmpInst::BAD_ICMP_PREDICATE },
+        { RTLIB::FPTOUINT_F32_I32, RTLIB::__fixunssfsivfp, CmpInst::BAD_ICMP_PREDICATE },
 
         // Conversions between floating types.
-        { RTLIB::FPROUND_F64_F32, "__truncdfsf2vfp",  CmpInst::BAD_ICMP_PREDICATE },
-        { RTLIB::FPEXT_F32_F64,   "__extendsfdf2vfp", CmpInst::BAD_ICMP_PREDICATE },
+        { RTLIB::FPROUND_F64_F32, RTLIB::__truncdfsf2vfp,  CmpInst::BAD_ICMP_PREDICATE },
+        { RTLIB::FPEXT_F32_F64,   RTLIB::__extendsfdf2vfp, CmpInst::BAD_ICMP_PREDICATE },
 
         // Integer to floating-point conversions.
         // i64 conversions are done via library routines even when generating VFP
         // instructions, so use the same ones.
         // FIXME: There appears to be some naming inconsistency in ARM libgcc:
         // e.g., __floatunsidf vs. __floatunssidfvfp.
-        { RTLIB::SINTTOFP_I32_F64, "__floatsidfvfp",    CmpInst::BAD_ICMP_PREDICATE },
-        { RTLIB::UINTTOFP_I32_F64, "__floatunssidfvfp", CmpInst::BAD_ICMP_PREDICATE },
-        { RTLIB::SINTTOFP_I32_F32, "__floatsisfvfp",    CmpInst::BAD_ICMP_PREDICATE },
-        { RTLIB::UINTTOFP_I32_F32, "__floatunssisfvfp", CmpInst::BAD_ICMP_PREDICATE },
+        { RTLIB::SINTTOFP_I32_F64, RTLIB::__floatsidfvfp,    CmpInst::BAD_ICMP_PREDICATE },
+        { RTLIB::UINTTOFP_I32_F64, RTLIB::__floatunssidfvfp, CmpInst::BAD_ICMP_PREDICATE },
+        { RTLIB::SINTTOFP_I32_F32, RTLIB::__floatsisfvfp,    CmpInst::BAD_ICMP_PREDICATE },
+        { RTLIB::UINTTOFP_I32_F32, RTLIB::__floatunssisfvfp, CmpInst::BAD_ICMP_PREDICATE },
       };
       // clang-format on
 
       for (const auto &LC : LibraryCalls) {
-        setLibcallName(LC.Op, LC.Name);
+        setLibcallImpl(LC.Op, LC.Impl);
         if (LC.Cond != CmpInst::BAD_ICMP_PREDICATE)
           setCmpLibcallCC(LC.Op, LC.Cond);
       }
@@ -590,97 +590,100 @@ ARMTargetLowering::ARMTargetLowering(const TargetMachine &TM_,
   // RTLIB
   if (TM.isAAPCS_ABI() && (TT.isTargetAEABI() || TT.isTargetGNUAEABI() ||
                            TT.isTargetMuslAEABI() || TT.isAndroid())) {
+    // FIXME: This does not depend on the subtarget and should go directly into
+    // RuntimeLibcalls. This is only here because of missing support for setting
+    // the calling convention of an implementation.
     // clang-format off
     static const struct {
       const RTLIB::Libcall Op;
-      const char * const Name;
+      const RTLIB::LibcallImpl Impl;
       const CallingConv::ID CC;
       const CmpInst::Predicate Cond;
     } LibraryCalls[] = {
       // Double-precision floating-point arithmetic helper functions
       // RTABI chapter 4.1.2, Table 2
-      { RTLIB::ADD_F64, "__aeabi_dadd", CallingConv::ARM_AAPCS, CmpInst::BAD_ICMP_PREDICATE },
-      { RTLIB::DIV_F64, "__aeabi_ddiv", CallingConv::ARM_AAPCS, CmpInst::BAD_ICMP_PREDICATE },
-      { RTLIB::MUL_F64, "__aeabi_dmul", CallingConv::ARM_AAPCS, CmpInst::BAD_ICMP_PREDICATE },
-      { RTLIB::SUB_F64, "__aeabi_dsub", CallingConv::ARM_AAPCS, CmpInst::BAD_ICMP_PREDICATE },
+      { RTLIB::ADD_F64, RTLIB::__aeabi_dadd, CallingConv::ARM_AAPCS, CmpInst::BAD_ICMP_PREDICATE },
+      { RTLIB::DIV_F64, RTLIB::__aeabi_ddiv, CallingConv::ARM_AAPCS, CmpInst::BAD_ICMP_PREDICATE },
+      { RTLIB::MUL_F64, RTLIB::__aeabi_dmul, CallingConv::ARM_AAPCS, CmpInst::BAD_ICMP_PREDICATE },
+      { RTLIB::SUB_F64, RTLIB::__aeabi_dsub, CallingConv::ARM_AAPCS, CmpInst::BAD_ICMP_PREDICATE },
 
       // Double-precision floating-point comparison helper functions
       // RTABI chapter 4.1.2, Table 3
-      { RTLIB::OEQ_F64, "__aeabi_dcmpeq", CallingConv::ARM_AAPCS, CmpInst::ICMP_NE },
-      { RTLIB::UNE_F64, "__aeabi_dcmpeq", CallingConv::ARM_AAPCS, CmpInst::ICMP_EQ },
-      { RTLIB::OLT_F64, "__aeabi_dcmplt", CallingConv::ARM_AAPCS, CmpInst::ICMP_NE },
-      { RTLIB::OLE_F64, "__aeabi_dcmple", CallingConv::ARM_AAPCS, CmpInst::ICMP_NE },
-      { RTLIB::OGE_F64, "__aeabi_dcmpge", CallingConv::ARM_AAPCS, CmpInst::ICMP_NE },
-      { RTLIB::OGT_F64, "__aeabi_dcmpgt", CallingConv::ARM_AAPCS, CmpInst::ICMP_NE },
-      { RTLIB::UO_F64,  "__aeabi_dcmpun", CallingConv::ARM_AAPCS, CmpInst::BAD_ICMP_PREDICATE },
+      { RTLIB::OEQ_F64, RTLIB::__aeabi_dcmpeq__ne, CallingConv::ARM_AAPCS, CmpInst::ICMP_NE },
+      { RTLIB::UNE_F64, RTLIB::__aeabi_dcmpeq__eq, CallingConv::ARM_AAPCS, CmpInst::ICMP_EQ },
+      { RTLIB::OLT_F64, RTLIB::__aeabi_dcmplt, CallingConv::ARM_AAPCS, CmpInst::ICMP_NE },
+      { RTLIB::OLE_F64, RTLIB::__aeabi_dcmple, CallingConv::ARM_AAPCS, CmpInst::ICMP_NE },
+      { RTLIB::OGE_F64, RTLIB::__aeabi_dcmpge, CallingConv::ARM_AAPCS, CmpInst::ICMP_NE },
+      { RTLIB::OGT_F64, RTLIB::__aeabi_dcmpgt, CallingConv::ARM_AAPCS, CmpInst::ICMP_NE },
+      { RTLIB::UO_F64,  RTLIB::__aeabi_dcmpun, CallingConv::ARM_AAPCS, CmpInst::BAD_ICMP_PREDICATE },
 
       // Single-precision floating-point arithmetic helper functions
       // RTABI chapter 4.1.2, Table 4
-      { RTLIB::ADD_F32, "__aeabi_fadd", CallingConv::ARM_AAPCS, CmpInst::BAD_ICMP_PREDICATE },
-      { RTLIB::DIV_F32, "__aeabi_fdiv", CallingConv::ARM_AAPCS, CmpInst::BAD_ICMP_PREDICATE },
-      { RTLIB::MUL_F32, "__aeabi_fmul", CallingConv::ARM_AAPCS, CmpInst::BAD_ICMP_PREDICATE },
-      { RTLIB::SUB_F32, "__aeabi_fsub", CallingConv::ARM_AAPCS, CmpInst::BAD_ICMP_PREDICATE },
+      { RTLIB::ADD_F32, RTLIB::__aeabi_fadd, CallingConv::ARM_AAPCS, CmpInst::BAD_ICMP_PREDICATE },
+      { RTLIB::DIV_F32, RTLIB::__aeabi_fdiv, CallingConv::ARM_AAPCS, CmpInst::BAD_ICMP_PREDICATE },
+      { RTLIB::MUL_F32, RTLIB::__aeabi_fmul, CallingConv::ARM_AAPCS, CmpInst::BAD_ICMP_PREDICATE },
+      { RTLIB::SUB_F32, RTLIB::__aeabi_fsub, CallingConv::ARM_AAPCS, CmpInst::BAD_ICMP_PREDICATE },
 
       // Single-precision floating-point comparison helper functions
       // RTABI chapter 4.1.2, Table 5
-      { RTLIB::OEQ_F32, "__aeabi_fcmpeq", CallingConv::ARM_AAPCS, CmpInst::ICMP_NE },
-      { RTLIB::UNE_F32, "__aeabi_fcmpeq", CallingConv::ARM_AAPCS, CmpInst::ICMP_EQ },
-      { RTLIB::OLT_F32, "__aeabi_fcmplt", CallingConv::ARM_AAPCS, CmpInst::ICMP_NE },
-      { RTLIB::OLE_F32, "__aeabi_fcmple", CallingConv::ARM_AAPCS, CmpInst::ICMP_NE },
-      { RTLIB::OGE_F32, "__aeabi_fcmpge", CallingConv::ARM_AAPCS, CmpInst::ICMP_NE },
-      { RTLIB::OGT_F32, "__aeabi_fcmpgt", CallingConv::ARM_AAPCS, CmpInst::ICMP_NE },
-      { RTLIB::UO_F32,  "__aeabi_fcmpun", CallingConv::ARM_AAPCS, CmpInst::BAD_ICMP_PREDICATE },
+      { RTLIB::OEQ_F32, RTLIB::__aeabi_fcmpeq__ne, CallingConv::ARM_AAPCS, CmpInst::ICMP_NE },
+      { RTLIB::UNE_F32, RTLIB::__aeabi_fcmpeq__eq, CallingConv::ARM_AAPCS, CmpInst::ICMP_EQ },
+      { RTLIB::OLT_F32, RTLIB::__aeabi_fcmplt, CallingConv::ARM_AAPCS, CmpInst::ICMP_NE },
+      { RTLIB::OLE_F32, RTLIB::__aeabi_fcmple, CallingConv::ARM_AAPCS, CmpInst::ICMP_NE },
+      { RTLIB::OGE_F32, RTLIB::__aeabi_fcmpge, CallingConv::ARM_AAPCS, CmpInst::ICMP_NE },
+      { RTLIB::OGT_F32, RTLIB::__aeabi_fcmpgt, CallingConv::ARM_AAPCS, CmpInst::ICMP_NE },
+      { RTLIB::UO_F32,  RTLIB::__aeabi_fcmpun, CallingConv::ARM_AAPCS, CmpInst::BAD_ICMP_PREDICATE },
 
       // Floating-point to integer conversions.
       // RTABI chapter 4.1.2, Table 6
-      { RTLIB::FPTOSINT_F64_I32, "__aeabi_d2iz",  CallingConv::ARM_AAPCS, CmpInst::BAD_ICMP_PREDICATE },
-      { RTLIB::FPTOUINT_F64_I32, "__aeabi_d2uiz", CallingConv::ARM_AAPCS, CmpInst::BAD_ICMP_PREDICATE },
-      { RTLIB::FPTOSINT_F64_I64, "__aeabi_d2lz",  CallingConv::ARM_AAPCS, CmpInst::BAD_ICMP_PREDICATE },
-      { RTLIB::FPTOUINT_F64_I64, "__aeabi_d2ulz", CallingConv::ARM_AAPCS, CmpInst::BAD_ICMP_PREDICATE },
-      { RTLIB::FPTOSINT_F32_I32, "__aeabi_f2iz",  CallingConv::ARM_AAPCS, CmpInst::BAD_ICMP_PREDICATE },
-      { RTLIB::FPTOUINT_F32_I32, "__aeabi_f2uiz", CallingConv::ARM_AAPCS, CmpInst::BAD_ICMP_PREDICATE },
-      { RTLIB::FPTOSINT_F32_I64, "__aeabi_f2lz",  CallingConv::ARM_AAPCS, CmpInst::BAD_ICMP_PREDICATE },
-      { RTLIB::FPTOUINT_F32_I64, "__aeabi_f2ulz", CallingConv::ARM_AAPCS, CmpInst::BAD_ICMP_PREDICATE },
+      { RTLIB::FPTOSINT_F64_I32, RTLIB::__aeabi_d2iz,  CallingConv::ARM_AAPCS, CmpInst::BAD_ICMP_PREDICATE },
+      { RTLIB::FPTOUINT_F64_I32, RTLIB::__aeabi_d2uiz, CallingConv::ARM_AAPCS, CmpInst::BAD_ICMP_PREDICATE },
+      { RTLIB::FPTOSINT_F64_I64, RTLIB::__aeabi_d2lz,  CallingConv::ARM_AAPCS, CmpInst::BAD_ICMP_PREDICATE },
+      { RTLIB::FPTOUINT_F64_I64, RTLIB::__aeabi_d2ulz, CallingConv::ARM_AAPCS, CmpInst::BAD_ICMP_PREDICATE },
+      { RTLIB::FPTOSINT_F32_I32, RTLIB::__aeabi_f2iz,  CallingConv::ARM_AAPCS, CmpInst::BAD_ICMP_PREDICATE },
+      { RTLIB::FPTOUINT_F32_I32, RTLIB::__aeabi_f2uiz, CallingConv::ARM_AAPCS, CmpInst::BAD_ICMP_PREDICATE },
+      { RTLIB::FPTOSINT_F32_I64, RTLIB::__aeabi_f2lz,  CallingConv::ARM_AAPCS, CmpInst::BAD_ICMP_PREDICATE },
+      { RTLIB::FPTOUINT_F32_I64, RTLIB::__aeabi_f2ulz, CallingConv::ARM_AAPCS, CmpInst::BAD_ICMP_PREDICATE },
 
       // Conversions between floating types.
       // RTABI chapter 4.1.2, Table 7
-      { RTLIB::FPROUND_F64_F32, "__aeabi_d2f", CallingConv::ARM_AAPCS, CmpInst::BAD_ICMP_PREDICATE },
-      { RTLIB::FPROUND_F64_F16, "__aeabi_d2h", CallingConv::ARM_AAPCS, CmpInst::BAD_ICMP_PREDICATE },
-      { RTLIB::FPEXT_F32_F64,   "__aeabi_f2d", CallingConv::ARM_AAPCS, CmpInst::BAD_ICMP_PREDICATE },
+      { RTLIB::FPROUND_F64_F32, RTLIB::__aeabi_d2f, CallingConv::ARM_AAPCS, CmpInst::BAD_ICMP_PREDICATE },
+      { RTLIB::FPROUND_F64_F16, RTLIB::__aeabi_d2h, CallingConv::ARM_AAPCS, CmpInst::BAD_ICMP_PREDICATE },
+      { RTLIB::FPEXT_F32_F64,   RTLIB::__aeabi_f2d, CallingConv::ARM_AAPCS, CmpInst::BAD_ICMP_PREDICATE },
 
       // Integer to floating-point conversions.
       // RTABI chapter 4.1.2, Table 8
-      { RTLIB::SINTTOFP_I32_F64, "__aeabi_i2d",  CallingConv::ARM_AAPCS, CmpInst::BAD_ICMP_PREDICATE },
-      { RTLIB::UINTTOFP_I32_F64, "__aeabi_ui2d", CallingConv::ARM_AAPCS, CmpInst::BAD_ICMP_PREDICATE },
-      { RTLIB::SINTTOFP_I64_F64, "__aeabi_l2d",  CallingConv::ARM_AAPCS, CmpInst::BAD_ICMP_PREDICATE },
-      { RTLIB::UINTTOFP_I64_F64, "__aeabi_ul2d", CallingConv::ARM_AAPCS, CmpInst::BAD_ICMP_PREDICATE },
-      { RTLIB::SINTTOFP_I32_F32, "__aeabi_i2f",  CallingConv::ARM_AAPCS, CmpInst::BAD_ICMP_PREDICATE },
-      { RTLIB::UINTTOFP_I32_F32, "__aeabi_ui2f", CallingConv::ARM_AAPCS, CmpInst::BAD_ICMP_PREDICATE },
-      { RTLIB::SINTTOFP_I64_F32, "__aeabi_l2f",  CallingConv::ARM_AAPCS, CmpInst::BAD_ICMP_PREDICATE },
-      { RTLIB::UINTTOFP_I64_F32, "__aeabi_ul2f", CallingConv::ARM_AAPCS, CmpInst::BAD_ICMP_PREDICATE },
+      { RTLIB::SINTTOFP_I32_F64, RTLIB::__aeabi_i2d,  CallingConv::ARM_AAPCS, CmpInst::BAD_ICMP_PREDICATE },
+      { RTLIB::UINTTOFP_I32_F64, RTLIB::__aeabi_ui2d, CallingConv::ARM_AAPCS, CmpInst::BAD_ICMP_PREDICATE },
+      { RTLIB::SINTTOFP_I64_F64, RTLIB::__aeabi_l2d,  CallingConv::ARM_AAPCS, CmpInst::BAD_ICMP_PREDICATE },
+      { RTLIB::UINTTOFP_I64_F64, RTLIB::__aeabi_ul2d, CallingConv::ARM_AAPCS, CmpInst::BAD_ICMP_PREDICATE },
+      { RTLIB::SINTTOFP_I32_F32, RTLIB::__aeabi_i2f,  CallingConv::ARM_AAPCS, CmpInst::BAD_ICMP_PREDICATE },
+      { RTLIB::UINTTOFP_I32_F32, RTLIB::__aeabi_ui2f, CallingConv::ARM_AAPCS, CmpInst::BAD_ICMP_PREDICATE },
+      { RTLIB::SINTTOFP_I64_F32, RTLIB::__aeabi_l2f,  CallingConv::ARM_AAPCS, CmpInst::BAD_ICMP_PREDICATE },
+      { RTLIB::UINTTOFP_I64_F32, RTLIB::__aeabi_ul2f, CallingConv::ARM_AAPCS, CmpInst::BAD_ICMP_PREDICATE },
 
       // Long long helper functions
       // RTABI chapter 4.2, Table 9
-      { RTLIB::MUL_I64, "__aeabi_lmul", CallingConv::ARM_AAPCS, CmpInst::BAD_ICMP_PREDICATE },
-      { RTLIB::SHL_I64, "__aeabi_llsl", CallingConv::ARM_AAPCS, CmpInst::BAD_ICMP_PREDICATE },
-      { RTLIB::SRL_I64, "__aeabi_llsr", CallingConv::ARM_AAPCS, CmpInst::BAD_ICMP_PREDICATE },
-      { RTLIB::SRA_I64, "__aeabi_lasr", CallingConv::ARM_AAPCS, CmpInst::BAD_ICMP_PREDICATE },
+      { RTLIB::MUL_I64, RTLIB::__aeabi_lmul, CallingConv::ARM_AAPCS, CmpInst::BAD_ICMP_PREDICATE },
+      { RTLIB::SHL_I64, RTLIB::__aeabi_llsl, CallingConv::ARM_AAPCS, CmpInst::BAD_ICMP_PREDICATE },
+      { RTLIB::SRL_I64, RTLIB::__aeabi_llsr, CallingConv::ARM_AAPCS, CmpInst::BAD_ICMP_PREDICATE },
+      { RTLIB::SRA_I64, RTLIB::__aeabi_lasr, CallingConv::ARM_AAPCS, CmpInst::BAD_ICMP_PREDICATE },
 
       // Integer division functions
       // RTABI chapter 4.3.1
-      { RTLIB::SDIV_I8,  "__aeabi_idiv",     CallingConv::ARM_AAPCS, CmpInst::BAD_ICMP_PREDICATE },
-      { RTLIB::SDIV_I16, "__aeabi_idiv",     CallingConv::ARM_AAPCS, CmpInst::BAD_ICMP_PREDICATE },
-      { RTLIB::SDIV_I32, "__aeabi_idiv",     CallingConv::ARM_AAPCS, CmpInst::BAD_ICMP_PREDICATE },
-      { RTLIB::SDIV_I64, "__aeabi_ldivmod",  CallingConv::ARM_AAPCS, CmpInst::BAD_ICMP_PREDICATE },
-      { RTLIB::UDIV_I8,  "__aeabi_uidiv",    CallingConv::ARM_AAPCS, CmpInst::BAD_ICMP_PREDICATE },
-      { RTLIB::UDIV_I16, "__aeabi_uidiv",    CallingConv::ARM_AAPCS, CmpInst::BAD_ICMP_PREDICATE },
-      { RTLIB::UDIV_I32, "__aeabi_uidiv",    CallingConv::ARM_AAPCS, CmpInst::BAD_ICMP_PREDICATE },
-      { RTLIB::UDIV_I64, "__aeabi_uldivmod", CallingConv::ARM_AAPCS, CmpInst::BAD_ICMP_PREDICATE },
+      { RTLIB::SDIV_I8,  RTLIB::__aeabi_idiv__i8,     CallingConv::ARM_AAPCS, CmpInst::BAD_ICMP_PREDICATE },
+      { RTLIB::SDIV_I16, RTLIB::__aeabi_idiv__i16,     CallingConv::ARM_AAPCS, CmpInst::BAD_ICMP_PREDICATE },
+      { RTLIB::SDIV_I32, RTLIB::__aeabi_idiv__i32,     CallingConv::ARM_AAPCS, CmpInst::BAD_ICMP_PREDICATE },
+      { RTLIB::SDIV_I64, RTLIB::__aeabi_ldivmod,  CallingConv::ARM_AAPCS, CmpInst::BAD_ICMP_PREDICATE },
+      { RTLIB::UDIV_I8,  RTLIB::__aeabi_uidiv__i8,    CallingConv::ARM_AAPCS, CmpInst::BAD_ICMP_PREDICATE },
+      { RTLIB::UDIV_I16, RTLIB::__aeabi_uidiv__i16,    CallingConv::ARM_AAPCS, CmpInst::BAD_ICMP_PREDICATE },
+      { RTLIB::UDIV_I32, RTLIB::__aeabi_uidiv__i32,    CallingConv::ARM_AAPCS, CmpInst::BAD_ICMP_PREDICATE },
+      { RTLIB::UDIV_I64, RTLIB::__aeabi_uldivmod, CallingConv::ARM_AAPCS, CmpInst::BAD_ICMP_PREDICATE },
     };
     // clang-format on
 
     for (const auto &LC : LibraryCalls) {
-      setLibcallName(LC.Op, LC.Name);
+      setLibcallImpl(LC.Op, LC.Impl);
       setLibcallCallingConv(LC.Op, LC.CC);
       if (LC.Cond != CmpInst::BAD_ICMP_PREDICATE)
         setCmpLibcallCC(LC.Op, LC.Cond);
@@ -691,18 +694,18 @@ ARMTargetLowering::ARMTargetLowering(const TargetMachine &TM_,
         TM.Options.EABIVersion == EABI::EABI5) {
       static const struct {
         const RTLIB::Libcall Op;
-        const char *const Name;
+        const RTLIB::LibcallImpl Impl;
         const CallingConv::ID CC;
       } MemOpsLibraryCalls[] = {
           // Memory operations
           // RTABI chapter 4.3.4
-          {RTLIB::MEMCPY, "__aeabi_memcpy", CallingConv::ARM_AAPCS},
-          {RTLIB::MEMMOVE, "__aeabi_memmove", CallingConv::ARM_AAPCS},
-          {RTLIB::MEMSET, "__aeabi_memset", CallingConv::ARM_AAPCS},
+          {RTLIB::MEMCPY, RTLIB::__aeabi_memcpy, CallingConv::ARM_AAPCS},
+          {RTLIB::MEMMOVE, RTLIB::__aeabi_memmove, CallingConv::ARM_AAPCS},
+          {RTLIB::MEMSET, RTLIB::__aeabi_memset, CallingConv::ARM_AAPCS},
       };
 
       for (const auto &LC : MemOpsLibraryCalls) {
-        setLibcallName(LC.Op, LC.Name);
+        setLibcallImpl(LC.Op, LC.Impl);
         setLibcallCallingConv(LC.Op, LC.CC);
       }
     }
@@ -726,23 +729,26 @@ ARMTargetLowering::ARMTargetLowering(const TargetMachine &TM_,
   // In EABI, these functions have an __aeabi_ prefix, but in GNUEABI they have
   // a __gnu_ prefix (which is the default).
   if (TT.isTargetAEABI()) {
+    // FIXME: This does not depend on the subtarget and should go directly into
+    // RuntimeLibcalls. This is only here because of missing support for setting
+    // the calling convention of an implementation.
     static const struct {
       const RTLIB::Libcall Op;
-      const char * const Name;
+      const RTLIB::LibcallImpl Impl;
       const CallingConv::ID CC;
     } LibraryCalls[] = {
-      { RTLIB::FPROUND_F32_F16, "__aeabi_f2h", CallingConv::ARM_AAPCS },
-      { RTLIB::FPROUND_F64_F16, "__aeabi_d2h", CallingConv::ARM_AAPCS },
-      { RTLIB::FPEXT_F16_F32, "__aeabi_h2f", CallingConv::ARM_AAPCS },
+        {RTLIB::FPROUND_F32_F16, RTLIB::__aeabi_f2h, CallingConv::ARM_AAPCS},
+        {RTLIB::FPROUND_F64_F16, RTLIB::__aeabi_d2h, CallingConv::ARM_AAPCS},
+        {RTLIB::FPEXT_F16_F32, RTLIB::__aeabi_h2f, CallingConv::ARM_AAPCS},
     };
 
     for (const auto &LC : LibraryCalls) {
-      setLibcallName(LC.Op, LC.Name);
+      setLibcallImpl(LC.Op, LC.Impl);
       setLibcallCallingConv(LC.Op, LC.CC);
     }
   } else if (!TT.isOSBinFormatMachO()) {
-    setLibcallName(RTLIB::FPROUND_F32_F16, "__gnu_f2h_ieee");
-    setLibcallName(RTLIB::FPEXT_F16_F32, "__gnu_h2f_ieee");
+    setLibcallImpl(RTLIB::FPROUND_F32_F16, RTLIB::__gnu_f2h_ieee);
+    setLibcallImpl(RTLIB::FPEXT_F16_F32, RTLIB::__gnu_h2f_ieee);
   }
 
   if (Subtarget->isThumb1Only())
@@ -1378,7 +1384,7 @@ ARMTargetLowering::ARMTargetLowering(const TargetMachine &TM_,
   setOperationAction(ISD::EH_SJLJ_LONGJMP, MVT::Other, Custom);
   setOperationAction(ISD::EH_SJLJ_SETUP_DISPATCH, MVT::Other, Custom);
   if (Subtarget->useSjLjEH())
-    setLibcallName(RTLIB::UNWIND_RESUME, "_Unwind_SjLj_Resume");
+    setLibcallImpl(RTLIB::UNWIND_RESUME, RTLIB::_Unwind_SjLj_Resume);
 
   setOperationAction(ISD::SETCC,     MVT::i32, Expand);
   setOperationAction(ISD::SETCC,     MVT::f32, Expand);
diff --git a/llvm/lib/Target/MSP430/MSP430ISelLowering.cpp b/llvm/lib/Target/MSP430/MSP430ISelLowering.cpp
index c2946de838d77..f8f688c8fbb14 100644
--- a/llvm/lib/Target/MSP430/MSP430ISelLowering.cpp
+++ b/llvm/lib/Target/MSP430/MSP430ISelLowering.cpp
@@ -151,62 +151,62 @@ MSP430TargetLowering::MSP430TargetLowering(const TargetMachine &TM,
   if (STI.hasHWMult16()) {
     const struct {
       const RTLIB::Libcall Op;
-      const char * const Name;
+      const RTLIB::LibcallImpl Impl;
     } LibraryCalls[] = {
-      // Integer Multiply - EABI Table 9
-      { RTLIB::MUL_I16,   "__mspabi_mpyi_hw" },
-      { RTLIB::MUL_I32,   "__mspabi_mpyl_hw" },
-      { RTLIB::MUL_I64,   "__mspabi_mpyll_hw" },
-      // TODO The __mspabi_mpysl*_hw functions ARE implemented in libgcc
-      // TODO The __mspabi_mpyul*_hw functions ARE implemented in libgcc
+        // Integer Multiply - EABI Table 9
+        {RTLIB::MUL_I16, RTLIB::__mspabi_mpyi_hw},
+        {RTLIB::MUL_I32, RTLIB::__mspabi_mpyl_hw},
+        {RTLIB::MUL_I64, RTLIB::__mspabi_mpyll_hw},
+        // TODO The __mspabi_mpysl*_hw functions ARE implemented in libgcc
+        // TODO The __mspabi_mpyul*_hw functions ARE implemented in libgcc
     };
     for (const auto &LC : LibraryCalls) {
-      setLibcallName(LC.Op, LC.Name);
+      setLibcallImpl(LC.Op, LC.Impl);
     }
   } else if (STI.hasHWMult32()) {
     const struct {
       const RTLIB::Libcall Op;
-      const char * const Name;
+      const RTLIB::LibcallImpl Impl;
     } LibraryCalls[] = {
-      // Integer Multiply - EABI Table 9
-      { RTLIB::MUL_I16,   "__mspabi_mpyi_hw" },
-      { RTLIB::MUL_I32,   "__mspabi_mpyl_hw32" },
-      { RTLIB::MUL_I64,   "__mspabi_mpyll_hw32" },
-      // TODO The __mspabi_mpysl*_hw32 functions ARE implemented in libgcc
-      // TODO The __mspabi_mpyul*_hw32 functions ARE implemented in libgcc
+        // Integer Multiply - EABI Table 9
+        {RTLIB::MUL_I16, RTLIB::__mspabi_mpyi_hw},
+        {RTLIB::MUL_I32, RTLIB::__mspabi_mpyl_hw32},
+        {RTLIB::MUL_I64, RTLIB::__mspabi_mpyll_hw32},
+        // TODO The __mspabi_mpysl*_hw32 functions ARE implemented in libgcc
+        // TODO The __mspabi_mpyul*_hw32 functions ARE implemented in libgcc
     };
     for (const auto &LC : LibraryCalls) {
-      setLibcallName(LC.Op, LC.Name);
+      setLibcallImpl(LC.Op, LC.Impl);
     }
   } else if (STI.hasHWMultF5()) {
     const struct {
       const RTLIB::Libcall Op;
-      const char * const Name;
+      const RTLIB::LibcallImpl Impl;
     } LibraryCalls[] = {
-      // Integer Multiply - EABI Table 9
-      { RTLIB::MUL_I16,   "__mspabi_mpyi_f5hw" },
-      { RTLIB::MUL_I32,   "__mspabi_mpyl_f5hw" },
-      { RTLIB::MUL_I64,   "__mspabi_mpyll_f5hw" },
-      // TODO The __mspabi_mpysl*_f5hw functions ARE implemented in libgcc
-      // TODO The __mspabi_mpyul*_f5hw functions ARE implemented in libgcc
+        // Integer Multiply - EABI Table 9
+        {RTLIB::MUL_I16, RTLIB::__mspabi_mpyi_f5hw},
+        {RTLIB::MUL_I32, RTLIB::__mspabi_mpyl_f5hw},
+        {RTLIB::MUL_I64, RTLIB::__mspabi_mpyll_f5hw},
+        // TODO The __mspabi_mpysl*_f5hw functions ARE implemented in libgcc
+        // TODO The __mspabi_mpyul*_f5hw functions ARE implemented in libgcc
     };
     for (const auto &LC : LibraryCalls) {
-      setLibcallName(LC.Op, LC.Name);
+      setLibcallImpl(LC.Op, LC.Impl);
     }
   } else { // NoHWMult
     const struct {
       const RTLIB::Libcall Op;
-      const char * const Name;
+      const RTLIB::LibcallImpl Impl;
     } LibraryCalls[] = {
-      // Integer Multiply - EABI Table 9
-      { RTLIB::MUL_I16,   "__mspabi_mpyi" },
-      { RTLIB::MUL_I32,   "__mspabi_mpyl" },
-      { RTLIB::MUL_I64,   "__mspabi_mpyll" },
-      // The __mspabi_mpysl* functions are NOT implemented in libgcc
-      // The __mspabi_mpyul* functions are NOT implemented in libgcc
+        // Integer Multiply - EABI Table 9
+        {RTLIB::MUL_I16, RTLIB::__mspabi_mpyi},
+        {RTLIB::MUL_I32, RTLIB::__mspabi_mpyl},
+        {RTLIB::MUL_I64, RTLIB::__mspabi_mpyll},
+        // The __mspabi_mpysl* functions are NOT implemented in libgcc
+        // The __mspabi_mpyul* functions are NOT implemented in libgcc
     };
     for (const auto &LC : LibraryCalls) {
-      setLibcallName(LC.Op, LC.Name);
+      setLibcallImpl(LC.Op, LC.Impl);
     }
     setLibcallCallingConv(RTLIB::MUL_I64, CallingConv::MSP430_BUILTIN);
   }
diff --git a/llvm/lib/Target/Mips/Mips16ISelLowering.cpp b/llvm/lib/Target/Mips/Mips16ISelLowering.cpp
index 4fca1f71fdb57..330cb4e0e206f 100644
--- a/llvm/lib/Target/Mips/Mips16ISelLowering.cpp
+++ b/llvm/lib/Target/Mips/Mips16ISelLowering.cpp
@@ -33,7 +33,8 @@ static cl::opt<bool> DontExpandCondPseudos16(
 namespace {
 struct Mips16Libcall {
   RTLIB::Libcall Libcall;
-  const char *Name;
+  RTLIB::LibcallImpl Impl;
+  const char *Name; // FIXME: Remove this
 
   bool operator<(const Mips16Libcall &RHS) const {
     return std::strcmp(Name, RHS.Name) < 0;
@@ -55,41 +56,48 @@ struct Mips16IntrinsicHelperType{
 
 // Libcalls for which no helper is generated. Sorted by name for binary search.
 static const Mips16Libcall HardFloatLibCalls[] = {
-  { RTLIB::ADD_F64, "__mips16_adddf3" },
-  { RTLIB::ADD_F32, "__mips16_addsf3" },
-  { RTLIB::DIV_F64, "__mips16_divdf3" },
-  { RTLIB::DIV_F32, "__mips16_divsf3" },
-  { RTLIB::OEQ_F64, "__mips16_eqdf2" },
-  { RTLIB::OEQ_F32, "__mips16_eqsf2" },
-  { RTLIB::FPEXT_F32_F64, "__mips16_extendsfdf2" },
-  { RTLIB::FPTOSINT_F64_I32, "__mips16_fix_truncdfsi" },
-  { RTLIB::FPTOSINT_F32_I32, "__mips16_fix_truncsfsi" },
-  { RTLIB::SINTTOFP_I32_F64, "__mips16_floatsidf" },
-  { RTLIB::SINTTOFP_I32_F32, "__mips16_floatsisf" },
-  { RTLIB::UINTTOFP_I32_F64, "__mips16_floatunsidf" },
-  { RTLIB::UINTTOFP_I32_F32, "__mips16_floatunsisf" },
-  { RTLIB::OGE_F64, "__mips16_gedf2" },
-  { RTLIB::OGE_F32, "__mips16_gesf2" },
-  { RTLIB::OGT_F64, "__mips16_gtdf2" },
-  { RTLIB::OGT_F32, "__mips16_gtsf2" },
-  { RTLIB::OLE_F64, "__mips16_ledf2" },
-  { RTLIB::OLE_F32, "__mips16_lesf2" },
-  { RTLIB::OLT_F64, "__mips16_ltdf2" },
-  { RTLIB::OLT_F32, "__mips16_ltsf2" },
-  { RTLIB::MUL_F64, "__mips16_muldf3" },
-  { RTLIB::MUL_F32, "__mips16_mulsf3" },
-  { RTLIB::UNE_F64, "__mips16_nedf2" },
-  { RTLIB::UNE_F32, "__mips16_nesf2" },
-  { RTLIB::UNKNOWN_LIBCALL, "__mips16_ret_dc" }, // No associated libcall.
-  { RTLIB::UNKNOWN_LIBCALL, "__mips16_ret_df" }, // No associated libcall.
-  { RTLIB::UNKNOWN_LIBCALL, "__mips16_ret_sc" }, // No associated libcall.
-  { RTLIB::UNKNOWN_LIBCALL, "__mips16_ret_sf" }, // No associated libcall.
-  { RTLIB::SUB_F64, "__mips16_subdf3" },
-  { RTLIB::SUB_F32, "__mips16_subsf3" },
-  { RTLIB::FPROUND_F64_F32, "__mips16_truncdfsf2" },
-  { RTLIB::UO_F64, "__mips16_unorddf2" },
-  { RTLIB::UO_F32, "__mips16_unordsf2" }
-};
+    {RTLIB::ADD_F64, RTLIB::__mips16_adddf3, "__mips16_adddf3"},
+    {RTLIB::ADD_F32, RTLIB::__mips16_addsf3, "__mips16_addsf3"},
+    {RTLIB::DIV_F64, RTLIB::__mips16_divdf3, "__mips16_divdf3"},
+    {RTLIB::DIV_F32, RTLIB::__mips16_divsf3, "__mips16_divsf3"},
+    {RTLIB::OEQ_F64, RTLIB::__mips16_eqdf2, "__mips16_eqdf2"},
+    {RTLIB::OEQ_F32, RTLIB::__mips16_eqsf2, "__mips16_eqsf2"},
+    {RTLIB::FPEXT_F32_F64, RTLIB::__mips16_extendsfdf2, "__mips16_extendsfdf2"},
+    {RTLIB::FPTOSINT_F64_I32, RTLIB::__mips16_fix_truncdfsi,
+     "__mips16_fix_truncdfsi"},
+    {RTLIB::FPTOSINT_F32_I32, RTLIB::__mips16_fix_truncsfsi,
+     "__mips16_fix_truncsfsi"},
+    {RTLIB::SINTTOFP_I32_F64, RTLIB::__mips16_floatsidf, "__mips16_floatsidf"},
+    {RTLIB::SINTTOFP_I32_F32, RTLIB::__mips16_floatsisf, "__mips16_floatsisf"},
+    {RTLIB::UINTTOFP_I32_F64, RTLIB::__mips16_floatunsidf,
+     "__mips16_floatunsidf"},
+    {RTLIB::UINTTOFP_I32_F32, RTLIB::__mips16_floatunsisf,
+     "__mips16_floatunsisf"},
+    {RTLIB::OGE_F64, RTLIB::__mips16_gedf2, "__mips16_gedf2"},
+    {RTLIB::OGE_F32, RTLIB::__mips16_gesf2, "__mips16_gesf2"},
+    {RTLIB::OGT_F64, RTLIB::__mips16_gtdf2, "__mips16_gtdf2"},
+    {RTLIB::OGT_F32, RTLIB::__mips16_gtsf2, "__mips16_gtsf2"},
+    {RTLIB::OLE_F64, RTLIB::__mips16_ledf2, "__mips16_ledf2"},
+    {RTLIB::OLE_F32, RTLIB::__mips16_lesf2, "__mips16_lesf2"},
+    {RTLIB::OLT_F64, RTLIB::__mips16_ltdf2, "__mips16_ltdf2"},
+    {RTLIB::OLT_F32, RTLIB::__mips16_ltsf2, "__mips16_ltsf2"},
+    {RTLIB::MUL_F64, RTLIB::__mips16_muldf3, "__mips16_muldf3"},
+    {RTLIB::MUL_F32, RTLIB::__mips16_mulsf3, "__mips16_mulsf3"},
+    {RTLIB::UNE_F64, RTLIB::__mips16_nedf2, "__mips16_nedf2"},
+    {RTLIB::UNE_F32, RTLIB::__mips16_nesf2, "__mips16_nesf2"},
+    {RTLIB::UNKNOWN_LIBCALL, RTLIB::__mips16_ret_dc,
+     "__mips16_ret_dc"}, // No associated libcall.
+    {RTLIB::UNKNOWN_LIBCALL, RTLIB::__mips16_ret_df,
+     "__mips16_ret_df"}, // No associated libcall.
+    {RTLIB::UNKNOWN_LIBCALL, RTLIB::__mips16_ret_sc,
+     "__mips16_ret_sc"}, // No associated libcall.
+    {RTLIB::UNKNOWN_LIBCALL, RTLIB::__mips16_ret_sf,
+     "__mips16_ret_sf"}, // No associated libcall.
+    {RTLIB::SUB_F64, RTLIB::__mips16_subdf3, "__mips16_subdf3"},
+    {RTLIB::SUB_F32, RTLIB::__mips16_subsf3, "__mips16_subsf3"},
+    {RTLIB::FPROUND_F64_F32, RTLIB::__mips16_truncdfsf2, "__mips16_truncdfsf2"},
+    {RTLIB::UO_F64, RTLIB::__mips16_unorddf2, "__mips16_unorddf2"},
+    {RTLIB::UO_F32, RTLIB::__mips16_unordsf2, "__mips16_unordsf2"}};
 
 static const Mips16IntrinsicHelperType Mips16IntrinsicHelper[] = {
   {"__fixunsdfsi", "__mips16_call_stub_2" },
@@ -250,7 +258,7 @@ void Mips16TargetLowering::setMips16HardFloatLibCalls() {
     assert((I == 0 || HardFloatLibCalls[I - 1] < HardFloatLibCalls[I]) &&
            "Array not sorted!");
     if (HardFloatLibCalls[I].Libcall != RTLIB::UNKNOWN_LIBCALL)
-      setLibcallName(HardFloatLibCalls[I].Libcall, HardFloatLibCalls[I].Name);
+      setLibcallImpl(HardFloatLibCalls[I].Libcall, HardFloatLibCalls[I].Impl);
   }
 }
 
@@ -425,7 +433,8 @@ getOpndList(SmallVectorImpl<SDValue> &Ops,
     //
     bool LookupHelper = true;
     if (ExternalSymbolSDNode *S = dyn_cast<ExternalSymbolSDNode>(CLI.Callee)) {
-      Mips16Libcall Find = { RTLIB::UNKNOWN_LIBCALL, S->getSymbol() };
+      Mips16Libcall Find = {RTLIB::UNKNOWN_LIBCALL, RTLIB::Unsupported,
+                            S->getSymbol()};
 
       if (llvm::binary_search(HardFloatLibCalls, Find))
         LookupHelper = false;
@@ -465,8 +474,8 @@ getOpndList(SmallVectorImpl<SDValue> &Ops,
       }
     } else if (GlobalAddressSDNode *G =
                    dyn_cast<GlobalAddressSDNode>(CLI.Callee)) {
-      Mips16Libcall Find = { RTLIB::UNKNOWN_LIBCALL,
-                             G->getGlobal()->getName().data() };
+      Mips16Libcall Find = {RTLIB::UNKNOWN_LIBCALL, RTLIB::Unsupported,
+                            G->getGlobal()->getName().data()};
 
       if (llvm::binary_search(HardFloatLibCalls, Find))
         LookupHelper = false;
diff --git a/llvm/lib/Target/Sparc/SparcISelLowering.cpp b/llvm/lib/Target/Sparc/SparcISelLowering.cpp
index 7abe84a2451b9..392d16883d990 100644
--- a/llvm/lib/Target/Sparc/SparcISelLowering.cpp
+++ b/llvm/lib/Target/Sparc/SparcISelLowering.cpp
@@ -1835,16 +1835,16 @@ SparcTargetLowering::SparcTargetLowering(const TargetMachine &TM,
     // .umul works for both signed and unsigned
     setOperationAction(ISD::SMUL_LOHI, MVT::i32, Expand);
     setOperationAction(ISD::UMUL_LOHI, MVT::i32, Expand);
-    setLibcallName(RTLIB::MUL_I32, ".umul");
+    setLibcallImpl(RTLIB::MUL_I32, RTLIB::sparc_umul);
 
     setOperationAction(ISD::SDIV, MVT::i32, Expand);
-    setLibcallName(RTLIB::SDIV_I32, ".div");
+    setLibcallImpl(RTLIB::SDIV_I32, RTLIB::sparc_div);
 
     setOperationAction(ISD::UDIV, MVT::i32, Expand);
-    setLibcallName(RTLIB::UDIV_I32, ".udiv");
+    setLibcallImpl(RTLIB::UDIV_I32, RTLIB::sparc_udiv);
 
-    setLibcallName(RTLIB::SREM_I32, ".rem");
-    setLibcallName(RTLIB::UREM_I32, ".urem");
+    setLibcallImpl(RTLIB::SREM_I32, RTLIB::sparc_rem);
+    setLibcallImpl(RTLIB::UREM_I32, RTLIB::sparc_urem);
   }
 
   if (Subtarget->is64Bit()) {
@@ -1905,10 +1905,10 @@ SparcTargetLowering::SparcTargetLowering(const TargetMachine &TM,
     }
 
     if (!Subtarget->is64Bit()) {
-      setLibcallName(RTLIB::FPTOSINT_F128_I64, "_Q_qtoll");
-      setLibcallName(RTLIB::FPTOUINT_F128_I64, "_Q_qtoull");
-      setLibcallName(RTLIB::SINTTOFP_I64_F128, "_Q_lltoq");
-      setLibcallName(RTLIB::UINTTOFP_I64_F128, "_Q_ulltoq");
+      setLibcallImpl(RTLIB::FPTOSINT_F128_I64, RTLIB::_Q_qtoll);
+      setLibcallImpl(RTLIB::FPTOUINT_F128_I64, RTLIB::_Q_qtoull);
+      setLibcallImpl(RTLIB::SINTTOFP_I64_F128, RTLIB::_Q_lltoq);
+      setLibcallImpl(RTLIB::UINTTOFP_I64_F128, RTLIB::_Q_ulltoq);
     }
 
   } else {
@@ -1928,41 +1928,41 @@ SparcTargetLowering::SparcTargetLowering(const TargetMachine &TM,
 
     // Setup Runtime library names.
     if (Subtarget->is64Bit() && !Subtarget->useSoftFloat()) {
-      setLibcallName(RTLIB::ADD_F128,  "_Qp_add");
-      setLibcallName(RTLIB::SUB_F128,  "_Qp_sub");
-      setLibcallName(RTLIB::MUL_F128,  "_Qp_mul");
-      setLibcallName(RTLIB::DIV_F128,  "_Qp_div");
-      setLibcallName(RTLIB::SQRT_F128, "_Qp_sqrt");
-      setLibcallName(RTLIB::FPTOSINT_F128_I32, "_Qp_qtoi");
-      setLibcallName(RTLIB::FPTOUINT_F128_I32, "_Qp_qtoui");
-      setLibcallName(RTLIB::SINTTOFP_I32_F128, "_Qp_itoq");
-      setLibcallName(RTLIB::UINTTOFP_I32_F128, "_Qp_uitoq");
-      setLibcallName(RTLIB::FPTOSINT_F128_I64, "_Qp_qtox");
-      setLibcallName(RTLIB::FPTOUINT_F128_I64, "_Qp_qtoux");
-      setLibcallName(RTLIB::SINTTOFP_I64_F128, "_Qp_xtoq");
-      setLibcallName(RTLIB::UINTTOFP_I64_F128, "_Qp_uxtoq");
-      setLibcallName(RTLIB::FPEXT_F32_F128, "_Qp_stoq");
-      setLibcallName(RTLIB::FPEXT_F64_F128, "_Qp_dtoq");
-      setLibcallName(RTLIB::FPROUND_F128_F32, "_Qp_qtos");
-      setLibcallName(RTLIB::FPROUND_F128_F64, "_Qp_qtod");
+      setLibcallImpl(RTLIB::ADD_F128, RTLIB::_Qp_add);
+      setLibcallImpl(RTLIB::SUB_F128, RTLIB::_Qp_sub);
+      setLibcallImpl(RTLIB::MUL_F128, RTLIB::_Qp_mul);
+      setLibcallImpl(RTLIB::DIV_F128, RTLIB::_Qp_div);
+      setLibcallImpl(RTLIB::SQRT_F128, RTLIB::_Qp_sqrt);
+      setLibcallImpl(RTLIB::FPTOSINT_F128_I32, RTLIB::_Qp_qtoi);
+      setLibcallImpl(RTLIB::FPTOUINT_F128_I32, RTLIB::_Qp_qtoui);
+      setLibcallImpl(RTLIB::SINTTOFP_I32_F128, RTLIB::_Qp_itoq);
+      setLibcallImpl(RTLIB::UINTTOFP_I32_F128, RTLIB::_Qp_uitoq);
+      setLibcallImpl(RTLIB::FPTOSINT_F128_I64, RTLIB::_Qp_qtox);
+      setLibcallImpl(RTLIB::FPTOUINT_F128_I64, RTLIB::_Qp_qtoux);
+      setLibcallImpl(RTLIB::SINTTOFP_I64_F128, RTLIB::_Qp_xtoq);
+      setLibcallImpl(RTLIB::UINTTOFP_I64_F128, RTLIB::_Qp_uxtoq);
+      setLibcallImpl(RTLIB::FPEXT_F32_F128, RTLIB::_Qp_stoq);
+      setLibcallImpl(RTLIB::FPEXT_F64_F128, RTLIB::_Qp_dtoq);
+      setLibcallImpl(RTLIB::FPROUND_F128_F32, RTLIB::_Qp_qtos);
+      setLibcallImpl(RTLIB::FPROUND_F128_F64, RTLIB::_Qp_qtod);
     } else if (!Subtarget->useSoftFloat()) {
-      setLibcallName(RTLIB::ADD_F128,  "_Q_add");
-      setLibcallName(RTLIB::SUB_F128,  "_Q_sub");
-      setLibcallName(RTLIB::MUL_F128,  "_Q_mul");
-      setLibcallName(RTLIB::DIV_F128,  "_Q_div");
-      setLibcallName(RTLIB::SQRT_F128, "_Q_sqrt");
-      setLibcallName(RTLIB::FPTOSINT_F128_I32, "_Q_qtoi");
-      setLibcallName(RTLIB::FPTOUINT_F128_I32, "_Q_qtou");
-      setLibcallName(RTLIB::SINTTOFP_I32_F128, "_Q_itoq");
-      setLibcallName(RTLIB::UINTTOFP_I32_F128, "_Q_utoq");
-      setLibcallName(RTLIB::FPTOSINT_F128_I64, "_Q_qtoll");
-      setLibcallName(RTLIB::FPTOUINT_F128_I64, "_Q_qtoull");
-      setLibcallName(RTLIB::SINTTOFP_I64_F128, "_Q_lltoq");
-      setLibcallName(RTLIB::UINTTOFP_I64_F128, "_Q_ulltoq");
-      setLibcallName(RTLIB::FPEXT_F32_F128, "_Q_stoq");
-      setLibcallName(RTLIB::FPEXT_F64_F128, "_Q_dtoq");
-      setLibcallName(RTLIB::FPROUND_F128_F32, "_Q_qtos");
-      setLibcallName(RTLIB::FPROUND_F128_F64, "_Q_qtod");
+      setLibcallImpl(RTLIB::ADD_F128, RTLIB::_Q_add);
+      setLibcallImpl(RTLIB::SUB_F128, RTLIB::_Q_sub);
+      setLibcallImpl(RTLIB::MUL_F128, RTLIB::_Q_mul);
+      setLibcallImpl(RTLIB::DIV_F128, RTLIB::_Q_div);
+      setLibcallImpl(RTLIB::SQRT_F128, RTLIB::_Q_sqrt);
+      setLibcallImpl(RTLIB::FPTOSINT_F128_I32, RTLIB::_Q_qtoi);
+      setLibcallImpl(RTLIB::FPTOUINT_F128_I32, RTLIB::_Q_qtou);
+      setLibcallImpl(RTLIB::SINTTOFP_I32_F128, RTLIB::_Q_itoq);
+      setLibcallImpl(RTLIB::UINTTOFP_I32_F128, RTLIB::_Q_utoq);
+      setLibcallImpl(RTLIB::FPTOSINT_F128_I64, RTLIB::_Q_qtoll);
+      setLibcallImpl(RTLIB::FPTOUINT_F128_I64, RTLIB::_Q_qtoull);
+      setLibcallImpl(RTLIB::SINTTOFP_I64_F128, RTLIB::_Q_lltoq);
+      setLibcallImpl(RTLIB::UINTTOFP_I64_F128, RTLIB::_Q_ulltoq);
+      setLibcallImpl(RTLIB::FPEXT_F32_F128, RTLIB::_Q_stoq);
+      setLibcallImpl(RTLIB::FPEXT_F64_F128, RTLIB::_Q_dtoq);
+      setLibcallImpl(RTLIB::FPROUND_F128_F32, RTLIB::_Q_qtos);
+      setLibcallImpl(RTLIB::FPROUND_F128_F64, RTLIB::_Q_qtod);
     }
   }
 
diff --git a/llvm/test/TableGen/RuntimeLibcallEmitter.td b/llvm/test/TableGen/RuntimeLibcallEmitter.td
index 8f66bedf860c8..d4030dd0a7e95 100644
--- a/llvm/test/TableGen/RuntimeLibcallEmitter.td
+++ b/llvm/test/TableGen/RuntimeLibcallEmitter.td
@@ -5,12 +5,18 @@ include "llvm/IR/RuntimeLibcallsImpl.td"
 
 def SHL_I32 : RuntimeLibcall;
 def SRL_I64 : RuntimeLibcall;
+
+def SQRT_F128 : RuntimeLibcall;
+def SQRT_F80 : RuntimeLibcall;
 def BZERO : RuntimeLibcall;
 
 // Test default names.
 let IsDefault = true in {
   def __ashlsi3 : RuntimeLibcallImpl<SHL_I32>;
   def __lshrdi3 : RuntimeLibcallImpl<SRL_I64>;
+
+  def sqrtl_f128 : RuntimeLibcallImpl<SQRT_F128, "sqrtl">;
+  def sqrtl_f80 : RuntimeLibcallImpl<SQRT_F80, "sqrtl">;
 }
 
 // Ignore non-default in initDefaultLibCallNames.
@@ -20,21 +26,52 @@ def bzero : RuntimeLibcallImpl<BZERO>;
 // CHECK: #ifdef GET_RUNTIME_LIBCALL_ENUM
 // CHECK-NEXT: namespace llvm {
 // CHECK-NEXT: namespace RTLIB {
-// CHECK-NEXT: enum Libcall {
+// CHECK-NEXT: enum Libcall : unsigned short {
 // CHECK-NEXT: BZERO = 0,
 // CHECK-NEXT: SHL_I32 = 1,
-// CHECK-NEXT: SRL_I64 = 2,
-// CHECK-NEXT: UNKNOWN_LIBCALL = 3
+// CHECK-NEXT: SQRT_F80 = 2,
+// CHECK-NEXT: SQRT_F128 = 3,
+// CHECK-NEXT: SRL_I64 = 4,
+// CHECK-NEXT: UNKNOWN_LIBCALL = 5
 // CHECK-NEXT: };
 // CHECK-EMPTY:
+// CHECK-NEXT:enum LibcallImpl : unsigned short {
+// CHECK-NEXT:  Unsupported = 0,
+// CHECK-NEXT:  __ashlsi3 = 1, // __ashlsi3
+// CHECK-NEXT:  __lshrdi3 = 2, // __lshrdi3
+// CHECK-NEXT:  bzero = 3, // bzero
+// CHECK-NEXT:  sqrtl_f80 = 4, // sqrtl
+// CHECK-NEXT:  sqrtl_f128 = 5, // sqrtl
+// CHECK-NEXT:  NumLibcallImpls = 6
+// CHECK-NEXT: };
 // CHECK-NEXT: } // End namespace RTLIB
 // CHECK-NEXT: } // End namespace llvm
 // CHECK-NEXT: #endif
 
 // CHECK: #ifdef GET_INIT_RUNTIME_LIBCALL_NAMES
-// CHECK-NEXT: const char *const llvm::RTLIB::RuntimeLibcallsInfo::DefaultLibcallRoutineNames[RTLIB::UNKNOWN_LIBCALL + 1] = {
-// CHECK-NEXT: nullptr, // RTLIB::BZERO
-// CHECK-NEXT: "__ashlsi3", // RTLIB::SHL_I32
-// CHECK-NEXT: "__lshrdi3", // RTLIB::SRL_I64
-// CHECK-NEXT: nullptr // RTLIB::UNKNOWN_LIBCALL
+// CHECK-NEXT: const RTLIB::LibcallImpl llvm::RTLIB::RuntimeLibcallsInfo::DefaultLibcallImpls[RTLIB::UNKNOWN_LIBCALL + 1] = {
+// CHECK-NEXT:   RTLIB::Unsupported, // RTLIB::BZERO
+// CHECK-NEXT:   RTLIB::__ashlsi3, // RTLIB::SHL_I32
+// CHECK-NEXT:   RTLIB::sqrtl_f80, // RTLIB::SQRT_F80
+// CHECK-NEXT:   RTLIB::sqrtl_f128, // RTLIB::SQRT_F128
+// CHECK-NEXT:   RTLIB::__lshrdi3, // RTLIB::SRL_I64
+// CHECK-NEXT:   RTLIB::Unsupported
+// CHECK-NEXT: };
+// CHECK-EMPTY:
+// CHECK-NEXT: const char *const llvm::RTLIB::RuntimeLibcallsInfo::LibCallImplNames[RTLIB::NumLibcallImpls] = {
+// CHECK-NEXT: nullptr, // RTLIB::Unsupported
+// CHECK-NEXT: "__ashlsi3", // RTLIB::__ashlsi3
+// CHECK-NEXT: "__lshrdi3", // RTLIB::__lshrdi3
+// CHECK-NEXT: "bzero", // RTLIB::bzero
+// CHECK-NEXT: "sqrtl", // RTLIB::sqrtl_f80
+// CHECK-NEXT: "sqrtl", // RTLIB::sqrtl_f128
+// CHECK-NEXT: };
+
+// CHECK: const RTLIB::Libcall llvm::RTLIB::RuntimeLibcallsInfo::ImplToLibcall[RTLIB::NumLibcallImpls] = {
+// CHECK-NEXT: RTLIB::UNKNOWN_LIBCALL, // RTLIB::Unsupported
+// CHECK-NEXT: RTLIB::SHL_I32, // RTLIB::__ashlsi3
+// CHECK-NEXT: RTLIB::SRL_I64, // RTLIB::__lshrdi3
+// CHECK-NEXT: RTLIB::BZERO, // RTLIB::bzero
+// CHECK-NEXT: RTLIB::SQRT_F80, // RTLIB::sqrtl_f80
+// CHECK-NEXT: RTLIB::SQRT_F128, // RTLIB::sqrtl_f128
 // CHECK-NEXT: };
diff --git a/llvm/utils/TableGen/Basic/RuntimeLibcallsEmitter.cpp b/llvm/utils/TableGen/Basic/RuntimeLibcallsEmitter.cpp
index 2691437e22edb..9d77631862ee5 100644
--- a/llvm/utils/TableGen/Basic/RuntimeLibcallsEmitter.cpp
+++ b/llvm/utils/TableGen/Basic/RuntimeLibcallsEmitter.cpp
@@ -165,10 +165,10 @@ void RuntimeLibcallEmitter::emitTargetOverrideFunc(
     // for (const Record *LibCallImpl : LibCallImplList) {
     for (const RuntimeLibcallImpl &LibCallImpl : LibCallImplList) {
       const RuntimeLibcall *Provides = LibCallImpl.getProvides();
-      OS << "  LibcallRoutineNames[";
+      OS << "  LibcallImpls[";
       Provides->emitEnumEntry(OS);
       OS << "] = ";
-      LibCallImpl.emitQuotedLibcallFuncName(OS);
+      LibCallImpl.emitEnumEntry(OS);
       OS << ";\n";
     }
   }
@@ -180,7 +180,7 @@ void RuntimeLibcallEmitter::emitGetRuntimeLibcallEnum(raw_ostream &OS) const {
   OS << "#ifdef GET_RUNTIME_LIBCALL_ENUM\n"
         "namespace llvm {\n"
         "namespace RTLIB {\n"
-        "enum Libcall {\n";
+        "enum Libcall : unsigned short {\n";
 
   size_t CallTypeEnumVal = 0;
   for (const RuntimeLibcall &LibCall : RuntimeLibcallDefList) {
@@ -192,6 +192,18 @@ void RuntimeLibcallEmitter::emitGetRuntimeLibcallEnum(raw_ostream &OS) const {
 
   OS << "  UNKNOWN_LIBCALL = " << CallTypeEnumVal
      << "\n};\n\n"
+        "enum LibcallImpl : unsigned short {\n"
+        "  Unsupported = 0,\n";
+
+  // FIXME: Emit this in a different namespace. And maybe use enum class.
+  size_t LibCallImplEnumVal = 1;
+  for (const RuntimeLibcallImpl &LibCall : RuntimeLibcallImplDefList) {
+    OS << "  " << LibCall.getName() << " = " << LibCallImplEnumVal++ << ", // "
+       << LibCall.getLibcallFuncName() << '\n';
+  }
+
+  OS << "  NumLibcallImpls = " << LibCallImplEnumVal
+     << "\n};\n"
         "} // End namespace RTLIB\n"
         "} // End namespace llvm\n"
         "#endif\n\n";
@@ -203,16 +215,16 @@ void RuntimeLibcallEmitter::emitWindowsArm64LibCallNameOverrides(
   OS << "void "
         "llvm::RTLIB::RuntimeLibcallsInfo::setWindowsArm64LibCallNameOverrides("
         ") {\n"
-        "  static const char *const "
-        "WindowsArm64RoutineNames[RTLIB::UNKNOWN_LIBCALL + 1] = {\n";
+        "  static const RTLIB::LibcallImpl "
+        "WindowsArm64RoutineImpls[RTLIB::UNKNOWN_LIBCALL + 1] = {\n";
   for (const RuntimeLibcall &LibCall : RuntimeLibcallDefList) {
     auto I = LibCallToDefaultImpl.find(&LibCall);
     if (I == LibCallToDefaultImpl.end())
-      OS << "    nullptr,";
+      OS << "    RTLIB::Unsupported,";
     else {
       const RuntimeLibcallImpl *LibCallImpl = I->second;
       assert(LibCallImpl);
-      OS << "    \"#" << LibCallImpl->getLibcallFuncName() << "\",";
+      OS << "    RTLIB::arm64ec_" << LibCallImpl->getName() << ',';
     }
 
     OS << " // ";
@@ -220,12 +232,12 @@ void RuntimeLibcallEmitter::emitWindowsArm64LibCallNameOverrides(
     OS << '\n';
   }
 
-  OS << "    nullptr // RTLIB::UNKNOWN_LIBCALL\n"
+  OS << "    RTLIB::Unsupported // RTLIB::UNKNOWN_LIBCALL\n"
         "  };\n\n"
-        "  std::memcpy(LibcallRoutineNames, WindowsArm64RoutineNames,\n"
-        "              sizeof(LibcallRoutineNames));\n"
-        "  static_assert(sizeof(LibcallRoutineNames) == "
-        "sizeof(WindowsArm64RoutineNames),\n"
+        "  std::memcpy(LibcallImpls, WindowsArm64RoutineImpls,\n"
+        "              sizeof(LibcallImpls));\n"
+        "  static_assert(sizeof(LibcallImpls) == "
+        "sizeof(WindowsArm64RoutineImpls),\n"
         "                \"libcall array size should match\");\n"
         "}\n#endif\n\n";
 }
@@ -235,19 +247,19 @@ void RuntimeLibcallEmitter::emitGetInitRuntimeLibcallNames(
   // TODO: Emit libcall names as string offset table.
 
   OS << "#ifdef GET_INIT_RUNTIME_LIBCALL_NAMES\n"
-        "const char *const "
+        "const RTLIB::LibcallImpl "
         "llvm::RTLIB::RuntimeLibcallsInfo::"
-        "DefaultLibcallRoutineNames[RTLIB::UNKNOWN_LIBCALL + 1] = {\n";
+        "DefaultLibcallImpls[RTLIB::UNKNOWN_LIBCALL + 1] = {\n";
 
   for (const RuntimeLibcall &LibCall : RuntimeLibcallDefList) {
     auto I = LibCallToDefaultImpl.find(&LibCall);
-    if (I == LibCallToDefaultImpl.end())
-      OS << "  nullptr,";
-    else {
+    if (I == LibCallToDefaultImpl.end()) {
+      OS << "  RTLIB::Unsupported,";
+    } else {
       const RuntimeLibcallImpl *LibCallImpl = I->second;
       OS << "  ";
-      LibCallImpl->emitQuotedLibcallFuncName(OS);
-      OS << ',';
+      LibCallImpl->emitEnumEntry(OS);
+      OS << ",";
     }
 
     OS << " // ";
@@ -255,9 +267,37 @@ void RuntimeLibcallEmitter::emitGetInitRuntimeLibcallNames(
     OS << '\n';
   }
 
-  OS << "  nullptr // RTLIB::UNKNOWN_LIBCALL\n"
+  OS << "  RTLIB::Unsupported\n"
         "};\n\n";
 
+  // Emit the implementation names
+  OS << "const char *const llvm::RTLIB::RuntimeLibcallsInfo::"
+        "LibCallImplNames[RTLIB::NumLibcallImpls] = {\n"
+        "  nullptr, // RTLIB::Unsupported\n";
+
+  for (const RuntimeLibcallImpl &LibCallImpl : RuntimeLibcallImplDefList) {
+    OS << "  \"" << LibCallImpl.getLibcallFuncName() << "\", // ";
+    LibCallImpl.emitEnumEntry(OS);
+    OS << '\n';
+  }
+
+  OS << "};\n\n";
+
+  // Emit the reverse mapping from implementation libraries to RTLIB::Libcall
+  OS << "const RTLIB::Libcall llvm::RTLIB::RuntimeLibcallsInfo::"
+        "ImplToLibcall[RTLIB::NumLibcallImpls] = {\n"
+        "  RTLIB::UNKNOWN_LIBCALL, // RTLIB::Unsupported\n";
+
+  for (const RuntimeLibcallImpl &LibCallImpl : RuntimeLibcallImplDefList) {
+    const RuntimeLibcall *Provides = LibCallImpl.getProvides();
+    OS << "  ";
+    Provides->emitEnumEntry(OS);
+    OS << ", // ";
+    LibCallImpl.emitEnumEntry(OS);
+    OS << '\n';
+  }
+  OS << "};\n\n";
+
   std::vector<RuntimeLibcallImpl> ZOSRuntimeLibcallImplList =
       getRuntimeLibcallImplSet("ZOSRuntimeLibcallImpl");
   emitTargetOverrideFunc(OS, "setZOSLibCallNameOverrides",



More information about the llvm-branch-commits mailing list