Skip to content

Merge fabsf16/32/64/128 into fabs::<F>#153834

Open
N1ark wants to merge 2 commits intorust-lang:mainfrom
N1ark:generic-float-intrinsics
Open

Merge fabsf16/32/64/128 into fabs::<F>#153834
N1ark wants to merge 2 commits intorust-lang:mainfrom
N1ark:generic-float-intrinsics

Conversation

@N1ark
Copy link
Contributor

@N1ark N1ark commented Mar 13, 2026

View all comments

Following a small conversation on Zulip (and because I'd be interested in starting to contribute on Rust), I thought I'd give a try at merging the float intrinsics :)

This PR just merges fabsf16, fabsf32, fabsf64, fabsf128, as it felt like an easy first target.

Notes:

  • I'm opening the PR for one intrinsic as it's probably easier if the shift is done one intrinsic at a time, but let me know if you'd rather I do several at a time to reduce the number of PRs.
  • Currently this PR increases LOCs, despite being an attempt at simplifying the intrinsics/compilers. I believe this increase is a one time thing as I had to define new functions and move some things around, and hopefully future PRs/commits will reduce overall LoCs
  • fabsf32 and fabsf64 are #[rustc_intrinsic_const_stable_indirect], while fabsf16 and fabsf128 aren't; because f32/f64 expect the function to be const, the generic version must be made indirectly stable too. We'd need to check with T-lang this change is ok; the only other intrinsics where there is such a mismatch is minnum, maxnum and copysign.
  • I haven't touched libm because I'm not familiar with how it works; any guidance would be welcome!

@rustbot
Copy link
Collaborator

rustbot commented Mar 13, 2026

Some changes occurred to the CTFE machinery

cc @RalfJung, @oli-obk, @lcnr

Some changes occurred to the CTFE / Miri interpreter

cc @rust-lang/miri

Some changes occurred in compiler/rustc_codegen_gcc

cc @antoyo, @GuillaumeGomez

Some changes occurred in compiler/rustc_codegen_cranelift

cc @bjorn3

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 A-LLVM Area: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues. S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels Mar 13, 2026
@rustbot rustbot added the T-libs Relevant to the library team, which will review and decide on the PR/issue. label Mar 13, 2026
@rustbot
Copy link
Collaborator

rustbot commented Mar 13, 2026

r? @TaKO8Ki

rustbot has assigned @TaKO8Ki.
They will have a look at your PR within the next two weeks and either review your PR or reassign to another reviewer.

Use r? to explicitly pick a reviewer

Why was this reviewer chosen?

The reviewer was selected based on:

  • Owners of files modified in this PR: compiler
  • compiler expanded to 69 candidates
  • Random selection from 15 candidates

@N1ark N1ark changed the title Merge fabsfN into fabs::<F> Merge fabsf16/32/64/128 into fabs::<F> Mar 13, 2026
@tgross35
Copy link
Contributor

r? tgross35

@rustbot rustbot assigned tgross35 and unassigned TaKO8Ki Mar 13, 2026
@rust-log-analyzer

This comment has been minimized.

@N1ark
Copy link
Contributor Author

N1ark commented Mar 13, 2026

ah oops i was wondering why gcc wasn't working locally, guess it never installed :') ill fix this soon

#[rustc_nounwind]
#[rustc_intrinsic]
pub const fn fabsf128(x: f128) -> f128;
pub const fn fabs<T: Copy>(x: T) -> T;
Copy link
Member

Choose a reason for hiding this comment

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

suggestion: like there's

/// Types with a built-in dereference operator in runtime MIR,
/// aka references and raw pointers.
///
/// # Safety
/// Must actually *be* such a type.
pub unsafe trait BuiltinDeref: Sized {
type Pointee: PointeeSized;
}
unsafe impl<T: PointeeSized> BuiltinDeref for &mut T {
type Pointee = T;
}
unsafe impl<T: PointeeSized> BuiltinDeref for &T {
type Pointee = T;
}
unsafe impl<T: PointeeSized> BuiltinDeref for *mut T {
type Pointee = T;
}
unsafe impl<T: PointeeSized> BuiltinDeref for *const T {
type Pointee = T;
}
, consider adding a trait there just to help emphasize that this is for floats only, so this could be

Suggested change
pub const fn fabs<T: Copy>(x: T) -> T;
pub const fn fabs<T: bounds::FloatPrimitive>(x: T) -> T;

or similar.

Copy link
Contributor Author

@N1ark N1ark Mar 14, 2026

Choose a reason for hiding this comment

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

Fixed in 74114c9; also added it to the other generic float intrinsics

Copy link
Contributor Author

Choose a reason for hiding this comment

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

note this changes the diagnostic when these intrinsics are misused: it now gives a type error (see 043f9ad) rather than a monomorphization error; i think this is a good thing :)

ty::Float(FloatTy::F32) | ty::Float(FloatTy::F64) => fx.bcx.ins().fabs(x),
// FIXME(bytecodealliance/wasmtime#8312): Use `fabsf16` once Cranelift
// backend lowerings are implemented.
ty::Float(FloatTy::F16) => codegen_f16_f128::abs_f16(fx, x),
Copy link
Member

