Skip to content

Conversation

@tgross35
Copy link
Contributor

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

@rustbot
Copy link
Collaborator

rustbot commented Jan 10, 2026

Some changes occurred to the intrinsics. Make sure the CTFE / Miri interpreter
gets adapted for the changes, if necessary.

cc @rust-lang/miri, @RalfJung, @oli-obk, @lcnr

@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-libs Relevant to the library team, which will review and decide on the PR/issue. labels Jan 10, 2026
Comment on lines 1410 to 1449
#[rustc_intrinsic_const_stable_indirect]
#[rustc_intrinsic]
#[rustc_nounwind]
pub const fn fmaf128(a: f128, b: f128, c: f128) -> f128;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think there is -- please file an issue.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Opened #150961

@rust-log-analyzer

This comment has been minimized.

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.
@tgross35 tgross35 force-pushed the float-intrinsic-fallback branch from d533ef5 to 90b9d6a Compare January 11, 2026 01:59
@rust-log-analyzer
Copy link
Collaborator

The job pr-check-2 failed! Check out the build log: (web) (plain enhanced) (plain)

Click to see the possible cause of the failure (guessed by this bot)
test library/std/src/collections/hash/map.rs - collections::hash::map::HashMap (line 72) ... ok
test library/std/src/collections/hash/map.rs - collections::hash::map::HashMap<K,V,RandomState>::new (line 264) ... ok
test library/std/src/collections/hash/map.rs - collections::hash::map::HashMap<K,V,RandomState>::with_capacity (line 283) ... ok
test library/std/src/collections/hash/map.rs - collections::hash::map::HashMap<K,V,RandomState>::from (line 1503) ... ok
test library/std/src/collections/hash/map.rs - collections::hash::map::HashMap<K,V,S,A>::capacity (line 445) ... ok
test library/std/src/collections/hash/map.rs - collections::hash::map::HashMap<K,V,S,A>::clear (line 819) ... ok
test library/std/src/collections/hash/map.rs - collections::hash::map::HashMap<K,V,S,A>::contains_key (line 1220) ... ok
test library/std/src/collections/hash/map.rs - collections::hash::map::HashMap<K,V,S,A>::drain (line 721) ... ok
test library/std/src/collections/hash/map.rs - collections::hash::map::HashMap<K,V,S,A>::entry (line 959) ... ok
test library/std/src/collections/hash/map.rs - collections::hash::map::HashMap<K,V,S,A>::get (line 987) ... ok
test library/std/src/collections/hash/map.rs - collections::hash::map::HashMap<K,V,S,A>::extract_if (line 761) ... ok
test library/std/src/collections/hash/map.rs - collections::hash::map::HashMap<K,V,S,A>::get_disjoint_mut (line 1077) ... ok
test library/std/src/collections/hash/map.rs - collections::hash::map::HashMap<K,V,S,A>::get_disjoint_mut (line 1119) ... ok
test library/std/src/collections/hash/map.rs - collections::hash::map::HashMap<K,V,S,A>::hasher (line 837) ... ok
test library/std/src/collections/hash/map.rs - collections::hash::map::HashMap<K,V,S,A>::get_key_value (line 1017) ... ok
test library/std/src/collections/hash/map.rs - collections::hash::map::HashMap<K,V,S,A>::get_disjoint_unchecked_mut (line 1162) ... ok
test library/std/src/collections/hash/map.rs - collections::hash::map::HashMap<K,V,S,A>::get_mut (line 1247) ... ok
test library/std/src/collections/hash/map.rs - collections::hash::map::HashMap<K,V,S,A>::insert (line 1280) ... ok
test library/std/src/collections/hash/map.rs - collections::hash::map::HashMap<K,V,S,A>::into_iter (line 2052) ... ok
test library/std/src/collections/hash/map.rs - collections::hash::map::HashMap<K,V,S,A>::into_keys (line 491) ... ok
test library/std/src/collections/hash/map.rs - collections::hash::map::HashMap<K,V,S,A>::into_values (line 586) ... ok
test library/std/src/collections/hash/map.rs - collections::hash::map::HashMap<K,V,S,A>::is_empty (line 698) ... ok
test library/std/src/collections/hash/map.rs - collections::hash::map::HashMap<K,V,S,A>::iter (line 618) ... ok
test library/std/src/collections/hash/map.rs - collections::hash::map::HashMap<K,V,S,A>::iter_mut (line 648) ... ok
test library/std/src/collections/hash/map.rs - collections::hash::map::HashMap<K,V,S,A>::keys (line 461) ... ok
test library/std/src/collections/hash/map.rs - collections::hash::map::HashMap<K,V,S,A>::len (line 681) ... ok
test library/std/src/collections/hash/map.rs - collections::hash::map::HashMap<K,V,S,A>::remove (line 1339) ... ok
test library/std/src/collections/hash/map.rs - collections::hash::map::HashMap<K,V,S,A>::reserve (line 870) ... ok
test library/std/src/collections/hash/map.rs - collections::hash::map::HashMap<K,V,S,A>::remove_entry (line 1367) ... ok
test library/std/src/collections/hash/map.rs - collections::hash::map::HashMap<K,V,S,A>::retain (line 792) ... ok
test library/std/src/collections/hash/map.rs - collections::hash::map::HashMap<K,V,S,A>::shrink_to (line 937) ... ok
test library/std/src/collections/hash/map.rs - collections::hash::map::HashMap<K,V,S,A>::shrink_to_fit (line 913) ... ok
test library/std/src/collections/hash/map.rs - collections::hash::map::HashMap<K,V,S,A>::try_insert (line 1309) ... ok
test library/std/src/collections/hash/map.rs - collections::hash::map::HashMap<K,V,S,A>::try_reserve (line 895) ... ok
test library/std/src/collections/hash/map.rs - collections::hash::map::HashMap<K,V,S,A>::values (line 523) ... ok
test library/std/src/collections/hash/map.rs - collections::hash::map::HashMap<K,V,S>::with_hasher (line 351) ... ok
test library/std/src/collections/hash/map.rs - collections::hash::map::HashMap<K,V,S>::with_capacity_and_hasher (line 383) ... ok
test library/std/src/collections/hash/map.rs - collections::hash::map::HashMap<K,V,S,A>::values_mut (line 552) ... ok
test library/std/src/collections/hash/map.rs - collections::hash::map::IntoIter (line 1610) ... ok
test library/std/src/collections/hash/map.rs - collections::hash::map::IntoKeys (line 1842) ... ok
---
test library/std/src/collections/hash/set.rs - collections::hash::set::HashSet<T,RandomState>::new (line 142) ... ok
test library/std/src/collections/hash/set.rs - collections::hash::set::HashSet<T,RandomState>::with_capacity (line 161) ... ok
test library/std/src/collections/hash/set.rs - collections::hash::set::HashSet<T,S,A>::capacity (line 313) ... ok
test library/std/src/collections/hash/set.rs - collections::hash::set::HashSet<T,RandomState>::from (line 1180) ... ok
test library/std/src/collections/hash/set.rs - collections::hash::set::HashSet<T,S,A>::clear (line 490) ... ok
test library/std/src/collections/hash/set.rs - collections::hash::set::HashSet<T,S,A>::contains (line 758) ... ok
test library/std/src/collections/hash/set.rs - collections::hash::set::HashSet<T,S,A>::drain (line 398) ... ok
test library/std/src/collections/hash/set.rs - collections::hash::set::HashSet<T,S,A>::difference (line 630) ... ok
test library/std/src/collections/hash/set.rs - collections::hash::set::HashSet<T,S,A>::entry (line 861) ... ok
test library/std/src/collections/hash/set.rs - collections::hash::set::HashSet<T,S,A>::get (line 783) ... ok
test library/std/src/collections/hash/set.rs - collections::hash::set::HashSet<T,S,A>::extract_if (line 434) ... ok
test library/std/src/collections/hash/set.rs - collections::hash::set::HashSet<T,S,A>::get_or_insert (line 805) ... ok
test library/std/src/collections/hash/set.rs - collections::hash::set::HashSet<T,S,A>::get_or_insert_with (line 829) ... ok
test library/std/src/collections/hash/set.rs - collections::hash::set::HashSet<T,S,A>::hasher (line 508) ... ok
test library/std/src/collections/hash/set.rs - collections::hash::set::HashSet<T,S,A>::insert (line 983) ... ok
test library/std/src/collections/hash/set.rs - collections::hash::set::HashSet<T,S,A>::into_iter (line 1642) ... ok
test library/std/src/collections/hash/set.rs - collections::hash::set::HashSet<T,S,A>::intersection (line 697) ... ok
test library/std/src/collections/hash/set.rs - collections::hash::set::HashSet<T,S,A>::is_disjoint (line 903) ... ok
test library/std/src/collections/hash/set.rs - collections::hash::set::HashSet<T,S,A>::is_empty (line 375) ... ok
test library/std/src/collections/hash/set.rs - collections::hash::set::HashSet<T,S,A>::is_subset (line 929) ... ok
test library/std/src/collections/hash/set.rs - collections::hash::set::HashSet<T,S,A>::iter (line 329) ... ok
test library/std/src/collections/hash/set.rs - collections::hash::set::HashSet<T,S,A>::is_superset (line 951) ... ok
test library/std/src/collections/hash/set.rs - collections::hash::set::HashSet<T,S,A>::len (line 357) ... ok
test library/std/src/collections/hash/set.rs - collections::hash::set::HashSet<T,S,A>::remove (line 1030) ... ok
test library/std/src/collections/hash/set.rs - collections::hash::set::HashSet<T,S,A>::reserve (line 541) ... ok
test library/std/src/collections/hash/set.rs - collections::hash::set::HashSet<T,S,A>::replace (line 1004) ... ok
test library/std/src/collections/hash/set.rs - collections::hash::set::HashSet<T,S,A>::retain (line 465) ... ok
test library/std/src/collections/hash/set.rs - collections::hash::set::HashSet<T,S,A>::shrink_to (line 607) ... ok
test library/std/src/collections/hash/set.rs - collections::hash::set::HashSet<T,S,A>::shrink_to_fit (line 584) ... ok
test library/std/src/collections/hash/set.rs - collections::hash::set::HashSet<T,S,A>::symmetric_difference (line 660) ... ok
test library/std/src/collections/hash/set.rs - collections::hash::set::HashSet<T,S,A>::take (line 1058) ... ok
test library/std/src/collections/hash/set.rs - collections::hash::set::HashSet<T,S,A>::try_reserve (line 567) ... ok
test library/std/src/collections/hash/set.rs - collections::hash::set::HashSet<T,S,A>::union (line 726) ... ok
test library/std/src/collections/hash/set.rs - collections::hash::set::HashSet<T,S>::with_capacity_and_hasher (line 255) ... ok
test library/std/src/collections/hash/set.rs - collections::hash::set::HashSet<T,S>::with_hasher (line 223) ... ok
test library/std/src/collections/hash/set.rs - collections::hash::set::Intersection (line 1506) ... ok
test library/std/src/collections/hash/set.rs - collections::hash::set::IntoIter (line 1421) ... ok
test library/std/src/collections/hash/set.rs - collections::hash::set::Iter (line 1391) ... ok
---
[RUSTC-TIMING] libc test:false 0.391
   Compiling unwind v0.0.0 (/checkout/library/unwind)
