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

dhartglassMSFT merged 94 commits into
dotnet:mainfrom
a74nh:truemasknode_github

Conversation

@a74nh

@a74nh a74nh 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

Copilot AI review requested due to automatic review settings April 28, 2026 17:32
@github-actions github-actions Bot 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-service dotnet-policy-service Bot 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()

Fixes dotnet#125057
@a74nh
a74nh force-pushed the truemasknode_github branch from 4754486 to 7fac1f9 Compare April 29, 2026 14:36
@a74nh

a74nh commented Apr 29, 2026

Copy link
Copy Markdown
Contributor Author

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 Copilot April 30, 2026 11:04

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

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
File Description
src/coreclr/jit/valuenum.h Adds VN support for scalable SIMD constants on Arm64
src/coreclr/jit/valuenum.cpp Creates/broadcasts scalable SIMD VN constants and dumps them
src/coreclr/jit/simd.h Defines new scalable vector/mask constant encodings and helper APIs
src/coreclr/jit/simd.cpp Implements scalable vector/mask helpers and conversions
src/coreclr/jit/lsraarm64.cpp Reserves temps for scalable vector constants that can’t be directly encoded
src/coreclr/jit/lowerarmarch.cpp Updates mask lowering + VectorT intrinsic handling
src/coreclr/jit/hwintrinsiclistarm64sve.h Enables VectorT intrinsics for SVE
src/coreclr/jit/hwintrinsiccodegenarm64.cpp Emits SVE instructions for VectorT intrinsics
src/coreclr/jit/hwintrinsicarm64.cpp Imports VectorT intrinsics and updates true/false mask creation
src/coreclr/jit/hwintrinsic.h Marks VectorT_* as special cases for scalar/broadcast creation
src/coreclr/jit/gentree.h Extends vector/mask constants to support scalable encodings
src/coreclr/jit/gentree.cpp Adds scalable constant construction, hashing, folding, and printing
src/coreclr/jit/emitarm64.h Repositions signed-immediate helpers used by new SVE paths
src/coreclr/jit/compiler.hpp Extends bitmask helpers for >64-register targets
src/coreclr/jit/compiler.h Adds new compiler helpers for scalable vector/mask constants
src/coreclr/jit/codegenarm64.cpp Adds emission for scalable vector/mask constants

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

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

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

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

github-actions Bot 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-actions github-actions Bot 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 EvaluateUnaryInPlace → TryEvaluateUnaryInPlace (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. EvaluateUnaryInPlace → TryEvaluateUnaryInPlace 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

a74nh commented Jul 23, 2026

Copy link
Copy Markdown
Contributor Author

@a74nh Needs rebase as discussed in meeting

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

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

Labels

area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI community-contribution Indicates 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