Error checking: properly signal a crit-edge requirement failure (used for regalloc.rs fuzzer)
This commit is contained in:
20
src/cfg.rs
20
src/cfg.rs
@@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
//! Lightweight CFG analyses.
|
//! Lightweight CFG analyses.
|
||||||
|
|
||||||
use crate::{domtree, postorder, Block, Function, Inst, OperandKind, ProgPoint};
|
use crate::{domtree, postorder, Block, Function, Inst, OperandKind, ProgPoint, RegAllocError};
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct CFGInfo {
|
pub struct CFGInfo {
|
||||||
@@ -37,7 +37,7 @@ pub struct CFGInfo {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl CFGInfo {
|
impl CFGInfo {
|
||||||
pub fn new<F: Function>(f: &F) -> CFGInfo {
|
pub fn new<F: Function>(f: &F) -> Result<CFGInfo, RegAllocError> {
|
||||||
let postorder =
|
let postorder =
|
||||||
postorder::calculate(f.blocks(), f.entry_block(), |block| f.block_succs(block));
|
postorder::calculate(f.blocks(), f.entry_block(), |block| f.block_succs(block));
|
||||||
let domtree = domtree::calculate(
|
let domtree = domtree::calculate(
|
||||||
@@ -74,20 +74,16 @@ impl CFGInfo {
|
|||||||
|
|
||||||
if f.block_preds(block).len() > 1 {
|
if f.block_preds(block).len() > 1 {
|
||||||
for (i, &pred) in f.block_preds(block).iter().enumerate() {
|
for (i, &pred) in f.block_preds(block).iter().enumerate() {
|
||||||
// Assert critical edge condition.
|
// Check critical edge condition.
|
||||||
assert_eq!(
|
if f.block_succs(pred).len() > 1 {
|
||||||
f.block_succs(pred).len(),
|
return Err(RegAllocError::CritEdge(pred, block));
|
||||||
1,
|
}
|
||||||
"Edge {} -> {} is critical",
|
|
||||||
pred.index(),
|
|
||||||
block.index(),
|
|
||||||
);
|
|
||||||
pred_pos[pred.index()] = i;
|
pred_pos[pred.index()] = i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CFGInfo {
|
Ok(CFGInfo {
|
||||||
postorder,
|
postorder,
|
||||||
domtree,
|
domtree,
|
||||||
insn_block,
|
insn_block,
|
||||||
@@ -96,7 +92,7 @@ impl CFGInfo {
|
|||||||
block_entry,
|
block_entry,
|
||||||
block_exit,
|
block_exit,
|
||||||
pred_pos,
|
pred_pos,
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn dominates(&self, a: Block, b: Block) -> bool {
|
pub fn dominates(&self, a: Block, b: Block) -> bool {
|
||||||
|
|||||||
@@ -4445,7 +4445,7 @@ impl<'a, F: Function> Env<'a, F> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn run<F: Function>(func: &F, mach_env: &MachineEnv) -> Result<Output, RegAllocError> {
|
pub fn run<F: Function>(func: &F, mach_env: &MachineEnv) -> Result<Output, RegAllocError> {
|
||||||
let cfginfo = CFGInfo::new(func);
|
let cfginfo = CFGInfo::new(func)?;
|
||||||
|
|
||||||
let mut env = Env::new(func, mach_env, cfginfo);
|
let mut env = Env::new(func, mach_env, cfginfo);
|
||||||
env.init()?;
|
env.init()?;
|
||||||
|
|||||||
@@ -958,6 +958,8 @@ impl Output {
|
|||||||
/// An error that prevents allocation.
|
/// An error that prevents allocation.
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub enum RegAllocError {
|
pub enum RegAllocError {
|
||||||
|
/// Critical edge is not split between given blocks.
|
||||||
|
CritEdge(Block, Block),
|
||||||
/// Invalid SSA for given vreg at given inst: multiple defs or
|
/// Invalid SSA for given vreg at given inst: multiple defs or
|
||||||
/// illegal use. `inst` may be `Inst::invalid()` if this concerns
|
/// illegal use. `inst` may be `Inst::invalid()` if this concerns
|
||||||
/// a block param.
|
/// a block param.
|
||||||
|
|||||||
Reference in New Issue
Block a user