feat(simd): x86_64 baseline of SSE4.2, architecture-aware USE_SIMD - #5411
Open
lgritz wants to merge 2 commits into
Open
feat(simd): x86_64 baseline of SSE4.2, architecture-aware USE_SIMD#5411lgritz wants to merge 2 commits into
lgritz wants to merge 2 commits into
Conversation
Contributor
There was a problem hiding this comment.
Pull request overview
This PR updates OpenImageIO’s SIMD baseline selection to be architecture-aware, defaulting x86_64 builds to SSE4.2, and improves cross-arch handling of USE_SIMD tokens (especially for ARM and Apple universal builds). It also adjusts MSVC behavior so simd.h can select SSE4 paths on Windows x64 even though MSVC doesn’t predefine the __SSE*__ macros.
Changes:
- Default
USE_SIMDtosse4.2on x86_64, leaving it empty on other architectures (withUSE_SIMD=0still disabling SIMD). - Parse
USE_SIMDtokens by CPU family, skipping incompatible tokens and qualifying flags per-slice for Apple universal builds. - Update
simd.h/INSTALL docs regarding baseline assumptions and downstream compilation requirements, and add a CI note to exercise the default SIMD level.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 5 comments.
| File | Description |
|---|---|
src/include/OpenImageIO/simd.h |
Documents baseline assumptions and adds an MSVC x64 path to enable SSE4 selection despite missing __SSE*__ macros. |
src/cmake/compiler.cmake |
Implements architecture-aware USE_SIMD defaulting and token classification, plus per-arch flag qualification for Apple universal builds. |
INSTALL.md |
Documents USE_SIMD, architecture defaults, and downstream implications of SIMD intrinsics gating. |
.github/workflows/ci.yml |
Adds a note ensuring a CI job exercises the x86_64 default SIMD level by leaving simd unset. |
Suppressed comments (4)
src/cmake/compiler.cmake:455
- Passing through unknown SIMD tokens is currently disabled for
CMAKE_COMPILER_IS_INTEL, which on non-Windows should generally behave like gcc/clang and accept-m...flags. If the intent is only to suppress-m...for MSVC-style toolchains, gate on Windows here as well.
if (NOT (MSVC OR CMAKE_COMPILER_IS_INTEL))
list (APPEND SIMD_COMPILE_FLAGS "-m${feature}")
endif ()
src/cmake/compiler.cmake:465
- This block unconditionally appends MSVC-style preprocessor flags (
/D...) whenCMAKE_COMPILER_IS_INTELis set. On non-Windows Intel classic builds,/Dis not a valid option (should be-D). Restrict this to MSVC-style toolchains (e.g., Windows) to avoid breaking Intel builds on Linux.
if ((MSVC OR CMAKE_COMPILER_IS_INTEL) AND SIMD_TARGET_X86_64)
# MSVC makes every intrinsic through AVX2 available regardless of
# the /arch: setting, and it never predefines the __SSE*__ macros
# that simd.h keys off. Since all x86-64 hardware is SSE4.2 or
# better, just say so.
list (APPEND SIMD_COMPILE_FLAGS "/D__SSE2__" "/D__SSE4_1__" "/D__SSE4_2__")
endif ()
src/cmake/compiler.cmake:477
/arch:...flags are MSVC-specific. BecauseCMAKE_COMPILER_IS_INTELcan be true on non-Windows, this condition can incorrectly add MSVC-only flags to Intel classic builds on Linux. Gate this logic to Windows/MSVC-style toolchains.
if (MSVC OR CMAKE_COMPILER_IS_INTEL)
if (_highest_msvc_arch EQUAL 1)
list (APPEND SIMD_COMPILE_FLAGS "/arch:AVX")
endif ()
if (_highest_msvc_arch EQUAL 2)
list (APPEND SIMD_COMPILE_FLAGS "/arch:AVX2")
endif ()
if (_highest_msvc_arch EQUAL 3)
list (APPEND SIMD_COMPILE_FLAGS "/arch:AVX512")
endif ()
INSTALL.md:224
- This section says downstream code only gets SSE4 code paths if compiled with
-msse4.2(or better), butsimd.henables SSE4 paths with either__SSE4_1__or__SSE4_2__. So-msse4.1should also be sufficient, and the wording is currently too strict.
is compiled. Because `simd.h` is a public header and gcc/clang only make the
SSE4/AVX intrinsics available when the corresponding `-m` flag is present,
downstream code that includes `simd.h` gets the SSE4 code paths only if it is
compiled with `-msse4.2` (or better) itself.
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Comment on lines
+85
to
+89
| // __SSE4_1__ and friends. OIIO's own build passes -msse4.2 (see USE_SIMD in | ||
| // src/cmake/compiler.cmake); a downstream translation unit that includes this | ||
| // header will only get the SSE4 code paths if it too is compiled with | ||
| // -msse4.2 or better. MSVC is the exception: it exposes all intrinsics | ||
| // regardless of /arch:, so we can and do assume SSE4 there unconditionally. |
USE_SIMD defaulted to empty, so we inherited whatever the compiler chose:
SSE2 for gcc/clang on Linux, penryn (SSE4.1, no 4.2) for Apple clang, and
plain SSE2 for MSVC, which never predefines the __SSE*__ macros that simd.h
keys off and which no Windows CI job overrides. Every x86-64 CPU has had
SSE4.2 since 2008, so we were leaving the 32 OIIO_SIMD_SSE >= 4 fast paths on
the floor for no reason.
Default USE_SIMD to sse4.2 when targeting x86_64, and leave it empty
elsewhere -- NEON is architecturally mandatory on ARMv8-A, so aarch64 needs
no help. USE_SIMD=0 still disables everything.
The block also had no notion of the target architecture at all: -m${feature}
was a blind passthrough, so USE_SIMD=avx2,f16c on ARM emitted -mavx2 and
failed to compile, which is why every ARM CI job leaves USE_SIMD unset. Now
tokens are classified, tokens for the wrong CPU family are skipped with a
status message, ARM tokens (neon, armv8.2-a+fp16, apple-m1, mcpu=...) are
understood, and universal Apple builds qualify the x86 flags with
-Xarch_x86_64 rather than handing -msse4.2 to the arm64 slice.
For MSVC on x64, emit the SSE4 defines unconditionally rather than only when
the user names those tokens, and let simd.h reach the same conclusion on its
own so that downstream users of the installed header benefit too. This is
safe because MSVC exposes every intrinsic through AVX2 regardless of /arch:.
gcc and clang do gate intrinsics on -m flags, so the header cannot do the
same for them; that limitation is now documented in simd.h and INSTALL.md.
Assisted-by: Claude Code / claude-opus-5
Signed-off-by: Larry Gritz <lg@larrygritz.com>
Improve the accuracy of some comments Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> Signed-off-by: Larry Gritz <lg@larrygritz.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
USE_SIMD defaulted to empty, so we inherited whatever the compiler chose: SSE2 for gcc/clang on Linux, penryn (SSE4.1, no 4.2) for Apple clang, and plain SSE2 for MSVC, which never predefines the SSE* macros that simd.h keys off and which no Windows CI job overrides. Every x86-64 CPU has had SSE4.2 since 2008, so we were leaving the 32 OIIO_SIMD_SSE >= 4 fast paths on the floor for no reason.
Default USE_SIMD to sse4.2 when targeting x86_64, and leave it empty elsewhere -- NEON is architecturally mandatory on ARMv8-A, so aarch64 needs no help. USE_SIMD=0 still disables everything.
The block also had no notion of the target architecture at all: -m${feature} was a blind passthrough, so USE_SIMD=avx2,f16c on ARM emitted -mavx2 and failed to compile, which is why every ARM CI job leaves USE_SIMD unset. Now tokens are classified, tokens for the wrong CPU family are skipped with a status message, ARM tokens (neon, armv8.2-a+fp16, apple-m1, mcpu=...) are understood, and universal Apple builds qualify the x86 flags with -Xarch_x86_64 rather than handing -msse4.2 to the arm64 slice.
For MSVC on x64, emit the SSE4 defines unconditionally rather than only when the user names those tokens, and let simd.h reach the same conclusion on its own so that downstream users of the installed header benefit too. This is safe because MSVC exposes every intrinsic through AVX2 regardless of /arch:. gcc and clang do gate intrinsics on -m flags, so the header cannot do the same for them; that limitation is now documented in simd.h and INSTALL.md.
Assisted-by: Claude Code / claude-opus-5