Promote the BasicBlock tuple to a real struct;
It makes reading code that uses it easier to understand.
This commit is contained in:
committed by
Dan Gohman
parent
ce177d643e
commit
f72ff791b4
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
use std::fmt::{Display, Formatter, Result, Write};
|
use std::fmt::{Display, Formatter, Result, Write};
|
||||||
|
|
||||||
use flowgraph::ControlFlowGraph;
|
use flowgraph::{BasicBlock, ControlFlowGraph};
|
||||||
use ir::instructions::BranchInfo;
|
use ir::instructions::BranchInfo;
|
||||||
use ir::Function;
|
use ir::Function;
|
||||||
|
|
||||||
@@ -61,7 +61,7 @@ impl<'a> CFGPrinter<'a> {
|
|||||||
|
|
||||||
fn cfg_connections(&self, w: &mut Write) -> Result {
|
fn cfg_connections(&self, w: &mut Write) -> Result {
|
||||||
for ebb in &self.func.layout {
|
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)?;
|
writeln!(w, " {}:{} -> {}", parent, inst, ebb)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -177,19 +177,19 @@ impl DominatorTree {
|
|||||||
layout: &Layout,
|
layout: &Layout,
|
||||||
) -> BasicBlock {
|
) -> BasicBlock {
|
||||||
loop {
|
loop {
|
||||||
match self.rpo_cmp_ebb(a.0, b.0) {
|
match self.rpo_cmp_ebb(a.ebb, b.ebb) {
|
||||||
Ordering::Less => {
|
Ordering::Less => {
|
||||||
// `a` comes before `b` in the RPO. Move `b` up.
|
// `a` comes before `b` in the RPO. Move `b` up.
|
||||||
let idom = self.nodes[b.0].idom.expect("Unreachable basic block?");
|
let idom = self.nodes[b.ebb].idom.expect("Unreachable basic block?");
|
||||||
b = (
|
b = BasicBlock::new(
|
||||||
layout.inst_ebb(idom).expect("Dangling idom instruction"),
|
layout.inst_ebb(idom).expect("Dangling idom instruction"),
|
||||||
idom,
|
idom,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
Ordering::Greater => {
|
Ordering::Greater => {
|
||||||
// `b` comes before `a` in the RPO. Move `a` up.
|
// `b` comes before `a` in the RPO. Move `a` up.
|
||||||
let idom = self.nodes[a.0].idom.expect("Unreachable basic block?");
|
let idom = self.nodes[a.ebb].idom.expect("Unreachable basic block?");
|
||||||
a = (
|
a = BasicBlock::new(
|
||||||
layout.inst_ebb(idom).expect("Dangling idom instruction"),
|
layout.inst_ebb(idom).expect("Dangling idom instruction"),
|
||||||
idom,
|
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.
|
// 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
|
a
|
||||||
} else {
|
} else {
|
||||||
b
|
b
|
||||||
@@ -420,7 +423,7 @@ impl DominatorTree {
|
|||||||
// Note that during the first pass, `rpo_number` is 1 for reachable blocks that haven't
|
// Note that during the first pass, `rpo_number` is 1 for reachable blocks that haven't
|
||||||
// been visited yet, 0 for unreachable blocks.
|
// been visited yet, 0 for unreachable blocks.
|
||||||
let mut reachable_preds = cfg.pred_iter(ebb)
|
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.
|
// The RPO must visit at least one predecessor before this node.
|
||||||
let mut idom = reachable_preds
|
let mut idom = reachable_preds
|
||||||
@@ -431,7 +434,7 @@ impl DominatorTree {
|
|||||||
idom = self.common_dominator(idom, pred, layout);
|
idom = self.common_dominator(idom, pred, layout);
|
||||||
}
|
}
|
||||||
|
|
||||||
idom.1
|
idom.inst
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -31,7 +31,20 @@ use std::mem;
|
|||||||
use timing;
|
use timing;
|
||||||
|
|
||||||
/// A basic block denoted by its enclosing Ebb and last instruction.
|
/// 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.
|
/// A container for the successors and predecessors of some Ebb.
|
||||||
#[derive(Clone, Default)]
|
#[derive(Clone, Default)]
|
||||||
@@ -110,11 +123,11 @@ impl ControlFlowGraph {
|
|||||||
for inst in func.layout.ebb_insts(ebb) {
|
for inst in func.layout.ebb_insts(ebb) {
|
||||||
match func.dfg.analyze_branch(inst) {
|
match func.dfg.analyze_branch(inst) {
|
||||||
BranchInfo::SingleDest(dest, _) => {
|
BranchInfo::SingleDest(dest, _) => {
|
||||||
self.add_edge((ebb, inst), dest);
|
self.add_edge(BasicBlock::new(ebb, inst), dest);
|
||||||
}
|
}
|
||||||
BranchInfo::Table(jt) => {
|
BranchInfo::Table(jt) => {
|
||||||
for (_, dest) in func.jump_tables[jt].entries() {
|
for (_, dest) in func.jump_tables[jt].entries() {
|
||||||
self.add_edge((ebb, inst), dest);
|
self.add_edge(BasicBlock::new(ebb, inst), dest);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
BranchInfo::NotABranch => {}
|
BranchInfo::NotABranch => {}
|
||||||
@@ -148,12 +161,12 @@ impl ControlFlowGraph {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn add_edge(&mut self, from: BasicBlock, to: Ebb) {
|
fn add_edge(&mut self, from: BasicBlock, to: Ebb) {
|
||||||
self.data[from.0]
|
self.data[from.ebb]
|
||||||
.successors
|
.successors
|
||||||
.insert(to, &mut self.succ_forest, &());
|
.insert(to, &mut self.succ_forest, &());
|
||||||
self.data[to]
|
self.data[to]
|
||||||
.predecessors
|
.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`.
|
/// Get an iterator over the CFG predecessors to `ebb`.
|
||||||
@@ -186,7 +199,7 @@ impl<'a> Iterator for PredIter<'a> {
|
|||||||
type Item = BasicBlock;
|
type Item = BasicBlock;
|
||||||
|
|
||||||
fn next(&mut self) -> Option<BasicBlock> {
|
fn next(&mut self) -> Option<BasicBlock> {
|
||||||
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!(ebb1_predecessors.len(), 2);
|
||||||
assert_eq!(ebb2_predecessors.len(), 2);
|
assert_eq!(ebb2_predecessors.len(), 2);
|
||||||
|
|
||||||
assert_eq!(ebb1_predecessors.contains(&(ebb0, jmp_ebb0_ebb1)), true);
|
assert_eq!(
|
||||||
assert_eq!(ebb1_predecessors.contains(&(ebb1, br_ebb1_ebb1)), true);
|
ebb1_predecessors.contains(&BasicBlock::new(ebb0, jmp_ebb0_ebb1)),
|
||||||
assert_eq!(ebb2_predecessors.contains(&(ebb0, br_ebb0_ebb2)), true);
|
true
|
||||||
assert_eq!(ebb2_predecessors.contains(&(ebb1, jmp_ebb1_ebb2)), 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!(ebb0_successors, [ebb1, ebb2]);
|
||||||
assert_eq!(ebb1_successors, [ebb1, ebb2]);
|
assert_eq!(ebb1_successors, [ebb1, ebb2]);
|
||||||
@@ -297,10 +322,22 @@ mod tests {
|
|||||||
assert_eq!(ebb1_predecessors.len(), 2);
|
assert_eq!(ebb1_predecessors.len(), 2);
|
||||||
assert_eq!(ebb2_predecessors.len(), 1);
|
assert_eq!(ebb2_predecessors.len(), 1);
|
||||||
|
|
||||||
assert_eq!(ebb1_predecessors.contains(&(ebb0, br_ebb0_ebb1)), true);
|
assert_eq!(
|
||||||
assert_eq!(ebb1_predecessors.contains(&(ebb1, br_ebb1_ebb1)), true);
|
ebb1_predecessors.contains(&BasicBlock::new(ebb0, br_ebb0_ebb1)),
|
||||||
assert_eq!(ebb2_predecessors.contains(&(ebb0, br_ebb0_ebb2)), false);
|
true
|
||||||
assert_eq!(ebb2_predecessors.contains(&(ebb1, jmp_ebb1_ebb2)), 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::<Vec<_>>(), [ebb1]);
|
assert_eq!(ebb0_successors.collect::<Vec<_>>(), [ebb1]);
|
||||||
assert_eq!(ebb1_successors.collect::<Vec<_>>(), [ebb1, ebb2]);
|
assert_eq!(ebb1_successors.collect::<Vec<_>>(), [ebb1, ebb2]);
|
||||||
|
|||||||
@@ -65,7 +65,7 @@
|
|||||||
//! instructions. These loops will remain in the program.
|
//! instructions. These loops will remain in the program.
|
||||||
|
|
||||||
use cursor::{Cursor, CursorPosition, FuncCursor};
|
use cursor::{Cursor, CursorPosition, FuncCursor};
|
||||||
use flowgraph::ControlFlowGraph;
|
use flowgraph::{BasicBlock, ControlFlowGraph};
|
||||||
use ir::{self, Ebb, Inst, InstBuilder, InstructionData, Opcode, Type, Value, ValueDef};
|
use ir::{self, Ebb, Inst, InstBuilder, InstructionData, Opcode, Type, Value, ValueDef};
|
||||||
use std::iter;
|
use std::iter;
|
||||||
use std::vec::Vec;
|
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.
|
// We have split the value requested, and now we may need to fix some EBB predecessors.
|
||||||
while let Some(repair) = repairs.pop() {
|
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();
|
let branch_opc = pos.func.dfg[inst].opcode();
|
||||||
debug_assert!(
|
debug_assert!(
|
||||||
branch_opc.is_branch(),
|
branch_opc.is_branch(),
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
use cursor::{Cursor, FuncCursor};
|
use cursor::{Cursor, FuncCursor};
|
||||||
use dominator_tree::DominatorTree;
|
use dominator_tree::DominatorTree;
|
||||||
use entity::{EntityList, ListPool};
|
use entity::{EntityList, ListPool};
|
||||||
use flowgraph::ControlFlowGraph;
|
use flowgraph::{BasicBlock, ControlFlowGraph};
|
||||||
use fx::FxHashSet;
|
use fx::FxHashSet;
|
||||||
use ir::{DataFlowGraph, Ebb, Function, Inst, InstBuilder, Layout, Opcode, Type, Value};
|
use ir::{DataFlowGraph, Ebb, Function, Inst, InstBuilder, Layout, Opcode, Type, Value};
|
||||||
use loop_analysis::{Loop, LoopAnalysis};
|
use loop_analysis::{Loop, LoopAnalysis};
|
||||||
@@ -77,7 +77,10 @@ fn create_pre_header(
|
|||||||
for typ in header_args_types {
|
for typ in header_args_types {
|
||||||
pre_header_args_value.push(func.dfg.append_ebb_param(pre_header, typ), pool);
|
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)
|
// We only follow normal edges (not the back edges)
|
||||||
if !domtree.dominates(header, last_inst, &func.layout) {
|
if !domtree.dominates(header, last_inst, &func.layout) {
|
||||||
change_branch_jump_destination(last_inst, pre_header, func);
|
change_branch_jump_destination(last_inst, pre_header, func);
|
||||||
@@ -106,7 +109,11 @@ fn has_pre_header(
|
|||||||
) -> Option<(Ebb, Inst)> {
|
) -> Option<(Ebb, Inst)> {
|
||||||
let mut result = None;
|
let mut result = None;
|
||||||
let mut found = false;
|
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)
|
// We only count normal edges (not the back edges)
|
||||||
if !domtree.dominates(header, last_inst, layout) {
|
if !domtree.dominates(header, last_inst, layout) {
|
||||||
if found {
|
if found {
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
use dominator_tree::DominatorTree;
|
use dominator_tree::DominatorTree;
|
||||||
use entity::EntityMap;
|
use entity::EntityMap;
|
||||||
use entity::{Keys, PrimaryMap};
|
use entity::{Keys, PrimaryMap};
|
||||||
use flowgraph::ControlFlowGraph;
|
use flowgraph::{BasicBlock, ControlFlowGraph};
|
||||||
use ir::{Ebb, Function, Layout};
|
use ir::{Ebb, Function, Layout};
|
||||||
use packed_option::PackedOption;
|
use packed_option::PackedOption;
|
||||||
use std::vec::Vec;
|
use std::vec::Vec;
|
||||||
@@ -137,7 +137,10 @@ impl LoopAnalysis {
|
|||||||
) {
|
) {
|
||||||
// We traverse the CFG in reverse postorder
|
// We traverse the CFG in reverse postorder
|
||||||
for &ebb in domtree.cfg_postorder().iter().rev() {
|
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 the ebb dominates one of its predecessors it is a back edge
|
||||||
if domtree.dominates(ebb, pred_inst, layout) {
|
if domtree.dominates(ebb, pred_inst, layout) {
|
||||||
// This ebb is a loop header, so we create its associated loop
|
// 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
|
// We handle each loop header in reverse order, corresponding to a pseudo postorder
|
||||||
// traversal of the graph.
|
// traversal of the graph.
|
||||||
for lp in self.loops().rev() {
|
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
|
// We follow the back edges
|
||||||
if domtree.dominates(self.loops[lp].header, pred_inst, layout) {
|
if domtree.dominates(self.loops[lp].header, pred_inst, layout) {
|
||||||
stack.push(pred);
|
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
|
// Now we have handled the popped node and need to continue the DFS by adding the
|
||||||
// predecessors of that node
|
// predecessors of that node
|
||||||
if let Some(continue_dfs) = continue_dfs {
|
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)
|
stack.push(pred)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ use cursor::{Cursor, EncCursor};
|
|||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
use dbg::DisplayList;
|
use dbg::DisplayList;
|
||||||
use dominator_tree::{DominatorTree, DominatorTreePreorder};
|
use dominator_tree::{DominatorTree, DominatorTreePreorder};
|
||||||
use flowgraph::ControlFlowGraph;
|
use flowgraph::{BasicBlock, ControlFlowGraph};
|
||||||
use fx::FxHashMap;
|
use fx::FxHashMap;
|
||||||
use ir::{self, InstBuilder, ProgramOrder};
|
use ir::{self, InstBuilder, ProgramOrder};
|
||||||
use ir::{Ebb, ExpandedProgramPoint, Function, Inst, Value};
|
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));
|
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
|
// 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.
|
// 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
|
// The quick pre-order dominance check is accurate because the EBB parameter is defined
|
||||||
// at the top of the EBB before any branches.
|
// at the top of the EBB before any branches.
|
||||||
if !self.preorder.dominates(ebb, pred_ebb) {
|
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) {
|
fn union_pred_args(&mut self, ebb: Ebb, argnum: usize) {
|
||||||
let param = self.func.dfg.ebb_params(ebb)[argnum];
|
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];
|
let arg = self.func.dfg.inst_variable_args(pred_inst)[argnum];
|
||||||
|
|
||||||
// Never coalesce incoming function parameters on the stack. These parameters are
|
// Never coalesce incoming function parameters on the stack. These parameters are
|
||||||
@@ -484,7 +492,11 @@ impl<'a> Context<'a> {
|
|||||||
// not loop backedges.
|
// not loop backedges.
|
||||||
debug_assert!(self.predecessors.is_empty());
|
debug_assert!(self.predecessors.is_empty());
|
||||||
debug_assert!(self.backedges.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) {
|
if self.preorder.dominates(ebb, pred_ebb) {
|
||||||
self.backedges.push(pred_inst);
|
self.backedges.push(pred_inst);
|
||||||
} else {
|
} else {
|
||||||
@@ -915,7 +927,10 @@ impl VirtualCopies {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// This EBB hasn't been seen before.
|
// 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));
|
self.branches.push((pred_inst, ebb));
|
||||||
}
|
}
|
||||||
last_ebb = Some(ebb);
|
last_ebb = Some(ebb);
|
||||||
|
|||||||
@@ -176,7 +176,7 @@
|
|||||||
//! There is some room for improvement.
|
//! There is some room for improvement.
|
||||||
|
|
||||||
use entity::SparseMap;
|
use entity::SparseMap;
|
||||||
use flowgraph::ControlFlowGraph;
|
use flowgraph::{BasicBlock, ControlFlowGraph};
|
||||||
use ir::dfg::ValueDef;
|
use ir::dfg::ValueDef;
|
||||||
use ir::{Ebb, Function, Inst, Layout, ProgramPoint, Value};
|
use ir::{Ebb, Function, Inst, Layout, ProgramPoint, Value};
|
||||||
use isa::{EncInfo, OperandConstraint, TargetIsa};
|
use isa::{EncInfo, OperandConstraint, TargetIsa};
|
||||||
@@ -272,7 +272,11 @@ fn extend_to_use(
|
|||||||
while let Some(livein) = worklist.pop() {
|
while let Some(livein) = worklist.pop() {
|
||||||
// We've learned that the value needs to be live-in to the `livein` EBB.
|
// 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`.
|
// 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) {
|
if lr.extend_in_ebb(pred, branch, &func.layout, forest) {
|
||||||
// This predecessor EBB also became live-in. We need to process it later.
|
// This predecessor EBB also became live-in. We need to process it later.
|
||||||
worklist.push(pred);
|
worklist.push(pred);
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
use dbg::DisplayList;
|
use dbg::DisplayList;
|
||||||
use dominator_tree::{DominatorTree, DominatorTreePreorder};
|
use dominator_tree::{DominatorTree, DominatorTreePreorder};
|
||||||
use flowgraph::ControlFlowGraph;
|
use flowgraph::{BasicBlock, ControlFlowGraph};
|
||||||
use ir::{ExpandedProgramPoint, Function};
|
use ir::{ExpandedProgramPoint, Function};
|
||||||
use regalloc::liveness::Liveness;
|
use regalloc::liveness::Liveness;
|
||||||
use regalloc::virtregs::VirtRegs;
|
use regalloc::virtregs::VirtRegs;
|
||||||
@@ -138,7 +138,7 @@ impl<'a> CssaVerifier<'a> {
|
|||||||
fn check_cssa(&self) -> VerifierResult<()> {
|
fn check_cssa(&self) -> VerifierResult<()> {
|
||||||
for ebb in self.func.layout.ebbs() {
|
for ebb in self.func.layout.ebbs() {
|
||||||
let ebb_params = self.func.dfg.ebb_params(ebb);
|
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);
|
let pred_args = self.func.dfg.inst_variable_args(pred);
|
||||||
// This should have been caught by an earlier verifier pass.
|
// This should have been caught by an earlier verifier pass.
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
//! Verify CPU flags values.
|
//! Verify CPU flags values.
|
||||||
|
|
||||||
use entity::{EntityMap, SparseSet};
|
use entity::{EntityMap, SparseSet};
|
||||||
use flowgraph::ControlFlowGraph;
|
use flowgraph::{BasicBlock, ControlFlowGraph};
|
||||||
use ir;
|
use ir;
|
||||||
use ir::instructions::BranchInfo;
|
use ir::instructions::BranchInfo;
|
||||||
use isa;
|
use isa;
|
||||||
@@ -61,7 +61,7 @@ impl<'a> FlagsVerifier<'a> {
|
|||||||
// Revisit any predecessor blocks the first time we see a live-in for `ebb`.
|
// Revisit any predecessor blocks the first time we see a live-in for `ebb`.
|
||||||
None => {
|
None => {
|
||||||
self.livein[ebb] = value.into();
|
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);
|
worklist.insert(pred);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
//! Liveness verifier.
|
//! Liveness verifier.
|
||||||
|
|
||||||
use flowgraph::ControlFlowGraph;
|
use flowgraph::{BasicBlock, ControlFlowGraph};
|
||||||
use ir::entities::AnyEntity;
|
use ir::entities::AnyEntity;
|
||||||
use ir::{ExpandedProgramPoint, Function, Inst, ProgramOrder, ProgramPoint, Value};
|
use ir::{ExpandedProgramPoint, Function, Inst, ProgramOrder, ProgramPoint, Value};
|
||||||
use isa::TargetIsa;
|
use isa::TargetIsa;
|
||||||
@@ -194,7 +194,7 @@ impl<'a> LivenessVerifier<'a> {
|
|||||||
// Check all the EBBs in the interval independently.
|
// Check all the EBBs in the interval independently.
|
||||||
loop {
|
loop {
|
||||||
// If `val` is live-in at `ebb`, it must be live at all the predecessors.
|
// 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) {
|
if !self.live_at_use(lr, pred) {
|
||||||
return err!(
|
return err!(
|
||||||
pred,
|
pred,
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ use self::flags::verify_flags;
|
|||||||
use dbg::DisplayList;
|
use dbg::DisplayList;
|
||||||
use dominator_tree::DominatorTree;
|
use dominator_tree::DominatorTree;
|
||||||
use entity::SparseSet;
|
use entity::SparseSet;
|
||||||
use flowgraph::ControlFlowGraph;
|
use flowgraph::{BasicBlock, ControlFlowGraph};
|
||||||
use ir;
|
use ir;
|
||||||
use ir::entities::AnyEntity;
|
use ir::entities::AnyEntity;
|
||||||
use ir::instructions::{BranchInfo, CallInfo, InstructionFormat, ResolvedConstraint};
|
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);
|
return err!(ebb, "cfg had unexpected successor(s) {:?}", excess_succs);
|
||||||
}
|
}
|
||||||
|
|
||||||
expected_preds.extend(self.expected_cfg.pred_iter(ebb).map(|(_, inst)| inst));
|
expected_preds.extend(
|
||||||
got_preds.extend(cfg.pred_iter(ebb).map(|(_, inst)| inst));
|
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<Inst> = expected_preds.difference(&got_preds).cloned().collect();
|
let missing_preds: Vec<Inst> = expected_preds.difference(&got_preds).cloned().collect();
|
||||||
if !missing_preds.is_empty() {
|
if !missing_preds.is_empty() {
|
||||||
|
|||||||
Reference in New Issue
Block a user