Skip to content

TableGen: Allow defining sets of runtime libraries #144978

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

Merged

Conversation

arsenm
Copy link
Contributor

@arsenm arsenm commented Jun 20, 2025

Add a way to define a SystemLibrary for a complete set of
libcalls, subdivided by a predicate based on the triple.
Libraries can be defined using dag set operations, and the
prior default set can be subtracted from and added to (though
I think eventually all targets should move to explicit opt-ins.
We're still doing things like reporting ppcf128 libcalls as
available dy default on all targets).

Start migrating some of the easier targets to only use the new
system. Targets that don't define a SystemLibrary are still
manually mutating a table set to the old defaults.

Copy link
Contributor Author

arsenm commented Jun 20, 2025

This stack of pull requests is managed by Graphite. Learn more about stacking.

Copy link

github-actions bot commented Jun 20, 2025

✅ With the latest revision this PR passed the C/C++ code formatter.

@llvmbot
Copy link
Member

llvmbot commented Jun 20, 2025

@llvm/pr-subscribers-tablegen

@llvm/pr-subscribers-llvm-ir

Author: Matt Arsenault (arsenm)

Changes

Add a way to define a SystemLibrary for a complete set of
libcalls, subdivided by a predicate based on the triple.
Libraries can be defined using dag set operations, and the
prior default set can be subtracted from and added to (though
I think eventually all targets should move to explicit opt-ins.
We're still doing things like reporting ppcf128 libcalls as
available dy default on all targets).

Start migrating some of the easier targets to only use the new
system. Targets that don't define a SystemLibrary are still
manually mutating a table set to the old defaults.


Patch is 71.70 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/144978.diff

9 Files Affected:

  • (modified) llvm/include/llvm/IR/RuntimeLibcalls.h (+2-8)
  • (modified) llvm/include/llvm/IR/RuntimeLibcalls.td (+309-184)
  • (modified) llvm/include/llvm/IR/RuntimeLibcallsImpl.td (+36)
  • (added) llvm/include/llvm/TableGen/SetTheory.td (+27)
  • (modified) llvm/lib/IR/RuntimeLibcalls.cpp (+6-121)
  • (added) llvm/test/TableGen/RuntimeLibcallEmitter-conflict-warning.td (+60)
  • (added) llvm/test/TableGen/RuntimeLibcallEmitter-nested-predicates-error.td (+18)
  • (modified) llvm/test/TableGen/RuntimeLibcallEmitter.td (+174-11)
  • (modified) llvm/utils/TableGen/Basic/RuntimeLibcallsEmitter.cpp (+257-94)
diff --git a/llvm/include/llvm/IR/RuntimeLibcalls.h b/llvm/include/llvm/IR/RuntimeLibcalls.h
index 912715fbf6b19..d69c23753da7a 100644
--- a/llvm/include/llvm/IR/RuntimeLibcalls.h
+++ b/llvm/include/llvm/IR/RuntimeLibcalls.h
@@ -52,7 +52,6 @@ struct RuntimeLibcallsInfo {
       FloatABI::ABIType FloatABI = FloatABI::Default,
       EABI EABIVersion = EABI::Default) {
     initSoftFloatCmpLibcallPredicates();
-    initDefaultLibCallImpls();
     initLibcalls(TT, ExceptionModel, FloatABI, EABIVersion);
   }
 
