- codegen: an arm64 sincos pairing miscompile is fixed (piano_render/audio_mix match rustc again); `&mut` field loops promote to registers; the domain base and `thread_local!` key-table reads are inline loads, not host calls - rwbench times from the moment the JIT reports optimised code settled - check: delayed bugs are internal failures only when nothing else was reported; the ahead helper backs off instead of printing a panic; suite crash rows 58 -> 20 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
69 lines
2.2 KiB
Rust
69 lines
2.2 KiB
Rust
// A sin and a cos of the same value in one block: rustc's LLVM (Darwin) combines them into one
|
|
// call of libm's `__sincosf_stret` / `__sincos_stret`, whose results differ from separate
|
|
// `sinf` / `cosf` calls in the last bit for about 3% of the arguments. Relax pairs them the same
|
|
// way (opt::fuse_sincos), so the printed checksums match rustc on every target. A lone call stays a call.
|
|
use std::hint::black_box;
|
|
|
|
fn fold(h: u64, v: u64) -> u64 {
|
|
(h.rotate_left(5) ^ v).wrapping_mul(0x9E37_79B9_7F4A_7C15)
|
|
}
|
|
|
|
fn pair32(x: f32) -> (f32, f32) {
|
|
(x.cos(), x.sin())
|
|
}
|
|
|
|
fn pair64(x: f64) -> (f64, f64) {
|
|
(x.sin(), x.cos())
|
|
}
|
|
|
|
// a store with a bounds check between the two: the same block once the check is proven away
|
|
fn table(out: &mut [f32; 8], x: f32, i: usize) {
|
|
out[i & 7] = x.cos();
|
|
out[(i + 1) & 7] = x.sin();
|
|
}
|
|
|
|
#[cfg(all(target_vendor = "apple", target_arch = "aarch64"))]
|
|
mod native {
|
|
#[repr(C)]
|
|
pub struct Sc32 {
|
|
pub sin: f32,
|
|
pub cos: f32,
|
|
}
|
|
extern "C" {
|
|
pub fn __sincosf_stret(x: f32) -> Sc32;
|
|
}
|
|
}
|
|
|
|
fn run() {
|
|
let (mut a, mut b, mut c) = (0u64, 0u64, 0u64);
|
|
let mut t = [0.0f32; 8];
|
|
// enough calls for the pair to be compiled by the optimiser in every tier
|
|
for round in 0..3 {
|
|
for i in 0..4000 {
|
|
let x = black_box(i as f32 * 0.00123 - 2.0);
|
|
let (co, si) = pair32(x);
|
|
let (s64, c64) = pair64(x as f64 * 3.1);
|
|
table(&mut t, x, i);
|
|
if round == 2 {
|
|
a = fold(a, co.to_bits() as u64 ^ (si.to_bits() as u64) << 32);
|
|
b = fold(b, s64.to_bits() ^ c64.to_bits().rotate_left(7));
|
|
c = fold(c, t[i & 7].to_bits() as u64 ^ (t[(i + 1) & 7].to_bits() as u64) << 32);
|
|
#[cfg(all(target_vendor = "apple", target_arch = "aarch64"))]
|
|
{
|
|
let r = unsafe { native::__sincosf_stret(x) };
|
|
assert!(r.sin.to_bits() == si.to_bits() && r.cos.to_bits() == co.to_bits(), "pair at {} is not __sincosf_stret", x);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
println!("{a:016x} {b:016x} {c:016x}");
|
|
}
|
|
|
|
#[test]
|
|
fn sin_cos_pairs_are_combined_like_rustc() {
|
|
run();
|
|
}
|
|
|
|
fn main() {
|
|
run();
|
|
}
|