Choose a reason for hiding this comment

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

pondering: these make me wonder if it'd be worth just having fallback mir for this?

See how there's

pub const unsafe fn disjoint_bitor<T: [const] fallback::DisjointBitOr>(a: T, b: T) -> T {

for example to give that one a fallback; might be reasonable to do the same for fabs (since it's easy to implement) and backends can just fallback to that if they haven't implemented it natively for f16/f128 yet.

Copy link
Member

Choose a reason for hiding this comment

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

(That said, it's a copysign+fabs thing only, really, since fallback MIR for most float ops is probably not a good idea. fpow is hard.)

Copy link
Contributor

Choose a reason for hiding this comment

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

I'd like to have fallbacks for all of these via libcalls; have some of that in progress at #150946.

abs and copysign probably shouldn't use the libcalls though, they can copy the implementation from https://github.com/rust-lang/compiler-builtins/blob/85db9f1923007c287b894d392b880545ec70d05e/libm/src/math/generic/fabs.rs and https://github.com/rust-lang/compiler-builtins/blob/85db9f1923007c287b894d392b880545ec70d05e/libm/src/math/generic/copysign.rs.

@rust-log-analyzer

This comment has been minimized.

@N1ark
Copy link
Contributor Author

N1ark commented Mar 14, 2026

btw; I saw in rustc_codegen_ssa there's two different errors relating to expecting float types; I picked BasicFloatType because in the same function BasicIntegerType is raised, but I'm curious if there's any reason to have both of these rather than merging them :) (FloatingPointType is only used in a couple places relating to SIMD intrinsics)

#[diag("invalid monomorphization of `{$name}` intrinsic: expected basic float type, found `{$ty}`", code = E0511)]
BasicFloatType {
#[primary_span]
span: Span,
name: Symbol,
ty: Ty<'tcx>,
},

#[diag("invalid monomorphization of `{$name}` intrinsic: `{$in_ty}` is not a floating-point type", code = E0511)]
FloatingPointType {
#[primary_span]
span: Span,
name: Symbol,
in_ty: Ty<'tcx>,
},

@RalfJung
Copy link
Member

The diagnostic error types are quite the mess there, feel free to adjust or replace them by string-based errors if that simplifies the code.

@rust-log-analyzer

This comment has been minimized.

@N1ark N1ark force-pushed the generic-float-intrinsics branch from 69be112 to 9210d78 Compare March 14, 2026 12:50
@N1ark
Copy link
Contributor Author

N1ark commented Mar 14, 2026

The diagnostic error types are quite the mess there, feel free to adjust or replace them by string-based errors if that simplifies the code.

fair enough :) removed the duplicate in ebb6dfb

@rust-log-analyzer

This comment has been minimized.

@rust-log-analyzer

This comment has been minimized.

@scottmcm
Copy link
Member

I saw in rustc_codegen_ssa there's two different errors relating to expecting float types

Misuse of intrinsics falls under rust-lang/compiler-team#620 -- you can feel free to rip out any inconvenient errors entirely and just have them ICE.

#[rustc_nounwind]
#[rustc_intrinsic]
pub const fn fabsf128(x: f128) -> f128;
pub const fn fabs<T: bounds::FloatPrimitive>(x: T) -> T;
Copy link
Member

@RalfJung RalfJung Mar 15, 2026

Choose a reason for hiding this comment

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

@rust-lang/lang this would mark fabs as indirectly const stable for all float types, not just f32 and f64. The const implementation is uniform across all types so I have no concerns about this -- the f16 and f128 implementation is and has been ready for stable for a while, it's the non-const implementation of f16 and f128 that's not ready. ;)

Nevertheless, new intrinsics being available to stable const code requires lang approval. Not sure if you think a full FCP is required for a trivial case like this.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

btw if a FCP is required, we should throw in copysign in there, which is in the same situation: const stable for f32/f64 but not for f16/f128, and it's also a binary operation

Copy link
Member

Choose a reason for hiding this comment

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

We should probably throw in all the intrinsics you intend to generalize that are easily implemented with apfloat. Do you have a list of them?

Copy link
Member

Choose a reason for hiding this comment

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

Oh, I didn't realize all the f16/f128 rounding methods have already been allowed in const-stable since #143604. That may have been an accident, but it's also not really a problem.

Copy link
Contributor Author

@N1ark N1ark Mar 15, 2026

Choose a reason for hiding this comment

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

yep, it's fabs, copysign, minnum and maxnum; all other float intrinsics are all const stable across all float types or not const stable for any

Copy link
Member

Choose a reason for hiding this comment

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

Personally (with my lang hat on but not speaking as team consensus) I would be fine treating this as "the previous FCP was saying that floating-point abs is allowed to be const-stable -- because it's easy to do reliably in const, being that it's only bitwise (without even NAN nondet, IIRC?) -- and how exactly that translates to specific intrinsics is a compiler/ctfe question without needing addtional lang FCPs".

But we'll see what the meeting says on Wed.

Copy link
Member

Choose a reason for hiding this comment

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

without even NAN nondet, IIRC?

Correct, fabs just mutates the sign bit and nothing else.

@RalfJung RalfJung added the I-lang-nominated Nominated for discussion during a lang team meeting. label Mar 15, 2026
@N1ark
Copy link
Contributor Author

N1ark commented Mar 15, 2026

the GCC issue here was because without type information get_simple_function_f128 would always match on fabs even if it wasn't a f128; to fix it I moved both get_simple_function_f128 and the _2args version inside the pattern match, fixing the TODO; that will conflict a bit with rust-lang/rustc_codegen_gcc#863, I hope that's ok ^^' cc @antoyo

overall the gcc handling of float intrinsics is.. not ideal right now, my goal is that as i genericize the rest of the intrinsics i can clean it up and make it simpler :) rn it's just in an in-between phase which is not super pretty

