diff --git a/src/libcretonne/layout.rs b/src/libcretonne/layout.rs index d803858d0a..e0ca2cc3cc 100644 --- a/src/libcretonne/layout.rs +++ b/src/libcretonne/layout.rs @@ -67,14 +67,18 @@ impl Layout { pub fn append_ebb(&mut self, ebb: Ebb) { assert!(!self.is_ebb_inserted(ebb), "Cannot append EBB that is already in the layout"); - let node = &mut self.ebbs[ebb]; - assert!(node.first_inst == NO_INST && node.last_inst == NO_INST); - node.prev = self.last_ebb.unwrap_or_default(); - node.next = NO_EBB; - self.last_ebb = Some(ebb); - if self.first_ebb.is_none() { + { + let node = &mut self.ebbs[ebb]; + assert!(node.first_inst == NO_INST && node.last_inst == NO_INST); + node.prev = self.last_ebb.unwrap_or_default(); + node.next = NO_EBB; + } + if let Some(last) = self.last_ebb { + self.ebbs[last].next = ebb; + } else { self.first_ebb = Some(ebb); } + self.last_ebb = Some(ebb); } /// Insert `ebb` in the layout before the existing EBB `before`. @@ -151,13 +155,18 @@ impl Layout { assert!(self.is_ebb_inserted(ebb), "Cannot append instructions to EBB not in layout"); let ebb_node = &mut self.ebbs[ebb]; - let inst_node = &mut self.insts[inst]; - inst_node.ebb = ebb; - inst_node.prev = ebb_node.last_inst; - assert_eq!(inst_node.next, NO_INST); + { + let inst_node = &mut self.insts[inst]; + inst_node.ebb = ebb; + inst_node.prev = ebb_node.last_inst; + assert_eq!(inst_node.next, NO_INST); + } if ebb_node.first_inst == NO_INST { ebb_node.first_inst = inst; + } else { + self.insts[ebb_node.last_inst].next = inst; } + ebb_node.last_inst = inst; } /// Insert `inst` before the instruction `before` in the same EBB. @@ -222,6 +231,44 @@ mod tests { use entity_map::EntityRef; use entities::{Ebb, Inst}; + #[test] + fn append_ebb() { + let mut layout = Layout::new(); + let e0 = Ebb::new(0); + let e1 = Ebb::new(1); + let e2 = Ebb::new(2); + + { + let imm = &layout; + assert!(!imm.is_ebb_inserted(e0)); + assert!(!imm.is_ebb_inserted(e1)); + + let v: Vec = layout.ebbs().collect(); + assert_eq!(v, []); + } + + layout.append_ebb(e1); + assert!(!layout.is_ebb_inserted(e0)); + assert!(layout.is_ebb_inserted(e1)); + assert!(!layout.is_ebb_inserted(e2)); + let v: Vec = layout.ebbs().collect(); + assert_eq!(v, [e1]); + + layout.append_ebb(e2); + assert!(!layout.is_ebb_inserted(e0)); + assert!(layout.is_ebb_inserted(e1)); + assert!(layout.is_ebb_inserted(e2)); + let v: Vec = layout.ebbs().collect(); + assert_eq!(v, [e1, e2]); + + layout.append_ebb(e0); + assert!(layout.is_ebb_inserted(e0)); + assert!(layout.is_ebb_inserted(e1)); + assert!(layout.is_ebb_inserted(e2)); + let v: Vec = layout.ebbs().collect(); + assert_eq!(v, [e1, e2, e0]); + } + #[test] fn insert_ebb() { let mut layout = Layout::new(); @@ -260,6 +307,45 @@ mod tests { assert_eq!(v, [e2, e0, e1]); } + #[test] + fn append_inst() { + let mut layout = Layout::new(); + let e1 = Ebb::new(1); + + layout.append_ebb(e1); + let v: Vec = layout.ebb_insts(e1).collect(); + assert_eq!(v, []); + + let i0 = Inst::new(0); + let i1 = Inst::new(1); + let i2 = Inst::new(2); + + assert_eq!(layout.inst_ebb(i0), None); + assert_eq!(layout.inst_ebb(i1), None); + assert_eq!(layout.inst_ebb(i2), None); + + layout.append_inst(i1, e1); + assert_eq!(layout.inst_ebb(i0), None); + assert_eq!(layout.inst_ebb(i1), Some(e1)); + assert_eq!(layout.inst_ebb(i2), None); + let v: Vec = layout.ebb_insts(e1).collect(); + assert_eq!(v, [i1]); + + layout.append_inst(i2, e1); + assert_eq!(layout.inst_ebb(i0), None); + assert_eq!(layout.inst_ebb(i1), Some(e1)); + assert_eq!(layout.inst_ebb(i2), Some(e1)); + let v: Vec = layout.ebb_insts(e1).collect(); + assert_eq!(v, [i1, i2]); + + layout.append_inst(i0, e1); + assert_eq!(layout.inst_ebb(i0), Some(e1)); + assert_eq!(layout.inst_ebb(i1), Some(e1)); + assert_eq!(layout.inst_ebb(i2), Some(e1)); + let v: Vec = layout.ebb_insts(e1).collect(); + assert_eq!(v, [i1, i2, i0]); + } + #[test] fn insert_inst() { let mut layout = Layout::new(); @@ -298,4 +384,30 @@ mod tests { let v: Vec = layout.ebb_insts(e1).collect(); assert_eq!(v, [i2, i0, i1]); } + + #[test] + fn multiple_ebbs() { + let mut layout = Layout::new(); + + let e0 = Ebb::new(0); + let e1 = Ebb::new(1); + + layout.append_ebb(e0); + layout.append_ebb(e1); + + let i0 = Inst::new(0); + let i1 = Inst::new(1); + let i2 = Inst::new(2); + let i3 = Inst::new(3); + + layout.append_inst(i0, e0); + layout.append_inst(i1, e0); + layout.append_inst(i2, e1); + layout.append_inst(i3, e1); + + let v0: Vec = layout.ebb_insts(e0).collect(); + let v1: Vec = layout.ebb_insts(e1).collect(); + assert_eq!(v0, [i0, i1]); + assert_eq!(v1, [i2, i3]); + } }