pub struct Operand { /* private fields */ }
Expand description
An Operand
encodes everything about a mention of a register in
an instruction: virtual register number, and any constraint that
applies to the register at this program point.
An Operand may be a use or def (this corresponds to LUse
and
LAllocation
in Ion).
Generally, regalloc2 considers operands to have their effects at one of two points that exist in an instruction: “Early” or “Late”. All operands at a given program-point are assigned non-conflicting locations based on their constraints. Each operand has a “kind”, one of use/def/mod, corresponding to read/write/read-write, respectively.
Usually, an instruction’s inputs will be “early uses” and outputs will be “late defs”, though there are valid use-cases for other combinations too. For example, a single “instruction” seen by the regalloc that lowers into multiple machine instructions and reads some of its inputs after it starts to write outputs must either make those input(s) “late uses” or those output(s) “early defs” so that the conflict (overlap) is properly accounted for. See comments on the constructors below for more.
Implementations§
source§impl Operand
impl Operand
sourcepub fn new(
vreg: VReg,
constraint: OperandConstraint,
kind: OperandKind,
pos: OperandPos,
) -> Self
pub fn new( vreg: VReg, constraint: OperandConstraint, kind: OperandKind, pos: OperandPos, ) -> Self
Construct a new operand.
sourcepub fn reg_use(vreg: VReg) -> Self
pub fn reg_use(vreg: VReg) -> Self
Create an Operand
that designates a use of a VReg that must
be in a register, and that is used at the “before” point,
i.e., can be overwritten by a result.
sourcepub fn reg_use_at_end(vreg: VReg) -> Self
pub fn reg_use_at_end(vreg: VReg) -> Self
Create an Operand
that designates a use of a VReg that must
be in a register, and that is used up until the “after” point,
i.e., must not conflict with any results.
sourcepub fn reg_def(vreg: VReg) -> Self
pub fn reg_def(vreg: VReg) -> Self
Create an Operand
that designates a definition of a VReg
that must be in a register, and that occurs at the “after”
point, i.e. may reuse a register that carried a use into this
instruction.
sourcepub fn reg_def_at_start(vreg: VReg) -> Self
pub fn reg_def_at_start(vreg: VReg) -> Self
Create an Operand
that designates a definition of a VReg
that must be in a register, and that occurs early at the
“before” point, i.e., must not conflict with any input to the
instruction.
Note that the register allocator will ensure that such an early-def operand is live throughout the instruction, i.e., also at the after-point. Hence it will also avoid conflicts with all outputs to the instruction. As such, early defs are appropriate for use as “temporary registers” that an instruction can use throughout its execution separately from the inputs and outputs.
sourcepub fn reg_temp(vreg: VReg) -> Self
pub fn reg_temp(vreg: VReg) -> Self
Create an Operand
that designates a def (and use) of a
temporary within the instruction. This register is assumed
to be written by the instruction, and will not conflict with
any input or output, but should not be used after the
instruction completes.
Note that within a single instruction, the dedicated scratch
register (as specified in the MachineEnv
) is also always
available for use. The register allocator may use the register
between instructions in order to implement certain sequences
of moves, but will never hold a value live in the scratch
register across an instruction.
sourcepub fn reg_reuse_def(vreg: VReg, idx: usize) -> Self
pub fn reg_reuse_def(vreg: VReg, idx: usize) -> Self
Create an Operand
that designates a def of a vreg that must
reuse the register assigned to an input to the
instruction. The input is identified by idx
(is the idx
th
Operand
for the instruction) and must be constraint to a
register, i.e., be the result of Operand::reg_use(vreg)
.
sourcepub fn reg_fixed_use(vreg: VReg, preg: PReg) -> Self
pub fn reg_fixed_use(vreg: VReg, preg: PReg) -> Self
Create an Operand
that designates a use of a vreg and
ensures that it is placed in the given, fixed PReg at the
use. It is guaranteed that the Allocation
resulting for this
operand will be preg
.
sourcepub fn reg_fixed_def(vreg: VReg, preg: PReg) -> Self
pub fn reg_fixed_def(vreg: VReg, preg: PReg) -> Self
Create an Operand
that designates a def of a vreg and
ensures that it is placed in the given, fixed PReg at the
def. It is guaranteed that the Allocation
resulting for this
operand will be preg
.
sourcepub fn any_use(vreg: VReg) -> Self
pub fn any_use(vreg: VReg) -> Self
Create an Operand
that designates a use of a vreg and places
no constraints on its location (i.e., it can be allocated into
either a register or on the stack).
sourcepub fn any_def(vreg: VReg) -> Self
pub fn any_def(vreg: VReg) -> Self
Create an Operand
that designates a def of a vreg and places
no constraints on its location (i.e., it can be allocated into
either a register or on the stack).
sourcepub fn fixed_nonallocatable(preg: PReg) -> Self
pub fn fixed_nonallocatable(preg: PReg) -> Self
Create an Operand
that always results in an assignment to the
given fixed preg
, without tracking liveranges in that
preg
. Must only be used for non-allocatable registers.
sourcepub fn vreg(self) -> VReg
pub fn vreg(self) -> VReg
Get the virtual register designated by an operand. Every operand must name some virtual register, even if it constrains the operand to a fixed physical register as well; the vregs are used to track dataflow.
sourcepub fn kind(self) -> OperandKind
pub fn kind(self) -> OperandKind
Get the “kind” of this operand: a definition (write) or a use (read).
sourcepub fn pos(self) -> OperandPos
pub fn pos(self) -> OperandPos
Get the “position” of this operand, i.e., where its read and/or write occurs: either before the instruction executes, or after it does. Ordinarily, uses occur at “before” and defs at “after”, though there are cases where this is not true.
sourcepub fn constraint(self) -> OperandConstraint
pub fn constraint(self) -> OperandConstraint
Get the “constraint” of this operand, i.e., what requirements its allocation must fulfill.
sourcepub fn as_fixed_nonallocatable(self) -> Option<PReg>
pub fn as_fixed_nonallocatable(self) -> Option<PReg>
If this operand is for a fixed non-allocatable register (see
[Operand::fixed
]), then returns the physical register that it will
be assigned to.
Trait Implementations§
source§impl Ord for Operand
impl Ord for Operand
source§impl PartialEq for Operand
impl PartialEq for Operand
source§impl PartialOrd for Operand
impl PartialOrd for Operand
1.0.0 · source§fn le(&self, other: &Rhs) -> bool
fn le(&self, other: &Rhs) -> bool
self
and other
) and is used by the <=
operator. Read moreimpl Copy for Operand
impl Eq for Operand
impl StructuralPartialEq for Operand
Auto Trait Implementations§
impl Freeze for Operand
impl RefUnwindSafe for Operand
impl Send for Operand
impl Sync for Operand
impl Unpin for Operand
impl UnwindSafe for Operand
Blanket Implementations§
source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
source§impl<T> CloneToUninit for Twhere
T: Copy,
impl<T> CloneToUninit for Twhere
T: Copy,
source§unsafe fn clone_to_uninit(&self, dst: *mut T)
unsafe fn clone_to_uninit(&self, dst: *mut T)
clone_to_uninit
)source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
source§default unsafe fn clone_to_uninit(&self, dst: *mut T)
default unsafe fn clone_to_uninit(&self, dst: *mut T)
clone_to_uninit
)