Skip to content

Commit 13f0c82

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 193ba9f commit 13f0c82

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
@@ -534,6 +534,13 @@ pub enum OperandConstraint {
534534
FixedReg(PReg),
535535
/// On defs only: reuse a use's register.
536536
Reuse(usize),
537+
/// Operand must be in a specific range of registers.
538+
///
539+
/// The contained `usize` indicates the (exclusive) upper limit of a
540+
/// register range, `n`. An operand with this constraint may allocate a
541+
/// register between `0 ..= n-1`. Due to encoding constraints, `n` must be a
542+
/// power of two and below 2^16.
543+
Limit(usize),
537544
}
538545

539546
impl core::fmt::Display for OperandConstraint {
@@ -542,8 +549,9 @@ impl core::fmt::Display for OperandConstraint {
542549
Self::Any => write!(f, "any"),
543550
Self::Reg => write!(f, "reg"),
544551
Self::Stack => write!(f, "stack"),
545-
Self::FixedReg(preg) => write!(f, "fixed({})", preg),
546-
Self::Reuse(idx) => write!(f, "reuse({})", idx),
552+
Self::FixedReg(preg) => write!(f, "fixed({preg})"),
553+
Self::Reuse(idx) => write!(f, "reuse({idx})"),
554+
Self::Limit(max) => write!(f, "limit(0..={})", max - 1),
547555
}
548556
}
549557
}
@@ -618,6 +626,7 @@ pub struct Operand {
618626
/// The constraints are encoded as follows:
619627
/// - 1xxxxxx => FixedReg(preg)
620628
/// - 01xxxxx => Reuse(index)
629+
/// - 001xxxx => Limit(max)
621630
/// - 0000000 => Any
622631
/// - 0000001 => Reg
623632
/// - 0000010 => Stack
@@ -646,6 +655,12 @@ impl Operand {
646655
debug_assert!(which <= 0b11111);
647656
0b0100000 | which as u32
648657
}
658+
OperandConstraint::Limit(max) => {
659+
assert!(max.is_power_of_two());
660+
let log2 = max.ilog2();
661+
debug_assert!(log2 <= 0b1111);
662+
0b0010000 | log2 as u32
663+
}
649664
};
650665
let class_field = vreg.class() as u8 as u32;
651666
let pos_field = pos as u8 as u32;
@@ -906,6 +921,8 @@ impl Operand {
906921
OperandConstraint::FixedReg(PReg::new(constraint_field & 0b0111111, self.class()))
907922
} else if constraint_field & 0b0100000 != 0 {
908923
OperandConstraint::Reuse(constraint_field & 0b0011111)
924+
} else if constraint_field & 0b0010000 != 0 {
925+
OperandConstraint::Limit(1 << (constraint_field & 0b0001111))
909926
} else {
910927
match constraint_field {
911928
0 => OperandConstraint::Any,

0 commit comments

Comments
 (0)