Skip to content

RuntimeLibcalls: Associate calling convention with libcall impls #144979

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: users/arsenm/tablegen/define-runtime-libcall-sets-tablegen
Choose a base branch
from

Conversation

arsenm
Copy link
Contributor

@arsenm arsenm commented Jun 20, 2025

Instead of associating the libcall with the RTLIB::Libcall, put it
into a table indexed by the RTLIB::LibcallImpl. The LibcallImpls
should contain all ABI details for a particular implementation, not
the abstract Libcall. In the future the wrappers in terms of the
RTLIB::Libcall should be removed.

Copy link
Contributor Author

arsenm commented Jun 20, 2025

@llvmbot
Copy link
Member

llvmbot commented Jun 20, 2025

@llvm/pr-subscribers-backend-arm
@llvm/pr-subscribers-backend-msp430

@llvm/pr-subscribers-llvm-ir

Author: Matt Arsenault (arsenm)

Changes

Instead of associating the libcall with the RTLIB::Libcall, put it
into a table indexed by the RTLIB::LibcallImpl. The LibcallImpls
should contain all ABI details for a particular implementation, not
the abstract Libcall. In the future the wrappers in terms of the
RTLIB::Libcall should be removed.


Full diff: https://github.com/llvm/llvm-project/pull/144979.diff

6 Files Affected:

  • (modified) llvm/include/llvm/CodeGen/TargetLowering.h (+14-2)
  • (modified) llvm/include/llvm/IR/RuntimeLibcalls.h (+23-9)
  • (modified) llvm/lib/IR/RuntimeLibcalls.cpp (+42-28)
  • (modified) llvm/lib/Target/ARM/ARMISelLowering.cpp (+15-9)
  • (modified) llvm/lib/Target/Lanai/LanaiISelLowering.cpp (+2-2)
  • (modified) llvm/lib/Target/MSP430/MSP430ISelLowering.cpp (+2-1)
diff --git a/llvm/include/llvm/CodeGen/TargetLowering.h b/llvm/include/llvm/CodeGen/TargetLowering.h
index 69ae4f80297d5..fa08eb64642de 100644
--- a/llvm/include/llvm/CodeGen/TargetLowering.h
+++ b/llvm/include/llvm/CodeGen/TargetLowering.h
@@ -3562,6 +3562,11 @@ class LLVM_ABI TargetLoweringBase {
     Libcalls.setLibcallImpl(Call, Impl);
   }
 
