Skip to content

Commit bc398bd

Browse files
authored
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
1 parent 346b7f3 commit bc398bd

File tree

1 file changed

+18
-0
lines changed

1 file changed

+18
-0
lines changed

src/ssa.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ pub fn validate_ssa<F: Function>(f: &F, cfginfo: &CFGInfo) -> Result<(), RegAllo
1717
let block = Block::new(block);
1818
let mut def = |vreg: VReg, inst| {
1919
if defined_in[vreg.vreg()].is_valid() {
20+
trace!("Multiple def constraints for {:?}", vreg);
2021
Err(RegAllocError::SSA(vreg, inst))
2122
} else {
2223
defined_in[vreg.vreg()] = block;
@@ -48,6 +49,12 @@ pub fn validate_ssa<F: Function>(f: &F, cfginfo: &CFGInfo) -> Result<(), RegAllo
4849
for iix in f.block_insns(block).iter() {
4950
let operands = f.inst_operands(iix);
5051
for operand in operands {
52+
// Fixed registers uses will likely not be SSA, but they also
53+
// won't receive assignments.
54+
if operand.as_fixed_nonallocatable().is_some() {
55+
continue;
56+
}
57+
5158
match operand.kind() {
5259
OperandKind::Use => {
5360
let def_block = defined_in[operand.vreg().vreg()];
@@ -58,6 +65,7 @@ pub fn validate_ssa<F: Function>(f: &F, cfginfo: &CFGInfo) -> Result<(), RegAllo
5865
cfginfo.dominates(def_block, block)
5966
};
6067
if !okay {
68+
trace!("Invalid use {:?}", operand.vreg());
6169
return Err(RegAllocError::SSA(operand.vreg(), iix));
6270
}
6371
}
@@ -69,10 +77,12 @@ pub fn validate_ssa<F: Function>(f: &F, cfginfo: &CFGInfo) -> Result<(), RegAllo
6977
// Mod (modify) operands are not used in SSA,
7078
// but can be used by non-SSA code (e.g. with
7179
// the regalloc.rs compatibility shim).
80+
trace!("Unexpected mod {:?}", operand.vreg());
7281
return Err(RegAllocError::SSA(operand.vreg(), iix));
7382
}
7483
}
7584
}
85+
7686
// In SSA form, an instruction can't use a VReg that it
7787
// also defines. So only record this instruction's defs
7888
// after its uses have been checked.
@@ -94,19 +104,26 @@ pub fn validate_ssa<F: Function>(f: &F, cfginfo: &CFGInfo) -> Result<(), RegAllo
94104
for insn in insns.iter() {
95105
if insn == insns.last() {
96106
if !(f.is_branch(insn) || f.is_ret(insn)) {
107+
trace!("block {:?} is not terminated by a branch or ret!", block);
97108
return Err(RegAllocError::BB(block));
98109
}
99110
if f.is_branch(insn) {
100111
for (i, &succ) in f.block_succs(block).iter().enumerate() {
101112
let blockparams_in = f.block_params(succ);
102113
let blockparams_out = f.branch_blockparams(block, insn, i);
103114
if blockparams_in.len() != blockparams_out.len() {
115+
trace!(
116+
"Mismatch on block params, found {} expected {}",
117+
blockparams_out.len(),
118+
blockparams_in.len()
119+
);
104120
return Err(RegAllocError::Branch(insn));
105121
}
106122
}
107123
}
108124
} else {
109125
if f.is_branch(insn) || f.is_ret(insn) {
126+
trace!("Block terminator found in the middle of a block");
110127
return Err(RegAllocError::BB(block));
111128
}
112129
}
@@ -116,6 +133,7 @@ pub fn validate_ssa<F: Function>(f: &F, cfginfo: &CFGInfo) -> Result<(), RegAllo
116133
// Check that the entry block has no block args: otherwise it is
117134
// undefined what their value would be.
118135
if f.block_params(f.entry_block()).len() > 0 {
136+
trace!("Entry block contains block args");
119137
return Err(RegAllocError::BB(f.entry_block()));
120138
}
121139

0 commit comments

Comments
 (0)