@rust-log-analyzer

This comment has been minimized.

@N1ark N1ark force-pushed the generic-float-intrinsics branch from b3e650e to 4affb1c Compare March 15, 2026 12:00
@rust-bors

This comment has been minimized.

@N1ark N1ark force-pushed the generic-float-intrinsics branch from 4affb1c to 48cec8c Compare March 15, 2026 18:08
@rust-log-analyzer

This comment has been minimized.

@N1ark N1ark force-pushed the generic-float-intrinsics branch from 48cec8c to 88a9639 Compare March 15, 2026 22:48
@rustbot

This comment has been minimized.

@rust-bors

This comment has been minimized.

@N1ark N1ark force-pushed the generic-float-intrinsics branch from 88a9639 to e21ccc5 Compare March 16, 2026 00:38
@rustbot
Copy link
Collaborator

rustbot commented Mar 16, 2026

This PR was rebased onto a different main commit. Here's a range-diff highlighting what actually changed.

Rebasing is a normal part of keeping PRs up to date, so no action is needed—this note is just to help reviewers.

@N1ark N1ark force-pushed the generic-float-intrinsics branch from e21ccc5 to 42c0625 Compare March 16, 2026 20:50
Copy link
Contributor

Choose a reason for hiding this comment

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

Cc @bjorn3 if you want to look at clif changes but this generally LGTM

@N1ark N1ark force-pushed the generic-float-intrinsics branch from 42c0625 to 2fdefdf Compare March 16, 2026 21:12
Copy link
Contributor

@tgross35 tgross35 left a comment

Choose a reason for hiding this comment

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

This needs the trivial lang approval for the intrinsics, and one more nit above. But aside from that, the changes here LGTM unless @RalfJung has anything else.

View changes since this review

N1ark added 2 commits March 16, 2026 21:49
Add `bounds::FloatPrimitive`

Exhaustive float pattern match

Fix GCC

use span bugs
@N1ark N1ark force-pushed the generic-float-intrinsics branch from 2fdefdf to 11c673b Compare March 16, 2026 21:49
@RalfJung
Copy link
Member

The const-eval parts LGTM.

@traviscross traviscross added the T-lang Relevant to the language team label Mar 17, 2026
@traviscross
Copy link
Contributor

Makes sense and sounds good to me. Thanks @N1ark.

@rfcbot fcp merge lang

@rust-rfcbot
Copy link
Collaborator

rust-rfcbot commented Mar 17, 2026

Team member @traviscross has proposed to merge this. The next step is review by the rest of the tagged team members:

No concerns currently listed.

Once a majority of reviewers approve (and at most 2 approvals are outstanding), this will enter its final comment period. If you spot a major issue that hasn't been raised at any point in this process, please speak up!

cc @rust-lang/lang-advisors: FCP proposed for lang, please feel free to register concerns.
See this document for info about what commands tagged team members can give me.

@rust-rfcbot rust-rfcbot added proposed-final-comment-period Proposed to merge/close by relevant subteam, see T-<team> label. Will enter FCP once signed off. disposition-merge This issue / PR is in PFCP or FCP with a disposition to merge it. labels Mar 17, 2026
@RalfJung
Copy link
Member

To be clear, the FCP covers doing this for fabs, copysign, minnum and maxnum. This PR only does the first step as that's easier for reviewing. (No other intrinsic has mixed const-stability across float types.)

That said, @scottmcm suggested we could consider this covered by the previous FCP for fabs on f32 and f64. We'll see what the meeting on Wed brings.

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

Labels

A-LLVM Area: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues. disposition-merge This issue / PR is in PFCP or FCP with a disposition to merge it. I-lang-easy-decision Issue: The decision needed by the team is conjectured to be easy; this does not imply nomination I-lang-nominated Nominated for discussion during a lang team meeting. proposed-final-comment-period Proposed to merge/close by relevant subteam, see T-<team> label. Will enter FCP once signed off. S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. T-lang Relevant to the language team 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.

9 participants