[RUSTC-TIMING] unwind test:false 0.072
   Compiling memchr v2.7.6
error: `compiler_builtins` cannot call functions through upstream monomorphizations; encountered invalid call from `core::intrinsics::sqrtf64` to `core::num::libm::sqrt`
    --> library/core/src/intrinsics/mod.rs:1047:1
     |
1047 | pub fn sqrtf64(x: f64) -> f64 {
     | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

@tgross35
Copy link
Contributor Author

error: `compiler_builtins` cannot call functions through upstream monomorphizations; encountered invalid call from `core::intrinsics::sqrtf64` to `core::num::libm::sqrt`
    --> library/core/src/intrinsics/mod.rs:1047:1
     |
1047 | pub fn sqrtf64(x: f64) -> f64 {
     | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Huh - so #[inline] doesn't make a difference here. The body itself shouldn't be a problem since it's calling an extern function. @saethlin any idea what is going on here?

@saethlin
Copy link
Member

At a glance, your reasoning is completely backwards. The fallback body for sqrtf64 is being monomorphized, which is disallowed because it calls a libm function that is upstream.

@tgross35
Copy link
Contributor Author

It shouldn't be; the libm module in core is only bindings to libm, the function call is just an extern.

@RalfJung
Copy link
Member

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. ;)
Is there anyone else who knows those details of libm and our compiler-builtins? If not, I'm also fine with approving this based on your judgment.

@tgross35
Copy link
Contributor Author

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 likely_available match that. Then the remaining maybe_available symbols are part of glibc (e.g. https://github.com/bminor/glibc/blob/e539a269990dac3ff4d2432c0eb6966a5ee4f274/sysdeps/unix/sysv/linux/i386/libm.abilist#L590), but not too much else.

@saethlin
Copy link
Member

saethlin commented Jan 11, 2026

It shouldn't be; the libm module in core is only bindings to libm, the function call is just an extern.

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-libs Relevant to the library team, which will review and decide on the PR/issue.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants