1use std::{collections::HashSet, fmt::Display, marker::PhantomData};
2
3use cubecl_core::{
4 ir::{BarrierLevel, Processor},
5 post_processing::saturating::SaturatingArithmeticProcessor,
6 prelude::Visibility,
7};
8
9use crate::{
10 Dialect,
11 cuda::{
12 extension::{Fragment, LdMatrix, MmaExecute, MmaExecuteScaled, MmaExtension, StMatrix},
13 processors::CudaMmaProcessor,
14 ptx::*,
15 },
16 shared::{
17 self, Component, DialectBindings, DialectCubeBuiltins, DialectIncludes,
18 DialectInstructions, DialectProcessors, DialectTypes, DialectWarpReduceCompiler,
19 DialectWmmaCompiler, Elem, FP4Kind, FP6Kind, FP8Kind, Flags, Instruction, Item, KernelArg,
20 ManualMma, PointerClass, Value, WarpInstruction, unary,
21 },
22};
23
24use super::{Extension, arch::CudaArchitecture};
25
26#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
27pub struct CudaDialect<M> {
28 _wmma_compiler: PhantomData<M>,
29}
30
31impl<M: DialectWmmaCompiler<Self>> Dialect for CudaDialect<M> {
32 type Architecture = CudaArchitecture;
33}
34
35impl<M: DialectWmmaCompiler<Self>> DialectIncludes<Self> for CudaDialect<M> {
36 type Extension = Extension<Self>;
37
38 fn compile_includes(f: &mut std::fmt::Formatter<'_>, flags: &Flags<Self>) -> std::fmt::Result {
39 f.write_str("#include <cuda_runtime.h>\n")?;
40 if flags.elem_fp4 {
41 f.write_str("#include <cuda_fp4.h>\n")?;
42 }
43 if flags.elem_fp6 {
44 f.write_str("#include <cuda_fp6.h>\n")?;
45 }
46 if flags.elem_fp8 {
47 f.write_str("#include <cuda_fp8.h>\n")?;
48 }
49 if flags.elem_bf16 {
50 f.write_str("#include <cuda_bf16.h>\n")?;
51 }
52 if flags.elem_f16 {
53 f.write_str("#include <cuda_fp16.h>\n")?;
54 }
55
56 if flags.inst_wmma || flags.elem_tf32 {
58 Self::compile_wmma_includes(f, flags)?;
59 }
60
61 if flags.op_barrier || flags.inst_tma || flags.indexes.cluster_pos {
62 f.write_str("#include <cooperative_groups.h>\n")?;
63 f.write_str("#include <cooperative_groups/memcpy_async.h>\n")?;
64 f.write_str("#include <cuda/barrier>\n")?;
65 }
66 if flags.inst_ptx_wrappers {
67 f.write_str("#include <cuda/ptx>\n")?;
68 }
69 if flags.inst_tma {
70 f.write_str(
71 "typedef struct CUtensorMap_st {
72alignas(64) unsigned long long int opaque[16];
73} CUtensorMap;\n",
74 )?;
75 }
76 Ok(())
77 }
78
79 fn compile_extensions(
80 f: &mut std::fmt::Formatter<'_>,
81 extensions: &[Self::Extension],
82 ) -> std::fmt::Result {
83 for extension in extensions {
84 match extension {
85 Extension::NoExtension => {}
86 Extension::Mma(mma) => mma.format_extension(f)?,
87 }
88 }
89 Ok(())
90 }
91
92 fn register_instruction_extension(
93 _extensions: &mut Vec<Self::Extension>,
94 _instruction: &Instruction<Self>,
95 ) {
96 }
97
98 fn register_warp_instruction_extension(
99 _extensions: &mut Vec<Self::Extension>,
100 _instruction: &WarpInstruction<Self>,
101 ) {
102 }
103
104 fn register_wmma_instruction_extension(
105 extensions: &mut Vec<Self::Extension>,
106 instruction: &shared::WmmaInstruction<Self>,
107 ) {
108 match instruction {
109 shared::WmmaInstruction::ExecuteManual {
110 shape,
111 frag_a,
112 frag_b,
113 frag_c,
114 frag_d,
115 } => {
116 let ext = Extension::Mma(MmaExtension::Execute(MmaExecute::new(
117 *shape,
118 Fragment(frag_a.elem()),
119 Fragment(frag_b.elem()),
120 Fragment(frag_c.elem()),
121 Fragment(frag_d.elem()),
122 )));
123 if !extensions.contains(&ext) {
124 extensions.push(ext);
125 }
126 }
127 shared::WmmaInstruction::ExecuteScaled {
128 shape,
129 frag_a,
130 frag_b,
131 frag_c,
132 frag_d,
133 scales_a,
134 scales_factor,
135 ..
136 } => {
137 let ext = Extension::Mma(MmaExtension::ExecuteScaled(MmaExecuteScaled::new(
138 *shape,
139 Fragment(frag_a.elem()),
140 Fragment(frag_b.elem()),
141 Fragment(frag_c.elem()),
142 Fragment(frag_d.elem()),
143 scales_a.elem(),
144 *scales_factor,
145 )));
146 if !extensions.contains(&ext) {
147 extensions.push(ext);
148 }
149 }
150 shared::WmmaInstruction::LdMatrix {
151 output,
152 factor,
153 transpose,
154 ..
155 } => {
156 let ext = Extension::Mma(MmaExtension::LdMatrix(LdMatrix::new(
157 output.elem(),
158 *factor,
159 *transpose,
160 )));
161 if !extensions.contains(&ext) {
162 extensions.push(ext);
163 }
164 }
165 shared::WmmaInstruction::StMatrix {
166 registers,
167 factor,
168 transpose,
169 ..
170 } => {
171 let ext = Extension::Mma(MmaExtension::StMatrix(StMatrix::new(
172 registers.elem(),
173 *factor,
174 *transpose,
175 )));
176 if !extensions.contains(&ext) {
177 extensions.push(ext);
178 }
179 }
180 _ => {}
181 }
182 }
183}
184
185impl<M: DialectWmmaCompiler<Self>> DialectTypes<Self> for CudaDialect<M> {
188 fn item_can_be_optimized() -> bool {
189 true
190 }
191
192 fn compile_type_definitions(
193 f: &mut std::fmt::Formatter<'_>,
194 items: &HashSet<Item<Self>>,
195 scalars: &[(Elem<Self>, usize)],
196 info: &cubecl_core::Info,
197 flags: &Flags<Self>,
198 ) -> std::fmt::Result {
199 let mut items_deduplicated = HashSet::new();
201
202 for item in items {
203 let mut item = *item.value_ty();
204 match item {
205 Item::NativeVector(..) => {
206 continue;
207 }
208 Item::Atomic(inner) => {
209 item = *inner;
210 }
211 _ => {}
212 }
213 match item.elem() {
214 Elem::FP4(_) => {
215 item = item.with_elem(Elem::FP4(FP4Kind::E2M1));
216 }
217 Elem::FP4x2(_) => {
218 item = item.with_elem(Elem::FP4x2(FP4Kind::E2M1));
219 }
220 Elem::FP6(_) => {
221 item = item.with_elem(Elem::FP6(FP6Kind::E2M3));
222 }
223 Elem::FP6x2(_) => {
224 item = item.with_elem(Elem::FP6x2(FP6Kind::E2M3));
225 }
226 Elem::FP8(_) => {
227 item = item.with_elem(Elem::FP8(FP8Kind::E4M3));
228 }
229 Elem::FP8x2(_) => {
230 item = item.with_elem(Elem::FP8x2(FP8Kind::E4M3));
231 }
232 _ => {}
233 }
234 items_deduplicated.insert(item);
235 }
236
237 shared::type_definitions::<Self>(f)?;
238 shared::type_vectorized_definitions::<Self>(f, &items_deduplicated)?;
239
240 shared::type_info_definition_sized(f, info, scalars, flags.address_type)?;
241
242 if flags.inst_wmma {
243 Self::compile_wmma_type_definitions(f, flags)?;
244 }
245
246 Ok(())
247 }
248
249 fn compile_polyfills(f: &mut std::fmt::Formatter<'_>, flags: &Flags<Self>) -> std::fmt::Result {
250 if flags.inst_tma_im2col {
251 writeln!(f, "{TMA_LOAD_IM2COL}")?;
252 }
253 if flags.inst_async_copy {
254 writeln!(f, "{COPY_ASYNC}")?;
255 }
256 Ok(())
257 }
258
259 fn compile_elem(
260 f: &mut std::fmt::Formatter<'_>,
261 elem: &shared::Elem<Self>,
262 words: bool,
263 ) -> std::fmt::Result {
264 if words {
265 match elem {
266 shared::Elem::F32 => f.write_str("float"),
267 shared::Elem::F64 => f.write_str("double"),
268 shared::Elem::TF32 => f.write_str("float"),
269 shared::Elem::I8 => f.write_str("char"),
270 shared::Elem::I16 => f.write_str("short"),
271 shared::Elem::I32 => f.write_str("int"),
272 shared::Elem::I64 => f.write_str("long"),
273 shared::Elem::U8 => f.write_str("uchar"),
274 shared::Elem::U16 => f.write_str("ushort"),
275 shared::Elem::U32 => f.write_str("uint"),
276 shared::Elem::U64 => f.write_str("ulong"),
277 _ => Self::compile_elem(f, elem, false),
278 }
279 } else {
280 match elem {
281 shared::Elem::FP4(_) => write!(f, "__nv_fp4_storage_t"),
282 shared::Elem::FP4x2(_) => write!(f, "__nv_fp4x2_storage_t"),
283 shared::Elem::FP6(_) => write!(f, "__nv_fp6_storage_t"),
284 shared::Elem::FP6x2(_) => write!(f, "__nv_fp6x2_storage_t"),
285 shared::Elem::FP8(_) => write!(f, "__nv_fp8_storage_t"),
286 shared::Elem::FP8x2(_) => write!(f, "__nv_fp8x2_storage_t"),
287 shared::Elem::F16 => f.write_str("__half"),
288 shared::Elem::F16x2 => f.write_str("__half2"),
289 shared::Elem::F32 => f.write_str("float"),
290 shared::Elem::F64 => f.write_str("double"),
291 shared::Elem::BF16 => f.write_str("__nv_bfloat16"),
292 shared::Elem::BF16x2 => f.write_str("__nv_bfloat162"),
293 shared::Elem::TF32 => f.write_str("float"),
294 shared::Elem::I8 => f.write_str("int8"),
295 shared::Elem::I16 => f.write_str("int16"),
296 shared::Elem::I32 => f.write_str("int32"),
297 shared::Elem::I64 => f.write_str("int64"),
298 shared::Elem::U8 => f.write_str("uint8"),
299 shared::Elem::U16 => f.write_str("uint16"),
300 shared::Elem::U32 => f.write_str("uint32"),
301 shared::Elem::U64 => f.write_str("uint64"),
302 shared::Elem::Bool => f.write_str("bool"),
303 shared::Elem::None => f.write_str("<none>"),
304 shared::Elem::_Dialect(_) => Ok(()),
305 }
306 }
307 }
308
309 fn compile_item(f: &mut std::fmt::Formatter<'_>, item: &Item<Self>) -> std::fmt::Result {
310 match item {
311 Item::Scalar(elem) => write!(f, "{elem}"),
312 Item::Vector(inner, vectorization) => {
313 write!(f, "{inner}_{vectorization}")
314 }
315 Item::NativeVector(elem, vectorization) => {
316 Self::compile_elem(f, elem, true)?;
317 write!(f, "{vectorization}")
318 }
319 Item::Atomic(inner) => Self::compile_item(f, inner.as_ref()),
320 Item::Pointer(inner, class) => {
321 if let PointerClass::Global(Visibility::Read | Visibility::Uniform) = class {
322 f.write_str("const ")?;
323 }
324 match inner.as_ref() {
325 Item::DynamicArray(inner) => write!(f, "{inner}*"),
326 other => write!(f, "{other}*"),
327 }
328 }
329 Item::Array(inner, size) => {
330 write!(f, "array<{inner}, {size}>")
331 }
332 Item::DynamicArray(inner) => {
333 write!(f, "{inner}*")
334 }
335 Item::Fragment(fragment_type) => write!(f, "{fragment_type}"),
336 Item::BarrierToken(BarrierLevel::Cube) => {
337 write!(f, "cuda::barrier<cuda::thread_scope_block>::arrival_token")
338 }
339 Item::BarrierToken(BarrierLevel::Unit) => {
340 write!(f, "cuda::barrier<cuda::thread_scope_thread>::arrival_token")
341 }
342 Item::TensorMap => f.write_str("CUtensorMap"),
343 Item::Barrier(BarrierLevel::Unit) => {
344 f.write_str("cuda::barrier<cuda::thread_scope_thread>")
345 }
346 Item::Barrier(BarrierLevel::Cube) => {
347 f.write_str("cuda::barrier<cuda::thread_scope_block>")
348 }
349 }
350 }
351
352 fn compile_local_memory_qualifier(_f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
353 Ok(())
354 }
355}
356
357impl<M: DialectWmmaCompiler<Self>> DialectBindings<Self> for CudaDialect<M> {
360 fn compile_kernel_signature(
361 f: &mut std::fmt::Formatter<'_>,
362 kernel_name: &str,
363 tensor_maps: &[KernelArg<Self>],
364 buffers: &[KernelArg<Self>],
365 flags: &Flags<Self>,
366 ) -> std::fmt::Result {
367 write!(
368 f,
369 "
370
371extern \"C\" __global__ void __launch_bounds__({})",
372 flags.cube_dim.num_elems()
373 )?;
374 if let Some(cluster_dim) = flags.cluster_dim {
375 write!(
376 f,
377 "__cluster_dims__({}, {}, {}) ",
378 cluster_dim.x, cluster_dim.y, cluster_dim.z
379 )?;
380 }
381 writeln!(f, "{kernel_name} (")?;
382
383 shared::compile_bindings(f, tensor_maps, buffers, flags.has_info)?;
384 if flags.use_grid_constants {
385 shared::compile_info_static(f, flags)?;
386 } else {
387 shared::compile_info_dynamic(f, flags)?;
388 }
389 f.write_str("\n)")?;
390 Ok(())
392 }
393
394 fn compile_bindings_body(
395 f: &mut std::fmt::Formatter<'_>,
396 body: &shared::Body<Self>,
397 ) -> std::fmt::Result {
398 if !body.shared_memories.is_empty() {
399 let max_align = body
400 .shared_memories
401 .iter()
402 .map(|smem| smem.align)
403 .max()
404 .unwrap();
405 writeln!(
408 f,
409 "extern __shared__ __align__({max_align}) uint8 dynamic_shared_mem[];"
410 )?;
411 }
412 if body.info_by_ptr {
413 f.write_str("const info_st& info = *info_ptr;\n")?;
414 writeln!(
416 f,
417 "const {addr}* dynamic_meta = reinterpret_cast<const {addr}*>(
418 reinterpret_cast<const char*>(info_ptr) + sizeof(info_st)
419 );\n",
420 addr = body.address_type,
421 )?;
422 }
423 Ok(())
424 }
425}
426
427impl<M: DialectWmmaCompiler<Self>> DialectWarpReduceCompiler<Self> for CudaDialect<M> {}
428
429impl<M: DialectWmmaCompiler<Self>> DialectCubeBuiltins<Self> for CudaDialect<M> {
432 fn compile_cluster_pos(f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
433 write!(f, "cluster.block_rank()")
434 }
435
436 fn compile_cluster_pos_x(f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
437 write!(f, "cluster.block_index().x")
438 }
439
440 fn compile_cluster_pos_y(f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
441 write!(f, "cluster.block_index().y")
442 }
443
444 fn compile_cluster_pos_z(f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
445 write!(f, "cluster.block_index().z")
446 }
447}
448
449impl<M: DialectWmmaCompiler<Self>> DialectInstructions<Self> for CudaDialect<M> {
452 fn compile_instruction_sync_threads(f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
454 writeln!(f, "__syncthreads();\n")
455 }
456
457 fn compile_instruction_sync_warp(f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
458 writeln!(f, "__syncwarp();\n")
459 }
460
461 fn compile_instruction_thread_fence(f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
462 writeln!(f, "__threadfence();")
463 }
464
465 fn compile_instruction_find_first_set<T: Component<Self>>(
467 f: &mut std::fmt::Formatter<'_>,
468 input: T,
469 out_elem: Elem<Self>,
470 ) -> std::fmt::Result {
471 write!(f, "{out_elem}(")?;
472 match input.elem() {
473 Elem::I32 => write!(f, "__ffs({input})"),
474 Elem::U32 => write!(f, "__ffs({}({input}))", Elem::<Self>::I32),
475 Elem::I64 => write!(f, "__ffsll({input})"),
476 Elem::U64 => write!(f, "__ffsll({}({input}))", Elem::<Self>::I64),
477 _ => write!(f, "__ffs({}({input}))", Elem::<Self>::I32),
478 }?;
479 write!(f, ")")
480 }
481
482 fn compile_instruction_leading_zeros_scalar<T: Component<Self>>(
483 f: &mut std::fmt::Formatter<'_>,
484 input: T,
485 out_elem: Elem<Self>,
486 ) -> std::fmt::Result {
487 write!(f, "{out_elem}(")?;
488 match input.elem() {
489 Elem::I32 => write!(f, "__clz({input})"),
490 Elem::U32 => write!(f, "__clz({}({input}))", Elem::<Self>::I32),
491 Elem::I64 => write!(f, "__clzll({input})"),
492 Elem::U64 => write!(f, "__clzll({}({input}))", Elem::<Self>::I64),
493 in_elem => write!(
494 f,
495 "{out_elem}(__clz({}) - {})",
496 unary::zero_extend(input),
497 (size_of::<u32>() - in_elem.size()) * 8
498 ),
499 }?;
500 write!(f, ")")
501 }
502
503 fn compile_instruction_trailing_zeros_scalar<T: Component<Self>>(
504 f: &mut std::fmt::Formatter<'_>,
505 input: T,
506 out_elem: Elem<Self>,
507 ) -> std::fmt::Result {
508 write!(f, "{out_elem}(")?;
512 match input.elem() {
513 Elem::I32 | Elem::U32 => {
514 write!(f, "({input} == 0 ? 32 : __ffs({input}) - 1)")
515 }
516 Elem::I64 | Elem::U64 => {
517 write!(f, "({input} == 0 ? 64 : __ffsll({input}) - 1)")
518 }
519 in_elem => {
520 let bits = in_elem.size() * 8;
521 let extended = unary::zero_extend(input);
522 write!(f, "({extended} == 0 ? {bits} : __ffs({extended}) - 1)")
523 }
524 }?;
525 write!(f, ")")
526 }
527
528 fn compile_saturating_add(
529 f: &mut std::fmt::Formatter<'_>,
530 lhs: impl Display,
531 rhs: impl Display,
532 item: Item<Self>,
533 ) -> std::fmt::Result {
534 let elem = item.elem();
535 match elem {
536 Elem::I32 => {
537 write!(
538 f,
539 r#"[&]() -> {elem} {{
540 {elem} result;
541 asm("add.sat.s32 %0, %1, %2;"
542 : "=r"(result)
543 : "r"({lhs}), "r"({rhs}));
544 return result;
545 }}()"#
546 )
547 }
548 _ => unreachable!("Should be replaced by polyfill"),
549 }
550 }
551
552 fn compile_saturating_sub(
553 f: &mut std::fmt::Formatter<'_>,
554 lhs: impl Display,
555 rhs: impl Display,
556 item: Item<Self>,
557 ) -> std::fmt::Result {
558 let elem = item.elem();
559 match elem {
561 Elem::I32 => {
562 write!(
563 f,
564 r#"[&]() -> {elem} {{
565 {elem} result;
566 asm("sub.sat.s32 %0, %1, %2;"
567 : "=r"(result)
568 : "r"({lhs}), "r"({rhs}));
569 return result;
570 }}()"#
571 )
572 }
573 _ => unreachable!("Should be replaced by polyfill"),
574 }
575 }
576
577 fn compile_instruction_max_function_name(
579 f: &mut std::fmt::Formatter<'_>,
580 item: Item<Self>,
581 ) -> std::fmt::Result {
582 let max = match item.elem() {
583 Elem::F16 | Elem::BF16 => "__hmax",
584 Elem::F16x2 | Elem::BF16x2 => "__hmax2",
585 _ => "max",
586 };
587 write!(f, "{max}")
588 }
589
590 fn compile_instruction_min_function_name(
591 f: &mut std::fmt::Formatter<'_>,
592 item: Item<Self>,
593 ) -> std::fmt::Result {
594 let min = match item.elem() {
595 Elem::F16 | Elem::BF16 => "__hmin",
596 Elem::F16x2 | Elem::BF16x2 => "__hmin2",
597 _ => "min",
598 };
599 write!(f, "{min}")
600 }
601
602 fn compile_warp_shuffle(
604 f: &mut std::fmt::Formatter<'_>,
605 val: &str,
606 _elem: &Elem<Self>,
607 source: &str,
608 ) -> std::fmt::Result {
609 write!(f, "__shfl_sync(-1, {val}, {source})")
610 }
611 fn compile_warp_shuffle_xor(
612 f: &mut std::fmt::Formatter<'_>,
613 val: &str,
614 _elem: &Elem<Self>,
615 offset: &str,
616 ) -> std::fmt::Result {
617 write!(f, "__shfl_xor_sync(-1, {val}, {offset})")
618 }
619 fn compile_warp_shuffle_up(
620 f: &mut std::fmt::Formatter<'_>,
621 val: &str,
622 _elem: &Elem<Self>,
623 offset: &str,
624 ) -> std::fmt::Result {
625 write!(f, "__shfl_up_sync(-1, {val}, {offset})")
626 }
627 fn compile_warp_shuffle_down(
628 f: &mut std::fmt::Formatter<'_>,
629 val: &str,
630 _elem: &Elem<Self>,
631 offset: &str,
632 ) -> std::fmt::Result {
633 write!(f, "__shfl_down_sync(-1, {val}, {offset})")
634 }
635 fn compile_warp_all<T: Component<Self>>(
636 f: &mut std::fmt::Formatter<'_>,
637 input: &T,
638 ) -> std::fmt::Result {
639 write!(f, "__all_sync(-1, {input})")
640 }
641 fn compile_warp_any<T: Component<Self>>(
642 f: &mut std::fmt::Formatter<'_>,
643 input: &T,
644 ) -> std::fmt::Result {
645 write!(f, "__any_sync(-1, {input})")
646 }
647
648 fn compile_warp_ballot(
649 f: &mut std::fmt::Formatter<'_>,
650 input: &Value<Self>,
651 _out_elem: &Elem<Self>,
652 ) -> std::fmt::Result {
653 write!(f, "__ballot_sync(-1, {input})")
654 }
655
656 fn compile_warp_elect(f: &mut std::fmt::Formatter<'_>, out: &str) -> std::fmt::Result {
657 let elem = Elem::<Self>::Bool;
658 let uint32 = Elem::<Self>::U32;
659 writeln!(
663 f,
664 r#"{out} = {elem}([&]() -> {uint32} {{
665 {uint32} pred = 0;
666 asm volatile(
667 "{{\n"
668 " .reg .pred %%px;\n"
669 " elect.sync _|%%px, 0xffffffff;\n"
670 " selp.b32 %0, 1, 0, %%px;\n"
671 "}}\n"
672 : "+r"(pred));
673 return pred;
674 }}());"#
675 )
676 }
677
678 fn compile_unreachable(f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
679 write!(f, "__builtin_unreachable();")
680 }
681}
682
683impl<M: DialectWmmaCompiler<Self>> DialectWmmaCompiler<Self> for CudaDialect<M> {
686 fn compile_wmma_includes(
687 f: &mut std::fmt::Formatter<'_>,
688 flags: &Flags<Self>,
689 ) -> std::fmt::Result {
690 M::compile_wmma_includes(f, flags)
691 }
692
693 fn compile_wmma_type_definitions(
694 f: &mut std::fmt::Formatter<'_>,
695 flags: &Flags<Self>,
696 ) -> std::fmt::Result {
697 M::compile_wmma_type_definitions(f, flags)
698 }
699
700 fn compile_wmma_local_variables(f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
701 M::compile_wmma_local_variables(f)
702 }
703
704 fn compile_wmma_fragment_declaration(
705 f: &mut std::fmt::Formatter<'_>,
706 val: &Value<Self>,
707 value_ty: &Item<Self>,
708 ) -> std::fmt::Result {
709 M::compile_wmma_fragment_declaration(f, val, value_ty)
710 }
711
712 fn compile_wwma_fragment_ident(
713 f: &mut std::fmt::Formatter<'_>,
714 ident: &crate::shared::FragmentIdent<Self>,
715 ) -> std::fmt::Result {
716 M::compile_wwma_fragment_ident(f, ident)
717 }
718
719 fn compile_wmma_fragment_layout(
720 f: &mut std::fmt::Formatter<'_>,
721 layout: &crate::shared::FragmentLayout<Self>,
722 ) -> std::fmt::Result {
723 M::compile_wmma_fragment_layout(f, layout)
724 }
725
726 fn compile_wmma_fragment(
727 f: &mut std::fmt::Formatter<'_>,
728 fragment: &crate::shared::FragmentType<Self>,
729 ) -> std::fmt::Result {
730 M::compile_wmma_fragment(f, fragment)
731 }
732
733 fn compile_wmma_instruction(
734 f: &mut std::fmt::Formatter<'_>,
735 instruction: &crate::shared::WmmaInstruction<Self>,
736 ) -> std::fmt::Result {
737 M::compile_wmma_instruction(f, instruction)
738 }
739
740 fn compile_manual_mma(
741 f: &mut std::fmt::Formatter<'_>,
742 mma: ManualMma<Self>,
743 ) -> std::fmt::Result {
744 M::compile_manual_mma(f, mma)
745 }
746
747 fn compile_scaled_mma(
748 f: &mut std::fmt::Formatter<'_>,
749 mma: ManualMma<Self>,
750 scales_a: Value<Self>,
751 scales_b: Value<Self>,
752 scales_factor: u32,
753 ) -> std::fmt::Result {
754 M::compile_scaled_mma(f, mma, scales_a, scales_b, scales_factor)
755 }
756
757 fn supported_wmma_combinations(
758 arch: &CudaArchitecture,
759 ) -> crate::shared::SupportedMmaCombinations {
760 M::supported_wmma_combinations(arch)
761 }
762
763 fn supported_mma_combinations(arch: &CudaArchitecture) -> shared::SupportedMmaCombinations {
764 M::supported_mma_combinations(arch)
765 }
766
767 fn supported_scaled_mma_combinations(
768 arch: &CudaArchitecture,
769 ) -> shared::SupportedScaledMmaCombinations {
770 M::supported_scaled_mma_combinations(arch)
771 }
772}
773
774impl<M: DialectWmmaCompiler<Self>> DialectProcessors<Self> for CudaDialect<M> {
775 fn processors() -> Vec<Box<dyn Processor>> {
776 vec![
777 Box::new(CudaMmaProcessor),
778 Box::new(SaturatingArithmeticProcessor::new(false)),
779 ]
780 }
781}