nx_cascade_test.nx source
↩ module page · 103 lines · 2549 B
1// nx_cascade_test.nx -- regression test for the parallel-copy
2// semantic violation bug in nxc2's copy-forward pass.
3//
4// Bug: copy-forward in opt.c walked through single-def OP_COPY
5// chains into multi-def merge values, breaking the cascade emitted
6// by mem2reg's out-of-SSA pass at end of loop bodies. Source
7// while c { h=g; g=f; ...; b=a; a=99 }
8// compiled to
9// mv a, 99 # writes a first
10// mv b, a # b gets NEW a, not OLD a
11// ... cascade collapsed
12//
13// Fixed 2026-05-17 in opt.c::opt_copy_forward_function by skipping
14// forwarding for OP_COPY whose result is multi-def (i.e., parallel-
15// copy glue at end of BB). This file must keep passing.
16//
17// This test covers FOUR cascade shapes:
18// T1: 8-var right-rotation (the original failing case)
19// T2: 3-var swap (a, b, c rotate)
20// T3: single-var redefine (a = a + 1)
21// T4: pair-wise swap via temp (a/b swap)
22//
23// expect_exit: 0
24// license_tier: ORIGINAL
25
26import "nx_syscalls.nx"
27
28func main() -> i64 {
29 // ---- T1: 8-var right rotation ----
30 var a: i64 = 1
31 var b: i64 = 2
32 var c: i64 = 3
33 var d: i64 = 4
34 var e: i64 = 5
35 var f: i64 = 6
36 var g: i64 = 7
37 var h: i64 = 8
38
39 var i: i64 = 0
40 while i < 1 {
41 h = g
42 g = f
43 f = e
44 e = d
45 d = c
46 c = b
47 b = a
48 a = 99
49 i = i + 1
50 }
51 if a != 99 { return 1 }
52 if b != 1 { return 2 }
53 if c != 2 { return 3 }
54 if d != 3 { return 4 }
55 if e != 4 { return 5 }
56 if f != 5 { return 6 }
57 if g != 6 { return 7 }
58 if h != 7 { return 8 }
59
60 // ---- T2: rotate three times so the bug compounds ----
61 var x: i64 = 10
62 var y: i64 = 20
63 var z: i64 = 30
64
65 var j: i64 = 0
66 while j < 3 {
67 z = y
68 y = x
69 x = x + 100
70 j = j + 1
71 }
72 // After 3 iters of x += 100; rotate(z,y,x):
73 // iter0: z=20, y=10, x=110
74 // iter1: z=10, y=110, x=210
75 // iter2: z=110, y=210, x=310
76 if x != 310 { return 20 }
77 if y != 210 { return 21 }
78 if z != 110 { return 22 }
79
80 // ---- T3: single-var self-update (no cascade -- sanity) ----
81 var n: i64 = 0
82 var k: i64 = 0
83 while k < 5 {
84 n = n + 1
85 k = k + 1
86 }
87 if n != 5 { return 30 }
88
89 // ---- T4: pair-wise swap via explicit temp ----
90 var p: i64 = 100
91 var q: i64 = 200
92 var l: i64 = 0
93 while l < 1 {
94 let tmp: i64 = p
95 p = q
96 q = tmp
97 l = l + 1
98 }
99 if p != 200 { return 40 }
100 if q != 100 { return 41 }
101
102 return 0
103}