SSA Validator Fixes (#105)
* Don't check for defs on a use of a fixed-nonallocatable operand * Add traces to the ssa validator to aid debugging * Format
This commit is contained in:
18
src/ssa.rs
18
src/ssa.rs
@@ -17,6 +17,7 @@ pub fn validate_ssa<F: Function>(f: &F, cfginfo: &CFGInfo) -> Result<(), RegAllo
|
|||||||
let block = Block::new(block);
|
let block = Block::new(block);
|
||||||
let mut def = |vreg: VReg, inst| {
|
let mut def = |vreg: VReg, inst| {
|
||||||
if defined_in[vreg.vreg()].is_valid() {
|
if defined_in[vreg.vreg()].is_valid() {
|
||||||
|
trace!("Multiple def constraints for {:?}", vreg);
|
||||||
Err(RegAllocError::SSA(vreg, inst))
|
Err(RegAllocError::SSA(vreg, inst))
|
||||||
} else {
|
} else {
|
||||||
defined_in[vreg.vreg()] = block;
|
defined_in[vreg.vreg()] = block;
|
||||||
@@ -48,6 +49,12 @@ pub fn validate_ssa<F: Function>(f: &F, cfginfo: &CFGInfo) -> Result<(), RegAllo
|
|||||||
for iix in f.block_insns(block).iter() {
|
for iix in f.block_insns(block).iter() {
|
||||||
let operands = f.inst_operands(iix);
|
let operands = f.inst_operands(iix);
|
||||||
for operand in operands {
|
for operand in operands {
|
||||||
|
// Fixed registers uses will likely not be SSA, but they also
|
||||||
|
// won't receive assignments.
|
||||||
|
if operand.as_fixed_nonallocatable().is_some() {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
match operand.kind() {
|
match operand.kind() {
|
||||||
OperandKind::Use => {
|
OperandKind::Use => {
|
||||||
let def_block = defined_in[operand.vreg().vreg()];
|
let def_block = defined_in[operand.vreg().vreg()];
|
||||||
@@ -58,6 +65,7 @@ pub fn validate_ssa<F: Function>(f: &F, cfginfo: &CFGInfo) -> Result<(), RegAllo
|
|||||||
cfginfo.dominates(def_block, block)
|
cfginfo.dominates(def_block, block)
|
||||||
};
|
};
|
||||||
if !okay {
|
if !okay {
|
||||||
|
trace!("Invalid use {:?}", operand.vreg());
|
||||||
return Err(RegAllocError::SSA(operand.vreg(), iix));
|
return Err(RegAllocError::SSA(operand.vreg(), iix));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -69,10 +77,12 @@ pub fn validate_ssa<F: Function>(f: &F, cfginfo: &CFGInfo) -> Result<(), RegAllo
|
|||||||
// Mod (modify) operands are not used in SSA,
|
// Mod (modify) operands are not used in SSA,
|
||||||
// but can be used by non-SSA code (e.g. with
|
// but can be used by non-SSA code (e.g. with
|
||||||
// the regalloc.rs compatibility shim).
|
// the regalloc.rs compatibility shim).
|
||||||
|
trace!("Unexpected mod {:?}", operand.vreg());
|
||||||
return Err(RegAllocError::SSA(operand.vreg(), iix));
|
return Err(RegAllocError::SSA(operand.vreg(), iix));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// In SSA form, an instruction can't use a VReg that it
|
// In SSA form, an instruction can't use a VReg that it
|
||||||
// also defines. So only record this instruction's defs
|
// also defines. So only record this instruction's defs
|
||||||
// after its uses have been checked.
|
// after its uses have been checked.
|
||||||
@@ -94,6 +104,7 @@ pub fn validate_ssa<F: Function>(f: &F, cfginfo: &CFGInfo) -> Result<(), RegAllo
|
|||||||
for insn in insns.iter() {
|
for insn in insns.iter() {
|
||||||
if insn == insns.last() {
|
if insn == insns.last() {
|
||||||
if !(f.is_branch(insn) || f.is_ret(insn)) {
|
if !(f.is_branch(insn) || f.is_ret(insn)) {
|
||||||
|
trace!("block {:?} is not terminated by a branch or ret!", block);
|
||||||
return Err(RegAllocError::BB(block));
|
return Err(RegAllocError::BB(block));
|
||||||
}
|
}
|
||||||
if f.is_branch(insn) {
|
if f.is_branch(insn) {
|
||||||
@@ -101,12 +112,18 @@ pub fn validate_ssa<F: Function>(f: &F, cfginfo: &CFGInfo) -> Result<(), RegAllo
|
|||||||
let blockparams_in = f.block_params(succ);
|
let blockparams_in = f.block_params(succ);
|
||||||
let blockparams_out = f.branch_blockparams(block, insn, i);
|
let blockparams_out = f.branch_blockparams(block, insn, i);
|
||||||
if blockparams_in.len() != blockparams_out.len() {
|
if blockparams_in.len() != blockparams_out.len() {
|
||||||
|
trace!(
|
||||||
|
"Mismatch on block params, found {} expected {}",
|
||||||
|
blockparams_out.len(),
|
||||||
|
blockparams_in.len()
|
||||||
|
);
|
||||||
return Err(RegAllocError::Branch(insn));
|
return Err(RegAllocError::Branch(insn));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if f.is_branch(insn) || f.is_ret(insn) {
|
if f.is_branch(insn) || f.is_ret(insn) {
|
||||||
|
trace!("Block terminator found in the middle of a block");
|
||||||
return Err(RegAllocError::BB(block));
|
return Err(RegAllocError::BB(block));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -116,6 +133,7 @@ pub fn validate_ssa<F: Function>(f: &F, cfginfo: &CFGInfo) -> Result<(), RegAllo
|
|||||||
// Check that the entry block has no block args: otherwise it is
|
// Check that the entry block has no block args: otherwise it is
|
||||||
// undefined what their value would be.
|
// undefined what their value would be.
|
||||||
if f.block_params(f.entry_block()).len() > 0 {
|
if f.block_params(f.entry_block()).len() > 0 {
|
||||||
|
trace!("Entry block contains block args");
|
||||||
return Err(RegAllocError::BB(f.entry_block()));
|
return Err(RegAllocError::BB(f.entry_block()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user