Add fixed-non-allocatable operand support (#77)

This allows a non-allocatable `PReg` to be passed on directly to the
allocations vector without any liverange tracking from the register
allocator. The main intended use case is to support ISA-specific special
registers such as a fixed zero register.
This commit is contained in:
Amanieu d'Antras
2022-09-20 03:23:53 +08:00
committed by GitHub
parent aeef47a06b
commit 1495c1e342
6 changed files with 67 additions and 13 deletions

View File

@@ -366,6 +366,9 @@ impl<'a, F: Function> Env<'a, F> {
for pos in &[OperandPos::Late, OperandPos::Early] {
for op in self.func.inst_operands(inst) {
if op.as_fixed_nonallocatable().is_some() {
continue;
}
if op.pos() == *pos {
let was_live = live.get(op.vreg().vreg());
trace!("op {:?} was_live = {}", op, was_live);
@@ -511,6 +514,9 @@ impl<'a, F: Function> Env<'a, F> {
let mut reused_input = None;
for op in self.func.inst_operands(inst) {
if let OperandConstraint::Reuse(i) = op.constraint() {
debug_assert!(self.func.inst_operands(inst)[i]
.as_fixed_nonallocatable()
.is_none());
reused_input = Some(self.func.inst_operands(inst)[i].vreg());
break;
}
@@ -931,6 +937,9 @@ impl<'a, F: Function> Env<'a, F> {
let mut operand_rewrites: FxHashMap<usize, Operand> = FxHashMap::default();
let mut late_def_fixed: SmallVec<[(PReg, Operand, usize); 2]> = smallvec![];
for (i, &operand) in self.func.inst_operands(inst).iter().enumerate() {
if operand.as_fixed_nonallocatable().is_some() {
continue;
}
if let OperandConstraint::FixedReg(preg) = operand.constraint() {
match operand.pos() {
OperandPos::Late => {
@@ -952,6 +961,9 @@ impl<'a, F: Function> Env<'a, F> {
}
}
for (i, &operand) in self.func.inst_operands(inst).iter().enumerate() {
if operand.as_fixed_nonallocatable().is_some() {
continue;
}
if let OperandConstraint::FixedReg(preg) = operand.constraint() {
match operand.pos() {
OperandPos::Early => {
@@ -1057,6 +1069,15 @@ impl<'a, F: Function> Env<'a, F> {
operand
);
// If this is a "fixed non-allocatable
// register" operand, set the alloc
// immediately and then ignore the operand
// hereafter.
if let Some(preg) = operand.as_fixed_nonallocatable() {
self.set_alloc(inst, i, Allocation::reg(preg));
continue;
}
match operand.kind() {
OperandKind::Def | OperandKind::Mod => {
trace!("Def of {} at {:?}", operand.vreg(), pos);