Skip to content

repr(scalable) #143924

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 12 commits into
base: master
Choose a base branch
from
Draft

repr(scalable) #143924

wants to merge 12 commits into from

Conversation

davidtwco
Copy link
Member

@davidtwco davidtwco commented Jul 14, 2025

Supercedes #118917.

Initial experimental implementation of rust-lang/rfcs#3838. Introduces a repr(simd, scalable(N)) attribute that can be applied to types with a single [$ty] field (for u{16,32,64}, i{16,32,64}, f{32,64}, bool). repr(scalable) types are lowered to scalable vectors in the codegen backend.

As with any unstable feature, there will necessarily be follow-ups as we experiment and find cases that we've not considered or still need some logic to handle, but this aims to be a decent baseline to start from.

This is pending approval from the relevant teams (and working out which team that is) to have an experimental implementation. I'll update this line when that approval is received.


Scalable vectors are non-const Sized in rust-lang/rfcs#3729 parlance, so while implementation of that RFC is in-progress (currently blocked on the next solver), this requires some special-casing in the type system: this implementation adds a built-in impl for Sized for these types.

That's definitely incorrect and there will be cases where it causes an ICE or incorrect code to be accepted (only when using the unstable feature!), but there is no intention of stabilising it like that, and given that an implementation of sized_hierarchy is coming, there is a clear path to removing this. A built-in implementation of Sized was chosen as the workaround over skipping the addition of Sized constraints in the first place for a few reasons:

  • A built-in impl of Sized is much closer to how the final implementation will look with non-const Sized. That will have a built-in impl for Sized, just not const Sized.
  • It's hard to check if a Sized obligation is being added for a scalable vector in every circumstance because sometimes you're adding an obligation on a inference variable or something like that and you just don't know yet. In those circumstances, all you can do is skip the Sized obligation if feature(repr_scalable) is true and that's way more incorrect.
  • This special-casing has a much smaller footprint than changing all of the places where a Sized obligation is added, and if we're going to add something incorrect temporarily, it's better for it to be small and in one place than small and in two dozen places.

@rustbot
Copy link
Collaborator

rustbot commented Jul 14, 2025

r? @compiler-errors

rustbot has assigned @compiler-errors.
They will have a look at your PR within the next two weeks and either review your PR or reassign to another reviewer.

Use r? to explicitly pick a reviewer

@rustbot rustbot added A-attributes Area: Attributes (`#[…]`, `#![…]`) A-LLVM Area: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues. S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. T-libs Relevant to the library team, which will review and decide on the PR/issue. WG-trait-system-refactor The Rustc Trait System Refactor Initiative (-Znext-solver) labels Jul 14, 2025
@rustbot
Copy link
Collaborator

rustbot commented Jul 14, 2025

Some changes occurred in compiler/rustc_attr_parsing

cc @jdonszelmann

Some changes occurred in compiler/rustc_attr_data_structures

cc @jdonszelmann

Some changes occurred in compiler/rustc_passes/src/check_attr.rs

cc @jdonszelmann

Some changes occurred to the intrinsics. Make sure the CTFE / Miri interpreter
gets adapted for the changes, if necessary.

cc @rust-lang/miri, @RalfJung, @oli-obk, @lcnr

Some changes occurred to the CTFE / Miri interpreter

cc @rust-lang/miri

Some changes occurred to the platform-builtins intrinsics. Make sure the
LLVM backend as well as portable-simd gets adapted for the changes.

cc @antoyo, @GuillaumeGomez, @bjorn3, @calebzulawski, @programmerjake

Some changes occurred to MIR optimizations

cc @rust-lang/wg-mir-opt

Some changes occurred in compiler/rustc_codegen_ssa

cc @WaffleLapkin

Some changes occurred in compiler/rustc_codegen_gcc

cc @antoyo, @GuillaumeGomez

changes to the core type system

cc @compiler-errors, @lcnr

Some changes occurred to the CTFE machinery

cc @RalfJung, @oli-obk, @lcnr

davidtwco and others added 4 commits July 14, 2025 11:19
Extend parsing of `ReprOptions` with `repr(scalable(N))` which always
accepts a single literal integral value - the base multiple of lanes
that are in a scalable vector. Can only be applied to structs and must
be used with `repr(simd)`.

Co-authored-by: Jamie Cunliffe <[email protected]>
Add a `repr_scalable` feature gate and require its use for the
`repr(scalable(N)` attribute.

Co-authored-by: Jamie Cunliffe <[email protected]>
Extend well-formedness checking and HIR analysis to prohibit the use of
scalable vectors in structs, enums, unions, tuples and arrays. LLVM does
not support scalable vectors being members of other types, so these
restrictions are necessary.

Co-authored-by: Jamie Cunliffe <[email protected]>
Scalable vectors can be passed by register over the FFI boundary to C
code, so they shouldn't be linted by `improper_ctypes`.
@davidtwco davidtwco marked this pull request as draft July 14, 2025 11:21
@rustbot rustbot added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Jul 14, 2025
@davidtwco
Copy link
Member Author

I've changed this back to a draft and marked it as S-waiting-on-author while I rebase it and get the approval for an experimental implementation to go ahead.

@davidtwco davidtwco force-pushed the sve-infrastructure branch from 0ed0434 to cf9474d Compare July 14, 2025 11:52
davidtwco and others added 2 commits July 14, 2025 11:53
Scalable vectors should behave like other value types - being permitted
as arguments, locals, return types, etc. This requires that these types
be `Sized`, despite not meeting the definition and requirements of
`Sized`. `feature(sized_hierarchy)` is being implemented to enable
scalable vectors to be non-`const Sized`, but in the mean time, add
a builtin impl for scalable vectors. This must be addressed prior to
stabilisation.
`simd_reinterpret` is a replacement for `transmute`, specifically for
use with scalable SIMD types. It is used in the tests for scalable
vectors and in stdarch.

