From 5722c43e988d7edb382ec86a15f004ab4a7aa663 Mon Sep 17 00:00:00 2001 From: Ayaka Yorihiro Date: Tue, 18 Nov 2025 17:15:50 -0500 Subject: [PATCH 01/13] First-pass impl of new experimental pass for simplifying ifs --- calyx/opt/src/default_passes.rs | 3 +- calyx/opt/src/passes_experimental/mod.rs | 2 + .../passes_experimental/simplify_if_comb.rs | 147 ++++++++++++++++++ 3 files changed, 151 insertions(+), 1 deletion(-) create mode 100644 calyx/opt/src/passes_experimental/simplify_if_comb.rs diff --git a/calyx/opt/src/default_passes.rs b/calyx/opt/src/default_passes.rs index c7470e22d5..2554511acd 100644 --- a/calyx/opt/src/default_passes.rs +++ b/calyx/opt/src/default_passes.rs @@ -15,7 +15,7 @@ use crate::passes::{ use crate::passes_experimental::{ CompileSync, CompileSyncWithoutSyncReg, DiscoverExternal, ExternalToRef, FSMAnnotator, FSMBuilder, HoleInliner, Metadata, ParToSeq, - RegisterUnsharing, + RegisterUnsharing, SimplifyIfComb, }; use crate::traversal::Named; use crate::{pass_manager::PassManager, register_alias}; @@ -86,6 +86,7 @@ impl PassManager { pm.register_pass::()?; pm.register_pass::()?; pm.register_pass::()?; + pm.register_pass::()?; // instrumentation pass to collect profiling information pm.register_pass::()?; diff --git a/calyx/opt/src/passes_experimental/mod.rs b/calyx/opt/src/passes_experimental/mod.rs index a37e59f073..f198d34d6b 100644 --- a/calyx/opt/src/passes_experimental/mod.rs +++ b/calyx/opt/src/passes_experimental/mod.rs @@ -6,6 +6,7 @@ mod hole_inliner; mod metadata_table_gen; mod par_to_seq; mod register_unsharing; +mod simplify_if_comb; mod sync; pub use discover_external::DiscoverExternal; @@ -16,5 +17,6 @@ pub use hole_inliner::HoleInliner; pub use metadata_table_gen::Metadata; pub use par_to_seq::ParToSeq; pub use register_unsharing::RegisterUnsharing; +pub use simplify_if_comb::SimplifyIfComb; pub use sync::CompileSync; pub use sync::CompileSyncWithoutSyncReg; diff --git a/calyx/opt/src/passes_experimental/simplify_if_comb.rs b/calyx/opt/src/passes_experimental/simplify_if_comb.rs new file mode 100644 index 0000000000..c1ccc74e68 --- /dev/null +++ b/calyx/opt/src/passes_experimental/simplify_if_comb.rs @@ -0,0 +1,147 @@ +use crate::traversal::{ + Action, ConstructVisitor, Named, ParseVal, PassOpt, VisResult, Visitor, +}; +use calyx_ir::{self as ir, LibrarySignatures}; +use calyx_utils::CalyxResult; + +/// Transforms all `par` into `seq`. When the `correctness-checking` option is on, +/// uses [analysis::ControlOrder] to get a sequentialization of `par` such that +/// the program still computes the same value, and errors out when +/// there is no such sequentialization. +/// +/// # Example +/// ``` +/// par { +/// par { A; B } +/// C; +/// } +/// ``` +/// into +/// ``` +/// seq { seq { A; B } C; } +/// ``` +/// +/// To remove uneccessarily nested `par` blocks, run collapse-control. + +/// Transforms `if`s with `comb` groups where the `then` block of the `if` consists +/// of a single enable into `if`s with the condition being computed via continuous +/// assignments. (Probably should check if any cells being used in the cond group +/// are used anywhere else) +/// +/// # Example +/// ``` +/// comb cond_comb { +/// lt.left = x.out; +/// lt.right = 32'd10; +/// } +/// ... +/// if lt.out with cond_comb { +/// then_group; +/// } +/// ``` +/// into +/// +/// ``` +/// // continuous assignments +/// lt.left = x.out; +/// lt.right = 32'd10; +/// ... +/// if lt.out { +/// then_group; +/// } +/// ``` +pub struct SimplifyIfComb {} + +impl Named for SimplifyIfComb { + fn name() -> &'static str { + "simplify-if-comb" + } + + fn description() -> &'static str { + "Transform `if` with comb groups into `if` with continuous assignments when there is only one enable in the `then` block and there is no `else` block." + } + + fn opts() -> Vec { + // vec![PassOpt::new( + // "correctness-checking", + // "Errors out when dataflow dependencies cannot be preserved.", + // ParseVal::Bool(false), + // PassOpt::parse_bool, + // )] + vec![] + } +} + +impl ConstructVisitor for SimplifyIfComb { + fn from(ctx: &ir::Context) -> CalyxResult + where + Self: Sized + Named, + { + // let opts = Self::get_opts(ctx); + + Ok(SimplifyIfComb { + // correctness_checking: opts[&"correctness-checking"].bool(), + }) + } + + fn clear_data(&mut self) { + /* All data can be transferred between components */ + } +} + +impl Visitor for SimplifyIfComb { + fn finish_if( + &mut self, + s: &mut calyx_ir::If, + comp: &mut calyx_ir::Component, + _sigs: &LibrarySignatures, + _comps: &[calyx_ir::Component], + ) -> VisResult { + // let mut builder = ir::Builder::new(comp, sigs); + match s.tbranch.as_ref() { + calyx_ir::Control::Enable(enable) => { + if let Some(cond_group_ref) = &s.cond + && s.fbranch.is_empty() + { + // move all assignments in cond group to continuous + for cond_group_asgn in &cond_group_ref.borrow().assignments + { + comp.continuous_assignments + .push(cond_group_asgn.clone()); + } + // create new enable + let new_tbranch = + calyx_ir::Control::enable(enable.group.clone()); + let new_if = calyx_ir::Control::if_( + s.port.clone(), + None, + Box::new(new_tbranch), + Box::new(calyx_ir::Control::empty()), + ); + Ok(Action::change(new_if)) + } else { + Ok(Action::Continue) + } + } + _ => Ok(Action::Continue), + } + + // only transform if the true branch consists of a single enable, the false branch is empty, and there is a cond group + // if let calyx_ir::Control::Enable(_) = *s.tbranch + // && let Some(cond_group_ref) = &s.cond + // && s.fbranch.is_empty() + // // there technically needs to be another check here for whether the cells used in the cond group are used in any other group + // { + // // create a new version of the if + // let new_if_group = calyx_ir::Control::if_( + // s.port.clone(), + // None, + // Box::new(*(s.tbranch.as_ref())), + // s.fbranch, + // ); + // Ok(Action::Continue) + // } else { + // Ok(Action::Continue) + // } + } +} From 39a2e17e53b5f22d3b6a6e697e37860f4879ab70 Mon Sep 17 00:00:00 2001 From: Ayaka Yorihiro Date: Wed, 19 Nov 2025 10:23:29 -0500 Subject: [PATCH 02/13] Creating clone of primitive cell used in comb group --- .../passes_experimental/simplify_if_comb.rs | 128 ++++++++++++++++-- 1 file changed, 120 insertions(+), 8 deletions(-) diff --git a/calyx/opt/src/passes_experimental/simplify_if_comb.rs b/calyx/opt/src/passes_experimental/simplify_if_comb.rs index c1ccc74e68..fe16c30fa2 100644 --- a/calyx/opt/src/passes_experimental/simplify_if_comb.rs +++ b/calyx/opt/src/passes_experimental/simplify_if_comb.rs @@ -1,8 +1,13 @@ -use crate::traversal::{ - Action, ConstructVisitor, Named, ParseVal, PassOpt, VisResult, Visitor, +use core::borrow; +use std::collections::{HashMap, HashSet}; + +use crate::traversal::{Action, ConstructVisitor, Named, VisResult, Visitor}; +use calyx_ir::{ + self as ir, GetAttributes, Id, LibrarySignatures, Primitive, RRC, Rewriter, + rewriter::{self, RewriteMap}, }; -use calyx_ir::{self as ir, LibrarySignatures}; use calyx_utils::CalyxResult; +use itertools::Itertools; /// Transforms all `par` into `seq`. When the `correctness-checking` option is on, /// uses [analysis::ControlOrder] to get a sequentialization of `par` such that @@ -89,15 +94,87 @@ impl ConstructVisitor for SimplifyIfComb { } } +// fn create_new_cell(builder: &mut ir::Builder, cell_ref: &RRC) { +// let cell = cell_ref.borrow(); +// match &cell.prototype { +// calyx_ir::CellType::Primitive { +// name, +// param_binding, +// is_comb, +// latency, +// } => todo!(), +// calyx_ir::CellType::Component { name } => todo!(), +// calyx_ir::CellType::ThisComponent => todo!(), +// calyx_ir::CellType::Constant { val, width } => todo!(), +// } +// } + impl Visitor for SimplifyIfComb { + // fn start( + // &mut self, + // comp: &mut calyx_ir::Component, + // _sigs: &LibrarySignatures, + // _comps: &[calyx_ir::Component], + // ) -> VisResult { + // // for each cell used in a comb_group, track if it's used anywhere else + // let mut comb_group_cell_map: HashMap> = + // HashMap::new(); + // for comb_group_ref in comp.comb_groups.iter() { + // let comb_group = comb_group_ref.borrow(); + // let comb_group_name = comb_group.name(); + // let mut cells_this_comb_group = HashSet::new(); + // // collect cells that are used in this comb group + // for comb_group_asgn in &comb_group.assignments { + // if let calyx_ir::PortParent::Cell(c) = + // &comb_group_asgn.dst.borrow().parent + // { + // let cell_ref = c.upgrade(); + // let cell_name = cell_ref.borrow().name(); + // cells_this_comb_group.insert(cell_name); + // } + // } + // for cell in cells_this_comb_group { + // match comb_group_cell_map.get_mut(&cell) { + // Some(v) => { + // v.push(comb_group_name); + // } + // None => { + // let mut v = Vec::new(); + // v.push(comb_group_name); + // comb_group_cell_map.insert(cell, v); + // } + // } + // } + // } + // // filter out any cells that were used in two comb groups + // comb_group_cell_map.retain(|_, v| v.len() == 1); + // // go through normal groups; remove any cells that were used in a normal group + // for group_ref in comp.groups.iter() { + // let group = group_ref.borrow(); + // for group_asgn in &group.assignments { + // if let calyx_ir::PortParent::Cell(c) = + // &group_asgn.dst.borrow().parent + // { + // let cell_ref = c.upgrade(); + // let cell_name = cell_ref.borrow().name(); + // if comb_group_cell_map.contains_key(&cell_name) { + // comb_group_cell_map.remove(&cell_name); + // } + // } + // } + // } + // Ok(Action::Continue) + // } + fn finish_if( &mut self, s: &mut calyx_ir::If, comp: &mut calyx_ir::Component, - _sigs: &LibrarySignatures, + sigs: &LibrarySignatures, _comps: &[calyx_ir::Component], ) -> VisResult { - // let mut builder = ir::Builder::new(comp, sigs); + let mut builder = ir::Builder::new(comp, sigs); + let mut rewrite_map = RewriteMap::new(); match s.tbranch.as_ref() { calyx_ir::Control::Enable(enable) => { if let Some(cond_group_ref) = &s.cond @@ -106,18 +183,53 @@ impl Visitor for SimplifyIfComb { // move all assignments in cond group to continuous for cond_group_asgn in &cond_group_ref.borrow().assignments { - comp.continuous_assignments - .push(cond_group_asgn.clone()); + if let calyx_ir::PortParent::Cell(c) = + &cond_group_asgn.dst.borrow().parent + { + let c_ref = c.upgrade(); + let c_name = c_ref.borrow().name(); + // let new_c_name = comp.generate_name(c_name); + + if let ir::CellType::Primitive { + name, + param_binding, + .. + } = &c_ref.borrow().prototype + { + let new_cell = builder.add_primitive( + c_name, + name.clone(), + ¶m_binding + .iter() + .map(|(_, v)| *v) + .collect_vec(), + ); + rewrite_map.insert(c_name, new_cell); + } + // create copy of cell? + } + } + let rewrite = Rewriter { + cell_map: rewrite_map, + ..Default::default() + }; + for cond_group_asgn in + &cond_group_ref.borrow_mut().assignments + { + let mut new_asgn = cond_group_asgn.clone(); + rewrite.rewrite_assign(&mut new_asgn); + comp.continuous_assignments.push(new_asgn); } // create new enable let new_tbranch = calyx_ir::Control::enable(enable.group.clone()); - let new_if = calyx_ir::Control::if_( + let mut new_if = calyx_ir::Control::if_( s.port.clone(), None, Box::new(new_tbranch), Box::new(calyx_ir::Control::empty()), ); + rewrite.rewrite_control(&mut new_if); Ok(Action::change(new_if)) } else { Ok(Action::Continue) From b1c3ef74707719b129d3309b0911823cd2377fe6 Mon Sep 17 00:00:00 2001 From: Ayaka Yorihiro Date: Wed, 19 Nov 2025 17:00:00 -0500 Subject: [PATCH 03/13] Tests and quick debugging --- .../passes_experimental/simplify_if_comb.rs | 11 ++--- .../simplify-if-comb/mult-cell-use.futil | 43 +++++++++++++++++++ tests/passes/simplify-if-comb/simple.futil | 28 ++++++++++++ 3 files changed, 77 insertions(+), 5 deletions(-) create mode 100644 tests/passes/simplify-if-comb/mult-cell-use.futil create mode 100644 tests/passes/simplify-if-comb/simple.futil diff --git a/calyx/opt/src/passes_experimental/simplify_if_comb.rs b/calyx/opt/src/passes_experimental/simplify_if_comb.rs index fe16c30fa2..e59ff879ba 100644 --- a/calyx/opt/src/passes_experimental/simplify_if_comb.rs +++ b/calyx/opt/src/passes_experimental/simplify_if_comb.rs @@ -190,11 +190,12 @@ impl Visitor for SimplifyIfComb { let c_name = c_ref.borrow().name(); // let new_c_name = comp.generate_name(c_name); - if let ir::CellType::Primitive { - name, - param_binding, - .. - } = &c_ref.borrow().prototype + if !rewrite_map.contains_key(&c_name) + && let ir::CellType::Primitive { + name, + param_binding, + .. + } = &c_ref.borrow().prototype { let new_cell = builder.add_primitive( c_name, diff --git a/tests/passes/simplify-if-comb/mult-cell-use.futil b/tests/passes/simplify-if-comb/mult-cell-use.futil new file mode 100644 index 0000000000..878e185050 --- /dev/null +++ b/tests/passes/simplify-if-comb/mult-cell-use.futil @@ -0,0 +1,43 @@ +// -p simplify-if-comb + +import "primitives/core.futil"; +import "primitives/memories/comb.futil"; + +component main(@go go: 1) -> (@done done: 1) { + cells { + @external(1) mem = comb_mem_d1(32, 1, 1); + lt = std_lt(32); + } + wires { + group the_answer { + mem.addr0 = 1'b0; + mem.write_data = 32'd42; + mem.write_en = 1'b1; + the_answer[done] = mem.done; + } + group the_answer_2 { + mem.addr0 = 1'b0; + mem.write_data = 32'd100; + mem.write_en = 1'b1; + the_answer_2[done] = mem.done; + } + comb group cond { + lt.left = 32'd1; + lt.right = 32'd8; + } + comb group cond2 { + lt.left = 32'd1; + lt.right = 32'd100; + } + } + control { + seq { + if lt.out with cond { + the_answer; + } + if lt.out with cond2 { + the_answer_2; + } + } + } +} diff --git a/tests/passes/simplify-if-comb/simple.futil b/tests/passes/simplify-if-comb/simple.futil new file mode 100644 index 0000000000..5b907e12bc --- /dev/null +++ b/tests/passes/simplify-if-comb/simple.futil @@ -0,0 +1,28 @@ +// -p simplify-if-comb + +import "primitives/core.futil"; +import "primitives/memories/comb.futil"; + +component main(@go go: 1) -> (@done done: 1) { + cells { + @external(1) mem = comb_mem_d1(32, 1, 1); + lt = std_lt(32); + } + wires { + group the_answer { + mem.addr0 = 1'b0; + mem.write_data = 32'd42; + mem.write_en = 1'b1; + the_answer[done] = mem.done; + } + comb group cond { + lt.left = 32'd1; + lt.right = 32'd8; + } + } + control { + if lt.out with cond { + the_answer; + } + } +} From 2798c6eb9f4395e0ce6e4999db85d7c682d2a93a Mon Sep 17 00:00:00 2001 From: Ayaka Yorihiro Date: Wed, 19 Nov 2025 22:49:50 -0500 Subject: [PATCH 04/13] Fix formatting and add tests --- .../passes_experimental/simplify_if_comb.rs | 153 ++---------------- .../simplify-if-comb/mult-cell-use.expect | 46 ++++++ tests/passes/simplify-if-comb/simple.expect | 28 ++++ 3 files changed, 88 insertions(+), 139 deletions(-) create mode 100644 tests/passes/simplify-if-comb/mult-cell-use.expect create mode 100644 tests/passes/simplify-if-comb/simple.expect diff --git a/calyx/opt/src/passes_experimental/simplify_if_comb.rs b/calyx/opt/src/passes_experimental/simplify_if_comb.rs index e59ff879ba..592ff4697a 100644 --- a/calyx/opt/src/passes_experimental/simplify_if_comb.rs +++ b/calyx/opt/src/passes_experimental/simplify_if_comb.rs @@ -1,37 +1,15 @@ -use core::borrow; -use std::collections::{HashMap, HashSet}; - use crate::traversal::{Action, ConstructVisitor, Named, VisResult, Visitor}; -use calyx_ir::{ - self as ir, GetAttributes, Id, LibrarySignatures, Primitive, RRC, Rewriter, - rewriter::{self, RewriteMap}, -}; +use calyx_ir::{self as ir, LibrarySignatures, Rewriter, rewriter::RewriteMap}; use calyx_utils::CalyxResult; use itertools::Itertools; -/// Transforms all `par` into `seq`. When the `correctness-checking` option is on, -/// uses [analysis::ControlOrder] to get a sequentialization of `par` such that -/// the program still computes the same value, and errors out when -/// there is no such sequentialization. -/// -/// # Example -/// ``` -/// par { -/// par { A; B } -/// C; -/// } -/// ``` -/// into -/// ``` -/// seq { seq { A; B } C; } -/// ``` -/// -/// To remove uneccessarily nested `par` blocks, run collapse-control. - /// Transforms `if`s with `comb` groups where the `then` block of the `if` consists /// of a single enable into `if`s with the condition being computed via continuous -/// assignments. (Probably should check if any cells being used in the cond group -/// are used anywhere else) +/// assignments. +/// +/// The cell used for the condition (and any other cells on the LHS of an assignment +/// in the comb group) will be cloned. Therefore, it is important that dead-cell-removal +/// and dead-group-removal is ran after this pass. /// /// # Example /// ``` @@ -48,10 +26,10 @@ use itertools::Itertools; /// /// ``` /// // continuous assignments -/// lt.left = x.out; -/// lt.right = 32'd10; +/// lt0.left = x.out; +/// lt0.right = 32'd10; /// ... -/// if lt.out { +/// if lt0.out { /// then_group; /// } /// ``` @@ -67,105 +45,22 @@ impl Named for SimplifyIfComb { } fn opts() -> Vec { - // vec![PassOpt::new( - // "correctness-checking", - // "Errors out when dataflow dependencies cannot be preserved.", - // ParseVal::Bool(false), - // PassOpt::parse_bool, - // )] vec![] } } impl ConstructVisitor for SimplifyIfComb { - fn from(ctx: &ir::Context) -> CalyxResult + fn from(_ctx: &ir::Context) -> CalyxResult where Self: Sized + Named, { - // let opts = Self::get_opts(ctx); - - Ok(SimplifyIfComb { - // correctness_checking: opts[&"correctness-checking"].bool(), - }) + Ok(SimplifyIfComb {}) } - fn clear_data(&mut self) { - /* All data can be transferred between components */ - } + fn clear_data(&mut self) {} } -// fn create_new_cell(builder: &mut ir::Builder, cell_ref: &RRC) { -// let cell = cell_ref.borrow(); -// match &cell.prototype { -// calyx_ir::CellType::Primitive { -// name, -// param_binding, -// is_comb, -// latency, -// } => todo!(), -// calyx_ir::CellType::Component { name } => todo!(), -// calyx_ir::CellType::ThisComponent => todo!(), -// calyx_ir::CellType::Constant { val, width } => todo!(), -// } -// } - impl Visitor for SimplifyIfComb { - // fn start( - // &mut self, - // comp: &mut calyx_ir::Component, - // _sigs: &LibrarySignatures, - // _comps: &[calyx_ir::Component], - // ) -> VisResult { - // // for each cell used in a comb_group, track if it's used anywhere else - // let mut comb_group_cell_map: HashMap> = - // HashMap::new(); - // for comb_group_ref in comp.comb_groups.iter() { - // let comb_group = comb_group_ref.borrow(); - // let comb_group_name = comb_group.name(); - // let mut cells_this_comb_group = HashSet::new(); - // // collect cells that are used in this comb group - // for comb_group_asgn in &comb_group.assignments { - // if let calyx_ir::PortParent::Cell(c) = - // &comb_group_asgn.dst.borrow().parent - // { - // let cell_ref = c.upgrade(); - // let cell_name = cell_ref.borrow().name(); - // cells_this_comb_group.insert(cell_name); - // } - // } - // for cell in cells_this_comb_group { - // match comb_group_cell_map.get_mut(&cell) { - // Some(v) => { - // v.push(comb_group_name); - // } - // None => { - // let mut v = Vec::new(); - // v.push(comb_group_name); - // comb_group_cell_map.insert(cell, v); - // } - // } - // } - // } - // // filter out any cells that were used in two comb groups - // comb_group_cell_map.retain(|_, v| v.len() == 1); - // // go through normal groups; remove any cells that were used in a normal group - // for group_ref in comp.groups.iter() { - // let group = group_ref.borrow(); - // for group_asgn in &group.assignments { - // if let calyx_ir::PortParent::Cell(c) = - // &group_asgn.dst.borrow().parent - // { - // let cell_ref = c.upgrade(); - // let cell_name = cell_ref.borrow().name(); - // if comb_group_cell_map.contains_key(&cell_name) { - // comb_group_cell_map.remove(&cell_name); - // } - // } - // } - // } - // Ok(Action::Continue) - // } - fn finish_if( &mut self, s: &mut calyx_ir::If, @@ -188,7 +83,6 @@ impl Visitor for SimplifyIfComb { { let c_ref = c.upgrade(); let c_name = c_ref.borrow().name(); - // let new_c_name = comp.generate_name(c_name); if !rewrite_map.contains_key(&c_name) && let ir::CellType::Primitive { @@ -199,7 +93,7 @@ impl Visitor for SimplifyIfComb { { let new_cell = builder.add_primitive( c_name, - name.clone(), + *name, ¶m_binding .iter() .map(|(_, v)| *v) @@ -207,7 +101,6 @@ impl Visitor for SimplifyIfComb { ); rewrite_map.insert(c_name, new_cell); } - // create copy of cell? } } let rewrite = Rewriter { @@ -221,7 +114,7 @@ impl Visitor for SimplifyIfComb { rewrite.rewrite_assign(&mut new_asgn); comp.continuous_assignments.push(new_asgn); } - // create new enable + // create new enable for the true branch let new_tbranch = calyx_ir::Control::enable(enable.group.clone()); let mut new_if = calyx_ir::Control::if_( @@ -238,23 +131,5 @@ impl Visitor for SimplifyIfComb { } _ => Ok(Action::Continue), } - - // only transform if the true branch consists of a single enable, the false branch is empty, and there is a cond group - // if let calyx_ir::Control::Enable(_) = *s.tbranch - // && let Some(cond_group_ref) = &s.cond - // && s.fbranch.is_empty() - // // there technically needs to be another check here for whether the cells used in the cond group are used in any other group - // { - // // create a new version of the if - // let new_if_group = calyx_ir::Control::if_( - // s.port.clone(), - // None, - // Box::new(*(s.tbranch.as_ref())), - // s.fbranch, - // ); - // Ok(Action::Continue) - // } else { - // Ok(Action::Continue) - // } } } diff --git a/tests/passes/simplify-if-comb/mult-cell-use.expect b/tests/passes/simplify-if-comb/mult-cell-use.expect new file mode 100644 index 0000000000..41e4de3204 --- /dev/null +++ b/tests/passes/simplify-if-comb/mult-cell-use.expect @@ -0,0 +1,46 @@ +import "primitives/core.futil"; +import "primitives/memories/comb.futil"; +component main(@go go: 1, @clk clk: 1, @reset reset: 1) -> (@done done: 1) { + cells { + @external mem = comb_mem_d1(32, 1, 1); + lt = std_lt(32); + @generated lt0 = std_lt(32); + @generated lt1 = std_lt(32); + } + wires { + group the_answer { + mem.addr0 = 1'd0; + mem.write_data = 32'd42; + mem.write_en = 1'd1; + the_answer[done] = mem.done; + } + group the_answer_2 { + mem.addr0 = 1'd0; + mem.write_data = 32'd100; + mem.write_en = 1'd1; + the_answer_2[done] = mem.done; + } + comb group cond { + lt.left = 32'd1; + lt.right = 32'd8; + } + comb group cond2 { + lt.left = 32'd1; + lt.right = 32'd100; + } + lt0.left = 32'd1; + lt0.right = 32'd8; + lt1.left = 32'd1; + lt1.right = 32'd100; + } + control { + seq { + if lt0.out { + the_answer; + } + if lt1.out { + the_answer_2; + } + } + } +} diff --git a/tests/passes/simplify-if-comb/simple.expect b/tests/passes/simplify-if-comb/simple.expect new file mode 100644 index 0000000000..11be6b6a76 --- /dev/null +++ b/tests/passes/simplify-if-comb/simple.expect @@ -0,0 +1,28 @@ +import "primitives/core.futil"; +import "primitives/memories/comb.futil"; +component main(@go go: 1, @clk clk: 1, @reset reset: 1) -> (@done done: 1) { + cells { + @external mem = comb_mem_d1(32, 1, 1); + lt = std_lt(32); + @generated lt0 = std_lt(32); + } + wires { + group the_answer { + mem.addr0 = 1'd0; + mem.write_data = 32'd42; + mem.write_en = 1'd1; + the_answer[done] = mem.done; + } + comb group cond { + lt.left = 32'd1; + lt.right = 32'd8; + } + lt0.left = 32'd1; + lt0.right = 32'd8; + } + control { + if lt0.out { + the_answer; + } + } +} From 70075e58628c11652f7e51f0c9f894f0096603d7 Mon Sep 17 00:00:00 2001 From: Ayaka Yorihiro Date: Wed, 19 Nov 2025 23:55:57 -0500 Subject: [PATCH 05/13] allow optimization for <= 1 enable else block --- .../passes_experimental/simplify_if_comb.rs | 117 ++++++++++-------- 1 file changed, 63 insertions(+), 54 deletions(-) diff --git a/calyx/opt/src/passes_experimental/simplify_if_comb.rs b/calyx/opt/src/passes_experimental/simplify_if_comb.rs index 592ff4697a..8c5cbf9556 100644 --- a/calyx/opt/src/passes_experimental/simplify_if_comb.rs +++ b/calyx/opt/src/passes_experimental/simplify_if_comb.rs @@ -60,6 +60,16 @@ impl ConstructVisitor for SimplifyIfComb { fn clear_data(&mut self) {} } +/// Checks if a block (then/else branch of an if) satsifies the heuristics +/// for when it is safe to transform an if. +/// Currently this is just when the block is either empty or a single enable. +fn eligible_block(branch: &ir::Control) -> bool { + matches!( + branch, + calyx_ir::Control::Enable(_) | calyx_ir::Control::Empty(_) + ) +} + impl Visitor for SimplifyIfComb { fn finish_if( &mut self, @@ -70,66 +80,65 @@ impl Visitor for SimplifyIfComb { ) -> VisResult { let mut builder = ir::Builder::new(comp, sigs); let mut rewrite_map = RewriteMap::new(); - match s.tbranch.as_ref() { - calyx_ir::Control::Enable(enable) => { - if let Some(cond_group_ref) = &s.cond - && s.fbranch.is_empty() + if let calyx_ir::Control::Enable(enable) = s.tbranch.as_ref() + && let Some(cond_group_ref) = &s.cond + && eligible_block(&s.fbranch) + { + // move all assignments in cond group to continuous + for cond_group_asgn in &cond_group_ref.borrow().assignments { + if let calyx_ir::PortParent::Cell(c) = + &cond_group_asgn.dst.borrow().parent { - // move all assignments in cond group to continuous - for cond_group_asgn in &cond_group_ref.borrow().assignments - { - if let calyx_ir::PortParent::Cell(c) = - &cond_group_asgn.dst.borrow().parent - { - let c_ref = c.upgrade(); - let c_name = c_ref.borrow().name(); + let c_ref = c.upgrade(); + let c_name = c_ref.borrow().name(); - if !rewrite_map.contains_key(&c_name) - && let ir::CellType::Primitive { - name, - param_binding, - .. - } = &c_ref.borrow().prototype - { - let new_cell = builder.add_primitive( - c_name, - *name, - ¶m_binding - .iter() - .map(|(_, v)| *v) - .collect_vec(), - ); - rewrite_map.insert(c_name, new_cell); - } - } - } - let rewrite = Rewriter { - cell_map: rewrite_map, - ..Default::default() - }; - for cond_group_asgn in - &cond_group_ref.borrow_mut().assignments + if !rewrite_map.contains_key(&c_name) + && let ir::CellType::Primitive { + name, + param_binding, + .. + } = &c_ref.borrow().prototype { - let mut new_asgn = cond_group_asgn.clone(); - rewrite.rewrite_assign(&mut new_asgn); - comp.continuous_assignments.push(new_asgn); + let new_cell = builder.add_primitive( + c_name, + *name, + ¶m_binding + .iter() + .map(|(_, v)| *v) + .collect_vec(), + ); + rewrite_map.insert(c_name, new_cell); } - // create new enable for the true branch - let new_tbranch = - calyx_ir::Control::enable(enable.group.clone()); - let mut new_if = calyx_ir::Control::if_( - s.port.clone(), - None, - Box::new(new_tbranch), - Box::new(calyx_ir::Control::empty()), - ); - rewrite.rewrite_control(&mut new_if); - Ok(Action::change(new_if)) - } else { - Ok(Action::Continue) } } - _ => Ok(Action::Continue), + let rewrite = Rewriter { + cell_map: rewrite_map, + ..Default::default() + }; + for cond_group_asgn in &cond_group_ref.borrow_mut().assignments { + let mut new_asgn = cond_group_asgn.clone(); + rewrite.rewrite_assign(&mut new_asgn); + comp.continuous_assignments.push(new_asgn); + } + // create new enable for the true branch + let new_tbranch = calyx_ir::Control::enable(enable.group.clone()); + // rewrite false branch if necessary + let new_fbranch = + if let ir::Control::Enable(f_enable) = s.fbranch.as_ref() { + ir::Control::enable(f_enable.group.clone()) + } else { + ir::Control::empty() + }; + let mut new_if = calyx_ir::Control::if_( + s.port.clone(), + None, + Box::new(new_tbranch), + Box::new(new_fbranch), + ); + rewrite.rewrite_control(&mut new_if); + Ok(Action::change(new_if)) + } else { + Ok(Action::Continue) } } } From b3587cfa0d643b5c4609d8dd89b0cabd9b4a4c7e Mon Sep 17 00:00:00 2001 From: Ayaka Yorihiro Date: Thu, 27 Nov 2025 21:16:39 -0500 Subject: [PATCH 06/13] Make pass available to any if with comb --- .../passes_experimental/simplify_if_comb.rs | 37 ++++++------------- 1 file changed, 11 insertions(+), 26 deletions(-) diff --git a/calyx/opt/src/passes_experimental/simplify_if_comb.rs b/calyx/opt/src/passes_experimental/simplify_if_comb.rs index 8c5cbf9556..1a38a625d0 100644 --- a/calyx/opt/src/passes_experimental/simplify_if_comb.rs +++ b/calyx/opt/src/passes_experimental/simplify_if_comb.rs @@ -3,9 +3,8 @@ use calyx_ir::{self as ir, LibrarySignatures, Rewriter, rewriter::RewriteMap}; use calyx_utils::CalyxResult; use itertools::Itertools; -/// Transforms `if`s with `comb` groups where the `then` block of the `if` consists -/// of a single enable into `if`s with the condition being computed via continuous -/// assignments. +/// Transforms `if`s with `comb` groups into `if`s with the condition being computed +/// via continuous assignments. /// /// The cell used for the condition (and any other cells on the LHS of an assignment /// in the comb group) will be cloned. Therefore, it is important that dead-cell-removal @@ -60,16 +59,6 @@ impl ConstructVisitor for SimplifyIfComb { fn clear_data(&mut self) {} } -/// Checks if a block (then/else branch of an if) satsifies the heuristics -/// for when it is safe to transform an if. -/// Currently this is just when the block is either empty or a single enable. -fn eligible_block(branch: &ir::Control) -> bool { - matches!( - branch, - calyx_ir::Control::Enable(_) | calyx_ir::Control::Empty(_) - ) -} - impl Visitor for SimplifyIfComb { fn finish_if( &mut self, @@ -80,10 +69,7 @@ impl Visitor for SimplifyIfComb { ) -> VisResult { let mut builder = ir::Builder::new(comp, sigs); let mut rewrite_map = RewriteMap::new(); - if let calyx_ir::Control::Enable(enable) = s.tbranch.as_ref() - && let Some(cond_group_ref) = &s.cond - && eligible_block(&s.fbranch) - { + if let Some(cond_group_ref) = &s.cond { // move all assignments in cond group to continuous for cond_group_asgn in &cond_group_ref.borrow().assignments { if let calyx_ir::PortParent::Cell(c) = @@ -121,19 +107,18 @@ impl Visitor for SimplifyIfComb { comp.continuous_assignments.push(new_asgn); } // create new enable for the true branch - let new_tbranch = calyx_ir::Control::enable(enable.group.clone()); // rewrite false branch if necessary - let new_fbranch = - if let ir::Control::Enable(f_enable) = s.fbranch.as_ref() { - ir::Control::enable(f_enable.group.clone()) - } else { - ir::Control::empty() - }; + // let new_fbranch = + // if let ir::Control::Enable(f_enable) = s.fbranch.as_ref() { + // ir::Control::enable(f_enable.group.clone()) + // } else { + // ir::Control::empty() + // }; let mut new_if = calyx_ir::Control::if_( s.port.clone(), None, - Box::new(new_tbranch), - Box::new(new_fbranch), + Box::new(s.tbranch.take_control()), + Box::new(s.fbranch.take_control()), ); rewrite.rewrite_control(&mut new_if); Ok(Action::change(new_if)) From b734410b792b45a9863a6ded95971892f68d66c3 Mon Sep 17 00:00:00 2001 From: Ayaka Yorihiro Date: Sun, 30 Nov 2025 01:31:08 -0500 Subject: [PATCH 07/13] upload script for comparing cycles --- .gitignore | 3 ++ tools/pass-cycle-check/pass-cycle-check.sh | 48 ++++++++++++++++++++++ tools/pass-cycle-check/queues-tests.txt | 14 +++++++ 3 files changed, 65 insertions(+) create mode 100644 tools/pass-cycle-check/pass-cycle-check.sh create mode 100644 tools/pass-cycle-check/queues-tests.txt diff --git a/.gitignore b/.gitignore index 084dffccaa..5d0fe79a55 100644 --- a/.gitignore +++ b/.gitignore @@ -71,6 +71,9 @@ tools/profiler/fg-tmp *.folded fud2-runs +# pass-cycle-check ignore +tools/pass-cycle-check/out* + temp/ # large queue .data and .expect files ignore diff --git a/tools/pass-cycle-check/pass-cycle-check.sh b/tools/pass-cycle-check/pass-cycle-check.sh new file mode 100644 index 0000000000..ab49a3bc3e --- /dev/null +++ b/tools/pass-cycle-check/pass-cycle-check.sh @@ -0,0 +1,48 @@ +# This script runs the queues programs unless if we wanted to use different benches + +if [ $# -lt 1 ]; then + echo "USAGE: bash $0 PASSES" + exit +fi + +PASSES=$1 + +SCRIPT_DIR=$( cd $( dirname $0 ) && pwd ) +SCRIPT_NAME=$( echo "$0" | rev | cut -d/ -f1 | rev ) +CALYX_DIR=$( dirname $( dirname ${SCRIPT_DIR} ) ) +OUT_DIR=${SCRIPT_DIR}/out +out=${OUT_DIR}/results.csv + +if [ -d ${OUT_DIR} ]; then + echo "****Moving old results" + mv ${OUT_DIR} ${OUT_DIR}-`date +%Y-%m-%d-%H-%M-%S` +fi +mkdir -p ${OUT_DIR} + +# rounding scheme +function round() { + echo $(printf %.$2f $(echo "scale=$2;(((10^$2)*$1)+0.5)/(10^$2)" | bc)) +}; + +( + cd ${CALYX_DIR} + echo "name,og,opt,diff,diff(%)" > ${out} + py_args="20000 --keepgoing" + for f in $( cat ${SCRIPT_DIR}/queues-tests.txt ); do + name=$( basename "${f}" | cut -d. -f1 ) + header=$( echo "${f}" | cut -d. -f1 ) + echo ====${name} + original=${OUT_DIR}/${name}-original.json + opt=${OUT_DIR}/${name}-opt.json + # run with -p all + fud2 ${f} -o ${original} --to dat --through verilator -s sim.data=${header}.data -s py.args="${py_args}" -q + # run with specified passes + fud2 ${f} -o ${opt} --to dat --through verilator -s sim.data=${header}.data -s calyx.args="${PASSES}" -s py.args="${py_args}" -q + # TODO: maybe have something that throws a warning message if more than just the cycles are different? + original_num=$( grep cycles ${original} | rev | cut -d, -f2 | cut -d' ' -f1 | rev ) + opt_num=$( grep cycles ${opt} | rev | cut -d, -f2 | cut -d' ' -f1 | rev ) + diff=$( echo "${original_num} - ${opt_num}" | bc -l ) + diff_percent=$( round $( echo "(${diff} / ${original_num}) * 100" | bc -l ) 2 ) + echo "${name},${original_num},${opt_num},${diff},${diff_percent}" >> ${out} + done +) diff --git a/tools/pass-cycle-check/queues-tests.txt b/tools/pass-cycle-check/queues-tests.txt new file mode 100644 index 0000000000..b09f138174 --- /dev/null +++ b/tools/pass-cycle-check/queues-tests.txt @@ -0,0 +1,14 @@ +frontends/queues/tests/strict/strict_6flow_test.py +frontends/queues/tests/strict/strict_order_test.py +frontends/queues/tests/strict/strict_5flow_test.py +frontends/queues/tests/strict/strict_4flow_test.py +frontends/queues/tests/strict/strict_2flow_test.py +frontends/queues/tests/strict/strict_7flow_test.py +frontends/queues/tests/strict/strict_3flow_test.py +frontends/queues/tests/round_robin/rr_3flow_test.py +frontends/queues/tests/round_robin/rr_4flow_test.py +frontends/queues/tests/round_robin/rr_5flow_test.py +frontends/queues/tests/round_robin/rr_6flow_test.py +frontends/queues/tests/round_robin/rr_7flow_test.py +frontends/queues/tests/round_robin/rr_2flow_test.py +frontends/queues/tests/binheap/complex_tree_test.py From 925675488364e5f232cc5f7e5f4b814f59317749 Mon Sep 17 00:00:00 2001 From: Ayaka Yorihiro Date: Mon, 1 Dec 2025 14:49:55 -0500 Subject: [PATCH 08/13] Clean up --- calyx/opt/src/passes_experimental/simplify_if_comb.rs | 8 -------- 1 file changed, 8 deletions(-) diff --git a/calyx/opt/src/passes_experimental/simplify_if_comb.rs b/calyx/opt/src/passes_experimental/simplify_if_comb.rs index 1a38a625d0..840d4b4d70 100644 --- a/calyx/opt/src/passes_experimental/simplify_if_comb.rs +++ b/calyx/opt/src/passes_experimental/simplify_if_comb.rs @@ -106,14 +106,6 @@ impl Visitor for SimplifyIfComb { rewrite.rewrite_assign(&mut new_asgn); comp.continuous_assignments.push(new_asgn); } - // create new enable for the true branch - // rewrite false branch if necessary - // let new_fbranch = - // if let ir::Control::Enable(f_enable) = s.fbranch.as_ref() { - // ir::Control::enable(f_enable.group.clone()) - // } else { - // ir::Control::empty() - // }; let mut new_if = calyx_ir::Control::if_( s.port.clone(), None, From 362f67b8a7714294381a3a948a1ca9f277d10ac4 Mon Sep 17 00:00:00 2001 From: Ayaka Yorihiro Date: Mon, 1 Dec 2025 14:52:53 -0500 Subject: [PATCH 09/13] more clean up --- calyx/opt/src/passes_experimental/simplify_if_comb.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/calyx/opt/src/passes_experimental/simplify_if_comb.rs b/calyx/opt/src/passes_experimental/simplify_if_comb.rs index 840d4b4d70..4bc83b2e83 100644 --- a/calyx/opt/src/passes_experimental/simplify_if_comb.rs +++ b/calyx/opt/src/passes_experimental/simplify_if_comb.rs @@ -70,7 +70,7 @@ impl Visitor for SimplifyIfComb { let mut builder = ir::Builder::new(comp, sigs); let mut rewrite_map = RewriteMap::new(); if let Some(cond_group_ref) = &s.cond { - // move all assignments in cond group to continuous + // create new cell for all cells in LHS of cond group assignments for cond_group_asgn in &cond_group_ref.borrow().assignments { if let calyx_ir::PortParent::Cell(c) = &cond_group_asgn.dst.borrow().parent @@ -101,6 +101,7 @@ impl Visitor for SimplifyIfComb { cell_map: rewrite_map, ..Default::default() }; + // move all assignments in cond group to continuous and rewrite cells for cond_group_asgn in &cond_group_ref.borrow_mut().assignments { let mut new_asgn = cond_group_asgn.clone(); rewrite.rewrite_assign(&mut new_asgn); From a99ab5a8e470a53cd284689e05e0385e30cfdb45 Mon Sep 17 00:00:00 2001 From: Ayaka Yorihiro Date: Mon, 1 Dec 2025 15:10:01 -0500 Subject: [PATCH 10/13] docmentation for script --- .gitignore | 4 ++-- .../compare-experimental-args.sh} | 7 +++++-- .../queues-tests.txt | 0 3 files changed, 7 insertions(+), 4 deletions(-) rename tools/{pass-cycle-check/pass-cycle-check.sh => compare-experimental-args/compare-experimental-args.sh} (79%) rename tools/{pass-cycle-check => compare-experimental-args}/queues-tests.txt (100%) diff --git a/.gitignore b/.gitignore index 5d0fe79a55..af6e45d311 100644 --- a/.gitignore +++ b/.gitignore @@ -71,8 +71,8 @@ tools/profiler/fg-tmp *.folded fud2-runs -# pass-cycle-check ignore -tools/pass-cycle-check/out* +# compare-experimental-args ignore +tools/compare-experimental-args/out* temp/ diff --git a/tools/pass-cycle-check/pass-cycle-check.sh b/tools/compare-experimental-args/compare-experimental-args.sh similarity index 79% rename from tools/pass-cycle-check/pass-cycle-check.sh rename to tools/compare-experimental-args/compare-experimental-args.sh index ab49a3bc3e..d2d48b9e73 100644 --- a/tools/pass-cycle-check/pass-cycle-check.sh +++ b/tools/compare-experimental-args/compare-experimental-args.sh @@ -1,7 +1,10 @@ -# This script runs the queues programs unless if we wanted to use different benches +# This script compares cycle counts between the default Calyx compiler and experimental compiler arguments. +# Currently this script runs the queues programs using Verilator to benchmark. if [ $# -lt 1 ]; then - echo "USAGE: bash $0 PASSES" + echo "USAGE: bash $0 CALYX_ARGS" + echo "where CALYX_ARGS is a string in quotes specifying experimental calyx args" + echo "ex) bash $0 \"-p simplify-if-comb -p dead-cell-removal -p dead-group-removal -p all\"" exit fi diff --git a/tools/pass-cycle-check/queues-tests.txt b/tools/compare-experimental-args/queues-tests.txt similarity index 100% rename from tools/pass-cycle-check/queues-tests.txt rename to tools/compare-experimental-args/queues-tests.txt From 1be5b81527b4234b7b3d466c81d1aba1b6c7221b Mon Sep 17 00:00:00 2001 From: Ayaka Yorihiro Date: Wed, 3 Dec 2025 15:24:52 -0500 Subject: [PATCH 11/13] clean up script --- .../compare-experimental-args.sh | 2 +- .../compare-experimental-args/queues-tests.txt | 18 +++++++++--------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/tools/compare-experimental-args/compare-experimental-args.sh b/tools/compare-experimental-args/compare-experimental-args.sh index d2d48b9e73..468172a22e 100644 --- a/tools/compare-experimental-args/compare-experimental-args.sh +++ b/tools/compare-experimental-args/compare-experimental-args.sh @@ -29,7 +29,7 @@ function round() { ( cd ${CALYX_DIR} - echo "name,og,opt,diff,diff(%)" > ${out} + echo "name,og,exp,diff,diff(%)" > ${out} py_args="20000 --keepgoing" for f in $( cat ${SCRIPT_DIR}/queues-tests.txt ); do name=$( basename "${f}" | cut -d. -f1 ) diff --git a/tools/compare-experimental-args/queues-tests.txt b/tools/compare-experimental-args/queues-tests.txt index b09f138174..2cedcbcb4d 100644 --- a/tools/compare-experimental-args/queues-tests.txt +++ b/tools/compare-experimental-args/queues-tests.txt @@ -1,14 +1,14 @@ -frontends/queues/tests/strict/strict_6flow_test.py -frontends/queues/tests/strict/strict_order_test.py -frontends/queues/tests/strict/strict_5flow_test.py -frontends/queues/tests/strict/strict_4flow_test.py -frontends/queues/tests/strict/strict_2flow_test.py -frontends/queues/tests/strict/strict_7flow_test.py -frontends/queues/tests/strict/strict_3flow_test.py +frontends/queues/tests/binheap/complex_tree_test.py +frontends/queues/tests/round_robin/rr_2flow_test.py frontends/queues/tests/round_robin/rr_3flow_test.py frontends/queues/tests/round_robin/rr_4flow_test.py frontends/queues/tests/round_robin/rr_5flow_test.py frontends/queues/tests/round_robin/rr_6flow_test.py frontends/queues/tests/round_robin/rr_7flow_test.py -frontends/queues/tests/round_robin/rr_2flow_test.py -frontends/queues/tests/binheap/complex_tree_test.py +frontends/queues/tests/strict/strict_2flow_test.py +frontends/queues/tests/strict/strict_3flow_test.py +frontends/queues/tests/strict/strict_4flow_test.py +frontends/queues/tests/strict/strict_5flow_test.py +frontends/queues/tests/strict/strict_6flow_test.py +frontends/queues/tests/strict/strict_7flow_test.py +frontends/queues/tests/strict/strict_order_test.py From d861e823deb7989ffc3c7cabfeaeac3bd22b3f04 Mon Sep 17 00:00:00 2001 From: Ayaka Yorihiro Date: Tue, 9 Dec 2025 17:21:02 -0500 Subject: [PATCH 12/13] update after PR comments --- .../passes_experimental/simplify_if_comb.rs | 93 ++++++++++--------- 1 file changed, 48 insertions(+), 45 deletions(-) diff --git a/calyx/opt/src/passes_experimental/simplify_if_comb.rs b/calyx/opt/src/passes_experimental/simplify_if_comb.rs index 4bc83b2e83..bad2fb2bdc 100644 --- a/calyx/opt/src/passes_experimental/simplify_if_comb.rs +++ b/calyx/opt/src/passes_experimental/simplify_if_comb.rs @@ -69,54 +69,57 @@ impl Visitor for SimplifyIfComb { ) -> VisResult { let mut builder = ir::Builder::new(comp, sigs); let mut rewrite_map = RewriteMap::new(); - if let Some(cond_group_ref) = &s.cond { - // create new cell for all cells in LHS of cond group assignments - for cond_group_asgn in &cond_group_ref.borrow().assignments { - if let calyx_ir::PortParent::Cell(c) = - &cond_group_asgn.dst.borrow().parent - { - let c_ref = c.upgrade(); - let c_name = c_ref.borrow().name(); + let mut new_continuous_assignments = Vec::new(); - if !rewrite_map.contains_key(&c_name) - && let ir::CellType::Primitive { - name, - param_binding, - .. - } = &c_ref.borrow().prototype - { - let new_cell = builder.add_primitive( - c_name, - *name, - ¶m_binding - .iter() - .map(|(_, v)| *v) - .collect_vec(), - ); - rewrite_map.insert(c_name, new_cell); - } + let Some(cond_group_ref) = &s.cond else { + return Ok(Action::Continue); + }; + // create new cell for all cells in LHS of cond group assignments + for cond_group_asgn in &cond_group_ref.borrow().assignments { + if let calyx_ir::PortParent::Cell(c) = + &cond_group_asgn.dst.borrow().parent + { + let c_ref = c.upgrade(); + let c_name = c_ref.borrow().name(); + if !rewrite_map.contains_key(&c_name) + && let ir::CellType::Primitive { + name, + param_binding, + .. + } = &c_ref.borrow().prototype + { + let new_cell = builder.add_primitive( + c_name, + *name, + ¶m_binding.iter().map(|(_, v)| *v).collect_vec(), + ); + rewrite_map.insert(c_name, new_cell); } } - let rewrite = Rewriter { - cell_map: rewrite_map, - ..Default::default() - }; - // move all assignments in cond group to continuous and rewrite cells - for cond_group_asgn in &cond_group_ref.borrow_mut().assignments { - let mut new_asgn = cond_group_asgn.clone(); - rewrite.rewrite_assign(&mut new_asgn); - comp.continuous_assignments.push(new_asgn); - } - let mut new_if = calyx_ir::Control::if_( - s.port.clone(), - None, - Box::new(s.tbranch.take_control()), - Box::new(s.fbranch.take_control()), - ); - rewrite.rewrite_control(&mut new_if); - Ok(Action::change(new_if)) - } else { - Ok(Action::Continue) } + + // move all assignments in cond group to continuous and rewrite cells + for cond_group_asgn in &cond_group_ref.borrow().assignments { + let new_asgn = cond_group_asgn.clone(); + new_continuous_assignments.push(new_asgn); + } + + let rewrite = Rewriter { + cell_map: rewrite_map, + ..Default::default() + }; + for asgn in new_continuous_assignments.iter_mut() { + rewrite.rewrite_assign(asgn); + comp.continuous_assignments.push(asgn.clone()); + } + s.cond = None; + let mut new_if = calyx_ir::Control::if_( + s.port.clone(), + None, + Box::new(s.tbranch.take_control()), + Box::new(s.fbranch.take_control()), + ); + rewrite.rewrite_control(&mut new_if); + Ok(Action::Change(Box::new(new_if))) } } From 6ae504d92efce2816cda3914e7fcfac658934387 Mon Sep 17 00:00:00 2001 From: Ayaka Yorihiro Date: Mon, 15 Dec 2025 19:40:07 -0500 Subject: [PATCH 13/13] additional documentation --- calyx/opt/src/passes_experimental/simplify_if_comb.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/calyx/opt/src/passes_experimental/simplify_if_comb.rs b/calyx/opt/src/passes_experimental/simplify_if_comb.rs index bad2fb2bdc..3cf08bf0f0 100644 --- a/calyx/opt/src/passes_experimental/simplify_if_comb.rs +++ b/calyx/opt/src/passes_experimental/simplify_if_comb.rs @@ -112,7 +112,10 @@ impl Visitor for SimplifyIfComb { rewrite.rewrite_assign(asgn); comp.continuous_assignments.push(asgn.clone()); } - s.cond = None; + + // NOTE: Technically no assignments within `s.tbranch` and `s.fbranch` should reference + // any cells that are being set in the original `s.comb` so we probably don't need + // to rewrite the whole `if`, but doing so in case someone refers to cells set in `s.comb` let mut new_if = calyx_ir::Control::if_( s.port.clone(), None,