-
Notifications
You must be signed in to change notification settings - Fork 13.1k
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
Inconsistency in behavior of MIR and SIMD shifts #91237
Comments
The consistent behavior should probably be that either both of them truncate, or both of them are UB when the offset is too big. I will try to summarize what I understood to be the arguments in favor of either solution. Arguments in favor of UB:
Arguments in favor of truncation:
|
My current hypothesis regarding the performance of lowering using Assuming that LLVM simply generates the appropriate This depends on the CPU, of course.
A side note: apparently Zig exposes a I would have to recheck everything with respect to |
In all other cases, we implement a wrapping logic where applicable. This is another case it applies, and per rust-lang/rust#91237, we may wish to specify this as the natural behavior of simd_{shl,shr}.
For all other operators, we use wrapping logic where applicable. This is another case it applies. Per rust-lang/rust#91237, we may wish to specify this as the natural behavior of `simd_{shl,shr}`.
On the PG-PSIMD end, we did in fact go the route of wrapping shifts in our implementation, so if that should be moved deeper into the compiler (so that our impl turns into a bare call to the intrinsic), that's fine from our POV. We may still want to have access to a |
Sounds great. :D So if someone with the required LLVM knowledge could implement the codegen changes for the simd_shr/shl intrinsics, it looks like all involved parties would approve of that change. |
Hm, if we did it in our own LLVM lowering, we could use a const-known parameter that is in-bounds to simply emit |
The MIR primitive binops for shifting are well-defined even when the shift offset is larger than the size of the left operand: the shift offset is truncated to that size before doing the shift. (MIR building relies on this, with overflow checks disabled it is entirely safe to produce MIR shift binops without any guards.)
On the other hand, the SIMD shift intrinsics are currently UB when the shift offset is larger than the size of the left operand. (This is based on the fact that they lower to LLVM operations that yield poison in that case.)
This is inconsistent. IMO it would be a good idea to make these two primitive shift operations in our language consistent. One is exposed as a binop and one as an intrinsic, but that does not fundamentally make one less primitive than the other. If they are consistent, this reduces possible sources of confusion for backend developers. It also makes implementing the SIMD intrinsics for CTFE/Miri a lot easier, since it can just call the MIR binop in a loop.
Also see the prior discussion at rust-lang/miri#1920 (comment).
The text was updated successfully, but these errors were encountered: