[llvm] RuntimeLibcalls: Describe register-returning divmod libcall ABIs (PR #217825)

via llvm-commits llvm-commits at lists.llvm.org
Thu Aug 20 23:30:40 PDT 2026


llvmorg-github-actions[bot] wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-backend-arm

Author: Matt Arsenault (arsenm)

<details>
<summary>Changes</summary>

Teach RuntimeLibcallsInfo::getFunctionTy about the ARM AEABI
(__aeabi_*divmod) and Windows (__rt_*div*) divmod sigantures. Currently
the custom lowering to these calls hardcodes the call signature information,
but in the future this should be automatically handled.

Co-authored-by: Claude (Claude-Opus-4.8) <noreply@<!-- -->anthropic.com>

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


2 Files Affected:

- (modified) llvm/lib/IR/RuntimeLibcalls.cpp (+57) 
- (added) llvm/test/Transforms/Util/DeclareRuntimeLibcalls/divmod.ll (+26) 


``````````diff
diff --git a/llvm/lib/IR/RuntimeLibcalls.cpp b/llvm/lib/IR/RuntimeLibcalls.cpp
index 1befff9d5f00e..7a040c36d99a5 100644
--- a/llvm/lib/IR/RuntimeLibcalls.cpp
+++ b/llvm/lib/IR/RuntimeLibcalls.cpp
@@ -275,6 +275,63 @@ RuntimeLibcallsInfo::getFunctionTy(LLVMContext &Ctx, const Triple &TT,
                               false),
             Attrs};
   }
+  case RTLIB::impl___aeabi_idivmod:
+  case RTLIB::impl___aeabi_uidivmod:
+  case RTLIB::impl___aeabi_ldivmod:
+  case RTLIB::impl___aeabi_uldivmod:
+  case RTLIB::impl___rt_sdiv:
+  case RTLIB::impl___rt_udiv:
+  case RTLIB::impl___rt_sdiv64:
+  case RTLIB::impl___rt_udiv64: {
+    // The ARM AEABI (__aeabi_*divmod) and Windows (__rt_*div*) divmod functions
+    // return both values modeled as an inreg { iN, iN } struct (quotient,
+    // remainder). The __rt_*div* cases pass the arguments in opposite order.
+    bool IsSigned;
+    unsigned Bits;
+    switch (LibcallImpl) {
+    case RTLIB::impl___aeabi_idivmod:
+    case RTLIB::impl___rt_sdiv:
+      IsSigned = true;
+      Bits = 32;
+      break;
+    case RTLIB::impl___aeabi_uidivmod:
+    case RTLIB::impl___rt_udiv:
+      IsSigned = false;
+      Bits = 32;
+      break;
+    case RTLIB::impl___aeabi_ldivmod:
+    case RTLIB::impl___rt_sdiv64:
+      IsSigned = true;
+      Bits = 64;
+      break;
+    case RTLIB::impl___aeabi_uldivmod:
+    case RTLIB::impl___rt_udiv64:
+      IsSigned = false;
+      Bits = 64;
+      break;
+    default:
+      llvm_unreachable("unexpected divmod libcall");
+    }
+
+    Type *IntTy = IntegerType::get(Ctx, Bits);
+    StructType *RetTy = StructType::get(IntTy, IntTy);
+    FunctionType *FuncTy = FunctionType::get(RetTy, {IntTy, IntTy}, false);
+
+    AttrBuilder FuncAttrBuilder(Ctx);
+    for (Attribute::AttrKind Attr : CommonFnAttrs)
+      FuncAttrBuilder.addAttribute(Attr);
+    FuncAttrBuilder.addMemoryAttr(MemoryEffects::none());
+
+    AttributeList Attrs;
+    Attrs = Attrs.addFnAttributes(Ctx, FuncAttrBuilder);
+
+    Attribute::AttrKind ExtKind = IsSigned ? Attribute::SExt : Attribute::ZExt;
+    Attrs = Attrs.addRetAttribute(Ctx, Attribute::InReg);
+    Attrs = Attrs.addParamAttribute(Ctx, 0, ExtKind);
+    Attrs = Attrs.addParamAttribute(Ctx, 1, ExtKind);
+
+    return {FuncTy, Attrs};
+  }
   case RTLIB::impl_sqrtf:
   case RTLIB::impl_sqrt: {
     AttrBuilder FuncAttrBuilder(Ctx);
diff --git a/llvm/test/Transforms/Util/DeclareRuntimeLibcalls/divmod.ll b/llvm/test/Transforms/Util/DeclareRuntimeLibcalls/divmod.ll
new file mode 100644
index 0000000000000..be7c8c62ff978
--- /dev/null
+++ b/llvm/test/Transforms/Util/DeclareRuntimeLibcalls/divmod.ll
@@ -0,0 +1,26 @@
+; REQUIRES: arm-registered-target
+
+; RUN: opt -S -passes=declare-runtime-libcalls -mtriple=armv7-none-eabi < %s | FileCheck -check-prefix=AEABI %s
+; RUN: opt -S -passes=declare-runtime-libcalls -mtriple=thumbv7-windows-msvc < %s | FileCheck -check-prefix=WINDOWS %s
+
+; RUN: opt -S -passes=declare-runtime-libcalls -mtriple=armv7-apple-ios5.0 < %s | FileCheck -check-prefix=DARWIN %s
+
+; AEABI: declare arm_aapcscc inreg { i32, i32 } @__aeabi_idivmod(i32 signext, i32 signext) #0
+; AEABI: declare arm_aapcscc inreg { i64, i64 } @__aeabi_ldivmod(i64 signext, i64 signext) #0
+; AEABI: declare arm_aapcscc inreg { i32, i32 } @__aeabi_uidivmod(i32 zeroext, i32 zeroext) #0
+; AEABI: declare arm_aapcscc inreg { i64, i64 } @__aeabi_uldivmod(i64 zeroext, i64 zeroext) #0
+; AEABI: attributes #0 = { nocallback nofree nosync nounwind willreturn memory(none) }
+
+; WINDOWS: declare arm_aapcscc inreg { i32, i32 } @__rt_sdiv(i32 signext, i32 signext) #0
+; WINDOWS: declare arm_aapcscc inreg { i64, i64 } @__rt_sdiv64(i64 signext, i64 signext) #0
+; WINDOWS: declare arm_aapcscc inreg { i32, i32 } @__rt_udiv(i32 zeroext, i32 zeroext) #0
+; WINDOWS: declare arm_aapcscc inreg { i64, i64 } @__rt_udiv64(i64 zeroext, i64 zeroext) #0
+; WINDOWS: attributes #0 = { nocallback nofree nosync nounwind willreturn memory(none) }
+
+; DARWIN: declare void @__divmodsi4(...)
+; DARWIN: declare void @__udivmodsi4(...)
+; DARWIN-NOT: inreg { i32, i32 } @__divmodsi4
+
+define void @f() {
+  ret void
+}

``````````

</details>


https://github.com/llvm/llvm-project/pull/217825


More information about the llvm-commits mailing list