AK/Math: Generic rint, and better rounding inlining + fallout care - #26835
AK/Math: Generic rint, and better rounding inlining + fallout care#26835Hendiadyoin1 wants to merge 14 commits into
Conversation
2873014 to
a5a35ba
Compare
|
Do we have any test coverage for Could a similar impl work in LibC/math.cpp for {,l}lrint{f,,l}? If so, this would also help with #25934. |
bf02a77 to
6b71064
Compare
as for tests, I added a few crude ones for |
6b71064 to
558801a
Compare
558801a to
69584fc
Compare
|
Hello! One or more of the commit messages in this PR do not match the SerenityOS code submission policy, please check the |
69584fc to
dd59493
Compare
| { | ||
| CONSTEXPR_STATE(round, x); | ||
| #if ARCH(AARCH64) || ARCH(RISCV64) || defined(__SSE4_1__) | ||
| ELEMENTWISE_BUILTIN(round, x); |
There was a problem hiding this comment.
let me confirm my understanding here.
The way these get stamped out is something like this:
constexpr FP foo(FP x) {
if (is_constant_evaluated()) // if consteval? 🤔
{ some slow path or builtin that the compiler can use at compile time }
if (has_builtin(builtin_elementwise_foo) {
call builtin_elementwise_foo(); // guaranteed to not libcall?
}
#if arch(aarch64)
call assembly for foo (FP == float, double)
#elif arch(riscv64)
call assembly for foo (FP == float, double, long double?)
#elif ( SSE 4.1 ) // or w/e revision
call x86_64 assembly for foo (FP == float, double, long double)
#endif
return some slow path;
}
-
Is that what all of these are doing?
-
Is there a way to keep track of which methods are doing which steps here?
-
Is anyone doing it out of order that you've touched in this PR?
-
Should we have all this gunk in AK, or move it to LibC and just have AK consumers call libc methods? (personally, I would prefer AK::foo to be: constexpr version and/or call builtin, and let the compiler call a libcall into libc if it wants)
I don't think we need to answer all these questions right now, but at the very least, question 3 should be answered before we merge this.
| { | ||
| if constexpr (sizeof(I) <= sizeof(u32)) { | ||
| i32 res; | ||
| asm("fcvt.w.d %0, %1" |
There was a problem hiding this comment.
It'd be nice if we could do builtins instead of inline asm as much as possible. The inline asm is a barrier for at least clang's autovectorizers, and I locally have sped up a bunch of loops dramatically by replacing Math/Rounding.h inline asm with intrinsics and telling clang to vectorize a loop.
There was a problem hiding this comment.
Don't we currently forward most LibC functions to AK? I'm a bit worried that some of these builtins get compiled to LibC calls. (I did already have that problem with __builtin_ffs before on RISC-V)
But I agree that AK should ideally be completely constexpr. Making it constexpr-only should probably(?) also prevent this exact problem.
There was a problem hiding this comment.
I think we should strive to strip the inline asm from AK and move it all into LibC. Then reversing the call-into arrow from LibC -> AK to AK -> LibC would be manageable. It's kind of pointless to include a bunch of if constexpr speculation in the implementation of libcalls.
The only concern imo would be integer operations that the Kernel calls. But for floating point operations, the only thing the kernel knows (and needs to know) how to do is push/pop the FP register state.
dd59493 to
879e25f
Compare
|
So with the latest commit, I think I can answer Andrew's questions a bit and alleviate some of thakis' concerns: I have not really checked all other inline asm spaghetti caves, but I know that the Trig header has some unnecessary nesting I think I should squash that commit, but I am not sure what the best final commit order and composition would be |
65bda6a to
bb01b9f
Compare
| { | ||
| if constexpr (sizeof(I) <= sizeof(u32)) { | ||
| i32 res; | ||
| asm("fcvt.w.d %0, %1" |
There was a problem hiding this comment.
let's not add new inline asm impls
There was a problem hiding this comment.
Sure...
Should I also remove the other ones?
afaict compilers really dont like rint that much, only clang 20+ risc-v and x86 clang 21+ seems to concat the rint with the ltrunc
bb01b9f to
0af939f
Compare
|
OK, |
|
Ah seems like i forgot to remove one, will fix |
75f3077 to
87caaa5
Compare
| }; | ||
| static_assert(AssertSize<FloatExtractor<f80>, sizeof(f80)>()); | ||
| #else | ||
| // On some platforms (Arm Mac and Arm Windows) long double is a distinct version of f64 |
There was a problem hiding this comment.
I think Windows in general (at least x86 windows) uses double precision floats for long double.
9eb6951 to
65c6a3a
Compare
65c6a3a to
8124303
Compare
Otherwise we try to convert a Nan to u8, which is undefined
This is a) computationally smarter, and b) prevents a division by 0 when "mixing" with a 0 alpha color and full weight
Seems like we never did, not sure how it ever worked without
That test previously succeeded, as it by coincidence produced a negative NaNs, which is not the correct result none the less. Explcitely checking the value does not help, as EXPECT_APPROXIMATE does not handle NaNs, and enabling them has quite the fallout
While both versions are constexpr-able, directly relying on the compiler feels nicer
While slightly less efficient with current compilers, this allows more reasoning and optimizations by those compilers. There were also some copy-os in the aarch version of the old code, which now disappears together with the other inline asm implementations
This makes it pick up generic implementations in these cases
To allow compiler reasoning and vectorization we should try to use the builtins when possible, and avoid assembly in other cases This commit does a few things: * Exclude long double from some early `if consteval` paths As noted, we cant round-trip cast those in all cases * Add a table of tested inlining behavior * Always rely on inlining when guaranteed * Adjust floor/ceil/trunc to match each other and the compiler (gcc) internal expansion more closely * Reimplement the round fallback based on a trick borrowed from clang This now also has an alive2 proof :^)
We now have AK tests relying on this and the fallback paths go through here
8124303 to
010542b
Compare
|
This pull request has been automatically marked as stale because it has not had recent activity. It will be closed in 7 days if no further activity occurs. Thank you for your contributions! |
No description provided.