Skip to content

Arm64 SVE: Support scalable constant vectors and masks - #127520

Merged
dhartglassMSFT merged 94 commits into
dotnet:mainfrom
a74nh:truemasknode_github
Jul 28, 2026
Merged

Arm64 SVE: Support scalable constant vectors and masks#127520
dhartglassMSFT merged 94 commits into
dotnet:mainfrom
a74nh:truemasknode_github

Conversation

@a74nh

@a74nha74nh commented Apr 28, 2026

Copy link
Copy Markdown
Contributor

Adds support to GenTreeVecCon and GenTreeMskCon for constants with unknown sizes. Instead of having a blob of data, the constant is represented as being one of either: a repeated value, an sequence with start and step values, or a value in the first lane and the rest zeroed. To handle this the base type is also required.

As this new structure is slightly bigger than a simd16, the simd_t typedef is pushed up to simd32 sized.

For vector constants, a vector is scalable because if it is of TYP_SIMD.

For mask constants, the type is always TYP_MASK. However on Arm64, masks are only used by SVE. Therefore to tell if a mask is scalable then JitUseScalableVectorT is checked.

The IsAllBitsSet() on mask constants is updated to include a base type. A mask that is all set for TYP_LONG will not be all set for TYP_BYTE, and instead will be 100010001000...

Given two scalable constants it may not be possible to add them together to produce a third scalable constant. Instead they will remain as two vectors in the IR.

To show this implementation is workable, scalable support is added for:

  • Sve.CreateTrueMask*()
  • Sve.CreateFalseMask*()
  • Vector.Create()
  • Vector.CreateScalar()
  • Vector.CreateScalarUnsafe()
  • Vector.CreateSequence()

Fixes#125057

CopilotAI review requested due to automatic review settings April 28, 2026 17:32
@github-actionsgithub-actionsBot added the area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI label Apr 28, 2026
@dotnet-policy-servicedotnet-policy-serviceBot added the community-contribution Indicates that the PR has been added by a community member label Apr 28, 2026
@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Tagging subscribers to this area: @JulieLeeMSFT, @jakobbotsch
See info in area-owners.md if you want to be subscribed.

Adds support to GenTreeVecCon and GenTreeMskCon for constants with unknown sizes. Instead of having a blob of data, the constant is represented as being one of either: a repeated value, an sequence with start and step values, or a value in the first lane and the rest zeroed. To handle this the base type is also required.
As this new structure is slightly bigger than a simd16, the simd_t typedef is pushed up to simd32 sized.
For vector constants, a vector is scalable because if it is of TYP_SIMD.
For mask constants, the type is always TYP_MASK. However on Arm64, masks are only used by SVE. Therefore to tell if a mask is scalable then JitUseScalableVectorT is checked.
The IsAllBitsSet() on mask constants is updated to include a base type. A mask that is all set for TYP_LONG will not be all set for TYP_BYTE, and instead will be 100010001000...
Given two scalable constants it may not be possible to add them together to produce a third scalable constant. Instead they will remain as two vectors in the IR.
To show this implementation is workable, scalable support is added for:
Sve.CreateTrueMask*()
Sve.CreateFalseMask*()
Vector.Create()
Vector.CreateScalar()
Vector.CreateScalarUnsafe()
Vector.CreateSequence()
Fixesdotnet#125057
@a74nh
a74nhforce-pushed the truemasknode_github branch from 4754486 to 7fac1f9CompareApril 29, 2026 14:36
@a74nh

Copy link
Copy Markdown
ContributorAuthor

Taking this out of draft now.

Because of the very limited support for scalable SVE, this is currently very hard to test. I've been working off the top of @snickolls-arm's WIP branch with all his code in, which allows me to to call handwritten tests. In current HEAD, there are too many errors before getting to my code.

There's still a lot of work to do on top of this. Eg, I need to get generic ops working, plus all the other Vector APIs which create constants. But, I didn't want this PR to grow too big. The important part is this serves as a base for further constant work.

@dotnet/arm64-contrib @jakobbotsch@tannergooding

@a74nh
a74nh requested review from Copilot and removed request for CopilotApril 30, 2026 11:04

CopilotAI 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

Note

Copilot was unable to run its full agentic suite in this review.

This PR adds Arm64 SVE “scalable VectorT” support across the JIT, including new encodings for scalable vector/mask constants and updates to value numbering, folding, lowering, LSRA, and codegen to recognize and emit SVE-friendly patterns.

Changes:

  • Introduce new scalable constant representations (simdscalable_t, simdmaskscalable_t) and plumb them through GenTree constant nodes and hashing.
  • Extend value numbering and folding to create/consume scalable SIMD constants on Arm64.
  • Implement Arm64 SVE VectorT intrinsics import and codegen pathways (create/broadcast/sequence), plus mask handling updates.

