makepad/libs/relax/compiler/tests/value_ranges.rs
Admin b22a714840 makepad run: the Rust JIT (libs/relax) and makepad-remote
The JIT that runs makepad apps from source: lexer, front end, type checker,
lazy borrow checker (Gandalf; `--check-first` opts in), codegen, session and
warm/cold caches keyed by compiler stamp, provided crates bound late,
startup images, live patching. User-facing name is `makepad run` (binary
`makepad`, MAKEPAD_RUN_* env, ~/.makepad-run); libs/relax stays the internal
library name. `makepad check` reports rustc-style diagnostics with rustc
error codes and checks a whole workspace (`--workspace`). Runs on macOS,
Linux, Windows and Android. makepad-remote: one tool schema for apps and the
WM (app/1): grabs, captures, traces, frame profiles and tweaks.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-13 12:26:21 +02:00

123 lines
4 KiB
Rust

// Compares that value ranges decide (codegen ranges.rs, O3) and wide loads built from mixed
// narrow ones (opt.rs combine_loads): masked indices into fixed arrays, an index bounded by a
// dominating branch through `x - 1`, `(x + 8) - x`, a u64 made of a u16 and six bytes -- and the
// cases that must keep their checks: a mask wider than the array (must panic), u8 sums that wrap,
// negative signed values, a loop variable at its header. Called often enough for O3;
// output = rustc --test.
const N: usize = 0x8102;
const MAX_LEN: usize = 258;
struct Dict {
b: [u8; N],
next: [u16; 0x8000],
}
#[inline(always)]
fn read_u16_le(s: &[u8; N], pos: usize) -> u16 {
s[pos] as u16 | ((s[pos + 1] as u16) << 8)
}
#[inline(always)]
fn read_u64_le(s: &[u8; N], pos: usize) -> u64 {
let lo = read_u16_le(s, pos) as u64;
lo | (s[pos + 2] as u64) << 16 | (s[pos + 3] as u64) << 24 | (s[pos + 4] as u64) << 32 | (s[pos + 5] as u64) << 40 | (s[pos + 6] as u64) << 48 | (s[pos + 7] as u64) << 56
}
#[inline(never)]
fn probe(d: &Dict, start: usize, match_len: u32, c01: u16) -> (u32, usize) {
let mut probe_pos = start & 0x7fff;
let mut hits = 0u32;
for _ in 0..3 {
let next = d.next[probe_pos] as usize;
if next == 0 || match_len as usize - 1 >= MAX_LEN {
return (hits, probe_pos);
}
probe_pos = next & 0x7fff;
if read_u16_le(&d.b, probe_pos + match_len as usize - 1) == c01 {
hits += 1;
}
}
(hits, probe_pos)
}
#[inline(never)]
fn words(d: &Dict, p: usize, q: usize) -> u64 {
let a = p & 0x7fff;
let b = q & 0x7fff;
let x = u64::from_le_bytes(d.b[a..a + 8].try_into().unwrap());
let y = read_u64_le(&d.b, b);
x ^ y.rotate_left(7)
}
// a mask wider than the array: the check stays and fires for big x
#[inline(never)]
fn wide_mask(d: &Dict, x: usize) -> u8 {
d.b[x & 0xffff]
}
// u8 arithmetic wraps: (a + b) < 200 is not decided by the operands being small
#[inline(never)]
fn wrap8(a: u8, b: u8) -> u32 {
let s = a.wrapping_add(b);
if s < 200 { 1 } else { 2 }
}
// signed: x - 1 may be negative, x < 3 may hold for negative x
#[inline(never)]
fn signed_cmp(x: i32) -> i32 {
let y = x - 1;
if y < 3 { y * 2 } else { y + 100 }
}
// a loop variable: its bound at the header comes from the loop, not the entry
#[inline(never)]
fn loop_var(n: usize, d: &Dict) -> u64 {
let mut i = 0usize;
let mut s = 0u64;
while i < n {
s += d.b[i % N] as u64;
i += 3;
}
s + i as u64
}
// signed division / remainder by powers of two (shift sequences, not idiv): negative values
#[inline(never)]
fn sdiv(x: i32, y: i64) -> i64 {
(x / 8) as i64 + (x % 1024) as i64 + y / 16 + y % 4096 + (x as i8 % 4) as i64
}
#[test]
fn value_ranges() {
let mut d = Box::new(Dict { b: [0; N], next: [0; 0x8000] });
for i in 0..N {
d.b[i] = (i * 131 + 7) as u8;
}
for i in 0..0x8000 {
d.next[i] = ((i * 7919 + 1) % 0x10000) as u16;
}
let mut h = 0u64;
let mut panics = 0u32;
let prev = std::panic::take_hook();
std::panic::set_hook(Box::new(|_| {}));
for rep in 0..60000usize {
let (hits, pos) = probe(&d, rep * 31, (rep % 300) as u32 + 1, (rep as u16).wrapping_mul(97));
h = h.rotate_left(5) ^ hits as u64 ^ pos as u64;
h = h.wrapping_add(words(&d, rep * 13, rep * 17 + 3));
if rep % 1000 == 0 {
let x = rep * 7;
match std::panic::catch_unwind(|| wide_mask(&d, x)) {
Ok(v) => h ^= v as u64,
Err(_) => panics += 1,
}
}
h = h.wrapping_add(wrap8(rep as u8, (rep >> 3) as u8) as u64);
h = h.wrapping_add(signed_cmp((rep as i32 % 9) - 4) as u64);
h = h.rotate_left(3) ^ sdiv(rep as i32 * 37 - 1_000_000, (rep as i64 - 30000) * 1_000_003) as u64;
if rep % 100 == 0 {
h ^= loop_var(rep % 97, &d);
}
}
std::panic::set_hook(prev);
println!("| {:016x} {}", h, panics);
}