cairo_lang_lowering/analysis/
use_sites.rs1use cairo_lang_utils::ordered_hash_map::{Entry, OrderedHashMap};
13
14use crate::analysis::UseLocation;
15use crate::{BlockEnd, Lowered, VariableId};
16
17pub struct UseSites {
19 sites: Vec<OrderedHashMap<UseLocation, usize>>,
20}
21
22impl UseSites {
23 pub fn analyze(lowered: &Lowered<'_>) -> Self {
25 let mut sites: Vec<OrderedHashMap<UseLocation, usize>> =
26 (0..lowered.variables.len()).map(|_| OrderedHashMap::default()).collect();
27 for (block_id, block) in lowered.blocks.iter() {
28 for (stmt_idx, stmt) in block.statements.iter().enumerate() {
29 let loc = UseLocation::Statement((block_id, stmt_idx));
30 for input in stmt.inputs() {
31 *sites[input.var_id.index()].entry(loc).or_default() += 1;
32 }
33 }
34 let end_loc = UseLocation::BlockEnd(block_id);
35 match &block.end {
36 BlockEnd::Return(returns, _) => {
37 for ret in returns {
38 *sites[ret.var_id.index()].entry(end_loc).or_default() += 1;
39 }
40 }
41 BlockEnd::Panic(var) => {
42 *sites[var.var_id.index()].entry(end_loc).or_default() += 1;
43 }
44 BlockEnd::Goto(_, remapping) => {
45 for (_, src) in remapping.iter() {
46 *sites[src.var_id.index()].entry(end_loc).or_default() += 1;
47 }
48 }
49 BlockEnd::Match { info } => {
50 for input in info.inputs() {
51 *sites[input.var_id.index()].entry(end_loc).or_default() += 1;
52 }
53 }
54 BlockEnd::NotSet => {}
55 }
56 }
57 Self { sites }
58 }
59
60 pub fn use_count(&self, var: VariableId) -> usize {
63 self.sites[var.index()].iter().map(|(_, count)| *count).sum()
64 }
65
66 pub fn move_uses(&mut self, from: VariableId, to: VariableId, loc: UseLocation) {
71 let Entry::Occupied(entry) = self.sites[from.index()].entry(loc) else {
72 return;
73 };
74 let count = entry.swap_remove();
75 *self.sites[to.index()].entry(loc).or_default() += count;
76 }
77
78 pub fn use_locs(
81 &self,
82 var: VariableId,
83 ) -> impl ExactSizeIterator<Item = (UseLocation, usize)> + '_ {
84 self.sites[var.index()].iter().map(|(loc, count)| (*loc, *count))
85 }
86}
87
88impl std::fmt::Debug for UseSites {
89 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
90 let mut list = f.debug_list();
91 for (idx, sites) in self.sites.iter().enumerate() {
92 let locs: Vec<_> = sites.iter().collect();
93 list.entry(&format_args!("v{idx}: {locs:?}"));
94 }
95 list.finish()
96 }
97}