1use crate::ir::{KernargField, Op, Program, TypeId, SFIR_SCHEMA};
4
5fn base(name: &str, provenance: &str, body: Vec<Op>, layout: Vec<KernargField>) -> Program {
6 base_group(name, provenance, body, layout, 0)
7}
8
9fn base_group(
10 name: &str,
11 provenance: &str,
12 body: Vec<Op>,
13 layout: Vec<KernargField>,
14 group_bytes: u32,
15) -> Program {
16 Program {
17 schema: SFIR_SCHEMA.into(),
18 fidelity: "functional".into(),
19 note: "not_gfx1201_isa_emulation".into(),
20 name: name.into(),
21 source_provenance: provenance.into(),
22 kernarg_layout: layout,
23 group_bytes,
24 body,
25 }
26}
27
28pub fn tiny_add() -> Program {
30 base(
31 "tiny_add",
32 "fixtures/functional/tiny_add.ref.c (hand-translated to softgpu-sfir-v1)",
33 vec![
34 Op::GlobalId {
35 dst: "i".into(),
36 dim: 0,
37 },
38 Op::Const {
39 dst: "four".into(),
40 ty: TypeId::U64,
41 value: 4,
42 },
43 Op::Mul {
44 dst: "off".into(),
45 lhs: "i".into(),
46 rhs: "four".into(),
47 ty: TypeId::U64,
48 },
49 Op::KernargLoad {
50 dst: "pa".into(),
51 offset: 0,
52 ty: TypeId::U64,
53 },
54 Op::Add {
55 dst: "addr_a".into(),
56 lhs: "pa".into(),
57 rhs: "off".into(),
58 ty: TypeId::U64,
59 },
60 Op::LoadGlobal {
61 dst: "va".into(),
62 addr: "addr_a".into(),
63 ty: TypeId::I32,
64 },
65 Op::Const {
66 dst: "one".into(),
67 ty: TypeId::I32,
68 value: 1,
69 },
70 Op::Add {
71 dst: "out".into(),
72 lhs: "va".into(),
73 rhs: "one".into(),
74 ty: TypeId::I32,
75 },
76 Op::KernargLoad {
77 dst: "pb".into(),
78 offset: 8,
79 ty: TypeId::U64,
80 },
81 Op::Add {
82 dst: "addr_b".into(),
83 lhs: "pb".into(),
84 rhs: "off".into(),
85 ty: TypeId::U64,
86 },
87 Op::StoreGlobal {
88 addr: "addr_b".into(),
89 src: "out".into(),
90 ty: TypeId::I32,
91 },
92 Op::Ret,
93 ],
94 vec![
95 KernargField {
96 name: "a".into(),
97 offset: 0,
98 size: 8,
99 kind: "global_ptr".into(),
100 },
101 KernargField {
102 name: "b".into(),
103 offset: 8,
104 size: 8,
105 kind: "global_ptr".into(),
106 },
107 ],
108 )
109}
110
111pub fn tiny_copy() -> Program {
113 base(
114 "tiny_copy",
115 "SoftGPU-authored softgpu-sfir-v1 (scalar copy)",
116 vec![
117 Op::GlobalId {
118 dst: "i".into(),
119 dim: 0,
120 },
121 Op::Const {
122 dst: "four".into(),
123 ty: TypeId::U64,
124 value: 4,
125 },
126 Op::Mul {
127 dst: "off".into(),
128 lhs: "i".into(),
129 rhs: "four".into(),
130 ty: TypeId::U64,
131 },
132 Op::KernargLoad {
133 dst: "pa".into(),
134 offset: 0,
135 ty: TypeId::U64,
136 },
137 Op::Add {
138 dst: "addr_a".into(),
139 lhs: "pa".into(),
140 rhs: "off".into(),
141 ty: TypeId::U64,
142 },
143 Op::LoadGlobal {
144 dst: "va".into(),
145 addr: "addr_a".into(),
146 ty: TypeId::I32,
147 },
148 Op::KernargLoad {
149 dst: "pb".into(),
150 offset: 8,
151 ty: TypeId::U64,
152 },
153 Op::Add {
154 dst: "addr_b".into(),
155 lhs: "pb".into(),
156 rhs: "off".into(),
157 ty: TypeId::U64,
158 },
159 Op::StoreGlobal {
160 addr: "addr_b".into(),
161 src: "va".into(),
162 ty: TypeId::I32,
163 },
164 Op::Ret,
165 ],
166 vec![
167 KernargField {
168 name: "a".into(),
169 offset: 0,
170 size: 8,
171 kind: "global_ptr".into(),
172 },
173 KernargField {
174 name: "b".into(),
175 offset: 8,
176 size: 8,
177 kind: "global_ptr".into(),
178 },
179 ],
180 )
181}
182
183pub fn tiny_index() -> Program {
185 base(
186 "tiny_index",
187 "SoftGPU-authored softgpu-sfir-v1 (index write)",
188 vec![
189 Op::GlobalId {
190 dst: "i".into(),
191 dim: 0,
192 },
193 Op::Const {
194 dst: "four".into(),
195 ty: TypeId::U64,
196 value: 4,
197 },
198 Op::Mul {
199 dst: "off".into(),
200 lhs: "i".into(),
201 rhs: "four".into(),
202 ty: TypeId::U64,
203 },
204 Op::KernargLoad {
205 dst: "p".into(),
206 offset: 0,
207 ty: TypeId::U64,
208 },
209 Op::Add {
210 dst: "addr".into(),
211 lhs: "p".into(),
212 rhs: "off".into(),
213 ty: TypeId::U64,
214 },
215 Op::StoreGlobal {
216 addr: "addr".into(),
217 src: "i".into(),
218 ty: TypeId::I32,
219 },
220 Op::Ret,
221 ],
222 vec![KernargField {
223 name: "out".into(),
224 offset: 0,
225 size: 8,
226 kind: "global_ptr".into(),
227 }],
228 )
229}
230
231pub fn kernarg_two_ptrs(a: u64, b: u64) -> [u8; 16] {
233 let mut k = [0u8; 16];
234 k[0..8].copy_from_slice(&a.to_le_bytes());
235 k[8..16].copy_from_slice(&b.to_le_bytes());
236 k
237}
238
239pub fn kernarg_one_ptr(p: u64) -> [u8; 8] {
240 p.to_le_bytes()
241}
242
243pub fn wave_lane_ids() -> Program {
245 base(
246 "wave_lane_ids",
247 "SoftGPU-authored softgpu-sfir-v1 (Phase 7 wave/lane indexing)",
248 vec![
249 Op::GlobalId {
250 dst: "i".into(),
251 dim: 0,
252 },
253 Op::WaveId { dst: "w".into() },
254 Op::LaneId { dst: "l".into() },
255 Op::Const {
256 dst: "thousand".into(),
257 ty: TypeId::I32,
258 value: 1000,
259 },
260 Op::Mul {
261 dst: "wh".into(),
262 lhs: "w".into(),
263 rhs: "thousand".into(),
264 ty: TypeId::I32,
265 },
266 Op::Add {
267 dst: "v".into(),
268 lhs: "wh".into(),
269 rhs: "l".into(),
270 ty: TypeId::I32,
271 },
272 Op::Const {
273 dst: "four".into(),
274 ty: TypeId::U64,
275 value: 4,
276 },
277 Op::Mul {
278 dst: "off".into(),
279 lhs: "i".into(),
280 rhs: "four".into(),
281 ty: TypeId::U64,
282 },
283 Op::KernargLoad {
284 dst: "p".into(),
285 offset: 0,
286 ty: TypeId::U64,
287 },
288 Op::Add {
289 dst: "addr".into(),
290 lhs: "p".into(),
291 rhs: "off".into(),
292 ty: TypeId::U64,
293 },
294 Op::StoreGlobal {
295 addr: "addr".into(),
296 src: "v".into(),
297 ty: TypeId::I32,
298 },
299 Op::Ret,
300 ],
301 vec![KernargField {
302 name: "out".into(),
303 offset: 0,
304 size: 8,
305 kind: "global_ptr".into(),
306 }],
307 )
308}
309
310pub fn predicated_inc() -> Program {
312 base(
313 "predicated_inc",
314 "SoftGPU-authored softgpu-sfir-v1 (Phase 7 divergence)",
315 vec![
316 Op::GlobalId {
317 dst: "i".into(),
318 dim: 0,
319 },
320 Op::LaneId { dst: "l".into() },
321 Op::Const {
322 dst: "one".into(),
323 ty: TypeId::I32,
324 value: 1,
325 },
326 Op::Const {
327 dst: "zero".into(),
328 ty: TypeId::I32,
329 value: 0,
330 },
331 Op::And {
332 dst: "odd".into(),
333 lhs: "l".into(),
334 rhs: "one".into(),
335 ty: TypeId::I32,
336 },
337 Op::CmpEq {
338 dst: "even".into(),
339 lhs: "odd".into(),
340 rhs: "zero".into(),
341 ty: TypeId::I32,
342 },
343 Op::Const {
344 dst: "four".into(),
345 ty: TypeId::U64,
346 value: 4,
347 },
348 Op::Mul {
349 dst: "off".into(),
350 lhs: "i".into(),
351 rhs: "four".into(),
352 ty: TypeId::U64,
353 },
354 Op::KernargLoad {
355 dst: "p".into(),
356 offset: 0,
357 ty: TypeId::U64,
358 },
359 Op::Add {
360 dst: "addr".into(),
361 lhs: "p".into(),
362 rhs: "off".into(),
363 ty: TypeId::U64,
364 },
365 Op::If {
366 cond: "even".into(),
367 then_body: vec![
368 Op::LoadGlobal {
369 dst: "v".into(),
370 addr: "addr".into(),
371 ty: TypeId::I32,
372 },
373 Op::Add {
374 dst: "out".into(),
375 lhs: "v".into(),
376 rhs: "one".into(),
377 ty: TypeId::I32,
378 },
379 Op::StoreGlobal {
380 addr: "addr".into(),
381 src: "out".into(),
382 ty: TypeId::I32,
383 },
384 ],
385 else_body: vec![],
386 },
387 Op::Ret,
388 ],
389 vec![KernargField {
390 name: "buf".into(),
391 offset: 0,
392 size: 8,
393 kind: "global_ptr".into(),
394 }],
395 )
396}
397
398pub fn group_exchange(workgroup_x: u32) -> Program {
400 let wg = i64::from(workgroup_x);
401 base_group(
402 "group_exchange",
403 "SoftGPU-authored softgpu-sfir-v1 (Phase 7 group memory + barrier)",
404 vec![
405 Op::LocalId {
406 dst: "lid".into(),
407 dim: 0,
408 },
409 Op::GlobalId {
410 dst: "gid".into(),
411 dim: 0,
412 },
413 Op::Const {
414 dst: "four".into(),
415 ty: TypeId::U64,
416 value: 4,
417 },
418 Op::Mul {
419 dst: "goff".into(),
420 lhs: "lid".into(),
421 rhs: "four".into(),
422 ty: TypeId::U64,
423 },
424 Op::StoreGroup {
425 addr: "goff".into(),
426 src: "lid".into(),
427 ty: TypeId::I32,
428 },
429 Op::Barrier,
430 Op::Const {
431 dst: "one".into(),
432 ty: TypeId::I32,
433 value: 1,
434 },
435 Op::Const {
436 dst: "wg".into(),
437 ty: TypeId::I32,
438 value: wg,
439 },
440 Op::Add {
441 dst: "np1".into(),
442 lhs: "lid".into(),
443 rhs: "one".into(),
444 ty: TypeId::I32,
445 },
446 Op::CmpEq {
447 dst: "wrap".into(),
448 lhs: "np1".into(),
449 rhs: "wg".into(),
450 ty: TypeId::I32,
451 },
452 Op::If {
453 cond: "wrap".into(),
454 then_body: vec![Op::Const {
455 dst: "nbr".into(),
456 ty: TypeId::I32,
457 value: 0,
458 }],
459 else_body: vec![Op::Add {
460 dst: "nbr".into(),
461 lhs: "lid".into(),
462 rhs: "one".into(),
463 ty: TypeId::I32,
464 }],
465 },
466 Op::Mul {
467 dst: "noff".into(),
468 lhs: "nbr".into(),
469 rhs: "four".into(),
470 ty: TypeId::U64,
471 },
472 Op::LoadGroup {
473 dst: "val".into(),
474 addr: "noff".into(),
475 ty: TypeId::I32,
476 },
477 Op::Mul {
478 dst: "ooff".into(),
479 lhs: "gid".into(),
480 rhs: "four".into(),
481 ty: TypeId::U64,
482 },
483 Op::KernargLoad {
484 dst: "p".into(),
485 offset: 0,
486 ty: TypeId::U64,
487 },
488 Op::Add {
489 dst: "addr".into(),
490 lhs: "p".into(),
491 rhs: "ooff".into(),
492 ty: TypeId::U64,
493 },
494 Op::StoreGlobal {
495 addr: "addr".into(),
496 src: "val".into(),
497 ty: TypeId::I32,
498 },
499 Op::Ret,
500 ],
501 vec![KernargField {
502 name: "out".into(),
503 offset: 0,
504 size: 8,
505 kind: "global_ptr".into(),
506 }],
507 workgroup_x * 4,
508 )
509}
510
511pub fn atomic_inc_reduce() -> Program {
513 use crate::ir::{AddrSpace, AtomicOrder, AtomicScope};
514 base(
515 "atomic_inc_reduce",
516 "SoftGPU-authored softgpu-sfir-v1 (Phase 7 atomics)",
517 vec![
518 Op::GlobalId {
519 dst: "i".into(),
520 dim: 0,
521 },
522 Op::Const {
523 dst: "one".into(),
524 ty: TypeId::I32,
525 value: 1,
526 },
527 Op::Const {
528 dst: "z".into(),
529 ty: TypeId::U64,
530 value: 0,
531 },
532 Op::KernargLoad {
533 dst: "pc".into(),
534 offset: 0,
535 ty: TypeId::U64,
536 },
537 Op::Add {
538 dst: "caddr".into(),
539 lhs: "pc".into(),
540 rhs: "z".into(),
541 ty: TypeId::U64,
542 },
543 Op::AtomicAdd {
544 dst: "old".into(),
545 addr: "caddr".into(),
546 src: "one".into(),
547 space: AddrSpace::Global,
548 scope: AtomicScope::Device,
549 order: AtomicOrder::Relaxed,
550 },
551 Op::Const {
552 dst: "four".into(),
553 ty: TypeId::U64,
554 value: 4,
555 },
556 Op::Mul {
557 dst: "off".into(),
558 lhs: "i".into(),
559 rhs: "four".into(),
560 ty: TypeId::U64,
561 },
562 Op::KernargLoad {
563 dst: "po".into(),
564 offset: 8,
565 ty: TypeId::U64,
566 },
567 Op::Add {
568 dst: "addr".into(),
569 lhs: "po".into(),
570 rhs: "off".into(),
571 ty: TypeId::U64,
572 },
573 Op::StoreGlobal {
574 addr: "addr".into(),
575 src: "old".into(),
576 ty: TypeId::I32,
577 },
578 Op::Ret,
579 ],
580 vec![
581 KernargField {
582 name: "counter".into(),
583 offset: 0,
584 size: 8,
585 kind: "global_ptr".into(),
586 },
587 KernargField {
588 name: "out".into(),
589 offset: 8,
590 size: 8,
591 kind: "global_ptr".into(),
592 },
593 ],
594 )
595}
596
597pub fn infinite_loop_watchdog() -> Program {
599 base(
600 "infinite_loop_watchdog",
601 "SoftGPU-authored softgpu-sfir-v1 (Phase 7 step-budget watchdog)",
602 vec![
603 Op::Const {
604 dst: "one".into(),
605 ty: TypeId::I32,
606 value: 1,
607 },
608 Op::Const {
609 dst: "tmp".into(),
610 ty: TypeId::I32,
611 value: 0,
612 },
613 Op::While {
614 cond: "one".into(),
615 body: vec![Op::Add {
616 dst: "tmp".into(),
617 lhs: "tmp".into(),
618 rhs: "one".into(),
619 ty: TypeId::I32,
620 }],
621 },
622 Op::Ret,
623 ],
624 vec![],
625 )
626}
627
628pub fn race_all_store_global_zero() -> Program {
630 base(
631 "race_all_store_global_zero",
632 "SoftGPU-authored softgpu-sfir-v1 (Phase 8 intentional global race)",
633 vec![
634 Op::Const {
635 dst: "z".into(),
636 ty: TypeId::U64,
637 value: 0,
638 },
639 Op::Const {
640 dst: "one".into(),
641 ty: TypeId::I32,
642 value: 1,
643 },
644 Op::KernargLoad {
645 dst: "p".into(),
646 offset: 0,
647 ty: TypeId::U64,
648 },
649 Op::Add {
650 dst: "addr".into(),
651 lhs: "p".into(),
652 rhs: "z".into(),
653 ty: TypeId::U64,
654 },
655 Op::StoreGlobal {
656 addr: "addr".into(),
657 src: "one".into(),
658 ty: TypeId::I32,
659 },
660 Op::Ret,
661 ],
662 vec![KernargField {
663 name: "buf".into(),
664 offset: 0,
665 size: 8,
666 kind: "global_ptr".into(),
667 }],
668 )
669}
670
671pub fn oob_store_past_end(n: u32) -> Program {
673 let past = i64::from(n) * 4;
674 base(
675 "oob_store_past_end",
676 "SoftGPU-authored softgpu-sfir-v1 (Phase 8 intentional OOB store)",
677 vec![
678 Op::Const {
679 dst: "off".into(),
680 ty: TypeId::U64,
681 value: past,
682 },
683 Op::Const {
684 dst: "one".into(),
685 ty: TypeId::I32,
686 value: 1,
687 },
688 Op::KernargLoad {
689 dst: "p".into(),
690 offset: 0,
691 ty: TypeId::U64,
692 },
693 Op::Add {
694 dst: "addr".into(),
695 lhs: "p".into(),
696 rhs: "off".into(),
697 ty: TypeId::U64,
698 },
699 Op::StoreGlobal {
700 addr: "addr".into(),
701 src: "one".into(),
702 ty: TypeId::I32,
703 },
704 Op::Ret,
705 ],
706 vec![KernargField {
707 name: "buf".into(),
708 offset: 0,
709 size: 8,
710 kind: "global_ptr".into(),
711 }],
712 )
713}
714
715pub fn group_exchange_missing_barrier(workgroup_x: u32) -> Program {
717 let wg = i64::from(workgroup_x);
718 base_group(
719 "group_exchange_missing_barrier",
720 "SoftGPU-authored softgpu-sfir-v1 (Phase 8 intentional missing barrier)",
721 vec![
722 Op::LocalId {
723 dst: "lid".into(),
724 dim: 0,
725 },
726 Op::GlobalId {
727 dst: "gid".into(),
728 dim: 0,
729 },
730 Op::Const {
731 dst: "four".into(),
732 ty: TypeId::U64,
733 value: 4,
734 },
735 Op::Mul {
736 dst: "goff".into(),
737 lhs: "lid".into(),
738 rhs: "four".into(),
739 ty: TypeId::U64,
740 },
741 Op::StoreGroup {
742 addr: "goff".into(),
743 src: "lid".into(),
744 ty: TypeId::I32,
745 },
746 Op::Const {
748 dst: "one".into(),
749 ty: TypeId::I32,
750 value: 1,
751 },
752 Op::Const {
753 dst: "wg".into(),
754 ty: TypeId::I32,
755 value: wg,
756 },
757 Op::Add {
758 dst: "np1".into(),
759 lhs: "lid".into(),
760 rhs: "one".into(),
761 ty: TypeId::I32,
762 },
763 Op::CmpEq {
764 dst: "wrap".into(),
765 lhs: "np1".into(),
766 rhs: "wg".into(),
767 ty: TypeId::I32,
768 },
769 Op::If {
770 cond: "wrap".into(),
771 then_body: vec![Op::Const {
772 dst: "nid".into(),
773 ty: TypeId::I32,
774 value: 0,
775 }],
776 else_body: vec![Op::Add {
777 dst: "nid".into(),
778 lhs: "lid".into(),
779 rhs: "one".into(),
780 ty: TypeId::I32,
781 }],
782 },
783 Op::Mul {
784 dst: "noff".into(),
785 lhs: "nid".into(),
786 rhs: "four".into(),
787 ty: TypeId::U64,
788 },
789 Op::LoadGroup {
790 dst: "val".into(),
791 addr: "noff".into(),
792 ty: TypeId::I32,
793 },
794 Op::Mul {
795 dst: "ooff".into(),
796 lhs: "gid".into(),
797 rhs: "four".into(),
798 ty: TypeId::U64,
799 },
800 Op::KernargLoad {
801 dst: "p".into(),
802 offset: 0,
803 ty: TypeId::U64,
804 },
805 Op::Add {
806 dst: "addr".into(),
807 lhs: "p".into(),
808 rhs: "ooff".into(),
809 ty: TypeId::U64,
810 },
811 Op::StoreGlobal {
812 addr: "addr".into(),
813 src: "val".into(),
814 ty: TypeId::I32,
815 },
816 Op::Ret,
817 ],
818 vec![KernargField {
819 name: "out".into(),
820 offset: 0,
821 size: 8,
822 kind: "global_ptr".into(),
823 }],
824 workgroup_x * 4,
825 )
826}
827
828pub fn uninit_group_read() -> Program {
830 base_group(
831 "uninit_group_read",
832 "SoftGPU-authored softgpu-sfir-v1 (Phase 8 intentional uninit group read)",
833 vec![
834 Op::Const {
835 dst: "z".into(),
836 ty: TypeId::U64,
837 value: 0,
838 },
839 Op::LoadGroup {
840 dst: "v".into(),
841 addr: "z".into(),
842 ty: TypeId::I32,
843 },
844 Op::KernargLoad {
845 dst: "p".into(),
846 offset: 0,
847 ty: TypeId::U64,
848 },
849 Op::StoreGlobal {
850 addr: "p".into(),
851 src: "v".into(),
852 ty: TypeId::I32,
853 },
854 Op::Ret,
855 ],
856 vec![KernargField {
857 name: "out".into(),
858 offset: 0,
859 size: 8,
860 kind: "global_ptr".into(),
861 }],
862 4,
863 )
864}
865
866pub fn cross_workgroup_store_zero() -> Program {
868 base(
869 "cross_workgroup_store_zero",
870 "SoftGPU-authored softgpu-sfir-v1 (Phase 8 intentional cross-WG race)",
871 vec![
872 Op::Const {
873 dst: "z".into(),
874 ty: TypeId::U64,
875 value: 0,
876 },
877 Op::WorkgroupId {
878 dst: "w".into(),
879 dim: 0,
880 },
881 Op::KernargLoad {
882 dst: "p".into(),
883 offset: 0,
884 ty: TypeId::U64,
885 },
886 Op::Add {
887 dst: "addr".into(),
888 lhs: "p".into(),
889 rhs: "z".into(),
890 ty: TypeId::U64,
891 },
892 Op::StoreGlobal {
893 addr: "addr".into(),
894 src: "w".into(),
895 ty: TypeId::I32,
896 },
897 Op::Ret,
898 ],
899 vec![KernargField {
900 name: "buf".into(),
901 offset: 0,
902 size: 8,
903 kind: "global_ptr".into(),
904 }],
905 )
906}
907
908pub fn sanitize_clean_index() -> Program {
910 tiny_index()
911}