nx_simd_i32x8_test.nx source
↩ module page · 130 lines · 4729 B
1// nx_simd_i32x8_test.nx -- exercise the i32x8 SIMD intrinsics.
2//
3// Same scalar-vs-SIMD-bit-exact gate as nx_simd_test.nx but with
4// 8 i32 lanes per vector (double the throughput of i64x4 for
5// 32-bit workloads -- ML token IDs, image pixels, hashes).
6
7import "nx_kernel_v2.nx"
8import "nx_log.nx"
9
10// NX_MO_SEQ_CST is no longer declared here: it moved to nx_syscalls.nx on 2026-08-25 and this file
11// already imports it transitively. This was the third of three independent declarations of the same
12// value (corpus_complete=1), deleted rather than kept in sync.
13
14func t1_round_trip_load_store() -> i64 {
15 let a_raw: *u8 = sys_mmap(64)
16 let r_raw: *u8 = sys_mmap(64)
17 let a: *i64 = a_raw as *i64
18 let r: *i64 = r_raw as *i64
19 // Fill 8 i32 lanes as 4 i64 words (lane order LE: low-i32 first).
20 // Encode (10, 20, 30, 40, 50, 60, 70, 80) -> pack into i64s.
21 a[0] = (20 << 32) | 10
22 a[1] = (40 << 32) | 30
23 a[2] = (60 << 32) | 50
24 a[3] = (80 << 32) | 70
25 let v: i64 = __simd_vload_i32_x8(a as *i64)
26 __simd_vstore_i32_x8(v, r as *i64)
27 if r[0] != ((20 << 32) | 10) { return 1 }
28 if r[1] != ((40 << 32) | 30) { return 2 }
29 if r[2] != ((60 << 32) | 50) { return 3 }
30 if r[3] != ((80 << 32) | 70) { return 4 }
31 return 0
32}
33
34func t2_vadd() -> i64 {
35 let a_raw: *u8 = sys_mmap(64)
36 let b_raw: *u8 = sys_mmap(64)
37 let r_raw: *u8 = sys_mmap(64)
38 let a: *i64 = a_raw as *i64
39 let b: *i64 = b_raw as *i64
40 let r: *i64 = r_raw as *i64
41 a[0] = (20 << 32) | 10
42 a[1] = (40 << 32) | 30
43 a[2] = (60 << 32) | 50
44 a[3] = (80 << 32) | 70
45 b[0] = (2 << 32) | 1
46 b[1] = (4 << 32) | 3
47 b[2] = (6 << 32) | 5
48 b[3] = (8 << 32) | 7
49 let va: i64 = __simd_vload_i32_x8(a as *i64)
50 let vb: i64 = __simd_vload_i32_x8(b as *i64)
51 let vsum: i64 = __simd_vadd_i32_x8(va, vb)
52 __simd_vstore_i32_x8(vsum, r as *i64)
53 // (10+1, 20+2, 30+3, 40+4, 50+5, 60+6, 70+7, 80+8) =
54 // (11, 22, 33, 44, 55, 66, 77, 88)
55 if r[0] != ((22 << 32) | 11) { return 10 }
56 if r[1] != ((44 << 32) | 33) { return 11 }
57 if r[2] != ((66 << 32) | 55) { return 12 }
58 if r[3] != ((88 << 32) | 77) { return 13 }
59 return 0
60}
61
62func t3_vmul() -> i64 {
63 let a_raw: *u8 = sys_mmap(64)
64 let b_raw: *u8 = sys_mmap(64)
65 let r_raw: *u8 = sys_mmap(64)
66 let a: *i64 = a_raw as *i64
67 let b: *i64 = b_raw as *i64
68 let r: *i64 = r_raw as *i64
69 a[0] = (20 << 32) | 10
70 a[1] = (40 << 32) | 30
71 a[2] = (60 << 32) | 50
72 a[3] = (80 << 32) | 70
73 b[0] = (2 << 32) | 1
74 b[1] = (4 << 32) | 3
75 b[2] = (6 << 32) | 5
76 b[3] = (8 << 32) | 7
77 let va: i64 = __simd_vload_i32_x8(a as *i64)
78 let vb: i64 = __simd_vload_i32_x8(b as *i64)
79 let vp: i64 = __simd_vmul_i32_x8(va, vb)
80 __simd_vstore_i32_x8(vp, r as *i64)
81 // (10, 40, 90, 160, 250, 360, 490, 640)
82 if r[0] != ((40 << 32) | 10) { return 20 }
83 if r[1] != ((160 << 32) | 90) { return 21 }
84 if r[2] != ((360 << 32) | 250) { return 22 }
85 if r[3] != ((640 << 32) | 490) { return 23 }
86 return 0
87}
88
89func t4_vbroadcast() -> i64 {
90 let r_raw: *u8 = sys_mmap(64)
91 let r: *i64 = r_raw as *i64
92 let v: i64 = __simd_vbroadcast_i32_x8(7)
93 __simd_vstore_i32_x8(v, r as *i64)
94 if r[0] != ((7 << 32) | 7) { return 30 }
95 if r[1] != ((7 << 32) | 7) { return 31 }
96 if r[2] != ((7 << 32) | 7) { return 32 }
97 if r[3] != ((7 << 32) | 7) { return 33 }
98 return 0
99}
100
101func t5_vreduce_sum() -> i64 {
102 let a_raw: *u8 = sys_mmap(64)
103 let a: *i64 = a_raw as *i64
104 a[0] = (20 << 32) | 10
105 a[1] = (40 << 32) | 30
106 a[2] = (60 << 32) | 50
107 a[3] = (80 << 32) | 70
108 let v: i64 = __simd_vload_i32_x8(a as *i64)
109 let s: i64 = __simd_vreduce_sum_i32_x8(v)
110 // Sum (10+20+30+40+50+60+70+80) = 360
111 if s != 360 { return 40 }
112 return 0
113}
114
115func main() -> nx_exit {
116 println("=== nx_simd_i32x8 smoke (8 lanes of 32-bit) ===" as *u8)
117 if t1_round_trip_load_store() != 0 { println("FAIL T1" as *u8); return 1 }
118 println("T1 vload+vstore PASS 8-lane i32 round-trip" as *u8)
119 if t2_vadd() != 0 { println("FAIL T2" as *u8); return 2 }
120 println("T2 vadd PASS lanes (11..88) bit-exact" as *u8)
121 if t3_vmul() != 0 { println("FAIL T3" as *u8); return 3 }
122 println("T3 vmul PASS lanes (10,40,90,160,250,360,490,640)" as *u8)
123 if t4_vbroadcast() != 0 { println("FAIL T4" as *u8); return 4 }
124 println("T4 vbroadcast PASS all 8 lanes = 7" as *u8)
125 if t5_vreduce_sum() != 0 { println("FAIL T5" as *u8); return 5 }
126 println("T5 vreduce_sum PASS 10+20+...+80 = 360" as *u8)
127 println("" as *u8)
128 println("All i32x8 SIMD ops bit-exact vs scalar; 8-lane throughput proven." as *u8)
129 return 0
130}