@@ -97,6 +96,7 @@ struct RuntimeLibcallsInfo {
   /// Get the comparison predicate that's to be used to test the result of the
   /// comparison libcall against zero. This should only be used with
   /// floating-point compare libcalls.
+  // FIXME: This should be a function of RTLIB::LibcallImpl
   CmpInst::Predicate
   getSoftFloatCmpLibcallPredicate(RTLIB::Libcall Call) const {
     return SoftFloatCompareLibcallPredicates[Call];
@@ -172,13 +172,7 @@ struct RuntimeLibcallsInfo {
   void initDefaultLibCallImpls();
 
   /// Generated by tablegen.
-  void setPPCLibCallNameOverrides();
-
-  /// Generated by tablegen.
-  void setZOSLibCallNameOverrides();
-
-  /// Generated by tablegen.
-  void setWindowsArm64LibCallNameOverrides();
+  void setTargetRuntimeLibcallSets(const Triple &TT);
 
   void initSoftFloatCmpLibcallPredicates();
 
diff --git a/llvm/include/llvm/IR/RuntimeLibcalls.td b/llvm/include/llvm/IR/RuntimeLibcalls.td
index 1d9f02dcf8ba8..e24b4c928b421 100644
--- a/llvm/include/llvm/IR/RuntimeLibcalls.td
+++ b/llvm/include/llvm/IR/RuntimeLibcalls.td
@@ -891,6 +891,17 @@ def calloc : RuntimeLibcallImpl<CALLOC>;
 } // End let IsDefault = true
 } // End defset DefaultRuntimeLibcallImpls
 
+defvar DefaultLibCalls =
+    !foreach(entry, DefaultRuntimeLibcallImpls, entry.Provides);
+
+defvar DefaultRuntimeLibcallImpls_f128 =
+    !filter(entry, DefaultRuntimeLibcallImpls,
+            !match(!cast<string>(entry.Provides), "_F128"));
+
+defvar DefaultRuntimeLibcallImpls_atomic =
+    !filter(entry, DefaultRuntimeLibcallImpls,
+            !match(!cast<string>(entry.Provides), "ATOMIC"));
+
 //--------------------------------------------------------------------
 // Define implementation other libcalls
 //--------------------------------------------------------------------
@@ -915,58 +926,61 @@ def _Unwind_SjLj_Resume : RuntimeLibcallImpl<UNWIND_RESUME>;
 // F128 libm Runtime Libcalls
 //===----------------------------------------------------------------------===//
 
-def logf128 : RuntimeLibcallImpl<LOG_F128>;
-def log2f128 : RuntimeLibcallImpl<LOG2_F128>;
-def log10f128 : RuntimeLibcallImpl<LOG10_F128>;
-def expf128 : RuntimeLibcallImpl<EXP_F128>;
-def exp2f128 : RuntimeLibcallImpl<EXP2_F128>;
-def exp10f128 : RuntimeLibcallImpl<EXP10_F128>;
-def sinf128 : RuntimeLibcallImpl<SIN_F128>;
-def cosf128 : RuntimeLibcallImpl<COS_F128>;
-def tanf128 : RuntimeLibcallImpl<TAN_F128>;
-def tanhf128 : RuntimeLibcallImpl<TANH_F128>;
-def sincosf128 : RuntimeLibcallImpl<SINCOS_F128>;
-def powf128 : RuntimeLibcallImpl<POW_F128>;
-def fminf128 : RuntimeLibcallImpl<FMIN_F128>;
-def fmaxf128 : RuntimeLibcallImpl<FMAX_F128>;
-def fmodf128 : RuntimeLibcallImpl<REM_F128>;
-def sqrtf128 : RuntimeLibcallImpl<SQRT_F128>;
-def ceilf128 : RuntimeLibcallImpl<CEIL_F128>;
-def floorf128 : RuntimeLibcallImpl<FLOOR_F128>;
-def truncf128 : RuntimeLibcallImpl<TRUNC_F128>;
-def roundf128 : RuntimeLibcallImpl<ROUND_F128>;
-def lroundf128 : RuntimeLibcallImpl<LROUND_F128>;
-def llroundf128 : RuntimeLibcallImpl<LLROUND_F128>;
-def rintf128 : RuntimeLibcallImpl<RINT_F128>;
-def lrintf128 : RuntimeLibcallImpl<LRINT_F128>;
-def llrintf128 : RuntimeLibcallImpl<LLRINT_F128>;
-def nearbyintf128 : RuntimeLibcallImpl<NEARBYINT_F128>;
-def fmaf128 : RuntimeLibcallImpl<FMA_F128>;
-def frexpf128 : RuntimeLibcallImpl<FREXP_F128>;
-
-def cbrtf128 : RuntimeLibcallImpl<CBRT_F128>;
-def fminimumf128 : RuntimeLibcallImpl<FMINIMUM_F128>;
-def fmaximumf128 : RuntimeLibcallImpl<FMAXIMUM_F128>;
-def fminimum_numf128 : RuntimeLibcallImpl<FMINIMUM_NUM_F128>;
-def fmaximum_numf128 : RuntimeLibcallImpl<FMAXIMUM_NUM_F128>;
-def asinf128 : RuntimeLibcallImpl<ASIN_F128>;
-def acosf128 : RuntimeLibcallImpl<ACOS_F128>;
-def atanf128 : RuntimeLibcallImpl<ATAN_F128>;
-def atan2f128 : RuntimeLibcallImpl<ATAN2_F128>;
-def ldexpf128 : RuntimeLibcallImpl<LDEXP_F128>;
-def roundevenf128 : RuntimeLibcallImpl<ROUNDEVEN_F128>;
-def modff128 : RuntimeLibcallImpl<MODF_F128>;
-def sinhf128 : RuntimeLibcallImpl<SINH_F128>;
-def coshf128 : RuntimeLibcallImpl<COSH_F128>;
-def copysignf128 : RuntimeLibcallImpl<COPYSIGN_F128>;
-
-def __logf128_finite : RuntimeLibcallImpl<LOG_FINITE_F128>;
-def __log2f128_finite : RuntimeLibcallImpl<LOG2_FINITE_F128>;
-def __log10f128_finite : RuntimeLibcallImpl<LOG10_FINITE_F128>;
-def __expf128_finite : RuntimeLibcallImpl<EXP_FINITE_F128>;
-def __exp2f128_finite : RuntimeLibcallImpl<EXP2_FINITE_F128>;
-def __exp10f128_finite : RuntimeLibcallImpl<EXP10_FINITE_F128>;
-def __powf128_finite : RuntimeLibcallImpl<POW_FINITE_F128>;
+defset list<RuntimeLibcallImpl> LibmF128Libcalls = {
+  def logf128 : RuntimeLibcallImpl<LOG_F128>;
+  def log2f128 : RuntimeLibcallImpl<LOG2_F128>;
+  def log10f128 : RuntimeLibcallImpl<LOG10_F128>;
+  def expf128 : RuntimeLibcallImpl<EXP_F128>;
+  def exp2f128 : RuntimeLibcallImpl<EXP2_F128>;
+  def exp10f128 : RuntimeLibcallImpl<EXP10_F128>;
+  def sinf128 : RuntimeLibcallImpl<SIN_F128>;
+  def cosf128 : RuntimeLibcallImpl<COS_F128>;
+  def tanf128 : RuntimeLibcallImpl<TAN_F128>;
+  def tanhf128 : RuntimeLibcallImpl<TANH_F128>;
+  def sincosf128 : RuntimeLibcallImpl<SINCOS_F128>;
+  def powf128 : RuntimeLibcallImpl<POW_F128>;
+  def fminf128 : RuntimeLibcallImpl<FMIN_F128>;
+  def fmaxf128 : RuntimeLibcallImpl<FMAX_F128>;
+  def fmodf128 : RuntimeLibcallImpl<REM_F128>;
+  def sqrtf128 : RuntimeLibcallImpl<SQRT_F128>;
+  def ceilf128 : RuntimeLibcallImpl<CEIL_F128>;
+  def floorf128 : RuntimeLibcallImpl<FLOOR_F128>;
+  def truncf128 : RuntimeLibcallImpl<TRUNC_F128>;
+  def roundf128 : RuntimeLibcallImpl<ROUND_F128>;
+  def lroundf128 : RuntimeLibcallImpl<LROUND_F128>;
+  def llroundf128 : RuntimeLibcallImpl<LLROUND_F128>;
+  def rintf128 : RuntimeLibcallImpl<RINT_F128>;
+  def lrintf128 : RuntimeLibcallImpl<LRINT_F128>;
+  def llrintf128 : RuntimeLibcallImpl<LLRINT_F128>;
+  def nearbyintf128 : RuntimeLibcallImpl<NEARBYINT_F128>;
+  def fmaf128 : RuntimeLibcallImpl<FMA_F128>;
+  def frexpf128 : RuntimeLibcallImpl<FREXP_F128>;
+  def cbrtf128 : RuntimeLibcallImpl<CBRT_F128>;
+  def fminimumf128 : RuntimeLibcallImpl<FMINIMUM_F128>;
+  def fmaximumf128 : RuntimeLibcallImpl<FMAXIMUM_F128>;
+  def fminimum_numf128 : RuntimeLibcallImpl<FMINIMUM_NUM_F128>;
+  def fmaximum_numf128 : RuntimeLibcallImpl<FMAXIMUM_NUM_F128>;
+  def asinf128 : RuntimeLibcallImpl<ASIN_F128>;
+  def acosf128 : RuntimeLibcallImpl<ACOS_F128>;
+  def atanf128 : RuntimeLibcallImpl<ATAN_F128>;
+  def atan2f128 : RuntimeLibcallImpl<ATAN2_F128>;
+  def ldexpf128 : RuntimeLibcallImpl<LDEXP_F128>;
+  def roundevenf128 : RuntimeLibcallImpl<ROUNDEVEN_F128>;
+  def modff128 : RuntimeLibcallImpl<MODF_F128>;
+  def sinhf128 : RuntimeLibcallImpl<SINH_F128>;
+  def coshf128 : RuntimeLibcallImpl<COSH_F128>;
+  def copysignf128 : RuntimeLibcallImpl<COPYSIGN_F128>;
+}
+
+defset list<RuntimeLibcallImpl> LibmF128FiniteLibcalls = {
+  def __logf128_finite : RuntimeLibcallImpl<LOG_FINITE_F128>;
+  def __log2f128_finite : RuntimeLibcallImpl<LOG2_FINITE_F128>;
+  def __log10f128_finite : RuntimeLibcallImpl<LOG10_FINITE_F128>;
+  def __expf128_finite : RuntimeLibcallImpl<EXP_FINITE_F128>;
+  def __exp2f128_finite : RuntimeLibcallImpl<EXP2_FINITE_F128>;
+  def __exp10f128_finite : RuntimeLibcallImpl<EXP10_FINITE_F128>;
+  def __powf128_finite : RuntimeLibcallImpl<POW_FINITE_F128>;
+}
 
 //===----------------------------------------------------------------------===//
 // AArch64 Runtime Libcalls
@@ -994,16 +1008,41 @@ defset list<RuntimeLibcallImpl> AArch64LibcallImpls = {
   def __arm_sc_memcpy : RuntimeLibcallImpl<SC_MEMCPY>;
   def __arm_sc_memmove : RuntimeLibcallImpl<SC_MEMMOVE>;
   def __arm_sc_memset : RuntimeLibcallImpl<SC_MEMSET>;
-}
+} // End AArch64LibcallImpls
 
