diff --git a/cranelift/codegen/src/isa/s390x/inst/mod.rs b/cranelift/codegen/src/isa/s390x/inst/mod.rs index 6ca7adadcf..5caf862c17 100644 --- a/cranelift/codegen/src/isa/s390x/inst/mod.rs +++ b/cranelift/codegen/src/isa/s390x/inst/mod.rs @@ -1068,6 +1068,12 @@ fn s390x_get_operands VReg>(inst: &Inst, collector: &mut OperandC for inst in body.iter() { s390x_get_operands(inst, collector); } + + // `reuse_def` constraints can't be permitted in a Loop instruction because the operand + // index will always be relative to the Loop instruction, not the individual + // instruction in the loop body. However, fixed-nonallocatable registers used with + // instructions that would have emitted `reuse_def` constraints are fine. + debug_assert!(collector.no_reuse_def()); } &Inst::CondBreak { .. } => {} &Inst::VirtualSPOffsetAdj { .. } => {} diff --git a/cranelift/codegen/src/machinst/reg.rs b/cranelift/codegen/src/machinst/reg.rs index 22249fffa4..32838fdab0 100644 --- a/cranelift/codegen/src/machinst/reg.rs +++ b/cranelift/codegen/src/machinst/reg.rs @@ -4,7 +4,7 @@ use alloc::{string::String, vec::Vec}; use core::{fmt::Debug, hash::Hash}; -use regalloc2::{Allocation, MachineEnv, Operand, PReg, PRegSet, VReg}; +use regalloc2::{Allocation, MachineEnv, Operand, OperandConstraint, PReg, PRegSet, VReg}; #[cfg(feature = "enable-serde")] use serde::{Deserialize, Serialize}; @@ -329,6 +329,16 @@ impl<'a, F: Fn(VReg) -> VReg> OperandCollector<'a, F> { } } + /// Returns true if no reuse_def constraints have been added. + pub fn no_reuse_def(&self) -> bool { + !self.operands[self.operands_start..] + .iter() + .any(|operand| match operand.constraint() { + OperandConstraint::Reuse(_) => true, + _ => false, + }) + } + fn is_allocatable_preg(&self, reg: PReg) -> bool { self.allocatable.contains(reg) }