Skip to content

Conversation

@folkertdev
Copy link
Contributor

This addresses two issues:

  • the docs on comparison operators (simd_gt etc.) said they only work for floating-point vectors, but they work for integer vectors too.
  • the docs on various functions that use a mask did not document that the mask must be a signed integer vector. Unsigned integer vectors would cause invalid behavior when the mask vector is widened (unsigned integers would use zero extension, producing incorrect results).

r? @workingjubilee

@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-libs Relevant to the library team, which will review and decide on the PR/issue. labels Feb 28, 2025
@rustbot
Copy link
Collaborator

rustbot commented Feb 28, 2025

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

cc @rust-lang/miri, @rust-lang/wg-const-eval

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

/// `U` must be a vector of pointers to the element type of `T`, with the same length as `T`.
///
/// `V` must be a vector of integers with the same length as `T` (but any element size).
/// `V` must be a vector of signed integers with the same length as `T` (but any element size).
Copy link
Member

Choose a reason for hiding this comment

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

Maybe outside the scope of this PR, but this would need to be checked in codegen and emit an ICE

Copy link
Contributor Author

@folkertdev folkertdev Feb 28, 2025

Choose a reason for hiding this comment

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

what exactly? you get a monomorphization error when these rules are violated. They are not the prettiest errros, but they are not ICEs either. Unless I'm missing something. e.g. https://godbolt.org/z/f5j5re5z8

Copy link
Member

Choose a reason for hiding this comment

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

Yep, that's a post-mono error.

Copy link
Member

Choose a reason for hiding this comment

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

Oh, good. I misunderstood and thought you meant the intrinsic was permitting invalid behavior.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

yeah this is just bringing the docs up to date with the behavior that we already have and enforce.

Copy link
Member

Choose a reason for hiding this comment

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

Looking at this in the LLVM backend I don't even see such a widening cast. This code converts the masks to i1 vectors which LLVM seems to use for them, and it does that with lshr and trunc. The lshr is entirely unnecessary for correctness as we require the input to be all-1 or all-0, but

    /// The rust simd semantics are that each element should either consist of all ones or all zeroes,
    /// but this information is not available to llvm. Truncating the vector effectively uses the lowest bit,
    /// but codegen for several targets is better if we consider the highest bit by shifting.

But I can't find anything that would go wrong with unsigned integers.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I personally agree, in that an intrinsic (that normal users should never have to worry about), we could either demand that the lane width matches the other arguments, or that the mask uses sign extension no matter the signedness of the argument.

From what I can tell the codegen backends already handle this, because e.g. in llvm (and from what i can see, also cranelift and gcc) the integers are just a bunch of bits.

The counter-argument was that performing sign extension on what rust believes is a vector with unsigned types would violate type safety.

Copy link
Member

Choose a reason for hiding this comment

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

The counter-argument was that performing sign extension on what rust believes is a vector with unsigned types would violate type safety.

I don't know what you mean by that. There's no sign extension happening, as far as I can tell. Also, all the backends have to do is implement the intended mask semantics, which is described in a bitwise way. If they use sign extension as part of that, that's completely fine. There's no type safety violation here.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I agree, the backends support it, and the intrinsic could (and in my opinion should) support it too. I'm just relaying the response I got when I suggested exactly that https://rust-lang.zulipchat.com/#narrow/channel/257879-project-portable-simd/topic/add.20.60simd_max.60.20and.20.60simd_min.60/near/502647748

Copy link
Member

Choose a reason for hiding this comment

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

these all also accept integer vectors as arguments
@folkertdev folkertdev force-pushed the simd-intrinsic-doc-fixes branch from 78636b7 to 417c51c Compare February 28, 2025 23:21
this is because they may be widened, and that only works when sign extension is used: zero extension would produce invalid results
@folkertdev folkertdev force-pushed the simd-intrinsic-doc-fixes branch from 417c51c to 854e9f4 Compare February 28, 2025 23:29
@workingjubilee
Copy link
Member

cool! looks good to me. test improvement stuff sounds nice as followup if people want but isn't required here and now.

@bors r+ rollup

@bors
Copy link
Collaborator

bors commented Feb 28, 2025

📌 Commit 854e9f4 has been approved by workingjubilee

It is now in the queue for this repository.

@bors bors added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Feb 28, 2025
matthiaskrgr added a commit to matthiaskrgr/rust that referenced this pull request Mar 1, 2025
…s, r=workingjubilee

Fix inaccurate `std::intrinsics::simd` documentation

This addresses two issues:

- the docs on comparison operators (`simd_gt` etc.) said they only work for floating-point vectors, but they work for integer vectors too.
- the docs on various functions that use a mask did not document that the mask must be a signed integer vector. Unsigned integer vectors would cause invalid behavior when the mask vector is widened (unsigned integers would use zero extension, producing incorrect results).

r? `@workingjubilee`
@bors bors merged commit c112b70 into rust-lang:master Mar 2, 2025
6 checks passed
@rustbot rustbot added this to the 1.87.0 milestone Mar 2, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. T-libs Relevant to the library team, which will review and decide on the PR/issue.