Skip to content

Commit 0195a64

Browse files
committed
Finish up regalloc verifier support for remat copies
It now disallows remat-to-spill copies (as decided for now) and verifies that rematerialized instructions have the expected operands.
1 parent 3ae0c6a commit 0195a64

File tree

1 file changed

+40
-8
lines changed

1 file changed

+40
-8
lines changed

crates/codegen/src/regalloc/verify.rs

Lines changed: 40 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -35,12 +35,15 @@ pub enum VerifierError {
3535
op: u32,
3636
found_vreg: Option<VirtReg>,
3737
},
38-
SpillToSpillCopy {
38+
IllegalSpillCopy {
3939
copy_idx: u32,
4040
},
4141
UndefCopySource {
4242
copy_idx: u32,
4343
},
44+
BadRematOperands {
45+
copy_idx: u32,
46+
},
4447
BadGhostCopyBlock {
4548
block: Block,
4649
},
@@ -119,9 +122,13 @@ impl<M: MachineCore> fmt::Display for DisplayVerifierError<'_, M> {
119122
"expected {instr} use {op} to be of {expected_vreg}, found {found_vreg}"
120123
)
121124
}
122-
VerifierError::SpillToSpillCopy { copy_idx } => {
125+
VerifierError::IllegalSpillCopy { copy_idx } => {
123126
let copy = &self.assignment.copies[copy_idx as usize];
124-
write!(f, "copy before {} copies between spill slots", copy.instr)
127+
write!(
128+
f,
129+
"copy before {} copies from non-register into spill",
130+
copy.instr
131+
)
125132
}
126133
VerifierError::UndefCopySource { copy_idx } => {
127134
let copy = &self.assignment.copies[copy_idx as usize];
@@ -133,6 +140,19 @@ impl<M: MachineCore> fmt::Display for DisplayVerifierError<'_, M> {
133140
copy.instr
134141
)
135142
}
143+
VerifierError::BadRematOperands { copy_idx } => {
144+
let copy = &self.assignment.copies[copy_idx as usize];
145+
let remat_instr = match copy.copy.from {
146+
AssignmentCopySource::Remat(instr) => instr,
147+
_ => unreachable!(),
148+
};
149+
150+
write!(
151+
f,
152+
"instruction {} rematerialized before {} has unsupported operands",
153+
remat_instr, copy.instr
154+
)
155+
}
136156
VerifierError::BadGhostCopyBlock { block } => {
137157
write!(f, "block '{block}' contained exit ghost copies despite not having a single successor")
138158
}
@@ -246,17 +266,29 @@ fn verify_copy<M: MachineCore>(
246266
copy: &AssignmentCopy,
247267
reg_state: &mut KnownRegState,
248268
) -> Result<(), VerifierError> {
249-
// TODO: Should remat into a stack slot should be disallowed?
250-
if copy.from.is_spill() && copy.to.is_spill() {
251-
return Err(VerifierError::SpillToSpillCopy { copy_idx });
269+
if !copy.from.is_reg() && copy.to.is_spill() {
270+
return Err(VerifierError::IllegalSpillCopy { copy_idx });
252271
}
253272

254273
let from_vreg = match copy.from {
255274
AssignmentCopySource::Operand(from) => *reg_state
256275
.get(&from)
257276
.ok_or(VerifierError::UndefCopySource { copy_idx })?,
258-
// TODO: Validate instruction shape.
259-
AssignmentCopySource::Remat(instr) => lir.instr_defs(instr)[0].reg(),
277+
AssignmentCopySource::Remat(instr) => {
278+
if !lir.instr_uses(instr).is_empty() {
279+
return Err(VerifierError::BadRematOperands { copy_idx });
280+
}
281+
282+
let [def] = lir.instr_defs(instr) else {
283+
return Err(VerifierError::BadRematOperands { copy_idx });
284+
};
285+
286+
if def.constraint() != DefOperandConstraint::AnyReg {
287+
return Err(VerifierError::BadRematOperands { copy_idx });
288+
}
289+
290+
def.reg()
291+
}
260292
};
261293

262294
reg_state.insert(copy.to, from_vreg);

0 commit comments

Comments
 (0)