Co-authored-by: Jamie Cunliffe <[email protected]>
@davidtwco davidtwco force-pushed the sve-infrastructure branch from cf9474d to d58c634 Compare July 14, 2025 11:53
@rust-log-analyzer

This comment was marked as resolved.

davidtwco and others added 3 commits July 14, 2025 12:08
Introduces `BackendRepr::ScalableVector` corresponding to scalable
vector types annotated with `repr(scalable)` which lowers to a scalable
vector type in LLVM.

Co-authored-by: Jamie Cunliffe <[email protected]>
LLVM doesn't handle stores on `<vscale x N x i1>` for `N != 16`, a type
used internally in SVE intrinsics. Spilling to the stack to create
debuginfo will cause errors during instruction selection. These types
that are an internal implementation detail to the intrinsic, so users
should never see them types and won't need any debuginfo.

Co-authored-by: Jamie Cunliffe <[email protected]>
Scalable vectors cannot be members of ADTs and thus cannot be kept over
await points in async functions.
@davidtwco davidtwco force-pushed the sve-infrastructure branch 2 times, most recently from 0c22701 to 3ad0898 Compare July 14, 2025 12:12
@rust-log-analyzer

This comment has been minimized.

As scalable vectors are ultimately just registers, they should be able
to implement `Copy` and `Clone`, which require some small special-casing
in the compiler to ignore the field within the scalable vector types.
@rust-log-analyzer

This comment has been minimized.

@davidtwco davidtwco force-pushed the sve-infrastructure branch from 5c92874 to 3edf1b6 Compare July 14, 2025 13:30
Scalable vector types only work with the relevant target features
enabled, so require this for any function with the types in its
signature.
Trivial changes to rust-analyzer to keep it compiling with changes to
`ReprOptions`.
@rust-log-analyzer

This comment has been minimized.

@davidtwco davidtwco force-pushed the sve-infrastructure branch from 3edf1b6 to 4f6b823 Compare July 14, 2025 14:20
Copy link
Member

@workingjubilee workingjubilee left a comment

Choose a reason for hiding this comment

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

I do not intend to have repr(simd) survive this year, so I do not think this should be added.

@davidtwco
Copy link
Member Author

I do not intend to have repr(simd) survive this year, so I do not think this should be added.

Could you elaborate?

@workingjubilee
Copy link
Member

I intend to replace it with an approach based on lang items for a variety of reasons, one of them being that to start with, the repr(simd) "attribute" does not compose and should not.

r? @workingjubilee

@workingjubilee
Copy link
Member

workingjubilee commented Jul 14, 2025

Likewise, scalable vectors do not really have a diversity in their representation. They either go in the scalable vector registers or they don't. They are one type, even if it is parameterized by the element type (and possibly the CPU's Matrix state, idk).

@davidtwco
Copy link
Member Author

I intend to replace it with an approach based on lang items for a variety of reasons, one of them being that to start with, the repr(simd) "attribute" does not compose and should not.

I think this discussion is better for the RFC - rust-lang/rfcs#3838 - rather than the implementation.

With that said, I definitely don't think this should to be blocked by your intentions to change repr(simd) - extending our existing, RFC-approved, SIMD infrastructure is a natural way to go about supporting scalable vectors. Unless there's an alternative proposal for changing repr(simd) out there that has been accepted or is on the cusp of being accepted and I've missed it, working from what we have today is all I can do.

Nothing in rust-lang/rfcs#3838 should make your plans impossible as it's just more internal infrastructure that could easily be changed to something else with a well-motivated proposal, no different than repr(simd). It'll be your responsibility to update your plans/proposal if repr(scalable) makes progress first. It goes the other way too, if you make progress changing repr(simd) prior to this making progress then I'll have to update my proposal, that's fine. Unless something I'm proposing completely shuts the door on your plans - which would be worth discussing! - and we decide we'd like to avoid that, then it shouldn't block this.

@workingjubilee
Copy link
Member

So you want me to race you?

@workingjubilee
Copy link
Member

workingjubilee commented Jul 14, 2025

  1. My understanding has always been that "an RFC approved it" doesn't mean much when it concerns internal-facing details. We've changed things away from RFC-approved implementation details without redoing the RFC. e.g. #[track_caller] only barely resembles the original implementation described in the RFC.
  2. Specifically, we have removed or heavily modified several parts of RFC1199 already, and each one was a lot of work.
  3. We have had to issue many patches like Ban projecting into SIMD types [MCP838] #143833 for fixing how repr(simd) is compiled. Yes, we have this existing infrastructure, which is how we know how flawed it is.
  4. This is not some random idea I had, it was an issue from some time ago. I am surprised to find out I am the only one who reviews related issues before commencing work on things. Remove repr(simd) attribute and use a lang-item instead #63633
  5. As someone paid to work on this full-time and also empowered as compiler team lead, I fear you have more ability to push through things than me, especially because for various reasons I take a great deal of care before pushing for things. For that reason, while I am willing to concede the changes here might not obstruct a future change, I do expect to be allowed to review this to make that determination, and hoped for a more collaborative approach instead of possibly fighting to rebase over each other.

@bors
Copy link
Collaborator

bors commented Jul 14, 2025

☔ The latest upstream changes (presumably #143934) made this pull request unmergeable. Please resolve the merge conflicts.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-attributes Area: Attributes (`#[…]`, `#![…]`) A-LLVM Area: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues. S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. T-libs Relevant to the library team, which will review and decide on the PR/issue. WG-trait-system-refactor The Rustc Trait System Refactor Initiative (-Znext-solver)
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants