diff --git a/cranelift/codegen/src/machinst/vcode.rs b/cranelift/codegen/src/machinst/vcode.rs index 68a0549d791a..66ab06009c77 100644 --- a/cranelift/codegen/src/machinst/vcode.rs +++ b/cranelift/codegen/src/machinst/vcode.rs @@ -602,6 +602,15 @@ impl VCodeBuilder { self.reverse_and_finalize(); } self.collect_operands(); + + // Apply register aliases to the `reftyped_vregs` list since this list + // will be returned directly to `regalloc2` eventually and all + // operands/results of instructions will use the alias-resolved vregs + // from `regalloc2`'s perspective. + for reg in self.vcode.reftyped_vregs.iter_mut() { + *reg = Self::resolve_vreg_alias_impl(&self.vcode.vreg_aliases, *reg); + } + self.compute_preds_from_succs(); self.vcode.debug_value_labels.sort_unstable(); self.vcode @@ -1122,6 +1131,29 @@ impl VCode { pub fn bindex_to_bb(&self, block: BlockIndex) -> Option { self.block_order.lowered_order()[block.index()].orig_block() } + + #[inline] + fn assert_no_vreg_aliases<'a>(&self, list: &'a [VReg]) -> &'a [VReg] { + for vreg in list { + self.assert_not_vreg_alias(*vreg); + } + list + } + + #[inline] + fn assert_not_vreg_alias(&self, vreg: VReg) -> VReg { + debug_assert!(VCodeBuilder::::resolve_vreg_alias_impl(&self.vreg_aliases, vreg) == vreg); + vreg + } + + #[inline] + fn assert_operand_not_vreg_alias(&self, op: Operand) -> Operand { + // It should be true by construction that `Operand`s do not contain any + // aliased vregs since they're all collected and mapped when the VCode + // is itself constructed. + self.assert_not_vreg_alias(op.vreg()); + op + } } impl RegallocFunction for VCode { @@ -1154,7 +1186,10 @@ impl RegallocFunction for VCode { fn block_params(&self, block: BlockIndex) -> &[VReg] { let (start, end) = self.block_params_range[block.index()]; - &self.block_params[start as usize..end as usize] + let ret = &self.block_params[start as usize..end as usize]; + // Currently block params are never aliased to another vreg, but + // double-check just to be sure. + self.assert_no_vreg_aliases(ret) } fn branch_blockparams(&self, block: BlockIndex, _insn: InsnIndex, succ_idx: usize) -> &[VReg] { @@ -1162,7 +1197,9 @@ impl RegallocFunction for VCode { let succ_ranges = &self.branch_block_arg_range[succ_range_start as usize..succ_range_end as usize]; let (branch_block_args_start, branch_block_args_end) = succ_ranges[succ_idx]; - &self.branch_block_args[branch_block_args_start as usize..branch_block_args_end as usize] + let ret = &self.branch_block_args + [branch_block_args_start as usize..branch_block_args_end as usize]; + self.assert_no_vreg_aliases(ret) } fn is_ret(&self, insn: InsnIndex) -> bool { @@ -1184,12 +1221,20 @@ impl RegallocFunction for VCode { } fn is_move(&self, insn: InsnIndex) -> Option<(Operand, Operand)> { - self.is_move.get(&insn).cloned() + let (a, b) = self.is_move.get(&insn)?; + Some(( + self.assert_operand_not_vreg_alias(*a), + self.assert_operand_not_vreg_alias(*b), + )) } fn inst_operands(&self, insn: InsnIndex) -> &[Operand] { let (start, end) = self.operand_ranges[insn.index()]; - &self.operands[start as usize..end as usize] + let ret = &self.operands[start as usize..end as usize]; + for op in ret { + self.assert_operand_not_vreg_alias(*op); + } + ret } fn inst_clobbers(&self, insn: InsnIndex) -> &[PReg] { @@ -1205,10 +1250,16 @@ impl RegallocFunction for VCode { } fn reftype_vregs(&self) -> &[VReg] { - &self.reftyped_vregs[..] + self.assert_no_vreg_aliases(&self.reftyped_vregs[..]) } fn debug_value_labels(&self) -> &[(VReg, InsnIndex, InsnIndex, u32)] { + // VRegs here are inserted into `debug_value_labels` after code is + // generated and aliases are fully defined, so no double-check that + // aliases are not lingering. + for (vreg, ..) in self.debug_value_labels.iter() { + self.assert_not_vreg_alias(*vreg); + } &self.debug_value_labels[..] }