[llvm] [aarch64] Fix Arm64EC libcall lowering after recent refactoring. (PR #143977)
Eli Friedman via llvm-commits
llvm-commits at lists.llvm.org
Thu Jun 12 18:05:57 PDT 2025
https://github.com/efriedma-quic updated https://github.com/llvm/llvm-project/pull/143977
>From 6824c9a8e9ada6e669f1e24d62834aeccaced384 Mon Sep 17 00:00:00 2001
From: Eli Friedman <efriedma at quicinc.com>
Date: Thu, 12 Jun 2025 14:32:04 -0700
Subject: [PATCH 1/2] [aarch64] Fix Arm64EC libcall lowering after recent
refactoring.
The refactored code accidentally tokenized a string instead of just
concatenating it.
Add a regression test and some assertions to ensure consistency.
---
llvm/include/llvm/IR/RuntimeLibcalls.def | 48 +++++++++----------
llvm/lib/IR/RuntimeLibcalls.cpp | 15 ++++--
.../WebAssemblyRuntimeLibcallSignatures.cpp | 2 +
llvm/test/CodeGen/AArch64/arm64ec-builtins.ll | 31 ++++++++++++
4 files changed, 68 insertions(+), 28 deletions(-)
create mode 100644 llvm/test/CodeGen/AArch64/arm64ec-builtins.ll
diff --git a/llvm/include/llvm/IR/RuntimeLibcalls.def b/llvm/include/llvm/IR/RuntimeLibcalls.def
index 4ddae8e48193f..247643525ff48 100644
--- a/llvm/include/llvm/IR/RuntimeLibcalls.def
+++ b/llvm/include/llvm/IR/RuntimeLibcalls.def
@@ -70,16 +70,16 @@ HANDLE_LIBCALL(UREM_I16, "__umodhi3")
HANDLE_LIBCALL(UREM_I32, "__umodsi3")
HANDLE_LIBCALL(UREM_I64, "__umoddi3")
HANDLE_LIBCALL(UREM_I128, "__umodti3")
-HANDLE_LIBCALL(SDIVREM_I8, nullptr)
-HANDLE_LIBCALL(SDIVREM_I16, nullptr)
-HANDLE_LIBCALL(SDIVREM_I32, nullptr)
-HANDLE_LIBCALL(SDIVREM_I64, nullptr)
-HANDLE_LIBCALL(SDIVREM_I128, nullptr)
-HANDLE_LIBCALL(UDIVREM_I8, nullptr)
-HANDLE_LIBCALL(UDIVREM_I16, nullptr)
-HANDLE_LIBCALL(UDIVREM_I32, nullptr)
-HANDLE_LIBCALL(UDIVREM_I64, nullptr)
-HANDLE_LIBCALL(UDIVREM_I128, nullptr)
+HANDLE_LIBCALL(SDIVREM_I8, LIBCALL_NO_NAME)
+HANDLE_LIBCALL(SDIVREM_I16, LIBCALL_NO_NAME)
+HANDLE_LIBCALL(SDIVREM_I32, LIBCALL_NO_NAME)
+HANDLE_LIBCALL(SDIVREM_I64, LIBCALL_NO_NAME)
+HANDLE_LIBCALL(SDIVREM_I128, LIBCALL_NO_NAME)
+HANDLE_LIBCALL(UDIVREM_I8, LIBCALL_NO_NAME)
+HANDLE_LIBCALL(UDIVREM_I16, LIBCALL_NO_NAME)
+HANDLE_LIBCALL(UDIVREM_I32, LIBCALL_NO_NAME)
+HANDLE_LIBCALL(UDIVREM_I64, LIBCALL_NO_NAME)
+HANDLE_LIBCALL(UDIVREM_I128, LIBCALL_NO_NAME)
HANDLE_LIBCALL(NEG_I32, "__negsi2")
HANDLE_LIBCALL(NEG_I64, "__negdi2")
HANDLE_LIBCALL(CTLZ_I32, "__clzsi2")
@@ -240,13 +240,13 @@ HANDLE_LIBCALL(ATAN2_F64, "atan2")
HANDLE_LIBCALL(ATAN2_F80, "atan2l")
HANDLE_LIBCALL(ATAN2_F128,"atan2l")
HANDLE_LIBCALL(ATAN2_PPCF128, "atan2l")
-HANDLE_LIBCALL(SINCOS_F32, nullptr)
-HANDLE_LIBCALL(SINCOS_F64, nullptr)
-HANDLE_LIBCALL(SINCOS_F80, nullptr)
-HANDLE_LIBCALL(SINCOS_F128, nullptr)
-HANDLE_LIBCALL(SINCOS_PPCF128, nullptr)
-HANDLE_LIBCALL(SINCOS_STRET_F32, nullptr)
-HANDLE_LIBCALL(SINCOS_STRET_F64, nullptr)
+HANDLE_LIBCALL(SINCOS_F32, LIBCALL_NO_NAME)
+HANDLE_LIBCALL(SINCOS_F64, LIBCALL_NO_NAME)
+HANDLE_LIBCALL(SINCOS_F80, LIBCALL_NO_NAME)
+HANDLE_LIBCALL(SINCOS_F128, LIBCALL_NO_NAME)
+HANDLE_LIBCALL(SINCOS_PPCF128, LIBCALL_NO_NAME)
+HANDLE_LIBCALL(SINCOS_STRET_F32, LIBCALL_NO_NAME)
+HANDLE_LIBCALL(SINCOS_STRET_F64, LIBCALL_NO_NAME)
HANDLE_LIBCALL(POW_F32, "powf")
HANDLE_LIBCALL(POW_F64, "pow")
HANDLE_LIBCALL(POW_F80, "powl")
@@ -518,7 +518,7 @@ HANDLE_LIBCALL(MEMMOVE, "memmove")
HANDLE_LIBCALL(MEMSET, "memset")
// DSEPass can emit calloc if it finds a pair of malloc/memset
HANDLE_LIBCALL(CALLOC, "calloc")
-HANDLE_LIBCALL(BZERO, nullptr)
+HANDLE_LIBCALL(BZERO, LIBCALL_NO_NAME)
// Element-wise unordered-atomic memory of different sizes
HANDLE_LIBCALL(MEMCPY_ELEMENT_UNORDERED_ATOMIC_1, "__llvm_memcpy_element_unordered_atomic_1")
@@ -669,10 +669,10 @@ HANDLE_LIBCALL(ATOMIC_FETCH_NAND_16, "__atomic_fetch_nand_16")
// Out-of-line atomics libcalls
#define HLCALLS(A, N) \
- HANDLE_LIBCALL(A##N##_RELAX, nullptr) \
- HANDLE_LIBCALL(A##N##_ACQ, nullptr) \
- HANDLE_LIBCALL(A##N##_REL, nullptr) \
- HANDLE_LIBCALL(A##N##_ACQ_REL, nullptr)
+ HANDLE_LIBCALL(A##N##_RELAX, LIBCALL_NO_NAME) \
+ HANDLE_LIBCALL(A##N##_ACQ, LIBCALL_NO_NAME) \
+ HANDLE_LIBCALL(A##N##_REL, LIBCALL_NO_NAME) \
+ HANDLE_LIBCALL(A##N##_ACQ_REL, LIBCALL_NO_NAME)
#define HLCALL5(A) \
HLCALLS(A, 1) HLCALLS(A, 2) HLCALLS(A, 4) HLCALLS(A, 8) HLCALLS(A, 16)
HLCALL5(OUTLINE_ATOMIC_CAS)
@@ -691,11 +691,11 @@ HANDLE_LIBCALL(STACKPROTECTOR_CHECK_FAIL, "__stack_chk_fail")
HANDLE_LIBCALL(DEOPTIMIZE, "__llvm_deoptimize")
// Return address
-HANDLE_LIBCALL(RETURN_ADDRESS, nullptr)
+HANDLE_LIBCALL(RETURN_ADDRESS, LIBCALL_NO_NAME)
// Clear cache
HANDLE_LIBCALL(CLEAR_CACHE, "__clear_cache")
HANDLE_LIBCALL(RISCV_FLUSH_ICACHE, "__riscv_flush_icache")
-HANDLE_LIBCALL(UNKNOWN_LIBCALL, nullptr)
+HANDLE_LIBCALL(UNKNOWN_LIBCALL, LIBCALL_NO_NAME)
diff --git a/llvm/lib/IR/RuntimeLibcalls.cpp b/llvm/lib/IR/RuntimeLibcalls.cpp
index d84c56f0af5c6..5cce688595b94 100644
--- a/llvm/lib/IR/RuntimeLibcalls.cpp
+++ b/llvm/lib/IR/RuntimeLibcalls.cpp
@@ -21,13 +21,17 @@ static void setAArch64LibcallNames(RuntimeLibcallsInfo &Info,
if (TT.isWindowsArm64EC()) {
// FIXME: are there calls we need to exclude from this?
#define HANDLE_LIBCALL(code, name) \
- { \
+ if (sizeof(name) != 1) { \
const char *libcallName = Info.getLibcallName(RTLIB::code); \
- if (libcallName && libcallName[0] != '#') \
- Info.setLibcallName(RTLIB::code, "#" #name); \
+ if (libcallName && libcallName[0] != '#') { \
+ assert(strcmp(libcallName, name) == 0 && "Unexpected name"); \
+ Info.setLibcallName(RTLIB::code, "#" name); \
+ } \
}
+#define LIBCALL_NO_NAME ""
#include "llvm/IR/RuntimeLibcalls.def"
#undef HANDLE_LIBCALL
+#undef LIBCALL_NO_NAME
}
}
@@ -223,8 +227,10 @@ void RuntimeLibcallsInfo::initLibcalls(const Triple &TT) {
nullptr);
#define HANDLE_LIBCALL(code, name) setLibcallName(RTLIB::code, name);
+#define LIBCALL_NO_NAME nullptr
#include "llvm/IR/RuntimeLibcalls.def"
#undef HANDLE_LIBCALL
+#undef LIBCALL_NO_NAME
// Initialize calling conventions to their default.
for (int LC = 0; LC < RTLIB::UNKNOWN_LIBCALL; ++LC)
@@ -462,7 +468,8 @@ void RuntimeLibcallsInfo::initLibcalls(const Triple &TT) {
}
// Setup Windows compiler runtime calls.
- if (TT.isWindowsMSVCEnvironment() || TT.isWindowsItaniumEnvironment()) {
+ if (TT.getArch() == Triple::x86 &&
+ (TT.isWindowsMSVCEnvironment() || TT.isWindowsItaniumEnvironment())) {
static const struct {
const RTLIB::Libcall Op;
const char *const Name;
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyRuntimeLibcallSignatures.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyRuntimeLibcallSignatures.cpp
index ce795d3dedc6a..d5c4532824c07 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyRuntimeLibcallSignatures.cpp
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyRuntimeLibcallSignatures.cpp
@@ -531,8 +531,10 @@ struct StaticLibcallNameMap {
StaticLibcallNameMap() {
static const std::pair<const char *, RTLIB::Libcall> NameLibcalls[] = {
#define HANDLE_LIBCALL(code, name) {(const char *)name, RTLIB::code},
+#define LIBCALL_NO_NAME nullptr
#include "llvm/IR/RuntimeLibcalls.def"
#undef HANDLE_LIBCALL
+#undef LIBCALL_NO_NAME
};
for (const auto &NameLibcall : NameLibcalls) {
if (NameLibcall.first != nullptr &&
diff --git a/llvm/test/CodeGen/AArch64/arm64ec-builtins.ll b/llvm/test/CodeGen/AArch64/arm64ec-builtins.ll
new file mode 100644
index 0000000000000..60b4bf7f39dd8
--- /dev/null
+++ b/llvm/test/CodeGen/AArch64/arm64ec-builtins.ll
@@ -0,0 +1,31 @@
+; RUN: llc -mtriple=arm64ec-pc-windows-msvc < %s | FileCheck %s
+
+define void @f1(ptr %p, i64 %n) {
+; CHECK-LABEL: "#f1":
+; CHECK: bl "#memset"
+ call void @llvm.memset.p0.i64(ptr %p, i8 0, i64 %n, i1 false)
+ ret void
+}
+
+define void @f2(ptr %p1, ptr %p2, i64 %n) {
+; CHECK-LABEL: "#f2":
+; CHECK: bl "#memcpy"
+ call void @llvm.memcpy.p0.i64(ptr %p1, ptr %p2, i64 %n, i1 false)
+ ret void
+}
+
+define double @f3(double %x, double %y) {
+; CHECK-LABEL: "#f3":
+; CHECK: b "#fmod"
+ %r = frem double %x, %y
+ ret double %r
+}
+
+
+define i128 @f4(i128 %x, i128 %y) {
+; CHECK-LABEL: "#f4":
+; CHECK: bl "#__divti3"
+ %r = sdiv i128 %x, %y
+ ret i128 %r
+}
+
>From 27a463b4187cbfe2d63db0527f5ddf403735327a Mon Sep 17 00:00:00 2001
From: Eli Friedman <efriedma at quicinc.com>
Date: Thu, 12 Jun 2025 18:05:36 -0700
Subject: [PATCH 2/2] Add a couple more tests.
---
llvm/test/CodeGen/AArch64/arm64ec-builtins.ll | 16 +++++++++++++++-
1 file changed, 15 insertions(+), 1 deletion(-)
diff --git a/llvm/test/CodeGen/AArch64/arm64ec-builtins.ll b/llvm/test/CodeGen/AArch64/arm64ec-builtins.ll
index 60b4bf7f39dd8..92b95a90d89a0 100644
--- a/llvm/test/CodeGen/AArch64/arm64ec-builtins.ll
+++ b/llvm/test/CodeGen/AArch64/arm64ec-builtins.ll
@@ -21,7 +21,6 @@ define double @f3(double %x, double %y) {
ret double %r
}
-
define i128 @f4(i128 %x, i128 %y) {
; CHECK-LABEL: "#f4":
; CHECK: bl "#__divti3"
@@ -29,3 +28,18 @@ define i128 @f4(i128 %x, i128 %y) {
ret i128 %r
}
+; FIXME: This is wrong; should be "#__aarch64_cas1_relax"
+define i8 @f5(i8 %expected, i8 %new, ptr %ptr) "target-features"="+outline-atomics" {
+; CHECK-LABEL: "#f5":
+; CHECK: bl __aarch64_cas1_relax
+ %pair = cmpxchg ptr %ptr, i8 %expected, i8 %new monotonic monotonic, align 1
+ %r = extractvalue { i8, i1 } %pair, 0
+ ret i8 %r
+}
+
+define float @f6(float %val, i32 %a) {
+; CHECK-LABEL: "#f6":
+; CHECK: bl "#ldexp"
+ %call = tail call fast float @llvm.ldexp.f32(float %val, i32 %a)
+ ret float %call
+}
More information about the llvm-commits
mailing list