Misc usability and functionality enhancements:

- Support preferred and non-preferred subsets of a register class. This
  allows allocating, e.g., caller-saved registers before callee-saved
  registers.
- Allow branch blockparam args to start an a certain offset in branch
  operands; this allows branches to have other operands too (e.g.,
  conditional-branch inputs).
- Allow `OperandOrAllocation` to be constructed from an `Allocation` and
  `OperandKind` as well (i.e., an allocation with an use/def bit).
This commit is contained in:
Chris Fallin
2021-04-30 21:14:09 -07:00
parent 414f3f828d
commit 49c54b6144
3 changed files with 104 additions and 44 deletions

View File

@@ -579,6 +579,15 @@ impl OperandOrAllocation {
debug_assert!(alloc.bits() >> 29 >= 5);
Self { bits: alloc.bits() }
}
pub fn from_alloc_and_kind(alloc: Allocation, kind: OperandKind) -> Self {
debug_assert!(alloc.bits() >> 29 >= 5);
let bits = alloc.bits()
| match kind {
OperandKind::Def => 0,
OperandKind::Use => 1 << 28,
};
Self { bits }
}
pub fn is_operand(&self) -> bool {
(self.bits >> 29) <= 4
}
@@ -659,10 +668,22 @@ pub trait Function {
fn is_ret(&self, insn: Inst) -> bool;
/// Determine whether an instruction is the end-of-block
/// branch. If so, its operands *must* be the block parameters for
/// each of its block's `block_succs` successor blocks, in order.
/// branch. If so, its operands at the indices given by
/// `branch_blockparam_arg_offset()` below *must* be the block
/// parameters for each of its block's `block_succs` successor
/// blocks, in order.
fn is_branch(&self, insn: Inst) -> bool;
/// If `insn` is a branch at the end of `block`, returns the
/// operand index at which outgoing blockparam arguments are
/// found. Starting at this index, blockparam arguments for each
/// successor block's blockparams, in order, must be found.
///
/// It is an error if `self.inst_operands(insn).len() -
/// self.branch_blockparam_arg_offset(insn)` is not exactly equal
/// to the sum of blockparam counts for all successor blocks.
fn branch_blockparam_arg_offset(&self, block: Block, insn: Inst) -> usize;
/// Determine whether an instruction is a safepoint and requires a stackmap.
fn is_safepoint(&self, _: Inst) -> bool {
false
@@ -842,7 +863,8 @@ pub enum Edit {
#[derive(Clone, Debug)]
pub struct MachineEnv {
regs: Vec<PReg>,
regs_by_class: Vec<Vec<PReg>>,
preferred_regs_by_class: Vec<Vec<PReg>>,
non_preferred_regs_by_class: Vec<Vec<PReg>>,
scratch_by_class: Vec<PReg>,
}