From d959cb66129dceb7e56ce6fbace85c22aebcfe0f Mon Sep 17 00:00:00 2001 From: Thiago Ize <10453105+ThiagoIze@users.noreply.github.com> Date: Thu, 29 Oct 2026 13:21:18 -0600 Subject: [PATCH] build: Make simd.h and thread.h compile for ARM64EC with clang-cl clang-cl defines _M_AMD64 and __x86_64__ for ARM64EC, so that data layouts match x64 code, but it provides no x86 intrinsics for it. - simd.h: the flush-to-zero and denormals functions use the SSE control register macros under __x86_64__. They also test !defined(__arm64ec__) now, so on ARM64EC they return false and do nothing, as on arm64. - thread.h: pause() called _mm_pause() under _M_AMD64. It takes the ARM64 branch (__dmb and __yield) for _M_ARM64EC now. This completes #5369, which switched simd.h to the NEON code path for ARM64EC. x86_64 builds are unchanged. Co-authored-by: Oscar Anson Assisted-by: Claude Code / Claude Opus 5.5 Signed-off-by: Thiago Ize <10453105+ThiagoIze@users.noreply.github.com> --- src/include/OpenImageIO/simd.h | 8 ++++---- src/include/OpenImageIO/thread.h | 5 +++-- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/src/include/OpenImageIO/simd.h b/src/include/OpenImageIO/simd.h index c6853a0e1f..bc843d2c22 100644 --- a/src/include/OpenImageIO/simd.h +++ b/src/include/OpenImageIO/simd.h @@ -3152,7 +3152,7 @@ vfloat16 nmsub (const vfloat16& a, const vfloat16& b, const vfloat16& c); // -a* // Try to set the flush_zero_mode CPU flag on x86. Return true if we are // able, otherwise false (because it's not available on that platform). inline bool set_flush_zero_mode (bool on) { -#if (defined(__x86_64__) || defined(__i386__)) && !defined(__CUDA_ARCH__) +#if (defined(__x86_64__) || defined(__i386__)) && !defined(__CUDA_ARCH__) && !defined(__arm64ec__) _MM_SET_FLUSH_ZERO_MODE (on ? _MM_FLUSH_ZERO_ON : _MM_FLUSH_ZERO_OFF); return true; #endif @@ -3162,7 +3162,7 @@ inline bool set_flush_zero_mode (bool on) { // Try to set the denorms_zero_mode CPU flag on x86. Return true if we are // able, otherwise false (because it's not available on that platform). inline bool set_denorms_zero_mode (bool on) { -#if (defined(__x86_64__) || defined(__i386__)) && !defined(__CUDA_ARCH__) +#if (defined(__x86_64__) || defined(__i386__)) && !defined(__CUDA_ARCH__) && !defined(__arm64ec__) _MM_SET_DENORMALS_ZERO_MODE (on ? _MM_DENORMALS_ZERO_ON : _MM_DENORMALS_ZERO_OFF); return true; #endif @@ -3171,7 +3171,7 @@ inline bool set_denorms_zero_mode (bool on) { // Get the flush_zero_mode CPU flag on x86. inline bool get_flush_zero_mode () { -#if (defined(__x86_64__) || defined(__i386__)) && !defined(__CUDA_ARCH__) +#if (defined(__x86_64__) || defined(__i386__)) && !defined(__CUDA_ARCH__) && !defined(__arm64ec__) return _MM_GET_FLUSH_ZERO_MODE() == _MM_FLUSH_ZERO_ON; #endif return false; @@ -3179,7 +3179,7 @@ inline bool get_flush_zero_mode () { // Get the denorms_zero_mode CPU flag on x86. inline bool get_denorms_zero_mode () { -#if (defined(__x86_64__) || defined(__i386__)) && !defined(__CUDA_ARCH__) +#if (defined(__x86_64__) || defined(__i386__)) && !defined(__CUDA_ARCH__) && !defined(__arm64ec__) return _MM_GET_DENORMALS_ZERO_MODE() == _MM_DENORMALS_ZERO_ON; #endif return false; diff --git a/src/include/OpenImageIO/thread.h b/src/include/OpenImageIO/thread.h index a0881222b9..851782b050 100644 --- a/src/include/OpenImageIO/thread.h +++ b/src/include/OpenImageIO/thread.h @@ -154,9 +154,10 @@ pause(int delay) noexcept #elif defined(_MSC_VER) // A reimplementation of winnt.h YieldProcessor, // to avoid including windows headers. -# if defined(_M_AMD64) +# if defined(_M_AMD64) && !defined(_M_ARM64EC) _mm_pause(); -# elif defined(_M_ARM64) || defined(_M_HYBRID_X86_ARM64) +# elif defined(_M_ARM64) || defined(_M_ARM64EC) \ + || defined(_M_HYBRID_X86_ARM64) __dmb(_ARM64_BARRIER_ISHST); __yield(); # elif defined(_M_ARM)