-
Notifications
You must be signed in to change notification settings - Fork 100
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
Test more targets against a custom-built musl libm #300
Conversation
fc28dfb
to
9df91b3
Compare
5d19904
to
9dd3156
Compare
@Amanieu when you get the chance this should be ready for a look. The goal here is mostly to get some easier testing options off the ground, which can be followed up with less random inputs (can probably leverage periodicity/domain for better coverage) and more accurate output checks (checking ULP against MPFR). The PR is pretty heavy because it adds a lot of framework, to make things easier it is by-commit reviewable. |
11fb3f5
to
3a15d71
Compare
The rules macro was getting pretty cumbersome to work with so I wound up replacing it with a proc macro. |
7c9a327
to
e5ced7a
Compare
ae8a70c
to
23d4b39
Compare
crates/libm-test/src/special_case.rs
Outdated
return None; | ||
} | ||
|
||
// The musl implementations seem to set the top bit of the mantissa for any NaN on i686. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is actually caused by the 32-bit x86 "C"
calling convention using x87 registers to return values, causing format conversions (and therefore causing signalling NaNs to be quietened as compilers use the standard conversion instructions) on every f32
/f64
function return. See llvm/llvm-project#66803 and rust-lang/rust#115567. This will also be a problem for copysign
.
(As a side note, musl's fabs
implementation does use the x87 fabs
instruction via inline ASM, but that's just for efficiency since the result is going to be returned in an x87 register anyway: the problem remains that the loading/storing f32
/f64
to and from the x87 register doesn't preserve signalling NaNs when the compiler uses the standard conversion instructions.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the context, updated the comment
23d4b39
to
f6f5946
Compare
Other than that, LGTM 👍 |
15b2ad5
to
b50bf16
Compare
Thanks for the review! This has been through quite a few cycles, let's get it merged. |
This crate builds math symbols from a musl checkout and provides a Rust interface. The intent is that we will be able to compare our implementations against musl on more than just linux (which are the only currently the only targets we run `*-musl` targets against for comparison). Musl libc can't compile on anything other than Linux; however, the routines in `src/math` are cross platform enough to build on MacOS and windows-gnu with only minor adjustments. We take advantage of this and build only needed files using `cc`. The build script also performs remapping (via defines) so that e.g. `cos` gets defined as `musl_cos`. This gives us more certainty that we are actually testing against the intended symbol; without it, it is easy to unknowingly link to system libraries or even Rust's `libm` itself and wind up with an ineffective test. There is also a small procedure to verify remapping worked correctly by checking symbols in object files.
Introduce `libm_test::for_each_function`. which macro takes a callback macro and invokes it once per function signature. This provides an easier way of registering various tests and benchmarks without duplicating the function names and signatures each time.
Use a build script for `libm-test` to enumerate all symbols provided by `libm` and provide this list in a variable. This will allow us to make sure no functions are missed anytime they must be manually listed. Additionally, introduce some helper config options.
Create a new test that checks `for_each_fn` against `ALL_FUNCTIONS`, i.e. the manually entered function list against the automatically collected list. If any are missing (e.g. new symbol added), then this will produce an error.
These traits are simplified versions of what we have in `compiler_builtins` and will be used for tests.
These traits give us a more generic way to interface with tuples used for (1) test input, (2) function arguments, and (3) test input.
Add a type that caches values used to implement `GenerateInput` on a variety of signatures.
Create a test generator that creates a known number of random inputs and caches them, such that the same inputs are used for all functions.
Sometimes we want to be able to xfail specific inputs without changing the checked ULP for all cases or skipping the tests. There are also some cases where we need to perform extra checks for only specific functions. Add a trait that provides a hook for providing extra checks or skipping existing checks on a per-function or per-input basis.
Check our functions against `musl-math-sys`. This is similar to the existing musl tests that go through binary serialization, but works on more platforms.
These targets are tested in `compiler-builtins`, but not yet `libm`. Add dockerfiles to prepare for this.
This brings the targets tested here in line with those tested in `compiler-builtins`.
b50bf16
to
fb9cd47
Compare
Just to be foiled by a Docker 502... |
We don't currently test on any non-linux targets because results always require running against a
linux-musl
target. This PR does the following:musl-math-sys
which builds musl's math symbols withcc
for a better test basislibm
against the build musl versioncompiler-builtins
CI testing is still somewhat limited (MSVC and Wasm can't build musl sources) but these changes should be enough to make future improvements easier.