-
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 a compiler intrinsic to back bigint_helper_methods
#133663
Conversation
r? @ibraheemdev rustbot has assigned @ibraheemdev. Use |
Some changes occurred to the intrinsics. Make sure the CTFE / Miri interpreter cc @rust-lang/miri, @rust-lang/wg-const-eval |
f52a909
to
09a8f68
Compare
Will take a look at this later, but I like that you managed to make fallback intrinsics work here when I couldn't quite get them to work for #132195. |
09a8f68
to
acbeaa2
Compare
☔ The latest upstream changes (presumably #133728) made this pull request unmergeable. Please resolve the merge conflicts. |
Also just to clarify my opinion on where this stands relative to #132195: I think that this PR just adding the intrinsic is okay, although I would like the intrinsic to also handle the signed case, even if it's only used at the moment for the unsigned case. That way, my PR can just update the library methods to use the intrinsic, without having to worry about the slow implementation. Although the signed version of the library methods will likely return an unsigned word always for the least-significant / high-order part, it vastly simplifies the intrinsic to just have the same type for the arguments and return value, so, I would prefer that we do this specifically for the intrinsic. Since it doesn't actually affect the returned bits, I think that it's okay to just cast half of it unsigned on the library side. You can see how I did this here in a previous (closed) PR. Otherwise, LGTM. Also, while the codegen test should suffice, if you want to copy over the library tests I added in my PR to verify that the intrinsic works correctly, feel free. I specifically added a bunch of edge cases with |
acbeaa2
to
c67e5f4
Compare
Success! No more "oh my this is hacky", just a couple of
It didn't, actually. Once the fallback was working, the implementation in cg_llvm was super-easy -- after all, at that level the signed and unsigned types are the same anyway. |
This comment has been minimized.
This comment has been minimized.
c67e5f4
to
5d91169
Compare
This comment has been minimized.
This comment has been minimized.
let high = self.trunc(high, narrow_llty); | ||
|
||
let pair_llty = self.type_struct(&[narrow_llty, narrow_llty], false); | ||
let pair = self.const_poison(pair_llty); |
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.
Just comparing to my version, this doesn't really matter that much, but const_undef
feels slightly more accurate here just semantically. Not actually sure if this affects codegen though.
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.
poison
is always preferred where possible, because it doesn't have the same complications as undef
. (undef << 1) & 1
is guaranteed to be 0
, but (poison << 1) & 1
is still poison. You'll also see that both what we emit for tuples and what the optimizer does for tuples both use poison
for this: https://rust.godbolt.org/z/WTnW4GPE6
ee18903
to
f636b64
Compare
/// => (2²ⁿ - 2ⁿ⁺¹ + 1) + (2ⁿ⁺¹ - 2) | ||
/// => 2²ⁿ - 1 | ||
/// | ||
/// For `iN`, the upper bound is MIN * MIN + MAX + MAX => 2²ⁿ⁻² + 2ⁿ - 2, |
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.
Pop Quiz: after a double-width isize::MIN * isize::MIN
(which is the largest possible positive result from a multiplication), how many more isize::MAX
s can you add to the result before it would need to carry to triple-width?
Answer: isize::MAX + 2
of them!
(The carrying_mul_add
really feels so much nicer for unsigned types, since uN::MAX * uN::MAX + uN::MAX + uN::MAX == u2N::MAX
-- no more space available after that.)
This is outside my territory so I'm going to pass this along. r? libs |
☔ The latest upstream changes (presumably #134516) made this pull request unmergeable. Please resolve the merge conflicts. |
f636b64
to
0c1cc9e
Compare
Since I'm not sure if the random-reroll notifies, friendly ping here @Amanieu |
Is it intentional that this intrinsic is only ever called with Otherwise LGTM |
Yes; once this is merged I'll be rebasing #132195 on top of it which does add methods that use this to its full extent. I think that scottmcm just wanted to lower the scope of this PR to just the intrinsic, and not any library changes. |
Yup, what @clarfonthey said -- this takes 4 arguments because So I'm happy to let them take over for how to actually expose it to stable :) @bors r=Amanieu |
Add a compiler intrinsic to back `bigint_helper_methods` cc rust-lang#85532 This adds a new `carrying_mul_add` intrinsic, to implement `wide_mul` and `carrying_mul`. It has fallback MIR for all types -- including `u128`, which isn't currently supported on nightly -- so that it'll continue to work on all backends, including CTFE. Then it's overridden in `cg_llvm` to use wider intermediate types, including `i256` for `u128::carrying_mul`.
This comment has been minimized.
This comment has been minimized.
💔 Test failed - checks-actions |
Including implementing it for `u128`, so it can be defined in `uint_impl!`. This way it works for all backends, including CTFE.
0c1cc9e
to
4669c0d
Compare
Fix was just changing some @bors r=Amanieu |
…iaskrgr Rollup of 6 pull requests Successful merges: - rust-lang#133663 (Add a compiler intrinsic to back `bigint_helper_methods`) - rust-lang#134798 (Make `ty::Error` implement all auto traits) - rust-lang#134808 (compiletest: Remove empty 'expected' files when blessing) - rust-lang#134809 (Add `--no-capture`/`--nocapture` as bootstrap arguments) - rust-lang#134826 (Add spastorino to users_on_vacation) - rust-lang#134828 (Add clubby789 back to bootstrap review rotation) r? `@ghost` `@rustbot` modify labels: rollup
Rollup merge of rust-lang#133663 - scottmcm:carrying_mul_add, r=Amanieu Add a compiler intrinsic to back `bigint_helper_methods` cc rust-lang#85532 This adds a new `carrying_mul_add` intrinsic, to implement `wide_mul` and `carrying_mul`. It has fallback MIR for all types -- including `u128`, which isn't currently supported on nightly -- so that it'll continue to work on all backends, including CTFE. Then it's overridden in `cg_llvm` to use wider intermediate types, including `i256` for `u128::carrying_mul`.
cc #85532
This adds a new
carrying_mul_add
intrinsic, to implementwide_mul
andcarrying_mul
.It has fallback MIR for all types -- including
u128
, which isn't currently supported on nightly -- so that it'll continue to work on all backends, including CTFE.Then it's overridden in
cg_llvm
to use wider intermediate types, includingi256
foru128::carrying_mul
.