Skip to content

feat(simd): x86_64 baseline of SSE4.2, architecture-aware USE_SIMD - #5411

Open
lgritz wants to merge 2 commits into
AcademySoftwareFoundation:mainfrom
lgritz:lg-usesimd
Open

feat(simd): x86_64 baseline of SSE4.2, architecture-aware USE_SIMD#5411
lgritz wants to merge 2 commits into
AcademySoftwareFoundation:mainfrom
lgritz:lg-usesimd

Conversation

@lgritz

@lgritz lgritz commented Aug 20, 2026

Copy link
Copy Markdown
Collaborator

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

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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_SIMD to sse4.2 on x86_64, leaving it empty on other architectures (with USE_SIMD=0 still disabling SIMD).
  • Parse USE_SIMD tokens 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...) when CMAKE_COMPILER_IS_INTEL is set. On non-Windows Intel classic builds, /D is 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. Because CMAKE_COMPILER_IS_INTEL can 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), but simd.h enables SSE4 paths with either __SSE4_1__ or __SSE4_2__. So -msse4.1 should 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 thread src/cmake/compiler.cmake Outdated
Comment thread src/cmake/compiler.cmake
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.
Comment thread src/include/OpenImageIO/simd.h
Comment thread INSTALL.md Outdated
lgritz and others added 2 commits August 25, 2026 17:35
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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants