mirror of
https://github.com/Nexoniarz/Finch.git
synced 2026-11-03 00:44:27 +00:00
Vectors for kernels: masks and select, shuffles and byte lookup, dot_add, @cpu and cpu_has; --cpu native on Nix
- comparisons of vectors give masks (boolxN): select(m, a, b), m.any/all/count, & | ^ !;
f32x8(list, i, fill) and v.store_part(list, i) for the end of a list (masked load/store)
- v.shuffle(constant lanes), v.lo(), v.hi(), concat(a, b), table.lookup(indices):
pshufb / vpshufb on x86 (SSSE3 and up), tbl on ARM64 (checked in the assembly, LLVM 18 and 21)
- acc.dot_add(a, b): i32 lanes gain 4 byte products each, exactly; vpdpbusd with AVX-VNNI or AVX-512 VNNI,
usdot/sdot/udot on ARM64, the sum written out elsewhere (pmaddwd); run here with all three paths agreeing
- @cpu("avx2,fma") fn: LLVM target-features for one function (+evex512 for AVX-512, which LLVM 18+ needs);
cpu_has("avx2"): CPUID + XGETBV on x86, hwcaps on Linux ARM64, sysctl on macOS; a wide vector can't be passed
between functions with different @cpu (its registers differ), and the compiler says so
- the compiler asks clang which features --cpu means (its predefined macros, cached), so dot_add picks the instruction
- Nix's clang wrapper dropped -march=native in nix-shell (reproduced): finch tells it NIX_ENFORCE_NO_NATIVE=0, shell.nix too,
and warns if --cpu native still made no difference
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Psc42moPLwP43Cmb9oZqSR
This commit is contained in:
parent
0ceaaa27c4
commit
04f1f94a21
23 changed files with 964 additions and 45 deletions
7
tests/fail/cpu_attr_name.fch
Normal file
7
tests/fail/cpu_attr_name.fch
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
// expect: @cpu: 'avx3' isn't a feature Finch knows
|
||||
@cpu("avx2,avx3")
|
||||
fn f() {
|
||||
}
|
||||
fn main() {
|
||||
f()
|
||||
}
|
||||
4
tests/fail/cpu_has_name.fch
Normal file
4
tests/fail/cpu_has_name.fch
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
// expect: cpu_has: 'avx-512' isn't a feature Finch knows
|
||||
fn main() {
|
||||
print(cpu_has("avx-512"))
|
||||
}
|
||||
8
tests/fail/cpu_wide_vector.fch
Normal file
8
tests/fail/cpu_wide_vector.fch
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
// expect: can't be passed between them (its registers differ)
|
||||
@cpu("avx2")
|
||||
fn double(f32x8 v) -> f32x8 {
|
||||
return v * 2.0
|
||||
}
|
||||
fn main() {
|
||||
print(double(f32x8(1.0)))
|
||||
}
|
||||
|
|
@ -1,5 +1,7 @@
|
|||
// expect: use min(v, w), max(v, w), or compare lanes: v[i] < w[i]
|
||||
// expect: use .all() or .any()
|
||||
fn main() {
|
||||
a := f32x4(1.0)
|
||||
print(a < a)
|
||||
if a < a {
|
||||
print("no")
|
||||
}
|
||||
}
|
||||
|
|
|
|||
5
tests/fail/vec_shuffle_range.fch
Normal file
5
tests/fail/vec_shuffle_range.fch
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
// expect: lane 4 isn't in a f32x4 (its lanes are 0 to 3)
|
||||
fn main() {
|
||||
v := f32x4(1.0)
|
||||
print(v.shuffle(0, 1, 2, 4))
|
||||
}
|
||||
6
tests/fail/vec_shuffle_var.fch
Normal file
6
tests/fail/vec_shuffle_var.fch
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
// expect: shuffle(...) takes lane numbers written in the code
|
||||
fn main() {
|
||||
v := f32x4(1.0)
|
||||
k := 2
|
||||
print(v.shuffle(k, 0, 1, 3))
|
||||
}
|
||||
Loading…
Reference in a new issue