cubecl_core/post_processing/
disaggregate.rs1use alloc::{format, vec::Vec};
2
3use cubecl_ir::{GlobalState, Instruction, NonSemantic, Operation, Scope, Value, ValueKind};
4use hashbrown::HashMap;
5
6use crate::post_processing::{
7 analysis_helper::GlobalAnalyses,
8 util::AtomicCounter,
9 visitor::{InstructionVisitor, Visitor},
10};
11
12type Substitutes = HashMap<ValueKind, Vec<Value>>;
13type Extracted = HashMap<ValueKind, Value>;
14
15#[derive(Debug, Default)]
18pub struct DisaggregateVisitor {
19 substitutes: Substitutes,
20 extracted: Extracted,
21}
22
23impl DisaggregateVisitor {
24 pub fn apply(scope: &Scope) {
25 let mut this = Self::default();
26 let changes = AtomicCounter::new(0);
27 let analyses = GlobalAnalyses::default();
29 this.visit_scope(scope, &analyses, &changes);
30 }
31}
32
33impl InstructionVisitor for DisaggregateVisitor {
34 fn visit_instruction(
35 &mut self,
36 mut instruction: Instruction,
37 _global_state: &GlobalState,
38 analyses: &GlobalAnalyses,
39 _changes: &AtomicCounter,
40 ) -> Vec<Instruction> {
41 let mut visitor = Visitor(());
42
43 visitor.visit_operation(&mut instruction.operation, analyses, |_, val| {
45 if let Some(replacement) = self.extracted.get(&val.kind).copied() {
46 *val = replacement;
47 }
48 });
49 visitor.visit_out(&mut instruction.out, |_, val| {
50 if let Some(replacement) = self.extracted.get(&val.kind) {
51 *val = *replacement;
52 }
53 });
54
55 let mut new_instructions = Vec::new();
56
57 match &mut instruction.operation {
58 Operation::ConstructAggregate(fields) => {
59 let fields = fields.clone();
60 self.substitutes.insert(instruction.out().kind, fields);
61 }
62 Operation::ExtractAggregateField(operands) => {
63 let substitutes = self.substitutes.get(&operands.aggregate.kind);
64 let substitutes =
65 substitutes.expect("Should have aggregate registered before any extraction");
66 let substitute = substitutes[operands.field];
67 self.extracted.insert(instruction.out().kind, substitute);
68 }
69 Operation::NonSemantic(NonSemantic::Print { format_string, .. }) => {
71 for (from, to) in self.extracted.iter() {
72 *format_string = format_string.replace(&format!("{from}"), &format!("{to}"));
73 }
74 new_instructions.push(instruction);
75 }
76 _ => new_instructions.push(instruction),
77 }
78
79 new_instructions
80 }
81}