[Openmp-commits] [openmp] [openmp] Add initial ARM64EC support (PR #138769)
Jacek Caban via Openmp-commits
openmp-commits at lists.llvm.org
Tue May 6 15:06:27 PDT 2025
https://github.com/cjacek updated https://github.com/llvm/llvm-project/pull/138769
>From af3bac5f0621a7fd85980eb9cc616a5c5a443bef Mon Sep 17 00:00:00 2001
From: Jacek Caban <jacek at codeweavers.com>
Date: Sat, 3 May 2025 19:24:19 +0200
Subject: [PATCH] [openmp] Add initial ARM64EC support
Treat ARM64EC as an AArch64 target for the most part. Since the vararg calling convention
differs, add a dedicated implementation based on the AArch64 variant. The differences include:
- Only the first four parameters are passed via registers
- x4 contains a pointer to the first stack argument
- x5 contains the size of arguments passed via the stack
- The call is preceded by a call to __os_arm64x_check_icall, which optionally sets up an indirect
call via an exit thunk if the target is x86_64 code
---
.../runtime/cmake/LibompGetArchitecture.cmake | 4 +-
openmp/runtime/src/kmp_platform.h | 9 +-
openmp/runtime/src/z_Linux_asm.S | 103 ++++++++++++++++++
3 files changed, 110 insertions(+), 6 deletions(-)
diff --git a/openmp/runtime/cmake/LibompGetArchitecture.cmake b/openmp/runtime/cmake/LibompGetArchitecture.cmake
index 81aa700e3b6db..f58b8c6464fb8 100644
--- a/openmp/runtime/cmake/LibompGetArchitecture.cmake
+++ b/openmp/runtime/cmake/LibompGetArchitecture.cmake
@@ -17,6 +17,8 @@ function(libomp_get_architecture return_arch)
set(detect_arch_src_txt "
#if defined(__KNC__)
#error ARCHITECTURE=mic
+ #elif defined(__aarch64__) || defined(_M_ARM64) || defined(__arm64ec__) || defined(_M_ARM64EC)
+ #error ARCHITECTURE=aarch64
#elif defined(__amd64__) || defined(__amd64) || defined(__x86_64__) || defined(__x86_64) || defined(_M_X64) || defined(_M_AMD64)
#error ARCHITECTURE=x86_64
#elif defined(__i386) || defined(__i386__) || defined(__IA32__) || defined(_M_I86) || defined(_M_IX86) || defined(__X86__) || defined(_X86_)
@@ -37,8 +39,6 @@ function(libomp_get_architecture return_arch)
#error ARCHITECTURE=arm
#elif defined(__ARM64_ARCH_8_32__)
#error ARCHITECTURE=aarch64_32
- #elif defined(__aarch64__) || defined(_M_ARM64)
- #error ARCHITECTURE=aarch64
#elif defined(__powerpc64__) && defined(__LITTLE_ENDIAN__)
#error ARCHITECTURE=ppc64le
#elif defined(__powerpc64__)
diff --git a/openmp/runtime/src/kmp_platform.h b/openmp/runtime/src/kmp_platform.h
index 80afba6c6af2e..d2b8aa96aa8b8 100644
--- a/openmp/runtime/src/kmp_platform.h
+++ b/openmp/runtime/src/kmp_platform.h
@@ -132,15 +132,16 @@
#define KMP_ARCH_SPARC 0
#if KMP_OS_WINDOWS
-#if defined(_M_AMD64) || defined(__x86_64)
-#undef KMP_ARCH_X86_64
-#define KMP_ARCH_X86_64 1
-#elif defined(__aarch64__) || defined(_M_ARM64)
+#if defined(__aarch64__) || defined(_M_ARM64) || defined(__arm64ec__) || \
+ defined(_M_ARM64EC)
#undef KMP_ARCH_AARCH64
#define KMP_ARCH_AARCH64 1
#elif defined(__arm__) || defined(_M_ARM)
#undef KMP_ARCH_ARMV7
#define KMP_ARCH_ARMV7 1
+#elif defined(_M_AMD64) || defined(__x86_64)
+#undef KMP_ARCH_X86_64
+#define KMP_ARCH_X86_64 1
#else
#undef KMP_ARCH_X86
#define KMP_ARCH_X86 1
diff --git a/openmp/runtime/src/z_Linux_asm.S b/openmp/runtime/src/z_Linux_asm.S
index 607bfd8e3cb0f..6ae8d1cc1b3ab 100644
--- a/openmp/runtime/src/z_Linux_asm.S
+++ b/openmp/runtime/src/z_Linux_asm.S
@@ -159,6 +159,7 @@ KMP_PREFIX_UNDERSCORE($0):
.globl KMP_PREFIX_UNDERSCORE(\proc)
KMP_PREFIX_UNDERSCORE(\proc):
.endm
+
# else // KMP_OS_DARWIN || KMP_OS_WINDOWS
# define KMP_PREFIX_UNDERSCORE(x) x // no extra underscore for Linux* OS symbols
// Format labels so that they don't override function names in gdb's backtraces
@@ -1301,6 +1302,106 @@ KMP_LABEL(kmp_no_args):
// '
#if (KMP_OS_LINUX || KMP_OS_DARWIN || KMP_OS_WINDOWS) && (KMP_ARCH_AARCH64 || KMP_ARCH_AARCH64_32)
+#ifdef __arm64ec__
+
+//------------------------------------------------------------------------
+// int
+// __kmp_invoke_microtask( void (*pkfn) (int gtid, int tid, ...),
+// int gtid, int tid,
+// int argc, void *p_argv[]) {
+// (*pkfn)( & gtid, & tid, argv[0], ... );
+// return 1;
+// }
+//
+// parameters:
+// x0: pkfn
+// w1: gtid
+// w2: tid
+// w3: argc
+// x4: p_argv
+//
+// locals:
+// __gtid: gtid parm pushed on stack so can pass >id to pkfn
+// __tid: tid parm pushed on stack so can pass &tid to pkfn
+//
+// reg temps:
+// x8: used as temporary for stack placement calculation
+// w9: used as temporary for number of pkfn parms
+// x10: used to traverse p_argv array
+// x11: used to hold pkfn address
+// x12: used as temporary for stack parameters
+// x19: used to preserve exit_frame_ptr, callee-save
+//
+// return: w0 (always 1/TRUE)
+//
+
+__gtid = 4
+__tid = 8
+
+// -- Begin __kmp_invoke_microtask
+// mark_begin;
+ .section .text,"xr",discard,"#__kmp_invoke_microtask"
+ .globl "#__kmp_invoke_microtask"
+ ALIGN 2
+"#__kmp_invoke_microtask":
+ stp x29, x30, [sp, #-16]!
+ mov x29, sp
+
+ mov w9, #1
+ add w9, w9, w3, lsr #1
+ sub sp, sp, w9, uxtw #4
+ mov x8, sp
+
+ mov x11, x0
+ str w1, [x29, #-__gtid]
+ str w2, [x29, #-__tid]
+ mov w9, w3
+ mov x10, x4
+
+ sub x0, x29, #__gtid
+ sub x1, x29, #__tid
+ mov x4, sp
+ mov w5, #0
+
+ cbz w9, KMP_LABEL(kmp_1)
+ ldr x2, [x10]
+
+ sub w9, w9, #1
+ cbz w9, KMP_LABEL(kmp_1)
+ ldr x3, [x10, #8]!
+
+ sub w5, w9, #1
+ lsl w5, w5, #3
+
+KMP_LABEL(kmp_0):
+ cbz w9, KMP_LABEL(kmp_1)
+ ldr x12, [x10, #8]!
+ str x12, [x8], #8
+ sub w9, w9, #1
+ b KMP_LABEL(kmp_0)
+KMP_LABEL(kmp_1):
+ adrp x10, $iexit_thunk$cdecl$v$varargs
+ add x10, x10, :lo12:$iexit_thunk$cdecl$v$varargs
+ adrp x8, __os_arm64x_check_icall
+ ldr x8, [x8, :lo12:__os_arm64x_check_icall]
+ blr x8
+ blr x11
+ mov w0, #1
+ mov sp, x29
+ ldp x29, x30, [sp], #16
+ ret
+
+ .weak_anti_dep __kmp_invoke_microtask
+ .set __kmp_invoke_microtask, "#__kmp_invoke_microtask"
+
+ .section .hybmp$x,"yi"
+ .symidx "#__kmp_invoke_microtask"
+ .symidx $ientry_thunk$cdecl$i8$i8i8i8i8i8
+ .word 1
+// -- End __kmp_invoke_microtask
+
+#else
+
//------------------------------------------------------------------------
// int
// __kmp_invoke_microtask( void (*pkfn) (int gtid, int tid, ...),
@@ -1425,6 +1526,8 @@ KMP_LABEL(kmp_1):
DEBUG_INFO __kmp_invoke_microtask
// -- End __kmp_invoke_microtask
+#endif
+
#endif /* (KMP_OS_LINUX || KMP_OS_DARWIN || KMP_OS_WINDOWS) && (KMP_ARCH_AARCH64 || KMP_ARCH_AARCH64_32) */
#if (KMP_OS_LINUX || KMP_OS_DARWIN || KMP_OS_WINDOWS) && KMP_ARCH_ARM
More information about the Openmp-commits
mailing list