summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatt Arsenault <Matthew.Arsenault@amd.com>2025-11-07 17:19:28 -0800
committerMatt Arsenault <arsenm2@gmail.com>2025-11-11 19:23:52 -0800
commitf4beefa35f8ffff3f38397d0c4998cf88e8f63a2 (patch)
tree9a0633b3f2380b3035a499379f5623c0d01741ed
parent22df2fbbf4df276e4962acb3eead47443aa7b1c4 (diff)
RuntimeLibcalls: Add malloc and free entriesusers/arsenm/runtime-libcalls/add-malloc-calloc-free
Calloc was already here, but not the others. Also add manual type information.
-rw-r--r--llvm/include/llvm/IR/RuntimeLibcalls.td5
-rw-r--r--llvm/lib/IR/RuntimeLibcalls.cpp75
-rw-r--r--llvm/test/Transforms/Util/DeclareRuntimeLibcalls/basic.ll9
3 files changed, 89 insertions, 0 deletions
diff --git a/llvm/include/llvm/IR/RuntimeLibcalls.td b/llvm/include/llvm/IR/RuntimeLibcalls.td
index 11e6127e0741..5a66b23051b2 100644
--- a/llvm/include/llvm/IR/RuntimeLibcalls.td
+++ b/llvm/include/llvm/IR/RuntimeLibcalls.td
@@ -382,7 +382,9 @@ def MEMMOVE : RuntimeLibcall;
def MEMMOVE_CHK : RuntimeLibcall;
def MEMSET : RuntimeLibcall;
def MEMSET_CHK : RuntimeLibcall;
+def MALLOC : RuntimeLibcall;
def CALLOC : RuntimeLibcall;
+def FREE : RuntimeLibcall;
def BZERO : RuntimeLibcall;
def STRLEN : RuntimeLibcall;
@@ -1101,8 +1103,11 @@ def __memcpy_chk : RuntimeLibcallImpl<MEMCPY_CHK>;
def __memmove_chk : RuntimeLibcallImpl<MEMMOVE_CHK>;
def __memset_chk : RuntimeLibcallImpl<MEMSET_CHK>;
+def malloc : RuntimeLibcallImpl<MALLOC>;
+
// DSEPass can emit calloc if it finds a pair of malloc/memset
def calloc : RuntimeLibcallImpl<CALLOC>;
+def free : RuntimeLibcallImpl<FREE>;
} // End let IsDefault = true
diff --git a/llvm/lib/IR/RuntimeLibcalls.cpp b/llvm/lib/IR/RuntimeLibcalls.cpp
index b63264b219f1..b80f7572f2af 100644
--- a/llvm/lib/IR/RuntimeLibcalls.cpp
+++ b/llvm/lib/IR/RuntimeLibcalls.cpp
@@ -129,13 +129,23 @@ bool RuntimeLibcallsInfo::darwinHasExp10(const Triple &TT) {
}
}
+/// TODO: There is really no guarantee that sizeof(size_t) is equal to the index
+/// size of the edfault address space. This matches TargetLibraryInfo and should
+/// be kept in sync.
+static IntegerType *getSizeTType(LLVMContext &Ctx, const DataLayout &DL) {
+ return DL.getIndexType(Ctx, /*AddressSpace=*/0);
+}
+
std::pair<FunctionType *, AttributeList>
RuntimeLibcallsInfo::getFunctionTy(LLVMContext &Ctx, const Triple &TT,
const DataLayout &DL,
RTLIB::LibcallImpl LibcallImpl) const {
+ // TODO: NoCallback probably unsafe in general
static constexpr Attribute::AttrKind CommonFnAttrs[] = {
Attribute::MustProgress, Attribute::NoCallback, Attribute::NoFree,
Attribute::NoSync, Attribute::NoUnwind, Attribute::WillReturn};
+ static constexpr Attribute::AttrKind MemoryFnAttrs[] = {
+ Attribute::MustProgress, Attribute::NoUnwind, Attribute::WillReturn};
static constexpr Attribute::AttrKind CommonPtrArgAttrs[] = {
Attribute::NoAlias, Attribute::WriteOnly, Attribute::NonNull};
@@ -181,6 +191,71 @@ RuntimeLibcallsInfo::getFunctionTy(LLVMContext &Ctx, const Triple &TT,
return {FunctionType::get(RetTy, {ScalarTy}, false), Attrs};
}
+ case RTLIB::impl_malloc:
+ case RTLIB::impl_calloc: {
+ AttrBuilder FuncAttrBuilder(Ctx);
+ for (Attribute::AttrKind Attr : MemoryFnAttrs)
+ FuncAttrBuilder.addAttribute(Attr);
+ FuncAttrBuilder.addAttribute(Attribute::NoFree);
+
+ AllocFnKind AllocKind = AllocFnKind::Alloc;
+ if (LibcallImpl == RTLIB::impl_malloc)
+ AllocKind |= AllocFnKind::Uninitialized;
+
+ // TODO: Set memory attribute
+ FuncAttrBuilder.addAllocKindAttr(AllocKind);
+ FuncAttrBuilder.addAttribute("alloc-family", "malloc");
+ FuncAttrBuilder.addAllocSizeAttr(0, LibcallImpl == RTLIB::impl_malloc
+ ? std::nullopt
+ : std::make_optional(1));
+
+ AttributeList Attrs;
+ Attrs = Attrs.addFnAttributes(Ctx, FuncAttrBuilder);
+
+ {
+ AttrBuilder ArgAttrBuilder(Ctx);
+ for (Attribute::AttrKind AK : CommonPtrArgAttrs)
+ ArgAttrBuilder.addAttribute(AK);
+
+ Attrs = Attrs.addRetAttribute(Ctx, Attribute::NoUndef);
+ Attrs = Attrs.addRetAttribute(Ctx, Attribute::NoAlias);
+ Attrs = Attrs.addParamAttribute(Ctx, 0, Attribute::NoUndef);
+ if (LibcallImpl == RTLIB::impl_calloc)
+ Attrs = Attrs.addParamAttribute(Ctx, 1, Attribute::NoUndef);
+ }
+
+ IntegerType *SizeT = getSizeTType(Ctx, DL);
+ PointerType *PtrTy = PointerType::get(Ctx, 0);
+ SmallVector<Type *, 2> ArgTys = {SizeT};
+ if (LibcallImpl == RTLIB::impl_calloc)
+ ArgTys.push_back(SizeT);
+
+ return {FunctionType::get(PtrTy, ArgTys, false), Attrs};
+ }
+ case RTLIB::impl_free: {
+ // TODO: Set memory attribute
+ AttrBuilder FuncAttrBuilder(Ctx);
+ for (Attribute::AttrKind Attr : MemoryFnAttrs)
+ FuncAttrBuilder.addAttribute(Attr);
+
+ FuncAttrBuilder.addAllocKindAttr(AllocFnKind::Free);
+ FuncAttrBuilder.addAttribute("alloc-family", "malloc");
+
+ AttributeList Attrs;
+ Attrs = Attrs.addFnAttributes(Ctx, FuncAttrBuilder);
+
+ {
+ AttrBuilder ArgAttrBuilder(Ctx);
+ ArgAttrBuilder.addAttribute(Attribute::NoUndef);
+ ArgAttrBuilder.addAttribute(Attribute::AllocatedPointer);
+ ArgAttrBuilder.addCapturesAttr(CaptureInfo::none());
+ Attrs = Attrs.addParamAttributes(Ctx, 0, ArgAttrBuilder);
+ }
+
+ return {FunctionType::get(Type::getVoidTy(Ctx), {PointerType::get(Ctx, 0)},
+ false),
+ Attrs};
+ }
case RTLIB::impl_sqrtf:
case RTLIB::impl_sqrt: {
AttrBuilder FuncAttrBuilder(Ctx);
diff --git a/llvm/test/Transforms/Util/DeclareRuntimeLibcalls/basic.ll b/llvm/test/Transforms/Util/DeclareRuntimeLibcalls/basic.ll
index db0cc24c287b..f1a039dc033a 100644
--- a/llvm/test/Transforms/Util/DeclareRuntimeLibcalls/basic.ll
+++ b/llvm/test/Transforms/Util/DeclareRuntimeLibcalls/basic.ll
@@ -20,10 +20,16 @@ define float @sinf(float %x) {
; CHECK: declare void @acosf(...)
+; CHECK: declare noalias noundef ptr @calloc(i64 noundef, i64 noundef) [[CALLOC_ATTRS:#[0-9]+]]
+
; CHECK: declare void @fdim(...)
; CHECK: declare void @fdimf(...)
; CHECK: declare void @fdiml(...)
+; CHECK: declare void @free(ptr allocptr noundef captures(none)) [[FREE_ATTRS:#[0-9]+]]
+
+; CHECK: declare noalias noundef ptr @malloc(i64 noundef) [[MALLOC_ATTRS:#[0-9]+]]
+
; CHECK: declare void @nan(...)
; CHECK: declare void @nanf(...)
; CHECK: declare void @nanl(...)
@@ -58,3 +64,6 @@ define float @sinf(float %x) {
; CHECK: declare void @truncl(...)
+; CHECK: attributes [[CALLOC_ATTRS]] = { mustprogress nofree nounwind willreturn allockind("alloc") allocsize(0,1) "alloc-family"="malloc" }
+; CHECK: attributes [[FREE_ATTRS]] = { mustprogress nounwind willreturn allockind("free") "alloc-family"="malloc" }
+; CHECK: attributes [[MALLOC_ATTRS]] = { mustprogress nofree nounwind willreturn allockind("alloc,uninitialized") allocsize(0) "alloc-family"="malloc" }