[llvm] 019fc9e - [openmp][WebAssembly] Add support for wasm64 (#181669)
via llvm-commits
llvm-commits at lists.llvm.org
Wed Aug 5 09:01:32 PDT 2026
Author: arsnyder16
Date: 2026-08-05T09:01:27-07:00
New Revision: 019fc9efa2dc8f36d9b4794caeca0738a06db667
URL: https://github.com/llvm/llvm-project/commit/019fc9efa2dc8f36d9b4794caeca0738a06db667
DIFF: https://github.com/llvm/llvm-project/commit/019fc9efa2dc8f36d9b4794caeca0738a06db667.diff
LOG: [openmp][WebAssembly] Add support for wasm64 (#181669)
Building on the existing ability to build wasm32, this change mostly
redefines `M_ARCH_WASM` to `M_ARCH_WASM32` and then introduces
`M_ARCH_WASM64` based on `__wasm64__` define
Added:
clang/test/OpenMP/wasm_codegen.c
Modified:
llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp
openmp/CMakeLists.txt
openmp/cmake/modules/LibompUtils.cmake
openmp/runtime/CMakeLists.txt
openmp/runtime/cmake/LibompGetArchitecture.cmake
openmp/runtime/src/kmp_gsupport.cpp
openmp/runtime/src/kmp_os.h
openmp/runtime/src/kmp_platform.h
openmp/runtime/src/kmp_runtime.cpp
openmp/runtime/src/z_Linux_asm.S
openmp/runtime/src/z_Linux_util.cpp
Removed:
################################################################################
diff --git a/clang/test/OpenMP/wasm_codegen.c b/clang/test/OpenMP/wasm_codegen.c
new file mode 100644
index 0000000000000..0d40cd68fb710
--- /dev/null
+++ b/clang/test/OpenMP/wasm_codegen.c
@@ -0,0 +1,58 @@
+// REQUIRES: webassembly-registered-target
+// RUN: %clang_cc1 -triple wasm32-unknown-emscripten -fopenmp -fnoopenmp-use-tls -emit-llvm -o - %s | FileCheck %s --check-prefixes=CHECK,WASM32
+// RUN: %clang_cc1 -triple wasm64-unknown-emscripten -fopenmp -fnoopenmp-use-tls -emit-llvm -o - %s | FileCheck %s --check-prefixes=CHECK,WASM64
+// RUN: %clang_cc1 -triple wasm32-unknown-emscripten -fopenmp -fnoopenmp-use-tls -emit-obj -o %t.wasm32.o %s
+// RUN: %clang_cc1 -triple wasm64-unknown-emscripten -fopenmp -fnoopenmp-use-tls -emit-obj -o %t.wasm64.o %s
+
+// Exercise representative host OpenMP lowering for both WebAssembly pointer
+// models. WebAssembly does not support common linkage, so compiler-generated
+// locks and caches must have internal linkage.
+// CHECK-DAG: @.gomp_critical_user_.var = internal global [8 x i32] zeroinitializer
+// CHECK-DAG: @.gomp_critical_user_named.var = internal global [8 x i32] zeroinitializer
+// CHECK-DAG: @.gomp_critical_user_.reduction.var = internal global [8 x i32] zeroinitializer
+// CHECK-DAG: @threadprivate_var.cache. = internal global ptr null
+
+// The dependency record and size_t parameters must follow the target pointer
+// width rather than assuming wasm32.
+// WASM32-DAG: %struct.kmp_depend_info = type { i32, i32, i8 }
+// WASM64-DAG: %struct.kmp_depend_info = type { i64, i64, i8 }
+// WASM32-DAG: call ptr @__kmpc_omp_task_alloc({{.*}}i32 {{[0-9]+}}, i32 {{[0-9]+}}, ptr
+// WASM64-DAG: call ptr @__kmpc_omp_task_alloc({{.*}}i64 {{[0-9]+}}, i64 {{[0-9]+}}, ptr
+// WASM32-DAG: call ptr @__kmpc_threadprivate_cached({{.*}}i32 4, ptr @threadprivate_var.cache.)
+// WASM64-DAG: call ptr @__kmpc_threadprivate_cached({{.*}}i64 4, ptr @threadprivate_var.cache.)
+// WASM32-DAG: call i32 @__kmpc_reduce_nowait({{.*}}i32 4, ptr
+// WASM64-DAG: call i32 @__kmpc_reduce_nowait({{.*}}i64 8, ptr
+
+// CHECK-DAG: call void (ptr, i32, ptr, ...) @__kmpc_fork_call(
+// CHECK-DAG: call void @__kmpc_for_static_init_4(
+// CHECK-DAG: call i32 @__kmpc_omp_task_with_deps(
+// CHECK-DAG: call i32 @__kmpc_omp_taskwait(
+// CHECK-DAG: call void @__kmpc_critical(
+
+void critical_regions(void) {
+#pragma omp critical
+ {}
+
+#pragma omp critical(named)
+ {}
+}
+
+int threadprivate_var;
+#pragma omp threadprivate(threadprivate_var)
+
+int openmp_constructs(int *values, int count) {
+ int sum = 0;
+#pragma omp parallel for reduction(+ : sum)
+ for (int i = 0; i < count; ++i)
+ sum += values[i];
+
+#pragma omp task shared(values) depend(inout : values[0 : count])
+ values[0] = sum;
+
+#pragma omp taskwait
+
+#pragma omp critical(named)
+ threadprivate_var += sum;
+
+ return sum;
+}
diff --git a/llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp b/llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp
index c85cfe15d058c..5a363d0ac3dbd 100644
--- a/llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp
+++ b/llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp
@@ -10257,7 +10257,7 @@ GlobalVariable *OpenMPIRBuilder::getOrCreateInternalVariable(
: M.getTargetTriple().isAMDGPU()
? 0
: DL.getDefaultGlobalsAddressSpace();
- auto Linkage = this->M.getTargetTriple().getArch() == Triple::wasm32
+ auto Linkage = this->M.getTargetTriple().isWasm()
? GlobalValue::InternalLinkage
: GlobalValue::CommonLinkage;
auto *GV = new GlobalVariable(M, Ty, /*IsConstant=*/false, Linkage,
diff --git a/openmp/CMakeLists.txt b/openmp/CMakeLists.txt
index 53ae187c8824f..f9a89859be7af 100644
--- a/openmp/CMakeLists.txt
+++ b/openmp/CMakeLists.txt
@@ -134,11 +134,12 @@ set(OPENMP_TEST_Fortran_FLAGS "${CMAKE_Fortran_FLAGS}" CACHE STRING
"Additional compiler flags to use for testing Fortran programs (e.g. additional module search paths via -fintrinsic-modules-path )")
set(ENABLE_LIBOMPTARGET ON)
-# Currently libomptarget cannot be compiled on Windows or MacOS X.
+# Currently libomptarget cannot be compiled on Windows, MacOS X, or WebAssembly.
# Since the device plugins are only supported on Linux anyway,
# there is no point in trying to compile libomptarget on other OSes.
# 32-bit systems are not supported either.
-if (APPLE OR WIN32 OR WASM OR NOT "cxx_std_17" IN_LIST CMAKE_CXX_COMPILE_FEATURES
+if (APPLE OR WIN32 OR "${CMAKE_SYSTEM_NAME}" MATCHES "^(Emscripten|WASI)$" OR
+ NOT "cxx_std_17" IN_LIST CMAKE_CXX_COMPILE_FEATURES
OR NOT CMAKE_SIZEOF_VOID_P EQUAL 8 OR "${CMAKE_SYSTEM_NAME}" MATCHES "AIX")
set(ENABLE_LIBOMPTARGET OFF)
endif()
diff --git a/openmp/cmake/modules/LibompUtils.cmake b/openmp/cmake/modules/LibompUtils.cmake
index 796487e2f9218..9dd80c28dcaf0 100644
--- a/openmp/cmake/modules/LibompUtils.cmake
+++ b/openmp/cmake/modules/LibompUtils.cmake
@@ -125,6 +125,10 @@ function(libomp_get_legal_arch return_arch_string)
set(${return_arch_string} "SPARC" PARENT_SCOPE)
elseif(SPARCV9)
set(${return_arch_string} "SPARCV9" PARENT_SCOPE)
+ elseif(WASM32)
+ set(${return_arch_string} "WASM32" PARENT_SCOPE)
+ elseif(WASM64)
+ set(${return_arch_string} "WASM64" PARENT_SCOPE)
else()
set(${return_arch_string} "${LIBOMP_ARCH}" PARENT_SCOPE)
libomp_warning_say("libomp_get_legal_arch(): Warning: Unknown architecture: Using ${LIBOMP_ARCH}")
diff --git a/openmp/runtime/CMakeLists.txt b/openmp/runtime/CMakeLists.txt
index c0f5b5a4b1596..0256bfaf4a892 100644
--- a/openmp/runtime/CMakeLists.txt
+++ b/openmp/runtime/CMakeLists.txt
@@ -60,8 +60,10 @@ elseif(LIBOMP_NATIVE_ARCH MATCHES "sparcv9")
set(LIBOMP_ARCH sparcv9)
elseif(LIBOMP_NATIVE_ARCH MATCHES "sparc")
set(LIBOMP_ARCH sparc)
-elseif(LIBOMP_NATIVE_ARCH MATCHES "wasm")
+elseif(LIBOMP_NATIVE_ARCH MATCHES "wasm32")
set(LIBOMP_ARCH wasm32)
+elseif(LIBOMP_NATIVE_ARCH MATCHES "wasm64")
+ set(LIBOMP_ARCH wasm64)
else()
# last ditch effort
libomp_get_architecture(LIBOMP_ARCH)
@@ -86,7 +88,7 @@ if(LIBOMP_ENABLE_ARM64X)
include(arm64x)
endif()
-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)
+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 wasm64)
set(LIBOMP_LIB_TYPE normal CACHE STRING
"Performance,Profiling,Stubs library (normal/profile/stubs)")
@@ -181,7 +183,8 @@ set(RISCV64 FALSE)
set(LOONGARCH64 FALSE)
set(VE FALSE)
set(S390X FALSE)
-set(WASM FALSE)
+set(WASM32 FALSE)
+set(WASM64 FALSE)
set(PPC FALSE)
set(SPARC FALSE)
set(SPARCV9 FALSE)
@@ -221,8 +224,10 @@ elseif("${LIBOMP_ARCH}" STREQUAL "ve") # VE architecture
set(VE TRUE)
elseif("${LIBOMP_ARCH}" STREQUAL "s390x") # S390x (Z) architecture
set(S390X TRUE)
-elseif("${LIBOMP_ARCH}" STREQUAL "wasm32") # WebAssembly architecture
- set(WASM TRUE)
+elseif("${LIBOMP_ARCH}" STREQUAL "wasm32") # WebAssembly 32 bit architecture
+ set(WASM32 TRUE)
+elseif("${LIBOMP_ARCH}" STREQUAL "wasm64") # WebAssembly 64 bit architecture
+ set(WASM64 TRUE)
elseif("${LIBOMP_ARCH}" STREQUAL "sparc") # SPARC architecture
set(SPARC TRUE)
elseif("${LIBOMP_ARCH}" STREQUAL "sparcv9") # SPARC V9 architecture
@@ -336,7 +341,7 @@ set(LIBOMP_USE_CANCEL_THREADS "${LIBOMP_HAVE_PTHREAD_CANCEL}" CACHE BOOL
set(LIBOMP_ENABLE_SHARED TRUE CACHE BOOL
"Shared library instead of static library?")
-if(WASM)
+if(WASM32 OR WASM64)
libomp_warning_say("The WebAssembly build currently only supports static libraries; forcing LIBOMP_ENABLE_SHARED to false")
set(LIBOMP_ENABLE_SHARED FALSE)
endif()
diff --git a/openmp/runtime/cmake/LibompGetArchitecture.cmake b/openmp/runtime/cmake/LibompGetArchitecture.cmake
index 56377a397bb40..77d3e3f90d47e 100644
--- a/openmp/runtime/cmake/LibompGetArchitecture.cmake
+++ b/openmp/runtime/cmake/LibompGetArchitecture.cmake
@@ -62,6 +62,8 @@ function(libomp_get_architecture return_arch)
#error ARCHITECTURE=s390x
#elif defined(__wasm32__)
#error ARCHITECTURE=wasm32
+ #elif defined(__wasm64__)
+ #error ARCHITECTURE=wasm64
#elif defined(__sparcv9)
#error ARCHITECTURE=sparcv9
#elif defined(__sparc)
diff --git a/openmp/runtime/src/kmp_gsupport.cpp b/openmp/runtime/src/kmp_gsupport.cpp
index 0d04045f7b165..be95e0f3de6e2 100644
--- a/openmp/runtime/src/kmp_gsupport.cpp
+++ b/openmp/runtime/src/kmp_gsupport.cpp
@@ -357,7 +357,7 @@ void KMP_EXPAND_NAME(KMP_API_NAME_GOMP_ORDERED_END)(void) {
// They come in two flavors: 64-bit unsigned, and either 32-bit signed
// (IA-32 architecture) or 64-bit signed (Intel(R) 64).
-#if KMP_ARCH_X86 || KMP_ARCH_ARM || KMP_ARCH_MIPS || KMP_ARCH_WASM || \
+#if KMP_ARCH_X86 || KMP_ARCH_ARM || KMP_ARCH_MIPS || KMP_ARCH_WASM32 || \
KMP_ARCH_PPC || KMP_ARCH_AARCH64_32 || KMP_ARCH_SPARC32
#define KMP_DISPATCH_INIT __kmp_aux_dispatch_init_4
#define KMP_DISPATCH_FINI_CHUNK __kmp_aux_dispatch_fini_chunk_4
diff --git a/openmp/runtime/src/kmp_os.h b/openmp/runtime/src/kmp_os.h
index c5da19dc2407b..be8c121e18736 100644
--- a/openmp/runtime/src/kmp_os.h
+++ b/openmp/runtime/src/kmp_os.h
@@ -178,18 +178,19 @@ typedef unsigned long long kmp_uint64;
#define KMP_UINT64_SPEC "llu"
#endif /* KMP_OS_UNIX */
-#if KMP_ARCH_X86 || KMP_ARCH_ARM || KMP_ARCH_MIPS || KMP_ARCH_WASM || \
+#if KMP_ARCH_X86 || KMP_ARCH_ARM || KMP_ARCH_MIPS || KMP_ARCH_WASM32 || \
KMP_ARCH_PPC || KMP_ARCH_AARCH64_32 || KMP_ARCH_SPARC32
#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_ARM64EC
+ KMP_ARCH_VE || KMP_ARCH_S390X || KMP_ARCH_SPARC64 || KMP_ARCH_WASM64 || \
+ KMP_ARCH_ARM64EC
#define KMP_SIZE_T_SPEC KMP_UINT64_SPEC
#else
#error "Can't determine size_t printf format specifier."
#endif
-#if KMP_ARCH_X86 || KMP_ARCH_ARM || KMP_ARCH_WASM || KMP_ARCH_PPC
+#if KMP_ARCH_X86 || KMP_ARCH_ARM || KMP_ARCH_WASM32 || KMP_ARCH_PPC
#define KMP_SIZE_T_MAX (0xFFFFFFFF)
#else
#define KMP_SIZE_T_MAX (0xFFFFFFFFFFFFFFFF)
@@ -218,7 +219,8 @@ typedef kmp_uint32 kmp_uint;
#define KMP_INT_MIN ((kmp_int32)0x80000000)
// stdarg handling
-#if (KMP_ARCH_ARM || KMP_ARCH_X86_64 || KMP_ARCH_AARCH64 || KMP_ARCH_WASM) && \
+#if (KMP_ARCH_ARM || KMP_ARCH_X86_64 || KMP_ARCH_AARCH64 || KMP_ARCH_WASM32 || \
+ KMP_ARCH_WASM64) && \
(KMP_OS_FREEBSD || KMP_OS_NETBSD || KMP_OS_OPENBSD || KMP_OS_DRAGONFLY || \
KMP_OS_LINUX || KMP_OS_WASI)
typedef va_list *kmp_va_list;
@@ -1155,7 +1157,7 @@ extern kmp_real64 __kmp_xchg_real64(volatile kmp_real64 *p, kmp_real64 v);
KMP_COMPARE_AND_STORE_REL64((volatile kmp_int64 *)(volatile void *)&(a), \
(kmp_int64)(b), (kmp_int64)(c))
-#if KMP_ARCH_X86 || KMP_ARCH_MIPS || KMP_ARCH_WASM || KMP_ARCH_PPC
+#if KMP_ARCH_X86 || KMP_ARCH_MIPS || KMP_ARCH_WASM32 || KMP_ARCH_PPC
// What about ARM?
#define TCR_PTR(a) ((void *)TCR_4(a))
#define TCW_PTR(a, b) TCW_4((a), (b))
diff --git a/openmp/runtime/src/kmp_platform.h b/openmp/runtime/src/kmp_platform.h
index 7d88c02e9cf37..3cafd90225614 100644
--- a/openmp/runtime/src/kmp_platform.h
+++ b/openmp/runtime/src/kmp_platform.h
@@ -249,7 +249,11 @@
#endif
#if defined(__wasm32__)
-#define KMP_ARCH_WASM 1
+#define KMP_ARCH_WASM32 1
+#endif
+
+#if defined(__wasm64__)
+#define KMP_ARCH_WASM64 1
#endif
#define KMP_ARCH_PPC64 \
@@ -283,7 +287,7 @@
/* Specify 32 bit architectures here */
#define KMP_32_BIT_ARCH \
- (KMP_ARCH_X86 || KMP_ARCH_ARM || KMP_ARCH_MIPS || KMP_ARCH_WASM || \
+ (KMP_ARCH_X86 || KMP_ARCH_ARM || KMP_ARCH_MIPS || KMP_ARCH_WASM32 || \
KMP_ARCH_PPC || KMP_ARCH_AARCH64_32 || KMP_ARCH_SPARC32)
// Platforms which support Intel(R) Many Integrated Core Architecture
@@ -294,8 +298,9 @@
#if (1 != KMP_ARCH_X86 + KMP_ARCH_X86_64 + KMP_ARCH_ARM + KMP_ARCH_PPC64 + \
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_ARM64EC)
+ KMP_ARCH_S390X + KMP_ARCH_WASM32 + KMP_ARCH_WASM64 + \
+ KMP_ARCH_PPC + 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 c402645af9ad6..234a211bcfba3 100644
--- a/openmp/runtime/src/kmp_runtime.cpp
+++ b/openmp/runtime/src/kmp_runtime.cpp
@@ -8924,7 +8924,8 @@ __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_ARM64EC
+ KMP_ARCH_VE || KMP_ARCH_S390X || KMP_ARCH_WASM32 || KMP_ARCH_WASM64 || \
+ 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 || \
@@ -8956,7 +8957,7 @@ __kmp_determine_reduction_method(
// KMP_OS_HURD || KMP_OS_SOLARIS || KMP_OS_WASI || KMP_OS_AIX
#elif KMP_ARCH_X86 || KMP_ARCH_ARM || KMP_ARCH_AARCH || KMP_ARCH_MIPS || \
- KMP_ARCH_WASM || KMP_ARCH_PPC || KMP_ARCH_AARCH64_32 || KMP_ARCH_SPARC
+ KMP_ARCH_PPC || KMP_ARCH_AARCH64_32 || KMP_ARCH_SPARC
#if KMP_OS_LINUX || KMP_OS_DRAGONFLY || KMP_OS_FREEBSD || KMP_OS_NETBSD || \
KMP_OS_OPENBSD || KMP_OS_WINDOWS || KMP_OS_HAIKU || KMP_OS_HURD || \
diff --git a/openmp/runtime/src/z_Linux_asm.S b/openmp/runtime/src/z_Linux_asm.S
index 867cb3024921d..68b755a089412 100644
--- a/openmp/runtime/src/z_Linux_asm.S
+++ b/openmp/runtime/src/z_Linux_asm.S
@@ -2512,7 +2512,7 @@ KMP_PREFIX_UNDERSCORE(__kmp_unnamed_critical_addr):
#if KMP_OS_LINUX
# if KMP_ARCH_ARM || KMP_ARCH_AARCH64
.section .note.GNU-stack,"",%progbits
-# elif !KMP_ARCH_WASM
+# elif !KMP_ARCH_WASM32 && !KMP_ARCH_WASM64
.section .note.GNU-stack,"", at progbits
# endif
#endif
diff --git a/openmp/runtime/src/z_Linux_util.cpp b/openmp/runtime/src/z_Linux_util.cpp
index f42fc68488c91..bd72a3d46a97f 100644
--- a/openmp/runtime/src/z_Linux_util.cpp
+++ b/openmp/runtime/src/z_Linux_util.cpp
@@ -321,7 +321,8 @@ int __kmp_futex_determine_capable() {
#endif // KMP_USE_FUTEX
-#if (KMP_ARCH_X86 || KMP_ARCH_X86_64 || KMP_ARCH_WASM) && (!KMP_ASM_INTRINS)
+#if (KMP_ARCH_X86 || KMP_ARCH_X86_64 || KMP_ARCH_WASM32 || KMP_ARCH_WASM64) && \
+ (!KMP_ASM_INTRINS)
/* Only 32-bit "add-exchange" instruction on IA-32 architecture causes us to
use compare_and_store for these routines */
@@ -381,7 +382,7 @@ kmp_uint32 __kmp_test_then_and32(volatile kmp_uint32 *p, kmp_uint32 d) {
return old_value;
}
-#if KMP_ARCH_X86 || KMP_ARCH_WASM
+#if KMP_ARCH_X86 || KMP_ARCH_WASM32
kmp_int8 __kmp_test_then_add8(volatile kmp_int8 *p, kmp_int8 d) {
kmp_int8 old_value, new_value;
More information about the llvm-commits
mailing list