calyx_opt/passes/
merge_assign.rs1use crate::traversal::{Action, Named, VisResult, Visitor};
2use calyx_ir::{self as ir, LibrarySignatures};
3use itertools::Itertools;
4use linked_hash_map::LinkedHashMap;
5
6#[derive(Default)]
22pub struct MergeAssign {}
23
24impl Named for MergeAssign {
25 fn name() -> &'static str {
26 "merge-assigns"
27 }
28
29 fn description() -> &'static str {
30 "Merge assignments with the same source-destination pairs"
31 }
32}
33
34fn merge_assigns<T: Eq>(
35 assigns: Vec<ir::Assignment<T>>,
36) -> Vec<ir::Assignment<T>> {
37 let mut map: LinkedHashMap<
39 (ir::Canonical, ir::Canonical),
40 ir::Assignment<T>,
41 > = LinkedHashMap::new();
42
43 for assign in assigns {
44 let src_key = assign.src.borrow().canonical();
45 let dst_key = assign.dst.borrow().canonical();
46 let key = (dst_key, src_key);
47 if let Some(asgn) = map.get_mut(&key) {
48 *asgn.guard |= *assign.guard;
49 } else {
50 map.insert(key, assign);
51 }
52 }
53
54 map.into_iter()
55 .sorted_by(|(k1, _), (k2, _)| Ord::cmp(k1, k2))
56 .map(|(_, v)| v)
57 .collect::<Vec<_>>()
58}
59
60impl Visitor for MergeAssign {
61 fn start(
62 &mut self,
63 comp: &mut ir::Component,
64 _ctx: &LibrarySignatures,
65 _comps: &[ir::Component],
66 ) -> VisResult {
67 for group in comp.get_groups().iter() {
68 let assigns = group.borrow_mut().assignments.drain(..).collect();
69 let merged = merge_assigns(assigns);
70 group.borrow_mut().assignments = merged;
71 }
72 for comb_group in comp.comb_groups.iter() {
73 let assigns =
74 comb_group.borrow_mut().assignments.drain(..).collect();
75 let merged = merge_assigns(assigns);
76 comb_group.borrow_mut().assignments = merged;
77 }
78 for st_group in comp.static_groups.iter() {
79 let assigns = st_group.borrow_mut().assignments.drain(..).collect();
80 let merged = merge_assigns(assigns);
81 st_group.borrow_mut().assignments = merged;
82 }
83
84 let cassigns = comp.continuous_assignments.drain(..).collect();
85 comp.continuous_assignments = merge_assigns(cassigns);
86
87 Ok(Action::Stop)
88 }
89}