[clr-ios] Fix Vector<T> width and R2R AVX baseline mismatch on x64 iOS/tvOS simulators#129012
Merged
kotlarmilos merged 10 commits intoJun 8, 2026
Merged
Conversation
…-JIT x64 The interpreter only supports 128-bit Vector<T>, but on Mac Catalyst and iOS simulator x64 it was ending up with 256-bit Vector<T>, which caused the NullReferenceException in Vector.get_IsHardwareAccelerated. The runtime already limits Vector<T> to 128-bit for the full interpreter mode, but it wasn't doing so on no-JIT builds where everything is interpreted anyway, so AVX2 on x64 silently bumped it up to 256-bit. Apply the same 128-bit limit whenever the interpreter is the only thing running code. arm64 was never affected since Vector<T> is always 128-bit there. Related dotnet#128898 Fixes dotnet#128901 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Contributor
There was a problem hiding this comment.
Pull request overview
This PR adjusts CoreCLR’s CPU feature initialization so that when execution is interpreter-only (either DOTNET_InterpMode=3 or when the runtime is built without dynamic code compilation/JIT), Vector<T> is constrained to 128-bit on x86/x64. This prevents the runtime from advertising/selecting 256-bit Vector<T> on AVX2-capable x64 machines in configurations where the interpreter can only handle 128-bit vectors.
Changes:
- Detect “interpreter-only” operation as
(InterpMode == 3) || !FEATURE_DYNAMIC_CODE_COMPILED. - Clamp
EXTERNAL_MaxVectorTBitWidthto 128 in interpreter-only mode to prevent enablingInstructionSet_VectorT256/512. - Clamp
EXTERNAL_PreferredVectorBitWidthto 128 in interpreter-only mode to keep vector-width preference consistent with interpreter constraints.
Show a summary per file
| File | Description |
|---|---|
| src/coreclr/vm/codeman.cpp | Updates EEJitManager::SetCpuInfo() to force 128-bit Vector<T> sizing when the interpreter is the only execution engine (including no-JIT builds). |
Copilot's findings
- Files reviewed: 1/1 changed files
- Comments generated: 0
Contributor
|
Tagging subscribers to 'os-ios': @vitek-karas, @kotlarmilos, @steveisok, @akoeplinger |
janvorli
reviewed
Jun 4, 2026
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
On interpreter-only runtimes (no JIT), R2R native code is the only executable form of a method. When the image was compiled with --strip-il-bodies and an eager fixup fails (e.g. an instruction-set check), R2R is disabled and the interpreter runs the throw stub left in place of the IL, which surfaces as an opaque self-recursing stack overflow. Fail fast with a clear message instead. Runtimes with a JIT already reject stripped images at load, so this path is only reachable when there is no recovery option. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
BrzVlad
reviewed
Jun 5, 2026
iOS and tvOS devices are ARM-only, so the x86/x64 branch is never reached for TargetOS.iOS/tvOS; only the simulator targets run x64 (Intel/Rosetta) and need the x86-64-v2 baseline. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The READYTORUN_FLAG_STRIPPED_IL_BODIES flag is emitted on each component assembly's own R2R header (RewriteComponentFile), not on the composite global header, so read it from m_pHeader like IsPartial() and the existing check in ReadyToRunInfo::InitializeForModule. Reading the composite header would miss stripped IL bodies for composite components and skip the fatal check on no-JIT builds. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
jkotas
reviewed
Jun 5, 2026
jkotas
reviewed
Jun 5, 2026
The first maxVectorTBitWidth check already pins Vector<T> to 128-bit, so VectorT256/VectorT512 are never set on interpreter-only runtimes. The preferredVectorBitWidth block only controls the JIT's internal preferred vector width, which is irrelevant when the interpreter is the only engine. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
3 tasks
janvorli
approved these changes
Jun 8, 2026
janvorli
left a comment
Member
There was a problem hiding this comment.
LGTM modulo a nit to consider. Thank you!
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.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.
Description
The interpreter only supports 128-bit Vector, but on Mac Catalyst and iOS simulator x64 it was ending up with 256-bit Vector, which is what caused the NullReferenceException in Vector.get_IsHardwareAccelerated. The runtime already limits Vector to 128-bit for the full interpreter mode, but it wasn't doing so on no-JIT builds where everything is interpreted anyway, so AVX2 on x64 silently bumped it up to 256-bit. This change applies the same 128-bit limit whenever the interpreter is the only thing running code. arm64 was never affected since Vector is always 128-bit there.
Crossgen2 had the matching problem where it presumed an x86-64-v3 (AVX2) ReadyToRun baseline for the Apple x64 simulator targets, so the precompiled R2R code and the interpreter disagreed on the Vector width. It now uses the x86-64-v2 baseline for the iOS/tvOS simulators as well, matching osx and maccatalyst, so both share the same 128-bit view. The x64 simulators also run under Rosetta, which does not support AVX, so presuming it was incorrect regardless.
As defense in depth, when an eager fixup failure disables R2R on a no-JIT runtime where the image was compiled with stripped IL bodies (so there is no IL to fall back to), the runtime now fails fast with a clear message instead of running the throw stub left in place of the IL, which previously surfaced as an opaque stack overflow.
Fixes #128901
Fixes #128898