-
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
Move sqrt from std
to core
#63455
Move sqrt from std
to core
#63455
Conversation
r? @shepmaster (rust_highfive has picked a reviewer for you, use r? to override) |
This can generate a libmath call on systems without hardware sqrt, I believe, which is why it was in std before. |
According to an issue on the compiler-builtins crate (link), that will apparently never happen with any current target. If it does on some new target that Rust is ported to, it's as "simple" as patching compiler-builtins to expose that function in |
We should probably resolve #62729 before exposing more things from libcore, as this will likely run into the same issue. |
I'll try to get a PR to #62729 rolling, exposing the necessary symbols for soft-float impls. The PR will probably need to add a number of new symbols anyways, I can add sqrt then too. |
Too deep knowledge for me; reassigning to someone from libs... r? @Amanieu |
I'm not certain that we're ready to do this just yet. There's a number of reasons that we haven't started moving so many intrinsics to libcore yet. While the compiler-builtins fallback implementation is a prerequisite it has unfortunate interactions with symbol visibility which also causes issues. Native platform By putting a symbol in Note that on some platforms LLVM will expand the intrinsic inline (such as x86/x86_64 most likely). These will have no performance regression even if Rust's |
I thought you said in the compiler-builtins issue that LLVM wouldn't do that? I guess you meant "LLVM won't do that on this particular target"? |
LLVM in general will sort of just do what's best at the time. If LLVM can lower an intrinsinc call like these to an inline instruction sequence, it will. Otherwise if LLVM can't it will lower it to a function call. For x86/x86_64 it seems to be dependent on whether the SSE feature is enabled. Although it's on by default it's not always on. I suspect that LLVM's logic for lowering is different for other architectures like ARM or AArch64. |
Note that Focusing back on point: What concrete action can be done to advance this PR towards being accepted? Regarding the concerns about possibly bad performance on some targets:
I certainly want to do this right, but I also want to try and have a clear path forward, to keep making progress, because "floating point in core" has been stalled for many months now. |
For moving this forward, are there parts of my previous comment that are unclear? Sorry I don't have a ton of time to manage this, so I can help out sometimes but I cannot personally lead the charge and make sure all the ducks are in a row for all PRs. |
Apart from those questions, I did do a quick check of core-only #![feature(core_intrinsics)]
#![no_std]
pub fn sqrt_f32(f: f32) -> f32 {
unsafe { core::intrinsics::sqrtf32(f) }
}
pub fn sqrt_f64(f: f64) -> f64 {
unsafe { core::intrinsics::sqrtf64(f) }
} into godbolt, using Nightly
and the compiler args
for each TARGET value. Here's the highlights, though you can also look at the spreadsheet too I guess:
The targets where a call to
If "Bare RISC-V" means "no OS" like I think it does, then they don't really have an existing system libm to get shadowed by us. Since the That just leaves PowerPC Linux... I don't know what libm they use, but if it's either MUSL or OpenLibm then that's the same In summary, I strongly suspect that we're in the clear. |
For me, I'd like to personally have faith that someone has investigated this to the degree that they know more about it than me, because I know that I at least personally do not know how this works on all platforms. I think doing something in terms of checking is required and we can see where we feel after that.
The compiler-builtins crate doesn't currently export symbols on main platforms that override those found in system libm implementations. It only does that on some platforms (not all) today and otherwise the symbols exported on all platforms are rustc-specific.
Thanks for investigating all that! One thing I'm also worried about though is what happens when the default codegen settings are tweaked. For example if |
But none of that is affected by this PR, right? Here's my logic:
That's why I'm confused about this concern.
What rust calls the example::sqrt_f32:
flds 4(%esp)
fsqrt
retl
example::sqrt_f64:
fldl 4(%esp)
fsqrt
retl Because the intel chips supported
Unfortunately, as mentioned, I don't have access to a mips, powerpc, or riscv device and I don't know anyone who does.
|
@Lokathor, you might want to have a look in https://internals.rust-lang.org/t/gcc-compile-farm-for-rustc/9511 . At the moment, they have mips, powerpc computers. See the list for more info: https://cfarm.tetaneutral.net/machines/list/. |
Sorry I think this got lost in my inbox. This whole discussion affects this PR because support in compiler-builtins is a prerequisite to landing this PR. You're right that this PR doesn't affect symbols of compiler-builtins but this feature wouldn't work on platforms where the intrinsic is lowered to a I also unfortunately do not know how to test on mips/powerpc/riscv/etc. A lack of resources to test though I don't think is a great reason to merge this PR. The purpose of review is to head off bug reports about performance regressions and update One thing I'm also realizing now is that if we add a |
Hmm, can the compiler-builtins and/or libm distribution packaged with rust utilize nightly features like core and std can? If so, we could cfg in the use of nightly intrinsics, or even just inline asm as necessary. |
Yes, both crates can use nightly features: |
I had noticed that, but wasn't clear on if that was just someone using it for nightly wanting it to be better for them or if even stable folks got those perks. So, I think that we need to
Is it correct to assume that we already export stuff from compiler-builtins as little as possible? Can we just focus the work on libm? |
That's certainly always good to have regardless! I was under the impression the purpose of this PR and what you wanted to do was to avoid this step. We haven't had this happen a lot before so I've been trying to figure this out as I go along. I think we've concluded that this isn't required in the specific case of All in all I think while it may have been possible originally to avoid updating libm, I don't think we can avoid that now. I think we need to make sure that if we move a symbol from libstd to libcore that we've improved our libm implementation to be more than "we just copied it from musl".
Yes and no. There's no way we can export something from compiler-builtins to only be used by Rust code due to how lowering to libcalls works in LLVM. (we can't configure symbol names, LLVM already picked them for us). In that sense if we export anything from compiler-builtins it is exposed for all C/C++/Rust code. That being said we don't just blindly reexport everything from libm, so we're still actually choosing what to export. |
I would say that the main reason for this PR is that right now math libraries can't also easily be So
I understand that the exports are global to the whole program across all languages, but does |
The concern is that we don't want to accidentally conflict with any existing libm package shipped with the system (which is probably written in C and/or ASM). If the target is bare-metal, then it has no existing anything (right?), so I don't think we can have a conflict problem. |
I think the best way forward here is to do something like:
That would mean we have support in for the symbol being optimized on relevant platforms and it's optimized in rust code in libcore. Platforms like mips and powerpc may be slow but all the infrastructure is in place to speed it up so we can handle that as it comes up. How's that sound? |
Yes, sounds good. I will attempt to PR an update to |
Ah As to the other question: The Please check the open libm PR for any other possible errors if you have time: rust-lang/libm#222 |
Hm yes that's correct that we may not be providing a 100% standards-compliant implementation of |
I don't have any specific examples but error handling is the main difference between the LLVM intrinsics and libm functions. Would it be so bad to expect |
The expectation of symbols is basically what already happens today in the sense that you can't use Symbols like I think though that the difference between LLVM's |
Labelling this as blocked (rust-lang/libm#222) per #63455 (comment) |
☔ The latest upstream changes (presumably #63871) made this pull request unmergeable. Please resolve the merge conflicts. |
I'm going to close this as I think it is indeed blocked and until the underlying issues here are worked out there's not much point in keeping it open. I also feel like with regards to the platform testing, in theory that'll start getting answered soonish with the "Tiers" RFC currently open; I suspect that will hopefully help answer the level of support we should provide given inability to test. Regardless, though, at this time it sounds like there's not any way to make progress on this PR here -- the work needs to happen elsewhere first. |
Agreed. |
`spinoso-math` documents itself to be `no_std` and has a `std` feature, but the crate did not declare the `#![no_std]` pragma. Many `f64` math functions require `std` and are not available in `core`. Despite missing support in `core`, without the crate properly declaring itself as `no_std`, tests with `--no-default-features` incorrectly passed since `std` is still linked in. It does not seem likely that `f64` math will be enabled in `core` any time soon, so make `spinoso-math` require `std`. See rust-lang/rust#63455. This commit bumps the version of `spinoso-math` to 0.2.0 since removing a feature is a breaking change (and did break the build of `artichoke-backend`).
Per #50145 (comment) and #50145 (comment)
sqrt
method of thef32
andf64
types fromlibstd
tolibcore
.tests/
folder in the project root like a normal crate has. Someone please tell me.cc @varkor, cc @alexcrichton