[Openmp-commits] [openmp] [openmp] Add support for arm64ec to libomp (PR #176151)
David Truby via Openmp-commits
openmp-commits at lists.llvm.org
Wed Jan 28 05:23:31 PST 2026
https://github.com/DavidTruby updated https://github.com/llvm/llvm-project/pull/176151
>From b36d30ec3e58a2a43cfa2dce7b234d1039c121cd Mon Sep 17 00:00:00 2001
From: David Truby <david.truby at arm.com>
Date: Tue, 11 Nov 2025 15:34:27 +0000
Subject: [PATCH 1/3] [openmp] Add support for arm64ec to libomp
This patch adds arm64ec support to libomp.
Note that this support isn't entirely usable on Windows hosts as libomp
requires LLVM_PER_TARGET_RUNTIME_DIR=On for to work correctly when
multiple runtimes are built, which is unsupported on Windows. A
following patch will add arm64x support to the build to rectify this.
---
openmp/cmake/modules/LibompUtils.cmake | 2 ++
openmp/runtime/CMakeLists.txt | 6 +++++-
openmp/runtime/cmake/LibompGetArchitecture.cmake | 3 +++
openmp/runtime/src/kmp.h | 3 ++-
openmp/runtime/src/kmp_atomic.cpp | 2 +-
openmp/runtime/src/kmp_os.h | 8 +++++---
openmp/runtime/src/kmp_platform.h | 8 ++++++--
openmp/runtime/src/kmp_runtime.cpp | 2 +-
.../runtime/src/thirdparty/ittnotify/ittnotify_config.h | 2 ++
openmp/runtime/src/z_Windows_NT-586_util.cpp | 8 +++++---
10 files changed, 32 insertions(+), 12 deletions(-)
diff --git a/openmp/cmake/modules/LibompUtils.cmake b/openmp/cmake/modules/LibompUtils.cmake
index a810881c2544e..b67b77339d074 100644
--- a/openmp/cmake/modules/LibompUtils.cmake
+++ b/openmp/cmake/modules/LibompUtils.cmake
@@ -105,6 +105,8 @@ function(libomp_get_legal_arch return_arch_string)
set(${return_arch_string} "AARCH64_32" PARENT_SCOPE)
elseif(${AARCH64_A64FX})
set(${return_arch_string} "AARCH64_A64FX" PARENT_SCOPE)
+ elseif(${ARM64EC})
+ set(${return_arch_string} "ARM64EC" PARENT_SCOPE)
elseif(${MIPS})
set(${return_arch_string} "MIPS" PARENT_SCOPE)
elseif(${MIPS64})
diff --git a/openmp/runtime/CMakeLists.txt b/openmp/runtime/CMakeLists.txt
index 93948b941f0dc..a8edcc3810be7 100644
--- a/openmp/runtime/CMakeLists.txt
+++ b/openmp/runtime/CMakeLists.txt
@@ -53,6 +53,8 @@ else() # Part of LLVM build
set(LIBOMP_ARCH aarch64_32)
elseif(LIBOMP_NATIVE_ARCH MATCHES "aarch64")
set(LIBOMP_ARCH aarch64)
+ elseif(LIBOMP_NATIVE_ARCH MATCHES "arm64ec")
+ set(LIBOMP_ARCH arm64ec)
elseif(LIBOMP_NATIVE_ARCH MATCHES "arm64")
set(LIBOMP_ARCH aarch64)
elseif(LIBOMP_NATIVE_ARCH MATCHES "arm")
@@ -91,7 +93,7 @@ if(LIBOMP_ARCH STREQUAL "aarch64")
endif()
endif()
-libomp_check_variable(LIBOMP_ARCH 32e x86_64 32 i386 arm ppc ppc64 ppc64le aarch64 aarch64_32 aarch64_a64fx mic mips mips64 riscv64 loongarch64 ve s390x sparc sparcv9 wasm32)
+libomp_check_variable(LIBOMP_ARCH 32e x86_64 32 i386 arm ppc ppc64 ppc64le aarch64 aarch64_32 aarch64_a64fx arm64ec mic mips mips64 riscv64 loongarch64 ve s390x sparc sparcv9 wasm32)
set(LIBOMP_LIB_TYPE normal CACHE STRING
"Performance,Profiling,Stubs library (normal/profile/stubs)")
@@ -193,6 +195,8 @@ elseif("${LIBOMP_ARCH}" STREQUAL "aarch64_32") # AARCH64_32 architecture
set(AARCH64_32 TRUE)
elseif("${LIBOMP_ARCH}" STREQUAL "aarch64_a64fx") # AARCH64_A64FX architecture
set(AARCH64_A64FX TRUE)
+elseif("${LIBOMP_ARCH}" STREQUAL "arm64ec") # ARM64EC architecture
+ set(ARM64EC TRUE)
elseif("${LIBOMP_ARCH}" STREQUAL "mic") # Intel(R) Many Integrated Core Architecture
set(MIC TRUE)
elseif("${LIBOMP_ARCH}" STREQUAL "mips") # MIPS architecture
diff --git a/openmp/runtime/cmake/LibompGetArchitecture.cmake b/openmp/runtime/cmake/LibompGetArchitecture.cmake
index 81aa700e3b6db..4127ea451ac91 100644
--- a/openmp/runtime/cmake/LibompGetArchitecture.cmake
+++ b/openmp/runtime/cmake/LibompGetArchitecture.cmake
@@ -17,6 +17,9 @@ function(libomp_get_architecture return_arch)
set(detect_arch_src_txt "
#if defined(__KNC__)
#error ARCHITECTURE=mic
+ // arm64ec also defines _M_AMD64 so this needs to be checked before that
+ #elif defined(_M_ARM64EC)
+ #error ARCHITECTURE=arm64ec
#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_)
diff --git a/openmp/runtime/src/kmp.h b/openmp/runtime/src/kmp.h
index 36c40abaf1ef4..55b1b5282df0f 100644
--- a/openmp/runtime/src/kmp.h
+++ b/openmp/runtime/src/kmp.h
@@ -3901,7 +3901,8 @@ extern void __kmp_check_stack_overlap(kmp_info_t *thr);
extern void __kmp_expand_host_name(char *buffer, size_t size);
extern void __kmp_expand_file_name(char *result, size_t rlen, char *pattern);
-#if KMP_ARCH_X86 || KMP_ARCH_X86_64 || (KMP_OS_WINDOWS && (KMP_ARCH_AARCH64 || KMP_ARCH_ARM))
+#if KMP_ARCH_X86 || KMP_ARCH_X86_64 || \
+ (KMP_OS_WINDOWS && (KMP_ARCH_AARCH64 || KMP_ARCH_ARM || KMP_ARCH_ARM64EC))
extern void
__kmp_initialize_system_tick(void); /* Initialize timer tick value */
#endif
diff --git a/openmp/runtime/src/kmp_atomic.cpp b/openmp/runtime/src/kmp_atomic.cpp
index 261e9f1beee67..d259737eb5ce1 100644
--- a/openmp/runtime/src/kmp_atomic.cpp
+++ b/openmp/runtime/src/kmp_atomic.cpp
@@ -832,7 +832,7 @@ static inline kmp_cmplx128_a16_t operator/(kmp_cmplx128_a16_t &lhs,
// end of the first part of the workaround for C78287
#endif // USE_CMPXCHG_FIX
-#if KMP_OS_WINDOWS && (KMP_ARCH_AARCH64 || KMP_ARCH_ARM)
+#if KMP_OS_WINDOWS && (KMP_ARCH_AARCH64 || KMP_ARCH_ARM || KMP_ARCH_ARM64EC)
// Undo explicit type casts to get MSVC ARM64 to build. Uses
// OP_CMPXCHG_WORKAROUND definition for OP_CMPXCHG
#undef OP_CMPXCHG
diff --git a/openmp/runtime/src/kmp_os.h b/openmp/runtime/src/kmp_os.h
index e8ad2a6fdb78e..0fdf5a99bd1f8 100644
--- a/openmp/runtime/src/kmp_os.h
+++ b/openmp/runtime/src/kmp_os.h
@@ -153,7 +153,7 @@ typedef struct kmp_struct64 kmp_uint64;
#undef KMP_USE_X87CONTROL
#define KMP_USE_X87CONTROL 1
#endif
-#if KMP_ARCH_X86_64 || KMP_ARCH_AARCH64
+#if KMP_ARCH_X86_64 || KMP_ARCH_AARCH64 || KMP_ARCH_ARM64EC
#define KMP_INTPTR 1
typedef __int64 kmp_intptr_t;
typedef unsigned __int64 kmp_uintptr_t;
@@ -183,7 +183,7 @@ typedef unsigned long long kmp_uint64;
#define KMP_SIZE_T_SPEC KMP_UINT32_SPEC
#elif KMP_ARCH_X86_64 || KMP_ARCH_PPC64 || KMP_ARCH_AARCH64 || \
KMP_ARCH_MIPS64 || KMP_ARCH_RISCV64 || KMP_ARCH_LOONGARCH64 || \
- KMP_ARCH_VE || KMP_ARCH_S390X || KMP_ARCH_SPARC64
+ KMP_ARCH_VE || KMP_ARCH_S390X || KMP_ARCH_SPARC64 || KMP_ARCH_ARM64EC
#define KMP_SIZE_T_SPEC KMP_UINT64_SPEC
#else
#error "Can't determine size_t printf format specifier."
@@ -464,7 +464,9 @@ enum kmp_mem_fence_type {
// Synchronization primitives
-#if KMP_ASM_INTRINS && KMP_OS_WINDOWS && !((KMP_ARCH_AARCH64 || KMP_ARCH_ARM) && (KMP_COMPILER_CLANG || KMP_COMPILER_GCC))
+#if KMP_ASM_INTRINS && KMP_OS_WINDOWS && \
+ !((KMP_ARCH_AARCH64 || KMP_ARCH_ARM || KMP_ARCH_ARM64EC) && \
+ (KMP_COMPILER_CLANG || KMP_COMPILER_GCC))
#if KMP_MSVC_COMPAT && !KMP_COMPILER_CLANG
#pragma intrinsic(InterlockedExchangeAdd)
diff --git a/openmp/runtime/src/kmp_platform.h b/openmp/runtime/src/kmp_platform.h
index 609b7c4688842..9c6628b019c49 100644
--- a/openmp/runtime/src/kmp_platform.h
+++ b/openmp/runtime/src/kmp_platform.h
@@ -119,6 +119,7 @@
#define KMP_ARCH_X86_64 0
#define KMP_ARCH_AARCH64 0
#define KMP_ARCH_AARCH64_32 0
+#define KMP_ARCH_ARM64EC 0
#define KMP_ARCH_PPC64_ELFv1 0
#define KMP_ARCH_PPC64_ELFv2 0
#define KMP_ARCH_PPC64_XCOFF 0
@@ -133,7 +134,10 @@
#define KMP_ARCH_SPARC 0
#if KMP_OS_WINDOWS
-#if defined(_M_AMD64) || defined(__x86_64)
+#if defined(_M_ARM64EC)
+#undef KMP_ARCH_ARM64EC
+#define KMP_ARCH_ARM64EC 1
+#elif defined(_M_AMD64) || defined(__x86_64)
#undef KMP_ARCH_X86_64
#define KMP_ARCH_X86_64 1
#elif defined(__aarch64__) || defined(_M_ARM64)
@@ -291,7 +295,7 @@
KMP_ARCH_AARCH64 + KMP_ARCH_MIPS + KMP_ARCH_MIPS64 + \
KMP_ARCH_RISCV64 + KMP_ARCH_LOONGARCH64 + KMP_ARCH_VE + \
KMP_ARCH_S390X + KMP_ARCH_WASM + KMP_ARCH_PPC + \
- KMP_ARCH_AARCH64_32 + KMP_ARCH_SPARC)
+ KMP_ARCH_AARCH64_32 + KMP_ARCH_SPARC + KMP_ARCH_ARM64EC)
#error Unknown or unsupported architecture
#endif
diff --git a/openmp/runtime/src/kmp_runtime.cpp b/openmp/runtime/src/kmp_runtime.cpp
index 48e29c9f9fe45..3ef8996c75372 100644
--- a/openmp/runtime/src/kmp_runtime.cpp
+++ b/openmp/runtime/src/kmp_runtime.cpp
@@ -8924,7 +8924,7 @@ __kmp_determine_reduction_method(
#if KMP_ARCH_X86_64 || KMP_ARCH_PPC64 || KMP_ARCH_AARCH64 || \
KMP_ARCH_MIPS64 || KMP_ARCH_RISCV64 || KMP_ARCH_LOONGARCH64 || \
- KMP_ARCH_VE || KMP_ARCH_S390X || KMP_ARCH_WASM
+ KMP_ARCH_VE || KMP_ARCH_S390X || KMP_ARCH_WASM || KMP_ARCH_ARM64EC
#if KMP_OS_LINUX || KMP_OS_DRAGONFLY || KMP_OS_FREEBSD || KMP_OS_NETBSD || \
KMP_OS_OPENBSD || KMP_OS_WINDOWS || KMP_OS_DARWIN || KMP_OS_HAIKU || \
diff --git a/openmp/runtime/src/thirdparty/ittnotify/ittnotify_config.h b/openmp/runtime/src/thirdparty/ittnotify/ittnotify_config.h
index bd3fd9b43e574..73d00847d2e77 100644
--- a/openmp/runtime/src/thirdparty/ittnotify/ittnotify_config.h
+++ b/openmp/runtime/src/thirdparty/ittnotify/ittnotify_config.h
@@ -173,6 +173,8 @@
#ifndef ITT_ARCH
#if defined _M_IX86 || defined __i386__
#define ITT_ARCH ITT_ARCH_IA32
+#elif defined _M_ARM64EC
+#define ITT_ARCH ITT_ARCH_ARM64
#elif defined _M_X64 || defined _M_AMD64 || defined __x86_64__
#define ITT_ARCH ITT_ARCH_IA32E
#elif defined _M_IA64 || defined __ia64__
diff --git a/openmp/runtime/src/z_Windows_NT-586_util.cpp b/openmp/runtime/src/z_Windows_NT-586_util.cpp
index 37759feafd453..946bdd30893c0 100644
--- a/openmp/runtime/src/z_Windows_NT-586_util.cpp
+++ b/openmp/runtime/src/z_Windows_NT-586_util.cpp
@@ -12,7 +12,8 @@
#include "kmp.h"
-#if (KMP_ARCH_X86 || KMP_ARCH_X86_64 || KMP_ARCH_AARCH64 || KMP_ARCH_ARM)
+#if (KMP_ARCH_X86 || KMP_ARCH_X86_64 || KMP_ARCH_AARCH64 || KMP_ARCH_ARM || \
+ KMP_ARCH_ARM64EC)
/* Only 32-bit "add-exchange" instruction on IA-32 architecture causes us to
use compare_and_store for these routines */
@@ -134,7 +135,7 @@ kmp_uint64 __kmp_test_then_and64(volatile kmp_uint64 *p, kmp_uint64 d) {
return old_value;
}
-#if KMP_ARCH_AARCH64 && KMP_COMPILER_MSVC
+#if (KMP_ARCH_AARCH64 && KMP_COMPILER_MSVC) || KMP_ARCH_ARM64EC
// For !KMP_COMPILER_MSVC, this function is provided in assembly form
// by z_Linux_asm.S.
int __kmp_invoke_microtask(microtask_t pkfn, int gtid, int tid, int argc,
@@ -189,4 +190,5 @@ int __kmp_invoke_microtask(microtask_t pkfn, int gtid, int tid, int argc,
}
#endif
-#endif /* KMP_ARCH_X86 || KMP_ARCH_X86_64 || KMP_ARCH_AARCH64 || KMP_ARCH_ARM */
+#endif /* KMP_ARCH_X86 || KMP_ARCH_X86_64 || KMP_ARCH_AARCH64 || KMP_ARCH_ARM \
+ || KMP_ARCH_ARM64EC */
>From 7d605b7c5e20b7a69da2409e1b55bb1e9a7c05ba Mon Sep 17 00:00:00 2001
From: David Truby <david.truby at arm.com>
Date: Tue, 27 Jan 2026 14:11:33 +0000
Subject: [PATCH 2/3] Switch to arm64 asm implementation for invoke_microtask
---
openmp/runtime/src/CMakeLists.txt | 2 +-
openmp/runtime/src/z_Linux_asm.S | 4 ++--
openmp/runtime/src/z_Windows_NT-586_util.cpp | 2 +-
3 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/openmp/runtime/src/CMakeLists.txt b/openmp/runtime/src/CMakeLists.txt
index 0c0804776a774..2cf61f46e2713 100644
--- a/openmp/runtime/src/CMakeLists.txt
+++ b/openmp/runtime/src/CMakeLists.txt
@@ -111,7 +111,7 @@ else()
libomp_append(LIBOMP_CXXFILES z_Windows_NT-586_util.cpp)
if(${LIBOMP_ARCH} STREQUAL "i386" OR ${LIBOMP_ARCH} STREQUAL "x86_64")
libomp_append(LIBOMP_ASMFILES z_Windows_NT-586_asm.asm) # Windows assembly file
- elseif((${LIBOMP_ARCH} STREQUAL "aarch64" OR ${LIBOMP_ARCH} STREQUAL "arm") AND (NOT MSVC OR CMAKE_C_COMPILER_ID STREQUAL "Clang"))
+ elseif((${LIBOMP_ARCH} STREQUAL "aarch64" OR ${LIBOMP_ARCH} STREQUAL "arm" OR ${LIBOMP_ARCH} STREQUAL "arm64ec") AND (NOT MSVC OR CMAKE_C_COMPILER_ID STREQUAL "Clang"))
# z_Linux_asm.S works for AArch64 and ARM Windows too.
libomp_append(LIBOMP_GNUASMFILES z_Linux_asm.S)
else()
diff --git a/openmp/runtime/src/z_Linux_asm.S b/openmp/runtime/src/z_Linux_asm.S
index 12fea67e000e8..aad495ccd1b2a 100644
--- a/openmp/runtime/src/z_Linux_asm.S
+++ b/openmp/runtime/src/z_Linux_asm.S
@@ -121,7 +121,7 @@ KMP_PREFIX_UNDERSCORE(\proc):
# endif // KMP_OS_DARWIN
#endif // KMP_ARCH_X86 || KMP_ARCH_x86_64
-#if KMP_ARCH_AARCH64 || KMP_ARCH_AARCH64_32 || KMP_ARCH_ARM
+#if KMP_ARCH_AARCH64 || KMP_ARCH_AARCH64_32 || KMP_ARCH_ARM || KMP_ARCH_ARM64EC
# if KMP_OS_DARWIN
# define KMP_PREFIX_UNDERSCORE(x) _##x // extra underscore for OS X* symbols
@@ -1300,7 +1300,7 @@ KMP_LABEL(kmp_no_args):
#endif /* KMP_ARCH_X86_64 */
// '
-#if KMP_ARCH_AARCH64 || KMP_ARCH_AARCH64_32
+#if KMP_ARCH_AARCH64 || KMP_ARCH_AARCH64_32 || KMP_ARCH_ARM64EC
//------------------------------------------------------------------------
// int
diff --git a/openmp/runtime/src/z_Windows_NT-586_util.cpp b/openmp/runtime/src/z_Windows_NT-586_util.cpp
index 946bdd30893c0..4ed309365b566 100644
--- a/openmp/runtime/src/z_Windows_NT-586_util.cpp
+++ b/openmp/runtime/src/z_Windows_NT-586_util.cpp
@@ -135,7 +135,7 @@ kmp_uint64 __kmp_test_then_and64(volatile kmp_uint64 *p, kmp_uint64 d) {
return old_value;
}
-#if (KMP_ARCH_AARCH64 && KMP_COMPILER_MSVC) || KMP_ARCH_ARM64EC
+#if KMP_ARCH_AARCH64 && KMP_COMPILER_MSVC
// For !KMP_COMPILER_MSVC, this function is provided in assembly form
// by z_Linux_asm.S.
int __kmp_invoke_microtask(microtask_t pkfn, int gtid, int tid, int argc,
>From fb91d843275b1670bc09bcfe5847223fa1072d43 Mon Sep 17 00:00:00 2001
From: David Truby <david.truby at arm.com>
Date: Wed, 28 Jan 2026 13:08:51 +0000
Subject: [PATCH 3/3] Add checks for mingw arm64ec macros
---
openmp/runtime/cmake/LibompGetArchitecture.cmake | 2 +-
openmp/runtime/src/kmp_platform.h | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/openmp/runtime/cmake/LibompGetArchitecture.cmake b/openmp/runtime/cmake/LibompGetArchitecture.cmake
index 4127ea451ac91..56377a397bb40 100644
--- a/openmp/runtime/cmake/LibompGetArchitecture.cmake
+++ b/openmp/runtime/cmake/LibompGetArchitecture.cmake
@@ -18,7 +18,7 @@ function(libomp_get_architecture return_arch)
#if defined(__KNC__)
#error ARCHITECTURE=mic
// arm64ec also defines _M_AMD64 so this needs to be checked before that
- #elif defined(_M_ARM64EC)
+ #elif defined(_M_ARM64EC) || defined(__arm64ec__)
#error ARCHITECTURE=arm64ec
#elif defined(__amd64__) || defined(__amd64) || defined(__x86_64__) || defined(__x86_64) || defined(_M_X64) || defined(_M_AMD64)
#error ARCHITECTURE=x86_64
diff --git a/openmp/runtime/src/kmp_platform.h b/openmp/runtime/src/kmp_platform.h
index 9c6628b019c49..7d88c02e9cf37 100644
--- a/openmp/runtime/src/kmp_platform.h
+++ b/openmp/runtime/src/kmp_platform.h
@@ -134,7 +134,7 @@
#define KMP_ARCH_SPARC 0
#if KMP_OS_WINDOWS
-#if defined(_M_ARM64EC)
+#if defined(_M_ARM64EC) || defined(__arm64ec__)
#undef KMP_ARCH_ARM64EC
#define KMP_ARCH_ARM64EC 1
#elif defined(_M_AMD64) || defined(__x86_64)
More information about the Openmp-commits
mailing list