intrinsics: Add a fallback for non-const libm float functions#150946
intrinsics: Add a fallback for non-const libm float functions#150946tgross35 wants to merge 6 commits into
Conversation
| #[rustc_intrinsic_const_stable_indirect] | ||
| #[rustc_intrinsic] | ||
| #[rustc_nounwind] | ||
| pub const fn fmaf128(a: f128, b: f128, c: f128) -> f128; |
There was a problem hiding this comment.
Is there a way to provide a non-const fallback for const intrinsics? In cases where CTFE definitely has to hook it rather than using the fallback, like here.
Not the worst thing if not.
There was a problem hiding this comment.
I don't think there is -- please file an issue.
This comment has been minimized.
This comment has been minimized.
d533ef5 to
90b9d6a
Compare
This comment has been minimized.
This comment has been minimized.
Huh - so |
|
At a glance, your reasoning is completely backwards. The fallback body for |
|
It shouldn't be; the |
|
The changes LGTM. However I can't actually check whether what you say about what is available where is correct -- you would be the person I ask about things like that. ;) |
|
https://github.com/rust-lang/compiler-builtins/blob/65624df7f55db9b7b494fbe3aa9dcea0a743eea4/compiler-builtins/src/math/mod.rs is what controls what we sometimes/always provide, so the module root symbols and |
Yes, that's the problem. The body for the function is not available in the crate compiler-builtins when compiling compiler-builtins. Remember the the rule is to ban linkage against other crates and the point of these extern declarations is to use linkage. |
This comment has been minimized.
This comment has been minimized.
Forgot to follow up here. In this case it there isn't anything technically incorrect right, and instead it's a limitation of the knowledge the compiler has to emit that error? Because c-b itself provides the It probably goes without saying but libm isn't calling the |
|
Oh I see, thanks for clarifying. I think this is actually a limitation of the check logic itself. The problem is that you have an item defined in an upstream crate, which is not So the missing check is whether the |
|
I threw this together to convince myself that this can work, and it seems to work. diff --git a/compiler/rustc_codegen_ssa/src/base.rs b/compiler/rustc_codegen_ssa/src/base.rs
index c8aa7c04585..3fc0411d2be 100644
--- a/compiler/rustc_codegen_ssa/src/base.rs
+++ b/compiler/rustc_codegen_ssa/src/base.rs
@@ -867,6 +867,10 @@ pub fn codegen_crate<B: ExtraBackendMethods>(
/// unlinkable calls.
///
/// Note that calls to LLVM intrinsics are uniquely okay because they won't make it to the linker.
+/// Note also that calls to foreign items that are actually exported by the local crate are also
+/// okay. This situation arises because compiler-builtins calls functions in core that are #[inline]
+/// wrappers for extern "C" declarations in core, which resolve to a symbol exported by
+/// compiler-builtins.
pub fn is_call_from_compiler_builtins_to_upstream_monomorphization<'tcx>(
tcx: TyCtxt<'tcx>,
instance: Instance<'tcx>,
@@ -879,11 +883,19 @@ fn is_llvm_intrinsic(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
}
}
+ fn is_extern_call_to_local_crate<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) -> bool {
+ tcx.is_foreign_item(instance.def_id())
+ && tcx.exported_non_generic_symbols(LOCAL_CRATE).iter().any(|(sym, _info)| {
+ sym.symbol_name_for_local_instance(tcx) == tcx.symbol_name(instance)
+ })
+ }
+
let def_id = instance.def_id();
!def_id.is_local()
&& tcx.is_compiler_builtins(LOCAL_CRATE)
&& !is_llvm_intrinsic(tcx, def_id)
&& !tcx.should_codegen_locally(instance)
+ && !is_extern_call_to_local_crate(tcx, instance)
}
impl CrateInfo {The linear search of all exported non-generic symbols seems bad. It's only done a handful of times so it doesn't have a visible impact on compile time of compiler-builtins... yet. |
|
@rustbot author |
|
Reminder, once the PR becomes ready for a review, use |
90b9d6a to
176fd06
Compare
This comment has been minimized.
This comment has been minimized.
|
This pull request was unapproved. This PR was contained in a rollup (#158958), which was unapproved. |
This comment has been minimized.
This comment has been minimized.
intrinsics: Add a fallback for non-const libm float functions try-job: i686-msvc-1
|
I actually suspect this is an interaction with #158927 (part of that same rollup), so the bors job here will likely be fine. But apparently we should go via |
|
This PR was contained in a rollup (#158958), which was closed. |
| libm::likely_available::sinf(x) | ||
| cfg_select! { | ||
| target_env = "msvc" => sinf64(x as f64) as f32, | ||
| _ => libm::likely_available::sinf(x), |
There was a problem hiding this comment.
Looks like we should remove the sinf import on Windows as well to avoid accidentally calling it? (Same for the others)
There was a problem hiding this comment.
Well they are already marked as likely available, but I can just cfg them out on x86 msvc?
There was a problem hiding this comment.
Seems wrong to call them likely available if we know them to be unavailable. ;)
This comment has been minimized.
This comment has been minimized.
8759054 to
109180e
Compare
|
@bors try jobs=i686-msvc-1,x86_64-msvc-1,aarch64-msvc-1,x86_64-mingw-1 |
This comment has been minimized.
This comment has been minimized.
intrinsics: Add a fallback for non-const libm float functions try-job: i686-msvc-1 try-job: x86_64-msvc-1 try-job: aarch64-msvc-1 try-job: x86_64-mingw-1
This comment has been minimized.
This comment has been minimized.
the 32-bit symbols are not available on msvc
109180e to
58c2c07
Compare
This comment has been minimized.
This comment has been minimized.
|
@bors try jobs=i686-msvc-1,x86_64-msvc-1,aarch64-msvc-1,x86_64-mingw-1 |
This comment has been minimized.
This comment has been minimized.
intrinsics: Add a fallback for non-const libm float functions try-job: i686-msvc-1 try-job: x86_64-msvc-1 try-job: aarch64-msvc-1 try-job: x86_64-mingw-1
This comment has been minimized.
This comment has been minimized.
we know that the symbols are not available there
| cfg_select! { | ||
| all(target_env = "msvc", target_arch = "x86") => { | ||
| /* these symbols are not available on x86 msvc */ | ||
| } | ||
| _ => { | ||
| #[allow(dead_code)] |
There was a problem hiding this comment.
The cfg_select is to work around
tidy [pal (library)]: library/core/src/num/imp/libm.rs:82: platform-specific cfg: cfg(not(all(target_env = "msvc", target_arch = "x86")))
tidy [pal (library)]: FAIL
but it gives a good place for a comment so it's probably fine this way.
There was a problem hiding this comment.
Anyhow, there might be some nicer refactor that can be done, but this PR means we can drop one of the cranelift patch files, so I think we can defer that additional work.
|
r=RalfJung,saethlin when CI is happy. |
|
better safe than sorry etc @bors try jobs=i686-msvc-1,x86_64-msvc-1,aarch64-msvc-1,x86_64-mingw-1 |
|
⌛ Trying commit e732dd1 with merge 5d627ac… To cancel the try build, run the command Workflow: https://github.com/rust-lang/rust/actions/runs/29009736809 |
intrinsics: Add a fallback for non-const libm float functions try-job: i686-msvc-1 try-job: x86_64-msvc-1 try-job: aarch64-msvc-1 try-job: x86_64-mingw-1
View all comments
A number of float operations from libm have intrinsics for optimization, but it is also okay to just call the libm functions directly. Add a fallback for these cases, including converting to/from another float size where needed, so the backends don't need to override these.
r? @RalfJung