diff --git a/lib/codegen/src/cfg_printer.rs b/lib/codegen/src/cfg_printer.rs index 932345ef5b..bdd57bc1cd 100644 --- a/lib/codegen/src/cfg_printer.rs +++ b/lib/codegen/src/cfg_printer.rs @@ -2,7 +2,7 @@ use std::fmt::{Display, Formatter, Result, Write}; -use flowgraph::ControlFlowGraph; +use flowgraph::{BasicBlock, ControlFlowGraph}; use ir::instructions::BranchInfo; use ir::Function; @@ -61,7 +61,7 @@ impl<'a> CFGPrinter<'a> { fn cfg_connections(&self, w: &mut Write) -> Result { for ebb in &self.func.layout { - for (parent, inst) in self.cfg.pred_iter(ebb) { + for BasicBlock { ebb: parent, inst } in self.cfg.pred_iter(ebb) { writeln!(w, " {}:{} -> {}", parent, inst, ebb)?; } } diff --git a/lib/codegen/src/dominator_tree.rs b/lib/codegen/src/dominator_tree.rs index ba066fe496..d8789fecb9 100644 --- a/lib/codegen/src/dominator_tree.rs +++ b/lib/codegen/src/dominator_tree.rs @@ -177,19 +177,19 @@ impl DominatorTree { layout: &Layout, ) -> BasicBlock { loop { - match self.rpo_cmp_ebb(a.0, b.0) { + match self.rpo_cmp_ebb(a.ebb, b.ebb) { Ordering::Less => { // `a` comes before `b` in the RPO. Move `b` up. - let idom = self.nodes[b.0].idom.expect("Unreachable basic block?"); - b = ( + let idom = self.nodes[b.ebb].idom.expect("Unreachable basic block?"); + b = BasicBlock::new( layout.inst_ebb(idom).expect("Dangling idom instruction"), idom, ); } Ordering::Greater => { // `b` comes before `a` in the RPO. Move `a` up. - let idom = self.nodes[a.0].idom.expect("Unreachable basic block?"); - a = ( + let idom = self.nodes[a.ebb].idom.expect("Unreachable basic block?"); + a = BasicBlock::new( layout.inst_ebb(idom).expect("Dangling idom instruction"), idom, ); @@ -198,10 +198,13 @@ impl DominatorTree { } } - debug_assert_eq!(a.0, b.0, "Unreachable block passed to common_dominator?"); + debug_assert_eq!( + a.ebb, b.ebb, + "Unreachable block passed to common_dominator?" + ); // We're in the same EBB. The common dominator is the earlier instruction. - if layout.cmp(a.1, b.1) == Ordering::Less { + if layout.cmp(a.inst, b.inst) == Ordering::Less { a } else { b @@ -420,7 +423,7 @@ impl DominatorTree { // Note that during the first pass, `rpo_number` is 1 for reachable blocks that haven't // been visited yet, 0 for unreachable blocks. let mut reachable_preds = cfg.pred_iter(ebb) - .filter(|&(pred, _)| self.nodes[pred].rpo_number > 1); + .filter(|&BasicBlock { ebb: pred, .. }| self.nodes[pred].rpo_number > 1); // The RPO must visit at least one predecessor before this node. let mut idom = reachable_preds @@ -431,7 +434,7 @@ impl DominatorTree { idom = self.common_dominator(idom, pred, layout); } - idom.1 + idom.inst } } diff --git a/lib/codegen/src/flowgraph.rs b/lib/codegen/src/flowgraph.rs index a954b73ac1..09a9708214 100644 --- a/lib/codegen/src/flowgraph.rs +++ b/lib/codegen/src/flowgraph.rs @@ -31,7 +31,20 @@ use std::mem; use timing; /// A basic block denoted by its enclosing Ebb and last instruction. -pub type BasicBlock = (Ebb, Inst); +#[derive(PartialEq, Eq)] +pub struct BasicBlock { + /// Enclosing Ebb key. + pub ebb: Ebb, + /// Last instruction in the basic block. + pub inst: Inst, +} + +impl BasicBlock { + /// Convenient method to construct new BasicBlock. + pub fn new(ebb: Ebb, inst: Inst) -> Self { + Self { ebb, inst } + } +} /// A container for the successors and predecessors of some Ebb. #[derive(Clone, Default)] @@ -110,11 +123,11 @@ impl ControlFlowGraph { for inst in func.layout.ebb_insts(ebb) { match func.dfg.analyze_branch(inst) { BranchInfo::SingleDest(dest, _) => { - self.add_edge((ebb, inst), dest); + self.add_edge(BasicBlock::new(ebb, inst), dest); } BranchInfo::Table(jt) => { for (_, dest) in func.jump_tables[jt].entries() { - self.add_edge((ebb, inst), dest); + self.add_edge(BasicBlock::new(ebb, inst), dest); } } BranchInfo::NotABranch => {} @@ -148,12 +161,12 @@ impl ControlFlowGraph { } fn add_edge(&mut self, from: BasicBlock, to: Ebb) { - self.data[from.0] + self.data[from.ebb] .successors .insert(to, &mut self.succ_forest, &()); self.data[to] .predecessors - .insert(from.1, from.0, &mut self.pred_forest, &()); + .insert(from.inst, from.ebb, &mut self.pred_forest, &()); } /// Get an iterator over the CFG predecessors to `ebb`. @@ -186,7 +199,7 @@ impl<'a> Iterator for PredIter<'a> { type Item = BasicBlock; fn next(&mut self) -> Option { - self.0.next().map(|(i, e)| (e, i)) + self.0.next().map(|(i, e)| BasicBlock::new(e, i)) } } @@ -268,10 +281,22 @@ mod tests { assert_eq!(ebb1_predecessors.len(), 2); assert_eq!(ebb2_predecessors.len(), 2); - assert_eq!(ebb1_predecessors.contains(&(ebb0, jmp_ebb0_ebb1)), true); - assert_eq!(ebb1_predecessors.contains(&(ebb1, br_ebb1_ebb1)), true); - assert_eq!(ebb2_predecessors.contains(&(ebb0, br_ebb0_ebb2)), true); - assert_eq!(ebb2_predecessors.contains(&(ebb1, jmp_ebb1_ebb2)), true); + assert_eq!( + ebb1_predecessors.contains(&BasicBlock::new(ebb0, jmp_ebb0_ebb1)), + true + ); + assert_eq!( + ebb1_predecessors.contains(&BasicBlock::new(ebb1, br_ebb1_ebb1)), + true + ); + assert_eq!( + ebb2_predecessors.contains(&BasicBlock::new(ebb0, br_ebb0_ebb2)), + true + ); + assert_eq!( + ebb2_predecessors.contains(&BasicBlock::new(ebb1, jmp_ebb1_ebb2)), + true + ); assert_eq!(ebb0_successors, [ebb1, ebb2]); assert_eq!(ebb1_successors, [ebb1, ebb2]); @@ -297,10 +322,22 @@ mod tests { assert_eq!(ebb1_predecessors.len(), 2); assert_eq!(ebb2_predecessors.len(), 1); - assert_eq!(ebb1_predecessors.contains(&(ebb0, br_ebb0_ebb1)), true); - assert_eq!(ebb1_predecessors.contains(&(ebb1, br_ebb1_ebb1)), true); - assert_eq!(ebb2_predecessors.contains(&(ebb0, br_ebb0_ebb2)), false); - assert_eq!(ebb2_predecessors.contains(&(ebb1, jmp_ebb1_ebb2)), true); + assert_eq!( + ebb1_predecessors.contains(&BasicBlock::new(ebb0, br_ebb0_ebb1)), + true + ); + assert_eq!( + ebb1_predecessors.contains(&BasicBlock::new(ebb1, br_ebb1_ebb1)), + true + ); + assert_eq!( + ebb2_predecessors.contains(&BasicBlock::new(ebb0, br_ebb0_ebb2)), + false + ); + assert_eq!( + ebb2_predecessors.contains(&BasicBlock::new(ebb1, jmp_ebb1_ebb2)), + true + ); assert_eq!(ebb0_successors.collect::>(), [ebb1]); assert_eq!(ebb1_successors.collect::>(), [ebb1, ebb2]); diff --git a/lib/codegen/src/legalizer/split.rs b/lib/codegen/src/legalizer/split.rs index bbb63397a5..a7cd37dc60 100644 --- a/lib/codegen/src/legalizer/split.rs +++ b/lib/codegen/src/legalizer/split.rs @@ -65,7 +65,7 @@ //! instructions. These loops will remain in the program. use cursor::{Cursor, CursorPosition, FuncCursor}; -use flowgraph::ControlFlowGraph; +use flowgraph::{BasicBlock, ControlFlowGraph}; use ir::{self, Ebb, Inst, InstBuilder, InstructionData, Opcode, Type, Value, ValueDef}; use std::iter; use std::vec::Vec; @@ -126,7 +126,7 @@ fn split_any( // We have split the value requested, and now we may need to fix some EBB predecessors. while let Some(repair) = repairs.pop() { - for (_, inst) in cfg.pred_iter(repair.ebb) { + for BasicBlock { inst, .. } in cfg.pred_iter(repair.ebb) { let branch_opc = pos.func.dfg[inst].opcode(); debug_assert!( branch_opc.is_branch(), diff --git a/lib/codegen/src/licm.rs b/lib/codegen/src/licm.rs index 8f32b640ac..f9954087b4 100644 --- a/lib/codegen/src/licm.rs +++ b/lib/codegen/src/licm.rs @@ -3,7 +3,7 @@ use cursor::{Cursor, FuncCursor}; use dominator_tree::DominatorTree; use entity::{EntityList, ListPool}; -use flowgraph::ControlFlowGraph; +use flowgraph::{BasicBlock, ControlFlowGraph}; use fx::FxHashSet; use ir::{DataFlowGraph, Ebb, Function, Inst, InstBuilder, Layout, Opcode, Type, Value}; use loop_analysis::{Loop, LoopAnalysis}; @@ -77,7 +77,10 @@ fn create_pre_header( for typ in header_args_types { pre_header_args_value.push(func.dfg.append_ebb_param(pre_header, typ), pool); } - for (_, last_inst) in cfg.pred_iter(header) { + for BasicBlock { + inst: last_inst, .. + } in cfg.pred_iter(header) + { // We only follow normal edges (not the back edges) if !domtree.dominates(header, last_inst, &func.layout) { change_branch_jump_destination(last_inst, pre_header, func); @@ -106,7 +109,11 @@ fn has_pre_header( ) -> Option<(Ebb, Inst)> { let mut result = None; let mut found = false; - for (pred_ebb, last_inst) in cfg.pred_iter(header) { + for BasicBlock { + ebb: pred_ebb, + inst: last_inst, + } in cfg.pred_iter(header) + { // We only count normal edges (not the back edges) if !domtree.dominates(header, last_inst, layout) { if found { diff --git a/lib/codegen/src/loop_analysis.rs b/lib/codegen/src/loop_analysis.rs index c2c73bba3f..fc1591b0cf 100644 --- a/lib/codegen/src/loop_analysis.rs +++ b/lib/codegen/src/loop_analysis.rs @@ -4,7 +4,7 @@ use dominator_tree::DominatorTree; use entity::EntityMap; use entity::{Keys, PrimaryMap}; -use flowgraph::ControlFlowGraph; +use flowgraph::{BasicBlock, ControlFlowGraph}; use ir::{Ebb, Function, Layout}; use packed_option::PackedOption; use std::vec::Vec; @@ -137,7 +137,10 @@ impl LoopAnalysis { ) { // We traverse the CFG in reverse postorder for &ebb in domtree.cfg_postorder().iter().rev() { - for (_, pred_inst) in cfg.pred_iter(ebb) { + for BasicBlock { + inst: pred_inst, .. + } in cfg.pred_iter(ebb) + { // If the ebb dominates one of its predecessors it is a back edge if domtree.dominates(ebb, pred_inst, layout) { // This ebb is a loop header, so we create its associated loop @@ -163,7 +166,11 @@ impl LoopAnalysis { // We handle each loop header in reverse order, corresponding to a pseudo postorder // traversal of the graph. for lp in self.loops().rev() { - for (pred, pred_inst) in cfg.pred_iter(self.loops[lp].header) { + for BasicBlock { + ebb: pred, + inst: pred_inst, + } in cfg.pred_iter(self.loops[lp].header) + { // We follow the back edges if domtree.dominates(self.loops[lp].header, pred_inst, layout) { stack.push(pred); @@ -213,7 +220,7 @@ impl LoopAnalysis { // Now we have handled the popped node and need to continue the DFS by adding the // predecessors of that node if let Some(continue_dfs) = continue_dfs { - for (pred, _) in cfg.pred_iter(continue_dfs) { + for BasicBlock { ebb: pred, .. } in cfg.pred_iter(continue_dfs) { stack.push(pred) } } diff --git a/lib/codegen/src/regalloc/coalescing.rs b/lib/codegen/src/regalloc/coalescing.rs index dd77b41937..0f00730fb8 100644 --- a/lib/codegen/src/regalloc/coalescing.rs +++ b/lib/codegen/src/regalloc/coalescing.rs @@ -9,7 +9,7 @@ use cursor::{Cursor, EncCursor}; #[cfg(feature = "std")] use dbg::DisplayList; use dominator_tree::{DominatorTree, DominatorTreePreorder}; -use flowgraph::ControlFlowGraph; +use flowgraph::{BasicBlock, ControlFlowGraph}; use fx::FxHashMap; use ir::{self, InstBuilder, ProgramOrder}; use ir::{Ebb, ExpandedProgramPoint, Function, Inst, Value}; @@ -174,7 +174,11 @@ impl<'a> Context<'a> { debug_assert_eq!(num_params, self.func.dfg.num_ebb_params(ebb)); // The only way a parameter value can interfere with a predecessor branch is if the EBB is // dominating the predecessor branch. That is, we are looking for loop back-edges. - for (pred_ebb, pred_inst) in self.cfg.pred_iter(ebb) { + for BasicBlock { + ebb: pred_ebb, + inst: pred_inst, + } in self.cfg.pred_iter(ebb) + { // The quick pre-order dominance check is accurate because the EBB parameter is defined // at the top of the EBB before any branches. if !self.preorder.dominates(ebb, pred_ebb) { @@ -211,7 +215,11 @@ impl<'a> Context<'a> { fn union_pred_args(&mut self, ebb: Ebb, argnum: usize) { let param = self.func.dfg.ebb_params(ebb)[argnum]; - for (pred_ebb, pred_inst) in self.cfg.pred_iter(ebb) { + for BasicBlock { + ebb: pred_ebb, + inst: pred_inst, + } in self.cfg.pred_iter(ebb) + { let arg = self.func.dfg.inst_variable_args(pred_inst)[argnum]; // Never coalesce incoming function parameters on the stack. These parameters are @@ -484,7 +492,11 @@ impl<'a> Context<'a> { // not loop backedges. debug_assert!(self.predecessors.is_empty()); debug_assert!(self.backedges.is_empty()); - for (pred_ebb, pred_inst) in self.cfg.pred_iter(ebb) { + for BasicBlock { + ebb: pred_ebb, + inst: pred_inst, + } in self.cfg.pred_iter(ebb) + { if self.preorder.dominates(ebb, pred_ebb) { self.backedges.push(pred_inst); } else { @@ -915,7 +927,10 @@ impl VirtualCopies { } // This EBB hasn't been seen before. - for (_, pred_inst) in cfg.pred_iter(ebb) { + for BasicBlock { + inst: pred_inst, .. + } in cfg.pred_iter(ebb) + { self.branches.push((pred_inst, ebb)); } last_ebb = Some(ebb); diff --git a/lib/codegen/src/regalloc/liveness.rs b/lib/codegen/src/regalloc/liveness.rs index 7f5ee4ae5d..d169acc459 100644 --- a/lib/codegen/src/regalloc/liveness.rs +++ b/lib/codegen/src/regalloc/liveness.rs @@ -176,7 +176,7 @@ //! There is some room for improvement. use entity::SparseMap; -use flowgraph::ControlFlowGraph; +use flowgraph::{BasicBlock, ControlFlowGraph}; use ir::dfg::ValueDef; use ir::{Ebb, Function, Inst, Layout, ProgramPoint, Value}; use isa::{EncInfo, OperandConstraint, TargetIsa}; @@ -272,7 +272,11 @@ fn extend_to_use( while let Some(livein) = worklist.pop() { // We've learned that the value needs to be live-in to the `livein` EBB. // Make sure it is also live at all predecessor branches to `livein`. - for (pred, branch) in cfg.pred_iter(livein) { + for BasicBlock { + ebb: pred, + inst: branch, + } in cfg.pred_iter(livein) + { if lr.extend_in_ebb(pred, branch, &func.layout, forest) { // This predecessor EBB also became live-in. We need to process it later. worklist.push(pred); diff --git a/lib/codegen/src/verifier/cssa.rs b/lib/codegen/src/verifier/cssa.rs index 8e3402208b..c2d745c4fb 100644 --- a/lib/codegen/src/verifier/cssa.rs +++ b/lib/codegen/src/verifier/cssa.rs @@ -2,7 +2,7 @@ use dbg::DisplayList; use dominator_tree::{DominatorTree, DominatorTreePreorder}; -use flowgraph::ControlFlowGraph; +use flowgraph::{BasicBlock, ControlFlowGraph}; use ir::{ExpandedProgramPoint, Function}; use regalloc::liveness::Liveness; use regalloc::virtregs::VirtRegs; @@ -138,7 +138,7 @@ impl<'a> CssaVerifier<'a> { fn check_cssa(&self) -> VerifierResult<()> { for ebb in self.func.layout.ebbs() { let ebb_params = self.func.dfg.ebb_params(ebb); - for (_, pred) in self.cfg.pred_iter(ebb) { + for BasicBlock { inst: pred, .. } in self.cfg.pred_iter(ebb) { let pred_args = self.func.dfg.inst_variable_args(pred); // This should have been caught by an earlier verifier pass. assert_eq!( diff --git a/lib/codegen/src/verifier/flags.rs b/lib/codegen/src/verifier/flags.rs index 05ce764310..04615bacd7 100644 --- a/lib/codegen/src/verifier/flags.rs +++ b/lib/codegen/src/verifier/flags.rs @@ -1,7 +1,7 @@ //! Verify CPU flags values. use entity::{EntityMap, SparseSet}; -use flowgraph::ControlFlowGraph; +use flowgraph::{BasicBlock, ControlFlowGraph}; use ir; use ir::instructions::BranchInfo; use isa; @@ -61,7 +61,7 @@ impl<'a> FlagsVerifier<'a> { // Revisit any predecessor blocks the first time we see a live-in for `ebb`. None => { self.livein[ebb] = value.into(); - for (pred, _) in self.cfg.pred_iter(ebb) { + for BasicBlock { ebb: pred, .. } in self.cfg.pred_iter(ebb) { worklist.insert(pred); } } diff --git a/lib/codegen/src/verifier/liveness.rs b/lib/codegen/src/verifier/liveness.rs index e2bf6a21ef..f884feea79 100644 --- a/lib/codegen/src/verifier/liveness.rs +++ b/lib/codegen/src/verifier/liveness.rs @@ -1,6 +1,6 @@ //! Liveness verifier. -use flowgraph::ControlFlowGraph; +use flowgraph::{BasicBlock, ControlFlowGraph}; use ir::entities::AnyEntity; use ir::{ExpandedProgramPoint, Function, Inst, ProgramOrder, ProgramPoint, Value}; use isa::TargetIsa; @@ -194,7 +194,7 @@ impl<'a> LivenessVerifier<'a> { // Check all the EBBs in the interval independently. loop { // If `val` is live-in at `ebb`, it must be live at all the predecessors. - for (_, pred) in self.cfg.pred_iter(ebb) { + for BasicBlock { inst: pred, .. } in self.cfg.pred_iter(ebb) { if !self.live_at_use(lr, pred) { return err!( pred, diff --git a/lib/codegen/src/verifier/mod.rs b/lib/codegen/src/verifier/mod.rs index aa3923456c..f92bdda1d8 100644 --- a/lib/codegen/src/verifier/mod.rs +++ b/lib/codegen/src/verifier/mod.rs @@ -60,7 +60,7 @@ use self::flags::verify_flags; use dbg::DisplayList; use dominator_tree::DominatorTree; use entity::SparseSet; -use flowgraph::ControlFlowGraph; +use flowgraph::{BasicBlock, ControlFlowGraph}; use ir; use ir::entities::AnyEntity; use ir::instructions::{BranchInfo, CallInfo, InstructionFormat, ResolvedConstraint}; @@ -990,8 +990,12 @@ impl<'a> Verifier<'a> { return err!(ebb, "cfg had unexpected successor(s) {:?}", excess_succs); } - expected_preds.extend(self.expected_cfg.pred_iter(ebb).map(|(_, inst)| inst)); - got_preds.extend(cfg.pred_iter(ebb).map(|(_, inst)| inst)); + expected_preds.extend( + self.expected_cfg + .pred_iter(ebb) + .map(|BasicBlock { inst, .. }| inst), + ); + got_preds.extend(cfg.pred_iter(ebb).map(|BasicBlock { inst, .. }| inst)); let missing_preds: Vec = expected_preds.difference(&got_preds).cloned().collect(); if !missing_preds.is_empty() {