+  /// Get the libcall impl routine name for the specified libcall.
+  RTLIB::LibcallImpl getLibcallImpl(RTLIB::Libcall Call) const {
+    return Libcalls.getLibcallImpl(Call);
+  }
+
   /// Get the libcall routine name for the specified libcall.
   const char *getLibcallName(RTLIB::Libcall Call) const {
     return Libcalls.getLibcallName(Call);
@@ -3584,11 +3589,18 @@ class LLVM_ABI TargetLoweringBase {
   }
 
   /// Set the CallingConv that should be used for the specified libcall.
-  void setLibcallCallingConv(RTLIB::Libcall Call, CallingConv::ID CC) {
-    Libcalls.setLibcallCallingConv(Call, CC);
+  void setLibcallImplCallingConv(RTLIB::LibcallImpl Call, CallingConv::ID CC) {
+    Libcalls.setLibcallImplCallingConv(Call, CC);
+  }
+
+  /// Get the CallingConv that should be used for the specified libcall
+  /// implementation.
+  CallingConv::ID getLibcallImplCallingConv(RTLIB::LibcallImpl Call) const {
+    return Libcalls.getLibcallImplCallingConv(Call);
   }
 
   /// Get the CallingConv that should be used for the specified libcall.
+  // FIXME: Remove this wrapper and directly use the used LibcallImpl
   CallingConv::ID getLibcallCallingConv(RTLIB::Libcall Call) const {
     return Libcalls.getLibcallCallingConv(Call);
   }
diff --git a/llvm/include/llvm/IR/RuntimeLibcalls.h b/llvm/include/llvm/IR/RuntimeLibcalls.h
index d69c23753da7a..dce16ab99171f 100644
--- a/llvm/include/llvm/IR/RuntimeLibcalls.h
+++ b/llvm/include/llvm/IR/RuntimeLibcalls.h
@@ -37,6 +37,10 @@ template <> struct enum_iteration_traits<RTLIB::Libcall> {
   static constexpr bool is_iterable = true;
 };
 
+template <> struct enum_iteration_traits<RTLIB::LibcallImpl> {
+  static constexpr bool is_iterable = true;
+};
+
 namespace RTLIB {
 
 // Return an iterator over all Libcall values.
@@ -44,6 +48,10 @@ static inline auto libcalls() {
   return enum_seq(static_cast<RTLIB::Libcall>(0), RTLIB::UNKNOWN_LIBCALL);
 }
 
+static inline auto libcall_impls() {
+  return enum_seq(static_cast<RTLIB::LibcallImpl>(1), RTLIB::NumLibcallImpls);
+}
+
 /// A simple container for information about the supported runtime calls.
 struct RuntimeLibcallsInfo {
   explicit RuntimeLibcallsInfo(
@@ -76,16 +84,21 @@ struct RuntimeLibcallsInfo {
     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;
+  /// Set the CallingConv that should be used for the specified libcall
+  /// implementation
+  void setLibcallImplCallingConv(RTLIB::LibcallImpl Call, CallingConv::ID CC) {
+    LibcallImplCallingConvs[Call] = CC;
   }
 
-  /// Get the CallingConv that should be used for the specified libcall.
-  // FIXME: This should be a function of RTLIB::LibcallImpl
+  // FIXME: Remove this wrapper in favor of directly using
+  // getLibcallImplCallingConv
   CallingConv::ID getLibcallCallingConv(RTLIB::Libcall Call) const {
-    return LibcallCallingConvs[Call];
+    return LibcallImplCallingConvs[LibcallImpls[Call]];
+  }
+
+  /// Get the CallingConv that should be used for the specified libcall.
+  CallingConv::ID getLibcallImplCallingConv(RTLIB::LibcallImpl Call) const {
+    return LibcallImplCallingConvs[Call];
   }
 
   ArrayRef<RTLIB::LibcallImpl> getLibcallImpls() const {
@@ -130,8 +143,9 @@ struct RuntimeLibcallsInfo {
   static_assert(static_cast<int>(CallingConv::C) == 0,
                 "default calling conv should be encoded as 0");
 
-  /// Stores the CallingConv that should be used for each libcall.
-  CallingConv::ID LibcallCallingConvs[RTLIB::UNKNOWN_LIBCALL] = {};
+  /// Stores the CallingConv that should be used for each libcall
+  /// implementation.;
+  CallingConv::ID LibcallImplCallingConvs[RTLIB::NumLibcallImpls] = {};
 
   /// The condition type that should be used to test the result of each of the
   /// soft floating-point comparison libcall against integer zero.
diff --git a/llvm/lib/IR/RuntimeLibcalls.cpp b/llvm/lib/IR/RuntimeLibcalls.cpp
index eaa2cf5100c77..9492aef16e638 100644
--- a/llvm/lib/IR/RuntimeLibcalls.cpp
+++ b/llvm/lib/IR/RuntimeLibcalls.cpp
@@ -29,8 +29,8 @@ static void setARMLibcallNames(RuntimeLibcallsInfo &Info, const Triple &TT,
     CallingConv::ID DefaultCC = FloatABIType == FloatABI::Hard
                                     ? CallingConv::ARM_AAPCS_VFP
                                     : CallingConv::ARM_AAPCS;
-    for (RTLIB::Libcall LC : RTLIB::libcalls())
-      Info.setLibcallCallingConv(LC, DefaultCC);
+    for (RTLIB::LibcallImpl LC : RTLIB::libcall_impls())
+      Info.setLibcallImplCallingConv(LC, DefaultCC);
   }
 
   // Register based DivRem for AEABI (RTABI 4.2)
@@ -50,7 +50,7 @@ static void setARMLibcallNames(RuntimeLibcallsInfo &Info, const Triple &TT,
 
       for (const auto &LC : LibraryCalls) {
         Info.setLibcallImpl(LC.Op, LC.Impl);
-        Info.setLibcallCallingConv(LC.Op, LC.CC);
+        Info.setLibcallImplCallingConv(LC.Impl, LC.CC);
       }
     } else {
       const struct {
@@ -66,7 +66,7 @@ static void setARMLibcallNames(RuntimeLibcallsInfo &Info, const Triple &TT,
 
       for (const auto &LC : LibraryCalls) {
         Info.setLibcallImpl(LC.Op, LC.Impl);
-        Info.setLibcallCallingConv(LC.Op, LC.CC);
+        Info.setLibcallImplCallingConv(LC.Impl, LC.CC);
       }
     }
   }
@@ -89,7 +89,7 @@ static void setARMLibcallNames(RuntimeLibcallsInfo &Info, const Triple &TT,
 
     for (const auto &LC : LibraryCalls) {
       Info.setLibcallImpl(LC.Op, LC.Impl);
-      Info.setLibcallCallingConv(LC.Op, LC.CC);
+      Info.setLibcallImplCallingConv(LC.Impl, LC.CC);
     }
   }
 
@@ -199,20 +199,34 @@ static void setMSP430Libcalls(RuntimeLibcallsInfo &Info, const Triple &TT) {
     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);
-  Info.setLibcallCallingConv(RTLIB::UREM_I64, CallingConv::MSP430_BUILTIN);
-  Info.setLibcallCallingConv(RTLIB::SDIV_I64, CallingConv::MSP430_BUILTIN);
-  Info.setLibcallCallingConv(RTLIB::SREM_I64, CallingConv::MSP430_BUILTIN);
-  Info.setLibcallCallingConv(RTLIB::ADD_F64, CallingConv::MSP430_BUILTIN);
-  Info.setLibcallCallingConv(RTLIB::SUB_F64, CallingConv::MSP430_BUILTIN);
-  Info.setLibcallCallingConv(RTLIB::MUL_F64, CallingConv::MSP430_BUILTIN);
-  Info.setLibcallCallingConv(RTLIB::DIV_F64, CallingConv::MSP430_BUILTIN);
-  Info.setLibcallCallingConv(RTLIB::OEQ_F64, CallingConv::MSP430_BUILTIN);
-  Info.setLibcallCallingConv(RTLIB::UNE_F64, CallingConv::MSP430_BUILTIN);
-  Info.setLibcallCallingConv(RTLIB::OGE_F64, CallingConv::MSP430_BUILTIN);
-  Info.setLibcallCallingConv(RTLIB::OLT_F64, CallingConv::MSP430_BUILTIN);
-  Info.setLibcallCallingConv(RTLIB::OLE_F64, CallingConv::MSP430_BUILTIN);
-  Info.setLibcallCallingConv(RTLIB::OGT_F64, CallingConv::MSP430_BUILTIN);
+  Info.setLibcallImplCallingConv(RTLIB::__mspabi_divull,
+                                 CallingConv::MSP430_BUILTIN);
+  Info.setLibcallImplCallingConv(RTLIB::__mspabi_remull,
+                                 CallingConv::MSP430_BUILTIN);
+  Info.setLibcallImplCallingConv(RTLIB::__mspabi_divlli,
+                                 CallingConv::MSP430_BUILTIN);
+  Info.setLibcallImplCallingConv(RTLIB::__mspabi_remlli,
+                                 CallingConv::MSP430_BUILTIN);
+  Info.setLibcallImplCallingConv(RTLIB::__mspabi_addd,
+                                 CallingConv::MSP430_BUILTIN);
+  Info.setLibcallImplCallingConv(RTLIB::__mspabi_subd,
+                                 CallingConv::MSP430_BUILTIN);
+  Info.setLibcallImplCallingConv(RTLIB::__mspabi_mpyd,
+                                 CallingConv::MSP430_BUILTIN);
+  Info.setLibcallImplCallingConv(RTLIB::__mspabi_divd,
+                                 CallingConv::MSP430_BUILTIN);
+  Info.setLibcallImplCallingConv(RTLIB::__mspabi_cmpd__oeq,
+                                 CallingConv::MSP430_BUILTIN);
+  Info.setLibcallImplCallingConv(RTLIB::__mspabi_cmpd__une,
+                                 CallingConv::MSP430_BUILTIN);
+  Info.setLibcallImplCallingConv(RTLIB::__mspabi_cmpd__oge,
+                                 CallingConv::MSP430_BUILTIN);
+  Info.setLibcallImplCallingConv(RTLIB::__mspabi_cmpd__olt,
+                                 CallingConv::MSP430_BUILTIN);
+  Info.setLibcallImplCallingConv(RTLIB::__mspabi_cmpd__ole,
+                                 CallingConv::MSP430_BUILTIN);
+  Info.setLibcallImplCallingConv(RTLIB::__mspabi_cmpd__ogt,
+                                 CallingConv::MSP430_BUILTIN);
 
   // TODO: __mspabi_srall, __mspabi_srlll, __mspabi_sllll
 }
@@ -361,10 +375,10 @@ void RuntimeLibcallsInfo::initLibcalls(const Triple &TT,
       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);
-        setLibcallCallingConv(RTLIB::SINCOS_STRET_F64,
-                              CallingConv::ARM_AAPCS_VFP);
+        setLibcallImplCallingConv(RTLIB::__sincosf_stret,
+                                  CallingConv::ARM_AAPCS_VFP);
+        setLibcallImplCallingConv(RTLIB::__sincos_stret,
+                                  CallingConv::ARM_AAPCS_VFP);
       }
     }
 
@@ -453,7 +467,7 @@ void RuntimeLibcallsInfo::initLibcalls(const Triple &TT,
 
     for (const auto &LC : LibraryCalls) {
       setLibcallImpl(LC.Op, LC.Impl);
-      setLibcallCallingConv(LC.Op, LC.CC);
+      setLibcallImplCallingConv(LC.Impl, LC.CC);
     }
   }
 
@@ -461,10 +475,10 @@ void RuntimeLibcallsInfo::initLibcalls(const Triple &TT,
     setARMLibcallNames(*this, TT, FloatABI, EABIVersion);
   else if (TT.getArch() == Triple::ArchType::avr) {
     // Several of the runtime library functions use a special calling conv
-    setLibcallCallingConv(RTLIB::SDIVREM_I8, CallingConv::AVR_BUILTIN);
-    setLibcallCallingConv(RTLIB::SDIVREM_I16, CallingConv::AVR_BUILTIN);
-    setLibcallCallingConv(RTLIB::UDIVREM_I8, CallingConv::AVR_BUILTIN);
-    setLibcallCallingConv(RTLIB::UDIVREM_I16, CallingConv::AVR_BUILTIN);
+    setLibcallImplCallingConv(RTLIB::__divmodqi4, CallingConv::AVR_BUILTIN);
+    setLibcallImplCallingConv(RTLIB::__divmodhi4, CallingConv::AVR_BUILTIN);
+    setLibcallImplCallingConv(RTLIB::__udivmodqi4, CallingConv::AVR_BUILTIN);
+    setLibcallImplCallingConv(RTLIB::__udivmodhi4, CallingConv::AVR_BUILTIN);
   }
 
   if (!TT.isWasm()) {
diff --git a/llvm/lib/Target/ARM/ARMISelLowering.cpp b/llvm/lib/Target/ARM/ARMISelLowering.cpp
index 478791699df88..85f0d99923f90 100644
--- a/llvm/lib/Target/ARM/ARMISelLowering.cpp
+++ b/llvm/lib/Target/ARM/ARMISelLowering.cpp
@@ -686,7 +686,7 @@ ARMTargetLowering::ARMTargetLowering(const TargetMachine &TM_,
 
     for (const auto &LC : LibraryCalls) {
       setLibcallImpl(LC.Op, LC.Impl);
-      setLibcallCallingConv(LC.Op, LC.CC);
+      setLibcallImplCallingConv(LC.Impl, LC.CC);
       if (LC.Cond != CmpInst::BAD_ICMP_PREDICATE)
         setCmpLibcallCC(LC.Op, LC.Cond);
     }
@@ -725,7 +725,7 @@ ARMTargetLowering::ARMTargetLowering(const TargetMachine &TM_,
 
       for (const auto &LC : MemOpsLibraryCalls) {
         setLibcallImpl(LC.Op, LC.Impl);
-        setLibcallCallingConv(LC.Op, LC.CC);
+        setLibcallImplCallingConv(LC.Impl, LC.CC);
       }
     }
   }
@@ -735,13 +735,19 @@ ARMTargetLowering::ARMTargetLowering(const TargetMachine &TM_,
   // hard-float calling convention by default.
   if (!TT.isWatchABI()) {
     if (TM.isAAPCS_ABI()) {
-      setLibcallCallingConv(RTLIB::FPROUND_F32_F16, CallingConv::ARM_AAPCS);
-      setLibcallCallingConv(RTLIB::FPROUND_F64_F16, CallingConv::ARM_AAPCS);
-      setLibcallCallingConv(RTLIB::FPEXT_F16_F32, CallingConv::ARM_AAPCS);
+      setLibcallImplCallingConv(getLibcallImpl(RTLIB::FPROUND_F32_F16),
+                                CallingConv::ARM_AAPCS);
+      setLibcallImplCallingConv(getLibcallImpl(RTLIB::FPROUND_F64_F16),
+                                CallingConv::ARM_AAPCS);
+      setLibcallImplCallingConv(getLibcallImpl(RTLIB::FPEXT_F16_F32),
+                                CallingConv::ARM_AAPCS);
     } else {
-      setLibcallCallingConv(RTLIB::FPROUND_F32_F16, CallingConv::ARM_APCS);
-      setLibcallCallingConv(RTLIB::FPROUND_F64_F16, CallingConv::ARM_APCS);
-      setLibcallCallingConv(RTLIB::FPEXT_F16_F32, CallingConv::ARM_APCS);
+      setLibcallImplCallingConv(getLibcallImpl(RTLIB::FPROUND_F32_F16),
+                                CallingConv::ARM_APCS);
+      setLibcallImplCallingConv(getLibcallImpl(RTLIB::FPROUND_F64_F16),
+                                CallingConv::ARM_APCS);
+      setLibcallImplCallingConv(getLibcallImpl(RTLIB::FPEXT_F16_F32),
+                                CallingConv::ARM_APCS);
     }
   }
 
@@ -763,7 +769,7 @@ ARMTargetLowering::ARMTargetLowering(const TargetMachine &TM_,
 
     for (const auto &LC : LibraryCalls) {
       setLibcallImpl(LC.Op, LC.Impl);
-      setLibcallCallingConv(LC.Op, LC.CC);
+      setLibcallImplCallingConv(LC.Impl, LC.CC);
     }
   } else if (!TT.isOSBinFormatMachO()) {
     setLibcallImpl(RTLIB::FPROUND_F32_F16, RTLIB::__gnu_f2h_ieee);
diff --git a/llvm/lib/Target/Lanai/LanaiISelLowering.cpp b/llvm/lib/Target/Lanai/LanaiISelLowering.cpp
index 7781817aef71a..a00c2870c9afc 100644
--- a/llvm/lib/Target/Lanai/LanaiISelLowering.cpp
+++ b/llvm/lib/Target/Lanai/LanaiISelLowering.cpp
@@ -151,8 +151,8 @@ LanaiTargetLowering::LanaiTargetLowering(const TargetMachine &TM,
   setMinimumJumpTableEntries(100);
 
   // Use fast calling convention for library functions.
-  for (RTLIB::Libcall LC : RTLIB::libcalls())
-    setLibcallCallingConv(LC, CallingConv::Fast);
+  for (RTLIB::LibcallImpl LC : RTLIB::libcall_impls())
+    setLibcallImplCallingConv(LC, CallingConv::Fast);
 
   MaxStoresPerMemset = 16; // For @llvm.memset -> sequence of stores
   MaxStoresPerMemsetOptSize = 8;
diff --git a/llvm/lib/Target/MSP430/MSP430ISelLowering.cpp b/llvm/lib/Target/MSP430/MSP430ISelLowering.cpp
index f8f688c8fbb14..d558dd253dc46 100644
--- a/llvm/lib/Target/MSP430/MSP430ISelLowering.cpp
+++ b/llvm/lib/Target/MSP430/MSP430ISelLowering.cpp
@@ -208,7 +208,8 @@ MSP430TargetLowering::MSP430TargetLowering(const TargetMachine &TM,
     for (const auto &LC : LibraryCalls) {
       setLibcallImpl(LC.Op, LC.Impl);
     }
-    setLibcallCallingConv(RTLIB::MUL_I64, CallingConv::MSP430_BUILTIN);
+    setLibcallImplCallingConv(RTLIB::__mspabi_mpyll,
+                              CallingConv::MSP430_BUILTIN);
   }
 
   setMinFunctionAlignment(Align(2));

@arsenm arsenm force-pushed the users/arsenm/ir/runtime-libcalls/make-calling-conv-property-of-impl branch from 191a077 to 31892e8 Compare June 23, 2025 13:27
@arsenm arsenm force-pushed the users/arsenm/tablegen/define-runtime-libcall-sets-tablegen branch 2 times, most recently from 3325765 to ab13366 Compare June 25, 2025 12:42
@arsenm arsenm force-pushed the users/arsenm/ir/runtime-libcalls/make-calling-conv-property-of-impl branch 2 times, most recently from 138da58 to fb4074a Compare June 27, 2025 07:31
@arsenm arsenm force-pushed the users/arsenm/tablegen/define-runtime-libcall-sets-tablegen branch from 18a2de6 to ac9385a Compare June 27, 2025 08:54
@arsenm arsenm force-pushed the users/arsenm/ir/runtime-libcalls/make-calling-conv-property-of-impl branch from fb4074a to 4f26f1e Compare June 27, 2025 08:55
@arsenm arsenm force-pushed the users/arsenm/tablegen/define-runtime-libcall-sets-tablegen branch from ac9385a to e45223b Compare June 27, 2025 14:21
@arsenm arsenm force-pushed the users/arsenm/ir/runtime-libcalls/make-calling-conv-property-of-impl branch from 4f26f1e to 60fa201 Compare June 27, 2025 14:21
Copy link
Collaborator

@RKSimon RKSimon left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

Instead of associating the libcall with the RTLIB::Libcall, put it
into a table indexed by the RTLIB::LibcallImpl. The LibcallImpls
should contain all ABI details for a particular implementation, not
the abstract Libcall. In the future the wrappers in terms of the
RTLIB::Libcall should be removed.
@arsenm arsenm force-pushed the users/arsenm/ir/runtime-libcalls/make-calling-conv-property-of-impl branch from 60fa201 to 5a8dc27 Compare June 28, 2025 02:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants