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.
use crate::{domtree, postorder, Block, Function, Inst, OperandKind, ProgPoint};
use crate::{domtree, postorder, Block, Function, Inst, OperandKind, ProgPoint, RegAllocError};
#[derive(Clone, Debug)]
pub struct CFGInfo {
@@ -37,7 +37,7 @@ pub struct CFGInfo {
}
impl CFGInfo {
pub fn new<F: Function>(f: &F) -> CFGInfo {
pub fn new<F: Function>(f: &F) -> Result<CFGInfo, RegAllocError> {
let postorder =
postorder::calculate(f.blocks(), f.entry_block(), |block| f.block_succs(block));
let domtree = domtree::calculate(
@@ -74,20 +74,16 @@ impl CFGInfo {
if f.block_preds(block).len() > 1 {
for (i, &pred) in f.block_preds(block).iter().enumerate() {
// Assert critical edge condition.
assert_eq!(
f.block_succs(pred).len(),
1,
"Edge {} -> {} is critical",
pred.index(),
block.index(),
);
// Check critical edge condition.
if f.block_succs(pred).len() > 1 {
return Err(RegAllocError::CritEdge(pred, block));
}
pred_pos[pred.index()] = i;
}
}
}
CFGInfo {
Ok(CFGInfo {
postorder,
domtree,
insn_block,
@@ -96,7 +92,7 @@ impl CFGInfo {
block_entry,
block_exit,
pred_pos,
}
})
}
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> {
let cfginfo = CFGInfo::new(func);
let cfginfo = CFGInfo::new(func)?;
let mut env = Env::new(func, mach_env, cfginfo);
env.init()?;

View File

@@ -958,6 +958,8 @@ impl Output {
/// An error that prevents allocation.
#[derive(Clone, Debug)]
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
/// illegal use. `inst` may be `Inst::invalid()` if this concerns
/// a block param.