cubecl_core/post_processing/
checked_io.rs1use alloc::{vec, vec::Vec};
2
3use alloc::string::String;
4use cubecl_ir::{GlobalState, Instruction, Memory, Operation, Scope};
5use cubecl_runtime::server::ExecutionMode;
6
7use crate::{
8 io::*,
9 post_processing::{
10 analysis_helper::GlobalAnalyses, util::AtomicCounter, visitor::InstructionVisitor,
11 },
12};
13
14#[derive(new, Debug)]
15pub struct CheckedIoVisitor {
16 mode: ExecutionMode,
17 kernel_name: String,
18}
19
20impl CheckedIoVisitor {
21 pub fn apply(&mut self, scope: &Scope) {
22 let changes = AtomicCounter::new(0);
23 let analyses = GlobalAnalyses::default();
25 self.visit_scope(scope, &analyses, &changes);
26 }
27}
28
29impl InstructionVisitor for CheckedIoVisitor {
30 fn visit_instruction(
31 &mut self,
32 instruction: Instruction,
33 global_state: &GlobalState,
34 _analyses: &GlobalAnalyses,
35 _changes: &AtomicCounter,
36 ) -> Vec<Instruction> {
37 match self.mode {
38 ExecutionMode::Checked => self.transform_checked(instruction, global_state),
39 ExecutionMode::Validate => self.transform_validate(instruction, global_state),
40 ExecutionMode::Unchecked => vec![instruction],
41 }
42 }
43}
44
45impl CheckedIoVisitor {
46 fn transform_checked(
47 &self,
48 instruction: Instruction,
49 global_state: &GlobalState,
50 ) -> Vec<Instruction> {
51 if let Operation::Memory(memory) = &instruction.operation {
52 match memory {
53 Memory::Index(op) if op.checked => {
54 let has_length = op.list.has_buffer_length();
55
56 if has_length {
57 let list = op.list;
58 let index = op.index;
59 let scope = Scope::root(false).with_global_state(global_state.clone());
60
61 expand_checked_index(
62 &scope,
63 list,
64 index,
65 instruction.out(),
66 op.unroll_factor,
67 );
68
69 return scope.take_instructions();
70 }
71 }
72 _ => {}
73 }
74 }
75 vec![instruction]
76 }
77
78 fn transform_validate(
79 &self,
80 instruction: Instruction,
81 global_state: &GlobalState,
82 ) -> Vec<Instruction> {
83 if let Operation::Memory(memory) = &instruction.operation {
84 match memory {
85 Memory::Index(op) if op.checked => {
86 let has_length = op.list.has_buffer_length();
87
88 if has_length {
89 let list = op.list;
90 let index = op.index;
91 let scope = Scope::root(false).with_global_state(global_state.clone());
92
93 expand_validate_index(
94 &scope,
95 list,
96 index,
97 instruction.out(),
98 op.unroll_factor,
99 &self.kernel_name,
100 );
101
102 return scope.take_instructions();
103 }
104 }
105 _ => {}
106 }
107 }
108 vec![instruction]
109 }
110}