calyx_opt/passes_experimental/
par_to_seq.rs

1use crate::analysis;
2use crate::traversal::{
3    Action, ConstructVisitor, Named, ParseVal, PassOpt, VisResult, Visitor,
4};
5use calyx_ir::{self as ir, LibrarySignatures};
6use calyx_utils::CalyxResult;
7
8/// Transforms all `par` into `seq`. When the `correctness-checking` option is on,
9/// uses [analysis::ControlOrder] to get a sequentialization of `par` such that
10/// the program still computes the same value, and errors out when
11/// there is no such sequentialization.
12///
13/// # Example
14/// ```
15/// par {
16///     par { A; B }
17///     C;
18/// }
19/// ```
20/// into
21/// ```
22/// seq { seq { A; B } C; }
23/// ```
24///
25/// To remove uneccessarily nested `par` blocks, run collapse-control.
26pub struct ParToSeq {
27    /// Guarantees correctness on shared reads and writes by erroring out
28    /// if sequentialization where program still computes the same value doesn't exist.
29    correctness_checking: bool,
30}
31
32impl Named for ParToSeq {
33    fn name() -> &'static str {
34        "par-to-seq"
35    }
36
37    fn description() -> &'static str {
38        "Transform `par` blocks to `seq`"
39    }
40
41    fn opts() -> Vec<crate::traversal::PassOpt> {
42        vec![PassOpt::new(
43            "correctness-checking",
44            "Errors out when dataflow dependencies cannot be preserved.",
45            ParseVal::Bool(false),
46            PassOpt::parse_bool,
47        )]
48    }
49}
50
51impl ConstructVisitor for ParToSeq {
52    fn from(ctx: &ir::Context) -> CalyxResult<Self>
53    where
54        Self: Sized + Named,
55    {
56        let opts = Self::get_opts(ctx);
57
58        Ok(ParToSeq {
59            correctness_checking: opts[&"correctness-checking"].bool(),
60        })
61    }
62
63    fn clear_data(&mut self) {
64        /* All data can be transferred between components */
65    }
66}
67
68impl Visitor for ParToSeq {
69    /// Collapse par { par { A }; B } into par { A; B }.
70    fn finish_par(
71        &mut self,
72        s: &mut ir::Par,
73        _comp: &mut ir::Component,
74        _c: &LibrarySignatures,
75        _comps: &[ir::Component],
76    ) -> VisResult {
77        let par = if self.correctness_checking {
78            let total_order = analysis::ControlOrder::<true>::get_total_order(
79                s.stmts.drain(..),
80            )?;
81            ir::Control::seq(total_order)
82        } else {
83            ir::Control::seq(s.stmts.drain(..).collect())
84        };
85        Ok(Action::change(par))
86    }
87}