cubecl_opt/
phi_frontiers.rs1use cubecl_ir::{Id, Type, Variable, VariableKind};
2use petgraph::graph::NodeIndex;
3
4use crate::{
5 Optimizer,
6 analyses::{dominance::DomFrontiers, liveness::Liveness, writes::Writes},
7};
8
9use super::version::{PhiEntry, PhiInstruction};
10
11impl Optimizer {
12 pub fn place_phi_nodes(&mut self) {
14 let keys: Vec<_> = self.program.variables.keys().cloned().collect();
15 let writes = self.analysis::<Writes>();
16 let liveness = self.analysis::<Liveness>();
17 let dom_frontiers = self.analysis::<DomFrontiers>();
18
19 for var in keys {
20 let mut workset: Vec<_> = self
21 .node_ids()
22 .iter()
23 .filter(|index| writes[*index].contains(&var))
24 .copied()
25 .collect();
26 let mut considered = workset.clone();
27 let mut already_inserted = Vec::new();
28
29 while let Some(node) = workset.pop() {
30 for frontier in dom_frontiers[&node].clone() {
31 if already_inserted.contains(&frontier) || liveness.is_dead(frontier, var) {
32 continue;
33 }
34 self.insert_phi(frontier, var, self.program.variables[&var]);
35 already_inserted.push(frontier);
36 if !considered.contains(&frontier) {
37 workset.push(frontier);
38 considered.push(frontier);
39 }
40 }
41 }
42 }
43 }
44
45 pub fn insert_phi(&mut self, block: NodeIndex, id: Id, item: Type) {
47 let var = Variable::new(VariableKind::Versioned { id, version: 0 }, item);
48 let entries = self.predecessors(block).into_iter().map(|pred| PhiEntry {
49 block: pred,
50 value: var,
51 });
52 let phi = PhiInstruction {
53 out: var,
54 entries: entries.collect(),
55 };
56 self.program[block].phi_nodes.borrow_mut().push(phi);
57 }
58}