Error checking: properly signal a crit-edge requirement failure (used for regalloc.rs fuzzer)

This commit is contained in:
Chris Fallin
2021-05-08 21:48:58 -07:00
parent f1fc9a8f7e
commit b9e89885c4
3 changed files with 11 additions and 13 deletions

View File

@@ -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 {

View File

@@ -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()?;

View File

@@ -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.