Reviewed changes

Copilot reviewed 16 out of 16 changed files in this pull request and generated 8 comments.

Show a summary per file
FileDescription
src/coreclr/jit/valuenum.hAdds VN support for scalable SIMD constants on Arm64
src/coreclr/jit/valuenum.cppCreates/broadcasts scalable SIMD VN constants and dumps them
src/coreclr/jit/simd.hDefines new scalable vector/mask constant encodings and helper APIs
src/coreclr/jit/simd.cppImplements scalable vector/mask helpers and conversions
src/coreclr/jit/lsraarm64.cppReserves temps for scalable vector constants that can’t be directly encoded
src/coreclr/jit/lowerarmarch.cppUpdates mask lowering + VectorT intrinsic handling
src/coreclr/jit/hwintrinsiclistarm64sve.hEnables VectorT intrinsics for SVE
src/coreclr/jit/hwintrinsiccodegenarm64.cppEmits SVE instructions for VectorT intrinsics
src/coreclr/jit/hwintrinsicarm64.cppImports VectorT intrinsics and updates true/false mask creation
src/coreclr/jit/hwintrinsic.hMarks VectorT_* as special cases for scalar/broadcast creation
src/coreclr/jit/gentree.hExtends vector/mask constants to support scalable encodings
src/coreclr/jit/gentree.cppAdds scalable constant construction, hashing, folding, and printing
src/coreclr/jit/emitarm64.hRepositions signed-immediate helpers used by new SVE paths
src/coreclr/jit/compiler.hppExtends bitmask helpers for >64-register targets
src/coreclr/jit/compiler.hAdds new compiler helpers for scalable vector/mask constants
src/coreclr/jit/codegenarm64.cppAdds emission for scalable vector/mask constants

Comment threadsrc/coreclr/jit/simd.h
Comment threadsrc/coreclr/jit/simd.cpp Outdated
Comment threadsrc/coreclr/jit/simd.h Outdated
Comment threadsrc/coreclr/jit/simd.cpp
Comment threadsrc/coreclr/jit/codegenarm64.cpp Outdated
Comment threadsrc/coreclr/jit/codegenarm64.cpp Outdated
Comment threadsrc/coreclr/jit/gentree.h Outdated
Comment threadsrc/coreclr/jit/gentree.h Outdated
CopilotAI review requested due to automatic review settings June 26, 2026 14:53

CopilotAI 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

Copilot reviewed 18 out of 18 changed files in this pull request and generated 5 comments.

Comment threadsrc/coreclr/jit/gentree.cpp
Comment threadsrc/coreclr/jit/gentree.cpp
Comment threadsrc/coreclr/jit/gentree.cpp
Comment threadsrc/coreclr/jit/gentree.cpp Outdated
Comment threadsrc/coreclr/jit/hwintrinsiclistarm64sve.h Outdated
@github-actions

github-actionsBot commented Jul 19, 2026

Copy link
Copy Markdown
Contributor

Workflow state for the Holistic Review Orchestrator.

{
"version": 5,
"last_dispatched_commit": "a7f17a70a3191b5f04900e39a3248e7148afebb7",
"last_dispatched_base_ref": "main",
"last_dispatched_base_sha": "c473d80e67a0e090fa4a3e67fbc5bc9d122b172a",
"last_reviewed_commit": "a7f17a70a3191b5f04900e39a3248e7148afebb7",
"last_reviewed_base_ref": "main",
"last_reviewed_base_sha": "c473d80e67a0e090fa4a3e67fbc5bc9d122b172a",
"last_recorded_worker_run_id": "29679155775",
"review_attempt_commit": "",
"review_attempt_base_ref": "",
"review_attempt_count": 0,
"max_review_attempts": 5,
"review_history_format": "holistic-review-disclosure-v1",
"review_history": [
{
"commit": "a7f17a70a3191b5f04900e39a3248e7148afebb7",
"review_id": 4730529285
}
]
}

@github-actionsgithub-actionsBot 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.

Holistic Review