-foreach libcall = AArch64LibcallImpls in {
-  def arm64ec_#libcall : DuplicateLibcallImplWithPrefix<libcall, "#">;
-}
+def isAArch64_ExceptArm64EC
+    : RuntimeLibcallPredicate<"(TT.isAArch64() && !TT.isWindowsArm64EC())">;
+def isWindowsArm64EC : RuntimeLibcallPredicate<"TT.isWindowsArm64EC()">;
+
+def AArch64SystemLibrary : SystemRuntimeLibrary<isAArch64_ExceptArm64EC,
+                                                (add DefaultRuntimeLibcallImpls,
+                                                    AArch64LibcallImpls)>;
 
-foreach libcall = DefaultRuntimeLibcallImpls in {
-  def arm64ec_#libcall : DuplicateLibcallImplWithPrefix<libcall, "#">;
+// Prepend a # to every name
+defset list<RuntimeLibcallImpl> WinArm64ECDefaultRuntimeLibcallImpls = {
+  foreach libcall = DefaultRuntimeLibcallImpls in {
+    def arm64ec_#libcall : DuplicateLibcallImplWithPrefix<libcall, "#">;
+  }
+
+  foreach libcall = AArch64LibcallImpls in {
+    def arm64ec_#libcall : DuplicateLibcallImplWithPrefix<libcall, "#">;
+  }
 }
 
+def WindowsARM64ECSystemLibrary
+    : SystemRuntimeLibrary<isWindowsArm64EC,
+                           (add WinArm64ECDefaultRuntimeLibcallImpls)>;
+
+//===----------------------------------------------------------------------===//
+// AMDGPU Runtime Libcalls
+//===----------------------------------------------------------------------===//
+
+def isAMDGPU : RuntimeLibcallPredicate<"TT.isAMDGPU()">;
+
+// No calls, except for dummy atomic calls to avoid crashes.
+def AMDGPUSystemLibrary
+    : SystemRuntimeLibrary<isAMDGPU, (add DefaultRuntimeLibcallImpls_atomic)>;
+
 //===----------------------------------------------------------------------===//
 // ARM Runtime Libcalls
 //===----------------------------------------------------------------------===//
@@ -1227,6 +1266,30 @@ def __udivmodhi4 : RuntimeLibcallImpl<UDIVREM_I16>; // CallingConv::AVR_BUILTIN
 def avr_sin : RuntimeLibcallImpl<SIN_F32, "sin">;
 def avr_cos : RuntimeLibcallImpl<COS_F32, "cos">;
 
+def isAVR : RuntimeLibcallPredicate<"TT.getArch() == Triple::avr">;
+
+def AVRSystemLibrary
+    : SystemRuntimeLibrary<
+          isAVR,
+          (add(sub DefaultRuntimeLibcallImpls,
+
+               // Division rtlib functions (not supported), use divmod
+               // functions instead
+               __divqi3, __divhi3, __divsi3, __udivqi3, __udivhi3, __udivsi3,
+
+               // Modulus rtlib functions (not supported), use divmod functions
+               // instead
+               __modqi3, __modhi3, __modsi3, __umodqi3, __umodhi3, __umodsi3,
+
+               // Standard f64 names are replaced
+               sin, cos, sinf, cosf),
+
+              __divmodqi4, __divmodhi4, __divmodsi4, __udivmodqi4, __udivmodhi4,
+              __udivmodsi4,
+
+              // Trigonometric rtlib functions
+              avr_sin, avr_cos)>;
+
 //===----------------------------------------------------------------------===//
 // Hexagon Runtime Libcalls
 //===----------------------------------------------------------------------===//
@@ -1447,52 +1510,94 @@ def __mspabi_mpyll : RuntimeLibcallImpl<MUL_I64>;
 // setLibcallCallingConv(MUL_I64, CallingConv::MSP430_BUILTIN);
 
 //===----------------------------------------------------------------------===//
-// PPC Runtime Libcalls
+// NVPTX Runtime Libcalls
 //===----------------------------------------------------------------------===//
 
-class PPCRuntimeLibcallImpl<RuntimeLibcall P, string Name = NAME>
-    : RuntimeLibcallImpl<P, Name>;
+def isNVPTX : RuntimeLibcallPredicate<"TT.isNVPTX()">;
+
+// No calls, except for dummy atomic calls to avoid crashes.
+def NVPTXSystemLibrary
+    : SystemRuntimeLibrary<isNVPTX, (add DefaultRuntimeLibcallImpls_atomic)>;
+
+//===----------------------------------------------------------------------===//
+// PPC Runtime Libcalls
+//===----------------------------------------------------------------------===//
 
 // For IEEE quad-precision libcall names, PPC uses "kf" instead of "tf".
-def __addkf3 : PPCRuntimeLibcallImpl<ADD_F128>;
-def __subkf3 : PPCRuntimeLibcallImpl<SUB_F128>;
-def __mulkf3 : PPCRuntimeLibcallImpl<MUL_F128>;
-def __divkf3 : PPCRuntimeLibcallImpl<DIV_F128>;
-def __powikf2 : PPCRuntimeLibcallImpl<POWI_F128>;
-def __extendsfkf2 : PPCRuntimeLibcallImpl<FPEXT_F32_F128>;
-def __extenddfkf2 : PPCRuntimeLibcallImpl<FPEXT_F64_F128>;
-def __trunckfhf2 : PPCRuntimeLibcallImpl<FPROUND_F128_F16>;
-def __trunckfsf2 : PPCRuntimeLibcallImpl<FPROUND_F128_F32>;
-def __trunckfdf2 : PPCRuntimeLibcallImpl<FPROUND_F128_F64>;
-def __fixkfsi : PPCRuntimeLibcallImpl<FPTOSINT_F128_I32>;
-def __fixkfdi : PPCRuntimeLibcallImpl<FPTOSINT_F128_I64>;
-def __fixkfti : PPCRuntimeLibcallImpl<FPTOSINT_F128_I128>;
-def __fixunskfsi : PPCRuntimeLibcallImpl<FPTOUINT_F128_I32>;
-def __fixunskfdi : PPCRuntimeLibcallImpl<FPTOUINT_F128_I64>;
-def __fixunskfti : PPCRuntimeLibcallImpl<FPTOUINT_F128_I128>;
-def __floatsikf : PPCRuntimeLibcallImpl<SINTTOFP_I32_F128>;
-def __floatdikf : PPCRuntimeLibcallImpl<SINTTOFP_I64_F128>;
-def __floattikf : PPCRuntimeLibcallImpl<SINTTOFP_I128_F128>;
-def __floatunsikf : PPCRuntimeLibcallImpl<UINTTOFP_I32_F128>;
-def __floatundikf : PPCRuntimeLibcallImpl<UINTTOFP_I64_F128>;
-def __floatuntikf : PPCRuntimeLibcallImpl<UINTTOFP_I128_F128>;
-def __eqkf2 : PPCRuntimeLibcallImpl<OEQ_F128>;
-def __nekf2 : PPCRuntimeLibcallImpl<UNE_F128>;
-def __gekf2 : PPCRuntimeLibcallImpl<OGE_F128>;
-def __ltkf2 : PPCRuntimeLibcallImpl<OLT_F128>;
-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>;
+defset list<RuntimeLibcallImpl> PPCRuntimeLibcalls = {
+  def __addkf3 : RuntimeLibcallImpl<ADD_F128>;
+  def __subkf3 : RuntimeLibcallImpl<SUB_F128>;
+  def __mulkf3 : RuntimeLibcallImpl<MUL_F128>;
+  def __divkf3 : RuntimeLibcallImpl<DIV_F128>;
+  def __powikf2 : RuntimeLibcallImpl<POWI_F128>;
+  def __extendsfkf2 : RuntimeLibcallImpl<FPEXT_F32_F128>;
+  def __extenddfkf2 : RuntimeLibcallImpl<FPEXT_F64_F128>;
+  def __trunckfhf2 : RuntimeLibcallImpl<FPROUND_F128_F16>;
+  def __trunckfsf2 : RuntimeLibcallImpl<FPROUND_F128_F32>;
+  def __trunckfdf2 : RuntimeLibcallImpl<FPROUND_F128_F64>;
+  def __fixkfsi : RuntimeLibcallImpl<FPTOSINT_F128_I32>;
+  def __fixkfdi : RuntimeLibcallImpl<FPTOSINT_F128_I64>;
+  def __fixkfti : RuntimeLibcallImpl<FPTOSINT_F128_I128>;
+  def __fixunskfsi : RuntimeLibcallImpl<FPTOUINT_F128_I32>;
+  def __fixunskfdi : RuntimeLibcallImpl<FPTOUINT_F128_I64>;
+  def __fixunskfti : RuntimeLibcallImpl<FPTOUINT_F128_I128>;
+  def __floatsikf : RuntimeLibcallImpl<SINTTOFP_I32_F128>;
+  def __floatdikf : RuntimeLibcallImpl<SINTTOFP_I64_F128>;
+  def __floattikf : RuntimeLibcallImpl<SINTTOFP_I128_F128>;
+  def __floatunsikf : RuntimeLibcallImpl<UINTTOFP_I32_F128>;
+  def __floatundikf : RuntimeLibcallImpl<UINTTOFP_I64_F128>;
+  def __floatuntikf : RuntimeLibcallImpl<UINTTOFP_I128_F128>;
+  def __eqkf2 : RuntimeLibcallImpl<OEQ_F128>;
+  def __nekf2 : RuntimeLibcallImpl<UNE_F128>;
+  def __gekf2 : RuntimeLibcallImpl<OGE_F128>;
+  def __ltkf2 : RuntimeLibcallImpl<OLT_F128>;
+  def __lekf2 : RuntimeLibcallImpl<OLE_F128>;
+  def __gtkf2 : RuntimeLibcallImpl<OGT_F128>;
+  def __unordkf2 : RuntimeLibcallImpl<UO_F128>;
+}
+
+defset list<RuntimeLibcallImpl> PPC64AIXCallList = {
+  def ___memmove64 : RuntimeLibcallImpl<MEMCPY>;
+  def ___memset64 : RuntimeLibcallImpl<MEMSET>;
+  def ___bzero64 : RuntimeLibcallImpl<BZERO>;
+}
+
+defset list<RuntimeLibcallImpl> PPC32AIXCallList = {
+  def ___memmove : RuntimeLibcallImpl<MEMMOVE>;
+  def ___memset : RuntimeLibcallImpl<MEMSET>;
+  def ___bzero : RuntimeLibcallImpl<BZERO>;
+}
+
+defvar PPCOverrides = !foreach(entry, PPCRuntimeLibcalls, entry.Provides);
+
+defvar ToPrune = !listremove(DefaultLibCalls, PPCOverrides);
+//  DefaultLibcalls item.Provides
+//);
+
+// defvar PPCOverride = !foldl([], DefaultRuntimeLibcallImpls, acc, item,
+//     !eq(item.Provides,
+//);
+
+def isPPC : RuntimeLibcallPredicate<"TT.isPPC()">;
+def isAIX : RuntimeLibcallPredicate<"TT.isOSAIX()">;
+def isNotAIX : RuntimeLibcallPredicate<"!TT.isOSAIX()">;
+def isPPC32_AIX : RuntimeLibcallPredicate<"(TT.isPPC32() && TT.isOSAIX())">;
+def isPPC64_AIX : RuntimeLibcallPredicate<"(TT.isPPC64() && TT.isOSAIX())">;
+
+def AIX32Calls : LibcallImpls<(add PPC32AIXCallList), isPPC32_AIX>;
+def AIX64Calls : LibcallImpls<(add PPC64AIXCallList), isPPC64_AIX>;
+
+// FIXME: Current emission behavior with multiple implementations is
+// janky. We need to filter out the conflicting cases with different
+// f128 names, and then add the overrides. We should switch to
+// explicitly adding subsets of the default calls.
+def PPCSystemLibrary
+    : SystemRuntimeLibrary<isPPC, (add PPCRuntimeLibcalls,
+                                      (sub DefaultRuntimeLibcallImpls, memcpy,
+                                          DefaultRuntimeLibcallImpls_f128),
+                                      __extendkftf2, __trunctfkf2,
+                                      LibmF128Libcalls, AIX32Calls, AIX64Calls,
+                                      AvailableIf<memcpy, isNotAIX>)>;
 
 //===----------------------------------------------------------------------===//
 // SPARC Runtime Libcalls
@@ -1562,94 +1667,105 @@ def _allmul : RuntimeLibcallImpl<MUL_I64>; // CallingConv::X86_StdCall
 
 def __memcpy_4 : RuntimeLibcallImpl<MEMCPY_ALIGN_4>;
 
+def isXCore : RuntimeLibcallPredicate<"TT.getArch() == Triple::xcore">;
+def XCoreSystemLibrary
+    : SystemRuntimeLibrary<isXCore, (add DefaultRuntimeLibcallImpls,
+                                        __memcpy_4)>;
+
 //===----------------------------------------------------------------------===//
 // ZOS Runtime Libcalls
 //===----------------------------------------------------------------------===//
 
-class ZOSRuntimeLibcallImpl<RuntimeLibcall P, string Name = NAME>
-    : RuntimeLibcallImpl<P, Name>;
-
-def zos___TRNC_B : ZOSRuntimeLibcallImpl<TRUNC_F64, "@@TRNC@B">;
-def zos___FTRC_B : ZOSRuntimeLibcallImpl<TRUNC_F32, "@@FTRC@B">;
-def zos___LTRC_B : ZOSRuntimeLibcallImpl<TRUNC_F128, "@@LTRC@B">;
-def zos___WSQT_B : ZOSRuntimeLibcallImpl<SQRT_F64, "@@WSQT@B">;
-def zos___FSQT_B : ZOSRuntimeLibcallImpl<SQRT_F32, "@@FSQT@B">;
-def zos___LSQT_B : ZOSRuntimeLibcallImpl<SQRT_F128, "@@LSQT@B">;
-def zos___SSIN_B : ZOSRuntimeLibcallImpl<SIN_F64, "@@SSIN@B">;
-def zos___FSIN_B : ZOSRuntimeLibcallImpl<SIN_F32, "@@FSIN@B">;
-def zos___LSIN_B : ZOSRuntimeLibcallImpl<SIN_F128, "@@LSIN@B">;
-def zos___ROUN_B : ZOSRuntimeLibcallImpl<ROUND_F64, "@@ROUN@B">;
-def zos___ROUNFB : ZOSRuntimeLibcallImpl<ROUND_F32, "@@ROUNFB">;
-def zos___ROUNLB : ZOSRuntimeLibcallImpl<ROUND_F128, "@@ROUNLB">;
-def zos___SRNT_B : ZOSRuntimeLibcallImpl<RINT_F64, "@@SRNT@B">;
-def zos___RINTFB : ZOSRuntimeLibcallImpl<RINT_F32, "@@RINTFB">;
-def zos___RINTLB : ZOSRuntimeLibcallImpl<RINT_F128, "@@RINTLB">;
-def zos___WFMD_B : ZOSRuntimeLibcallImpl<REM_F64, "@@WFMD@B">;
-def zos___FFMD_B : ZOSRuntimeLibcallImpl<REM_F32, "@@FFMD@B">;
-def zos___LFMD_B : ZOSRuntimeLibcallImpl<REM_F128, "@@LFMD@B">;
-def zos___WPOW_B : ZOSRuntimeLibcallImpl<POW_F64, "@@WPOW@B">;
-def zos___FPOW_B : ZOSRuntimeLibcallImpl<POW_F32, "@@FPOW@B">;
-def zos___LPOW_B : ZOSRuntimeLibcallImpl<POW_F128, "@@LPOW@B">;
-def zos___NBYI_B : ZOSRuntimeLibcallImpl<NEARBYINT_F64, "@@NBYI@B">;
-def zos___NBYIFB : ZOSRuntimeLibcallImpl<NEARBYINT_F32, "@@NBYIFB">;
-def zos___NBYILB : ZOSRuntimeLibcallImpl<NEARBYINT_F128, "@@NBYILB">;
-def zos___ROND_B : ZOSRuntimeLibcallImpl<LROUND_F64, "@@ROND@B">;
-def zos___FRND_B : ZOSRuntimeLibcallImpl<LROUND_F32, "@@FRND@B">;
-def zos___LRND_B : ZOSRuntimeLibcallImpl<LROUND_F128, "@@LRND@B">;
-def zos___LRNT_B : ZOSRuntimeLibcallImpl<LRINT_F64, "@@LRNT@B">;
-def zos___LRNTFB : ZOSRuntimeLibcallImpl<LRINT_F32, "@@LRNTFB">;
-def zos___LRNTL...
[truncated]

@arsenm arsenm marked this pull request as ready for review June 20, 2025 02:55
@arsenm arsenm force-pushed the users/arsenm/aarch64/add-libcall-impl-for-sc-mem-functions branch from ec3e89d to 3b3d494 Compare June 23, 2025 13:27
@arsenm arsenm force-pushed the users/arsenm/tablegen/define-runtime-libcall-sets-tablegen branch from f5f142d to 3325765 Compare June 23, 2025 13:27
Copy link
Contributor Author

arsenm commented Jul 8, 2025

Merge activity

  • Jul 8, 1:13 AM UTC: A user started a stack merge that includes this pull request via Graphite.
  • Jul 8, 1:15 AM UTC: Graphite rebased this pull request as part of a merge.
  • Jul 8, 1:17 AM UTC: @arsenm merged this pull request with Graphite.

arsenm added 12 commits July 8, 2025 01:14
Add a way to define a SystemLibrary for a complete set of
libcalls, subdivided by a predicate based on the triple.
Libraries can be defined using dag set operations, and the
prior default set can be subtracted from and added to (though
I think eventually all targets should move to explicit opt-ins.
We're still doing things like reporting ppcf128 libcalls as
available dy default on all targets).

Start migrating some of the easier targets to only use the new
system. Targets that don't define a SystemLibrary are still
manually mutating a table set to the old defaults.
@arsenm arsenm force-pushed the users/arsenm/tablegen/define-runtime-libcall-sets-tablegen branch from 11f878f to 41a5c3b Compare July 8, 2025 01:14
@arsenm arsenm merged commit 5088231 into main Jul 8, 2025
7 of 9 checks passed
@arsenm arsenm deleted the users/arsenm/tablegen/define-runtime-libcall-sets-tablegen branch July 8, 2025 01:17
@mikaelholmen
Copy link
Collaborator

Hi @arsenm

I see the following when I build opt with EXPENSIVE_CHECKS with this patch:

[286/2984] Building RuntimeLibcalls.inc...
FAILED: include/llvm/IR/RuntimeLibcalls.inc /repo/llvm/build-all-expensive/include/llvm/IR/RuntimeLibcalls.inc 
cd /repo/llvm/build-all-expensive/include/llvm/IR && /repo/llvm/build-all-expensive/bin/llvm-min-tblgen -gen-runtime-libcalls -I/repo/llvm/include/llvm/IR -I/repo/llvm/build-all-expensive/include -I/repo/llvm/include /repo/llvm/include/llvm/IR/RuntimeLibcalls.td --write-if-changed -o RuntimeLibcalls.inc -d RuntimeLibcalls.inc.d && /afs/sero.gic.ericsson.se/app/vbuild/RHEL8-x86_64/cmake/3.27.2/bin/cmake -E cmake_transform_depfile Ninja gccdepfile /repo/llvm /repo/llvm/include/llvm/IR /repo/llvm/build-all-expensive /repo/llvm/build-all-expensive/include/llvm/IR /repo/llvm/build-all-expensive/include/llvm/IR/RuntimeLibcalls.inc.d /repo/llvm/build-all-expensive/CMakeFiles/d/d57c3848066209cf93d709536d81207635c4152e2e83b5b2e7dc5d61b977a39f.d
/compiler/include/c++/13.3.0/bits/stl_algo.h:4892:
In function:
    void std::sort(_RandomAccessIterator, _RandomAccessIterator, _Compare) 
    [_RandomAccessIterator = const llvm::Record **, _Compare = (lambda at 
    ../utils/TableGen/Basic/RuntimeLibcallsEmitter.cpp:356:28)]

Error: comparison doesn't meet irreflexive requirements, assert(!(a < a)).

Objects involved in the operation:
    instance "functor" @ 0x7ffdfae1c150 {
    }
    iterator::value_type "ordered type"  {
    }
PLEASE submit a bug report to https://github.com/llvm/llvm-project/issues/ and include the crash backtrace.
Stack dump:
0.	Program arguments: /repo/llvm/build-all-expensive/bin/llvm-min-tblgen -gen-runtime-libcalls -I/repo/llvm/include/llvm/IR -I/repo/llvm/build-all-expensive/include -I/repo/llvm/include /repo/llvm/include/llvm/IR/RuntimeLibcalls.td --write-if-changed -o RuntimeLibcalls.inc -d RuntimeLibcalls.inc.d
 #0 0x0000555a7fef46d6 llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) (/repo/llvm/build-all-expensive/bin/llvm-min-tblgen+0x1656d6)
 #1 0x0000555a7fef1e95 llvm::sys::RunSignalHandlers() (/repo/llvm/build-all-expensive/bin/llvm-min-tblgen+0x162e95)
 #2 0x0000555a7fef5529 SignalHandler(int, siginfo_t*, void*) Signals.cpp:0:0
 #3 0x00007f1da2eaad10 __restore_rt (/lib64/libpthread.so.0+0x12d10)
 #4 0x00007f1da084a52f raise (/lib64/libc.so.6+0x4e52f)
 #5 0x00007f1da081de65 abort (/lib64/libc.so.6+0x21e65)
 #6 0x0000555a7ff7b703 (/repo/llvm/build-all-expensive/bin/llvm-min-tblgen+0x1ec703)
 #7 0x0000555a7fe8ccb5 (anonymous namespace)::RuntimeLibcallEmitter::emitSystemRuntimeLibrarySetCalls(llvm::raw_ostream&) const RuntimeLibcallsEmitter.cpp:0:0
 #8 0x0000555a7fe86d14 llvm::TableGen::Emitter::OptClass<(anonymous namespace)::RuntimeLibcallEmitter>::run(llvm::RecordKeeper const&, llvm::raw_ostream&) RuntimeLibcallsEmitter.cpp:0:0
 #9 0x0000555a7ff3d354 llvm::TableGen::Emitter::ApplyCallback(llvm::RecordKeeper const&, llvm::raw_ostream&) (/repo/llvm/build-all-expensive/bin/llvm-min-tblgen+0x1ae354)
#10 0x0000555a7ff05dd3 llvm::TableGenMain(char const*, std::function<bool (llvm::raw_ostream&, llvm::RecordKeeper const&)>) (/repo/llvm/build-all-expensive/bin/llvm-min-tblgen+0x176dd3)
#11 0x0000555a7fe946fe tblgen_main(int, char**) (/repo/llvm/build-all-expensive/bin/llvm-min-tblgen+0x1056fe)
#12 0x00007f1da08367e5 __libc_start_main (/lib64/libc.so.6+0x3a7e5)
#13 0x0000555a7fe2814e _start (/repo/llvm/build-all-expensive/bin/llvm-min-tblgen+0x9914e)
/bin/sh: line 1: 2905861 Aborted                 (core dumped) /repo/llvm/build-all-expensive/bin/llvm-min-tblgen -gen-runtime-libcalls -I/repo/llvm/include/llvm/IR -I/repo/llvm/build-all-expensive/include -I/repo/llvm/include /repo/llvm/include/llvm/IR/RuntimeLibcalls.td --write-if-changed -o RuntimeLibcalls.inc -d RuntimeLibcalls.inc.d
[288/2984] Building RISCVTargetParserDef.inc...
ninja: build stopped: subcommand failed.
system(/app/vbuild/RHEL8-x86_64/ninja/1.10.2/bin/ninja -j96 -C llvm/build-all-expensive  opt) failed: child exited with value 1

I can't say I know anything about this but I guess the

      if (!A)
        return true;

in the comparison that breaks the

!(a < a)

requirement for nullptr?

@arsenm
Copy link
Contributor Author

arsenm commented Jul 8, 2025

I can't say I know anything about this but I guess the

      if (!A)
        return true;

The sort changed again in 58ad996, does it work now? I don't see this break with EXPENSIVE_CHECKS now

@mikaelholmen
Copy link
Collaborator

I still get this at latest trunk, 763131b:

In function:
    void std::sort(_RandomAccessIterator, _RandomAccessIterator, _Compare) 
    [_RandomAccessIterator = (anonymous namespace)::PredicateWithCC *, 
    _Compare = (lambda at 
    ../utils/TableGen/Basic/RuntimeLibcallsEmitter.cpp:439:28)]

Error: comparison doesn't meet irreflexive requirements, assert(!(a < a)).

@mikaelholmen
Copy link
Collaborator

I guess it still violates the "comp(a, a) == false" requirement due to

     if (!A.Predicate)
        return true;

( https://en.cppreference.com/w/cpp/named_req/Compare )

arsenm added a commit that referenced this pull request Jul 8, 2025
@mikaelholmen
Copy link
Collaborator

With a1ea9e6 it compiles without problems.

@llvm-ci
Copy link
Collaborator

llvm-ci commented Jul 9, 2025

LLVM Buildbot has detected a new failure on builder llvm-clang-x86_64-expensive-checks-debian running on gribozavr4 while building llvm at step 6 "test-build-unified-tree-check-all".

Full details are available at: https://lab.llvm.org/buildbot/#/builders/16/builds/22248

Here is the relevant piece of the build log for the reference
Step 6 (test-build-unified-tree-check-all) failure: test (failure)
******************** TEST 'LLVM :: TableGen/RuntimeLibcallEmitter-conflict-warning.td' FAILED ********************
Exit Code: 1

Command Output (stderr):
--
/b/1/llvm-clang-x86_64-expensive-checks-debian/build/bin/llvm-tblgen -gen-runtime-libcalls -I /b/1/llvm-clang-x86_64-expensive-checks-debian/llvm-project/llvm/test/TableGen/../../include /b/1/llvm-clang-x86_64-expensive-checks-debian/llvm-project/llvm/test/TableGen/RuntimeLibcallEmitter-conflict-warning.td 2> /b/1/llvm-clang-x86_64-expensive-checks-debian/build/test/TableGen/Output/RuntimeLibcallEmitter-conflict-warning.td.tmp.err | /b/1/llvm-clang-x86_64-expensive-checks-debian/build/bin/FileCheck /b/1/llvm-clang-x86_64-expensive-checks-debian/llvm-project/llvm/test/TableGen/RuntimeLibcallEmitter-conflict-warning.td # RUN: at line 1
+ /b/1/llvm-clang-x86_64-expensive-checks-debian/build/bin/FileCheck /b/1/llvm-clang-x86_64-expensive-checks-debian/llvm-project/llvm/test/TableGen/RuntimeLibcallEmitter-conflict-warning.td
+ /b/1/llvm-clang-x86_64-expensive-checks-debian/build/bin/llvm-tblgen -gen-runtime-libcalls -I /b/1/llvm-clang-x86_64-expensive-checks-debian/llvm-project/llvm/test/TableGen/../../include /b/1/llvm-clang-x86_64-expensive-checks-debian/llvm-project/llvm/test/TableGen/RuntimeLibcallEmitter-conflict-warning.td
/b/1/llvm-clang-x86_64-expensive-checks-debian/llvm-project/llvm/test/TableGen/RuntimeLibcallEmitter-conflict-warning.td:40:16: error: CHECK-NEXT: is not on the line after the previous match
// CHECK-NEXT: {RTLIB::SOME_FUNC, RTLIB::func_a}, // func_a
               ^
<stdin>:98:2: note: 'next' match was here
 {RTLIB::SOME_FUNC, RTLIB::func_a}, // func_a
 ^
<stdin>:84:55: note: previous match ended here
 {RTLIB::OTHER_FUNC, RTLIB::other_func}, // other_func
                                                      ^
<stdin>:85:1: note: non-matching line after previous match is here
 {RTLIB::SOME_FUNC, RTLIB::func_b}, // func_b
^

Input file: <stdin>
Check file: /b/1/llvm-clang-x86_64-expensive-checks-debian/llvm-project/llvm/test/TableGen/RuntimeLibcallEmitter-conflict-warning.td

-dump-input=help explains the following input dump.

Input was:
<<<<<<
         .
         .
         .
        93:  
        94:  if (isTargetArchC()) { 
        95:  static const LibcallImplPair LibraryCalls[] = { 
        96:  {RTLIB::ANOTHER_DUP, RTLIB::dup1}, // dup1 
        97:  {RTLIB::OTHER_FUNC, RTLIB::other_func}, // other_func 
        98:  {RTLIB::SOME_FUNC, RTLIB::func_a}, // func_a 
next:40      !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~  error: match on wrong line
        99:  }; 
       100:  
       101:  for (const auto [Func, Impl] : LibraryCalls) { 
       102:  setLibcallImpl(Func, Impl); 
       103:  } 
         .
         .
         .
>>>>>>

--

...

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.

6 participants