calyx_opt/passes/
infer_share.rs1use crate::analysis::{DominatorMap, ShareSet};
2use crate::traversal::{
3 Action, ConstructVisitor, Named, Order, ParseVal, PassOpt, VisResult,
4 Visitor,
5};
6use calyx_ir as ir;
7use calyx_utils::{CalyxResult, OutputFile};
8
9pub struct InferShare {
15 print_dmap: Option<OutputFile>,
16 print_static_analysis: Option<OutputFile>,
17 state_shareable: ShareSet,
18 shareable: ShareSet,
19 main: ir::Id,
21}
22
23impl Named for InferShare {
24 fn name() -> &'static str {
25 "infer-share"
26 }
27
28 fn description() -> &'static str {
29 "Infer User Defined Components as Shareable"
30 }
31
32 fn opts() -> Vec<PassOpt> {
33 vec![
34 PassOpt::new(
35 "print-dmap",
36 "Print the domination map",
37 ParseVal::OutStream(OutputFile::Null),
38 PassOpt::parse_outstream,
39 ),
40 PassOpt::new(
41 "print-static-analysis",
42 "Prints the domination analysis for static dmaps",
43 ParseVal::OutStream(OutputFile::Null),
44 PassOpt::parse_outstream,
45 ),
46 ]
47 }
48}
49
50impl ConstructVisitor for InferShare {
51 fn from(ctx: &ir::Context) -> CalyxResult<Self>
52 where
53 Self: Sized + Named,
54 {
55 let opts = Self::get_opts(ctx);
56
57 let state_shareable = ShareSet::from_context::<true>(ctx);
58 let shareable = ShareSet::from_context::<false>(ctx);
59
60 Ok(InferShare {
61 print_dmap: opts[&"print-dmap"].not_null_outstream(),
62 print_static_analysis: opts[&"print-static-analysis"]
63 .not_null_outstream(),
64 state_shareable,
65 shareable,
66 main: ctx.entrypoint,
67 })
68 }
69
70 fn clear_data(&mut self) {}
71}
72
73impl Visitor for InferShare {
74 fn iteration_order() -> Order {
75 Order::Post
76 }
77 fn start(
78 &mut self,
79 comp: &mut ir::Component,
80 _sigs: &ir::LibrarySignatures,
81 _comps: &[ir::Component],
82 ) -> VisResult {
83 if comp.name == self.main {
85 return Ok(Action::Stop);
86 }
87
88 let const_or_this = |cell: &ir::RRC<ir::Cell>| -> bool {
90 matches!(
91 cell.borrow().prototype,
92 ir::CellType::ThisComponent | ir::CellType::Constant { .. }
93 )
94 };
95
96 let type_is_shareable = |cell: &ir::RRC<ir::Cell>| -> bool {
98 const_or_this(cell)
99 || self.shareable.is_shareable_component(cell)
100 || self.state_shareable.is_shareable_component(cell)
101 };
102
103 if comp.cells.iter().any(|cell| {
106 !type_is_shareable(cell) && !cell.borrow().is_reference()
107 }) {
108 return Ok(Action::Stop);
109 }
110
111 let mut dmap =
113 DominatorMap::new(&mut comp.control.borrow_mut(), comp.name);
114
115 if let Some(s) = &mut self.print_dmap {
117 write!(s.get_write(), "{dmap:?}").unwrap();
118 }
119 if let Some(s) = &mut self.print_static_analysis {
120 write!(s.get_write(), "{:?}", dmap.static_par_domination).unwrap();
121 }
122
123 for (node, dominators) in dmap.map.iter_mut() {
124 let reads =
126 DominatorMap::get_node_reads(node, comp, &self.state_shareable);
127
128 dominators.remove(node);
131 for cell_name in reads {
132 if !DominatorMap::key_written_guaranteed(
133 cell_name, dominators, comp,
134 ) {
135 return Ok(Action::Stop);
136 }
137 }
138 }
139 comp.attributes.insert(ir::BoolAttr::StateShare, 1);
140 self.state_shareable.add(comp.name);
141 Ok(Action::Stop)
142 }
143}