Motivation: The PR adds vector-length-agnostic constant support for Arm64 SVE (Fixes #125057). Previously scalable SIMD constants and predicate masks could not be represented, because a fixed-size data blob presumes a known vector width. This blocks constant folding and efficient codegen for Sve.CreateTrue/FalseMask* and Vector.Create/CreateScalar/CreateScalarUnsafe/CreateSequence on scalable types. The motivation is real and well-scoped.

Approach: Instead of a data blob, scalable constants are modeled abstractly via a new simdscalable_t (baseType + kind Repeated/Sequence/Scalar + 64-bit index/step unions) and simdmaskscalable_t (baseType + 0/1 index). The simd_t typedef is widened to simd32_t on Arm64 (guarded by static_assert(sizeof(simd_t) >= sizeof(simdscalable_t))) so existing storage can hold the new struct. Value numbering gains a simdmaskvalue_t wrapper plus new VN maps and specializations, codegen (genSetRegToConst TYP_SIMD) emits SVE dup/index/fmov/ins with a data-section fallback, and LSRA reserves internal registers when the constant isn't immediate-encodable. Crucially, scalable mask behavior is gated behind the DEBUG-only JitConfig.JitUseScalableVectorT(), which meaningfully limits release-codegen risk; scalable vector constants (TYP_SIMD) are wired in more broadly. The EvaluateUnaryInPlaceTryEvaluateUnaryInPlace (bool) refactor correctly threads fold-failure early-outs through all callers, since scalable constants cannot always be folded. The abstraction is clean and the layering is sensible.

Summary: ⚠️Needs Human Review. This is a large (+2328/-311 across 16 JIT files), intricate SVE codegen change that a JIT/SVE maintainer should validate on real hardware and against the differential/antigen suites. I reviewed by reading only — this worker cannot build or run the JIT — so codegen correctness (SVE instruction selection/encoding, immediate encodability decisions, LSRA internal-register reservation) and VN round-tripping cannot be empirically confirmed here. No blocking defect was found on read-through, and the DEBUG-gating of scalable masks substantially reduces shipping risk. The change is well-structured and the correctness-sensitive refactor is threaded correctly.

Detailed Findings

Try* fold-failure threading is correct.EvaluateUnaryInPlaceTryEvaluateUnaryInPlace and gtFoldExprConvertVecCnsToMask returning GenTree* (original tree on failure) are handled at all call sites (morph.cpp x4, gtFoldExprHWIntrinsic) with proper early-outs; the caller only consumes the result when conversion succeeds.

genFindLowestBit/genMaxOneBit predicate-register handling (compiler.hpp). These are changed from asserting the high mask is RBM_NONE to actually handling high registers under HAS_MORE_THAN_64_REGISTERS. This is a genuine behavioral change enabling predicate-register masks and appears correct and necessary; flagging it as a focus area for the human reviewer since it affects register-mask math beyond the scalable-constant paths.

emitarm64.h isValidSimm hardening. The relocation/shift now guards against undefined-behavior shift overflow when bits == ssize_t bit-width — a real improvement.

💡 Zero-canonicalization equivalence (simd.h/simd.cpp).simdscalable_t::operator== and the VN hash canonicalize any IsZero() value equal regardless of baseType/kind, and a Sequence with index 0 / step 0 is treated as zero. This equivalence (zero-step sequence == repeated-zero) is semantically sound, but it is load-bearing for VN correctness and deduplication; worth a maintainer's confirmation that no consumer distinguishes those representations by baseType.

💡 FP sequence path.gtNewSimdCreateSequenceNode folds integral sequences to a scalable Sequence constant but keeps the FP path as an explicit indices*step+broadcast expression (codegen asserts integral for the sequence form). This appears intentional; noting it so the reviewer confirms the FP path is covered by existing tests.

💡 Test coverage. Per the repo's JIT guidance, new regression tests are not expected for mechanical/infra refactors, and differential testing covers codegen — so this is not a blocker. Given the breadth of new scalable codegen, confirming green SVE CI (and Antigen/Fuzzlyn differential runs) before merge is the primary validation.

Note

This review was generated by this repository's Holistic Review agentic workflow to complement the built-in Copilot review.

Generated by Holistic Review · 270.4 AIC · ⌖ 11.1 AIC · ⊞ 10K

@dhartglassMSFT

Copy link
Copy Markdown
Contributor

@a74nh Needs rebase as discussed in meeting

@a74nh

Copy link
Copy Markdown
ContributorAuthor

@a74nh Needs rebase as discussed in meeting

Rebased. All existing comments addressed/resolved. Back to you :)

Comment threadsrc/coreclr/jit/gentree.cpp
Comment threadsrc/coreclr/jit/simd.cpp Outdated
Comment threadsrc/coreclr/jit/valuenum.cpp
@dhartglassMSFT
dhartglassMSFT merged commit a41ab8d into dotnet:mainJul 28, 2026
143 checks passed
@a74nh
a74nh deleted the truemasknode_github branch July 28, 2026 08:39
@dotnet-milestone-botdotnet-milestone-botBot added this to the 11.0-rc1 milestone Jul 29, 2026
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Aug 30, 2026
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

area-CodeGen-coreclrCLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMIcommunity-contributionIndicates that the PR has been added by a community member

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Design for Vector Constants with agnostic SVE

4 participants

@a74nh@dhartglassMSFT@jakobbotsch