use alloc::{format, vec::Vec};
use cubecl_ir::{GlobalState, Instruction, NonSemantic, Operation, Scope, Value, ValueKind};
use hashbrown::HashMap;
use crate::post_processing::{
analysis_helper::GlobalAnalyses,
util::AtomicCounter,
visitor::{InstructionVisitor, Visitor},
};
type Substitutes = HashMap<ValueKind, Vec<Value>>;
type Extracted = HashMap<ValueKind, Value>;
#[derive(Debug, Default)]
pub struct DisaggregateVisitor {
substitutes: Substitutes,
extracted: Extracted,
}
impl DisaggregateVisitor {
pub fn apply(scope: &Scope) {
let mut this = Self::default();
let changes = AtomicCounter::new(0);
let analyses = GlobalAnalyses::default();
this.visit_scope(scope, &analyses, &changes);
}
}
impl InstructionVisitor for DisaggregateVisitor {
fn visit_instruction(
&mut self,
mut instruction: Instruction,
_global_state: &GlobalState,
analyses: &GlobalAnalyses,
_changes: &AtomicCounter,
) -> Vec<Instruction> {
let mut visitor = Visitor(());
visitor.visit_operation(&mut instruction.operation, analyses, |_, val| {
if let Some(replacement) = self.extracted.get(&val.kind).copied() {
*val = replacement;
}
});
visitor.visit_out(&mut instruction.out, |_, val| {
if let Some(replacement) = self.extracted.get(&val.kind) {
*val = *replacement;
}
});
let mut new_instructions = Vec::new();
match &mut instruction.operation {
Operation::ConstructAggregate(fields) => {
let fields = fields.clone();
self.substitutes.insert(instruction.out().kind, fields);
}
Operation::ExtractAggregateField(operands) => {
let substitutes = self.substitutes.get(&operands.aggregate.kind);
let substitutes =
substitutes.expect("Should have aggregate registered before any extraction");
let substitute = substitutes[operands.field];
self.extracted.insert(instruction.out().kind, substitute);
}
Operation::NonSemantic(NonSemantic::Print { format_string, .. }) => {
for (from, to) in self.extracted.iter() {
*format_string = format_string.replace(&format!("{from}"), &format!("{to}"));
}
new_instructions.push(instruction);
}
_ => new_instructions.push(instruction),
}
new_instructions
}
}