-
Notifications
You must be signed in to change notification settings - Fork 12.9k
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
Add rustc_intrinsic_const_vector_arg attribute to allow vectors to be passed as constants #118980
Conversation
r? @wesleywiser (rustbot has picked a reviewer for you, use r? to override) |
rust-analyzer is developed in its own repository. If possible, consider making this change to rust-lang/rust-analyzer instead. cc @rust-lang/rust-analyzer These commits modify the If this was unintentional then you should revert the changes before this PR is merged. Some changes occurred in compiler/rustc_codegen_gcc |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
cc @bjorn3
☔ The latest upstream changes (presumably #119070) made this pull request unmergeable. Please resolve the merge conflicts. |
I have narrowed the scope of this attribute to only being applicable to simd types defined in the local crate as I do not know how to check if the type is a simd type when it is not local in HIR. |
This comment has been minimized.
This comment has been minimized.
☔ The latest upstream changes (presumably #119146) made this pull request unmergeable. Please resolve the merge conflicts. |
b71f4ab
to
66d3179
Compare
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
☔ The latest upstream changes (presumably #120500) made this pull request unmergeable. Please resolve the merge conflicts. |
@GeorgeWort can you address the CI test failure? once that's done you can comment with |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This diff is much bigger than needed. See #121225 for a PR that makes some other intrinsics require a constant argument; this should share that same check.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In fact the even better alternative is probably to remove the simd_shuffle case entirely, and just add the new attribute to simd_shuffle.
let mut copied_constant_arguments = vec![]; | ||
'make_args: for (i, arg) in first_args.iter().enumerate() { | ||
let mut op = self.codegen_operand(bx, &arg.node); | ||
let mut op = if const_vec_arg_indexes.contains(&i) { | ||
// Force the specified argument to be constant by using const-qualification to promote any complex rvalues to constant. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This comment is misleading. You are not promoting anything here, and you shouldn't. You are not forcing anything to be a constant either, you are relying on the fact that typecheck already already ensured that this is a constant.
fn foo2(a: i8x2, b: i8); | ||
} | ||
|
||
#[rustc_intrinsic_const_vector_arg(0)] //~ ERROR attribute should be applied to functions in `extern "unadjusted"` modules |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there a reason this argument needs to be about const vectors?
If this were to become a general rustc_intrinsic_const_arg
, then it could also be used for simd_insert/extract.
This comment has been minimized.
This comment has been minimized.
@rustbot ready |
fwiw I don't think this should be done. We're just digging ourselves a bigger hole. This explicitly works around a type system limitation in ways that we may never be able to recover from. I'm aware of the precedent, but that doesn't really make it better to use it more widely. If this stays assigned to me I will just close it and the corresponding issue. I am aware of the ugliness and limitations of using const generics right now, but these limitations are there for a reason, and further going around our stability rules without a long term plan and lang team approval seems just wrong. |
Thanks for your feedback. I appreciate your thoughts about this seeming like a work around the limitations of the type system. I could be mistaken on the following; this problem seems more with 'const vectors' as opposed to a problem const generics more broadly? Though I appreciate I could be wrong on that and that these are these in fact entwined? Also what stability features are being circumvented? |
Since it allows complex computations to be done for the const argument (e.g. via |
That said, if someone else wants to deal with this, that's fine. I just won't be able to do any compiler work that would unblock anything here in the next 4 months, and I don't just want to approve something just because it works and I don't have time to dig into it. Also I would prefer having a long term strategy of T-libs, T-lang and SIMD folk for what is going to happen here, but I can totally see that there's no capacity for doing that work rn and we already have a hack so why not use it more. |
Overall the situation is similar to simd_shuffle -- there we also punted on this and trust stdarch to do all the required checking. Unfortunately it turns out hardware is But anyway, with simd_shuffle we were okay trusting stdarch to do all the required checks, so we could consider doing the same here. We'd have to make it clear that this is really just a hack to support the Regarding the PR itself, I am concerned that this seems to largely duplicate the simd_shuffle infrastructure instead of replacing it. IMO if we do this, we do it right: rip out all special-casing of simd_shuffle and make it use the attribute instead. And in fact this should cover simd_insert and simd_extract as well, which are part of the same hack. I wouldn't mind having other people involved in the discussion though, let's get a compiler reviewer. |
/// process constant containing SIMD shuffle indices | ||
pub fn simd_shuffle_indices( | ||
/// process constant SIMD vector or constant containing SIMD shuffle indices | ||
pub fn early_evaluate_const_vector( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I find "early" here quite confusing, I don't think we otherwise use this adjective to refer to compile-time evaluation. Why not just evaluate_const_vector
?
// call([1, 0]); | ||
// | ||
// And outputting: @call(<2 x i32> <i32 0, i32 1>) | ||
// thus treating them the same if they are a const vector |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't understand any part of this comment. What's call
? Why does it not involve defn
at all? Also, the code below needs comments explaining how it relates to these two cases.
But really, the biggest issue is that a nested loop makes no sense. There should be only one loop, the one that goes over all vector elements. The only difference between the two representations is that in one case we need one extra unwrap_branch()[0]
since the "struct wrapping an array" adds one extra layer to the tree.
if let mir::Operand::Constant(constant) = &arg.node | ||
&& constant.ty().is_simd() | ||
{ | ||
let (llval, ty) = self.early_evaluate_const_vector(bx, &constant); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So is there no LLVM intrinsic that needs a constant integer? It's only ever vectors? That seems odd.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This test has nothing to do with any lint, does it? It checks that the attribute actually works?
It has an awful lot of static asserts, tho outside the type system |
let mut copied_constant_arguments = vec![]; | ||
'make_args: for (i, arg) in first_args.iter().enumerate() { | ||
let mut op = self.codegen_operand(bx, &arg.node); | ||
let mut op = if const_vec_arg_indexes.contains(&i) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you can just remove this if
. It's always correct to use this translation if the value happens to be a constant SIMD vector, right?
In fact, should we maybe do this in OperandRef::from_const
? Then it just happens for all constant SIMD vectors? That would in fact make the attribute entirely optional -- a nice-to-have to prevent LLVM errors, but not actually required to unblock stdarch.
Yeah, tons of inline consts with assertions. That's even available on stable now so it should be acceptable. After reading through the PR (against better judgment, but this is more fun than the things I should be doing ;), I think there's actually two largely orthogonal issues here:
|
So @GeorgeWort I would propose that you make a new PR that does the first part of what I described in my previous issue. I'd suggest changing |
☔ The latest upstream changes (presumably #125443) made this pull request unmergeable. Please resolve the merge conflicts. |
Thanks @RalfJung, hope the things you should be doing eventually get done! I have avoided replying to your individual comments on this PR as it seems we're looking at a different approach to tackle this problem. What you have stated makes sense to have a generalised place, potentially named With respect to odd failures with LLVM, in debug mode we are currently experiencing; Are there any further places in the code that you could point me to where I should investigate further? @oli-obk what are your thought's on these suggestions? Do they seem reasonable to you? |
Not sure what else is there to investigate; as far as I am concerned, we can move to implementation. That's a fairly local change inside the codegen backend, without any new guarantees or language-level surface, doing for vector constants what we already happen to do for integer constants -- generating them as LLVM immediates. I'm not an LLVM expert though so maybe there's something I missed. @nikic @Amanieu @workingjubilee does this sound like a reasonable plan? |
@RalfJung Sounds reasonable to me. |
The CPU instruction only takes an immediate constant. For some reason LLVM decided to make their intrinsic take a vector and then require all elements of that vector to have the same value (which must also be a constant). While this is a rather bizarre choice, in the end all we have to do is ensure that the LLVM intrinsic gets its immediate constant vector from our const eval. |
Thanks, I will close this PR and commence work on a new branch and open a new pull request against the same issue. |
Please mention the new PR in #118209 once it exists. Backlinks won't trigger notifications. :) |
This allows constant vectors using a repr(simd) type to be propagated
through to the backend by reusing the functionality used to do a similar
thing for the simd_shuffle intrinsic.
fix #118209