Skip to content

Commit 0a2d1bd

Browse files
committed
Add OperandConstraint::Limit
This allows users of `regalloc2` to specify a register range, `0..n-1`, in which to allocate an operand. The upper limit, `n`, must be a power of two to fit in the bits available in the `Operand` encoding.
1 parent 454cd01 commit 0a2d1bd

File tree

1 file changed

+19
-2
lines changed

1 file changed

+19
-2
lines changed

src/lib.rs

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -547,6 +547,13 @@ pub enum OperandConstraint {
547547
FixedReg(PReg),
548548
/// On defs only: reuse a use's register.
549549
Reuse(usize),
550+
/// Operand must be in a specific range of registers.
551+
///
552+
/// The contained `usize` indicates the (exclusive) upper limit of a
553+
/// register range, `n`. An operand with this constraint may allocate a
554+
/// register between `0 ..= n-1`. Due to encoding constraints, `n` must be a
555+
/// power of two and below 2^16.
556+
Limit(usize),
550557
}
551558

552559
impl core::fmt::Display for OperandConstraint {
@@ -555,8 +562,9 @@ impl core::fmt::Display for OperandConstraint {
555562
Self::Any => write!(f, "any"),
556563
Self::Reg => write!(f, "reg"),
557564
Self::Stack => write!(f, "stack"),
558-
Self::FixedReg(preg) => write!(f, "fixed({})", preg),
559-
Self::Reuse(idx) => write!(f, "reuse({})", idx),
565+
Self::FixedReg(preg) => write!(f, "fixed({preg})"),
566+
Self::Reuse(idx) => write!(f, "reuse({idx})"),
567+
Self::Limit(max) => write!(f, "limit(0..={})", max - 1),
560568
}
561569
}
562570
}
@@ -631,6 +639,7 @@ pub struct Operand {
631639
/// The constraints are encoded as follows:
632640
/// - 1xxxxxx => FixedReg(preg)
633641
/// - 01xxxxx => Reuse(index)
642+
/// - 001xxxx => Limit(max)
634643
/// - 0000000 => Any
635644
/// - 0000001 => Reg
636645
/// - 0000010 => Stack
@@ -659,6 +668,12 @@ impl Operand {
659668
debug_assert!(which <= 0b11111);
660669
0b0100000 | which as u32
661670
}
671+
OperandConstraint::Limit(max) => {
672+
assert!(max.is_power_of_two());
673+
let log2 = max.ilog2();
674+
debug_assert!(log2 <= 0b1111);
675+
0b0010000 | log2 as u32
676+
}
662677
};
663678
let class_field = vreg.class() as u8 as u32;
664679
let pos_field = pos as u8 as u32;
@@ -919,6 +934,8 @@ impl Operand {
919934
OperandConstraint::FixedReg(PReg::new(constraint_field & 0b0111111, self.class()))
920935
} else if constraint_field & 0b0100000 != 0 {
921936
OperandConstraint::Reuse(constraint_field & 0b0011111)
937+
} else if constraint_field & 0b0010000 != 0 {
938+
OperandConstraint::Limit(1 << (constraint_field & 0b0001111))
922939
} else {
923940
match constraint_field {
924941
0 => OperandConstraint::Any,

0 commit comments

Comments
 (0)