@@ -373,7 +373,7 @@ impl<'a, F: Function> Env<'a, F> {
|
|||||||
let was_live = live.get(op.vreg().vreg());
|
let was_live = live.get(op.vreg().vreg());
|
||||||
trace!("op {:?} was_live = {}", op, was_live);
|
trace!("op {:?} was_live = {}", op, was_live);
|
||||||
match op.kind() {
|
match op.kind() {
|
||||||
OperandKind::Use | OperandKind::Mod => {
|
OperandKind::Use => {
|
||||||
live.set(op.vreg().vreg(), true);
|
live.set(op.vreg().vreg(), true);
|
||||||
}
|
}
|
||||||
OperandKind::Def => {
|
OperandKind::Def => {
|
||||||
@@ -776,7 +776,6 @@ impl<'a, F: Function> Env<'a, F> {
|
|||||||
.cloned()
|
.cloned()
|
||||||
.unwrap_or(self.func.inst_operands(inst)[i]);
|
.unwrap_or(self.func.inst_operands(inst)[i]);
|
||||||
let pos = match (operand.kind(), operand.pos()) {
|
let pos = match (operand.kind(), operand.pos()) {
|
||||||
(OperandKind::Mod, _) => ProgPoint::before(inst),
|
|
||||||
(OperandKind::Def, OperandPos::Early) => ProgPoint::before(inst),
|
(OperandKind::Def, OperandPos::Early) => ProgPoint::before(inst),
|
||||||
(OperandKind::Def, OperandPos::Late) => ProgPoint::after(inst),
|
(OperandKind::Def, OperandPos::Late) => ProgPoint::after(inst),
|
||||||
(OperandKind::Use, OperandPos::Late) => ProgPoint::after(inst),
|
(OperandKind::Use, OperandPos::Late) => ProgPoint::after(inst),
|
||||||
@@ -817,7 +816,7 @@ impl<'a, F: Function> Env<'a, F> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
match operand.kind() {
|
match operand.kind() {
|
||||||
OperandKind::Def | OperandKind::Mod => {
|
OperandKind::Def => {
|
||||||
trace!("Def of {} at {:?}", operand.vreg(), pos);
|
trace!("Def of {} at {:?}", operand.vreg(), pos);
|
||||||
|
|
||||||
// Get or create the LiveRange.
|
// Get or create the LiveRange.
|
||||||
@@ -825,11 +824,7 @@ impl<'a, F: Function> Env<'a, F> {
|
|||||||
trace!(" -> has existing LR {:?}", lr);
|
trace!(" -> has existing LR {:?}", lr);
|
||||||
// If there was no liverange (dead def), create a trivial one.
|
// If there was no liverange (dead def), create a trivial one.
|
||||||
if !live.get(operand.vreg().vreg()) {
|
if !live.get(operand.vreg().vreg()) {
|
||||||
let from = match operand.kind() {
|
let from = pos;
|
||||||
OperandKind::Def => pos,
|
|
||||||
OperandKind::Mod => self.cfginfo.block_entry[block.index()],
|
|
||||||
_ => unreachable!(),
|
|
||||||
};
|
|
||||||
// We want to we want to span
|
// We want to we want to span
|
||||||
// until Before of the next
|
// until Before of the next
|
||||||
// inst. This ensures that early
|
// inst. This ensures that early
|
||||||
|
|||||||
@@ -906,7 +906,7 @@ impl<'a, F: Function> Env<'a, F> {
|
|||||||
let inst = Inst::new(inst);
|
let inst = Inst::new(inst);
|
||||||
for (i, op) in this.func.inst_operands(inst).iter().enumerate() {
|
for (i, op) in this.func.inst_operands(inst).iter().enumerate() {
|
||||||
match op.kind() {
|
match op.kind() {
|
||||||
OperandKind::Def | OperandKind::Mod => {
|
OperandKind::Def => {
|
||||||
let alloc = this.get_alloc(inst, i);
|
let alloc = this.get_alloc(inst, i);
|
||||||
redundant_moves.clear_alloc(alloc);
|
redundant_moves.clear_alloc(alloc);
|
||||||
}
|
}
|
||||||
|
|||||||
33
src/lib.rs
33
src/lib.rs
@@ -426,14 +426,13 @@ impl std::fmt::Display for OperandConstraint {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The "kind" of the operand: whether it reads a vreg (Use), writes a
|
/// The "kind" of the operand: whether it reads a vreg (Use) or writes
|
||||||
/// vreg (Def), or reads and then writes (Mod, for "modify").
|
/// a vreg (Def).
|
||||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||||
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
|
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
|
||||||
pub enum OperandKind {
|
pub enum OperandKind {
|
||||||
Def = 0,
|
Def = 0,
|
||||||
Mod = 1,
|
Use = 1,
|
||||||
Use = 2,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The "position" of the operand: where it has its read/write
|
/// The "position" of the operand: where it has its read/write
|
||||||
@@ -488,7 +487,7 @@ pub enum OperandPos {
|
|||||||
pub struct Operand {
|
pub struct Operand {
|
||||||
/// Bit-pack into 32 bits.
|
/// Bit-pack into 32 bits.
|
||||||
///
|
///
|
||||||
/// constraint:7 kind:2 pos:1 class:1 vreg:21
|
/// constraint:7 kind:1 pos:1 class:2 vreg:21
|
||||||
///
|
///
|
||||||
/// where `constraint` is an `OperandConstraint`, `kind` is an
|
/// where `constraint` is an `OperandConstraint`, `kind` is an
|
||||||
/// `OperandKind`, `pos` is an `OperandPos`, `class` is a
|
/// `OperandKind`, `pos` is an `OperandPos`, `class` is a
|
||||||
@@ -532,8 +531,8 @@ impl Operand {
|
|||||||
Operand {
|
Operand {
|
||||||
bits: vreg.vreg() as u32
|
bits: vreg.vreg() as u32
|
||||||
| (class_field << 21)
|
| (class_field << 21)
|
||||||
| (pos_field << 22)
|
| (pos_field << 23)
|
||||||
| (kind_field << 23)
|
| (kind_field << 24)
|
||||||
| (constraint_field << 25),
|
| (constraint_field << 25),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -719,7 +718,7 @@ impl Operand {
|
|||||||
/// Get the register class used by this operand.
|
/// Get the register class used by this operand.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn class(self) -> RegClass {
|
pub fn class(self) -> RegClass {
|
||||||
let class_field = (self.bits >> 21) & 1;
|
let class_field = (self.bits >> 21) & 3;
|
||||||
match class_field {
|
match class_field {
|
||||||
0 => RegClass::Int,
|
0 => RegClass::Int,
|
||||||
1 => RegClass::Float,
|
1 => RegClass::Float,
|
||||||
@@ -727,15 +726,14 @@ impl Operand {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the "kind" of this operand: a definition (write), a use
|
/// Get the "kind" of this operand: a definition (write) or a use
|
||||||
/// (read), or a "mod" / modify (a read followed by a write).
|
/// (read).
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn kind(self) -> OperandKind {
|
pub fn kind(self) -> OperandKind {
|
||||||
let kind_field = (self.bits >> 23) & 3;
|
let kind_field = (self.bits >> 24) & 1;
|
||||||
match kind_field {
|
match kind_field {
|
||||||
0 => OperandKind::Def,
|
0 => OperandKind::Def,
|
||||||
1 => OperandKind::Mod,
|
1 => OperandKind::Use,
|
||||||
2 => OperandKind::Use,
|
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -746,7 +744,7 @@ impl Operand {
|
|||||||
/// at "after", though there are cases where this is not true.
|
/// at "after", though there are cases where this is not true.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn pos(self) -> OperandPos {
|
pub fn pos(self) -> OperandPos {
|
||||||
let pos_field = (self.bits >> 22) & 1;
|
let pos_field = (self.bits >> 23) & 1;
|
||||||
match pos_field {
|
match pos_field {
|
||||||
0 => OperandPos::Early,
|
0 => OperandPos::Early,
|
||||||
1 => OperandPos::Late,
|
1 => OperandPos::Late,
|
||||||
@@ -808,8 +806,7 @@ impl std::fmt::Debug for Operand {
|
|||||||
impl std::fmt::Display for Operand {
|
impl std::fmt::Display for Operand {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||||
match (self.kind(), self.pos()) {
|
match (self.kind(), self.pos()) {
|
||||||
(OperandKind::Def, OperandPos::Late)
|
(OperandKind::Def, OperandPos::Late) | (OperandKind::Use, OperandPos::Early) => {
|
||||||
| (OperandKind::Mod | OperandKind::Use, OperandPos::Early) => {
|
|
||||||
write!(f, "{:?}", self.kind())?;
|
write!(f, "{:?}", self.kind())?;
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
@@ -1058,8 +1055,8 @@ pub trait Function {
|
|||||||
/// it in a given PReg chosen by the client prior to regalloc.
|
/// it in a given PReg chosen by the client prior to regalloc.
|
||||||
///
|
///
|
||||||
/// Every register written by an instruction must either
|
/// Every register written by an instruction must either
|
||||||
/// correspond to (be assigned to) an Operand of kind `Def` or
|
/// correspond to (be assigned to) an Operand of kind `Def`, or
|
||||||
/// `Mod`, or else must be a "clobber".
|
/// else must be a "clobber".
|
||||||
///
|
///
|
||||||
/// This can be used to, for example, describe ABI-specified
|
/// This can be used to, for example, describe ABI-specified
|
||||||
/// registers that are not preserved by a call instruction, or
|
/// registers that are not preserved by a call instruction, or
|
||||||
|
|||||||
@@ -73,13 +73,6 @@ pub fn validate_ssa<F: Function>(f: &F, cfginfo: &CFGInfo) -> Result<(), RegAllo
|
|||||||
// Check all the uses in this instruction
|
// Check all the uses in this instruction
|
||||||
// first, before recording its defs below.
|
// first, before recording its defs below.
|
||||||
}
|
}
|
||||||
OperandKind::Mod => {
|
|
||||||
// Mod (modify) operands are not used in SSA,
|
|
||||||
// but can be used by non-SSA code (e.g. with
|
|
||||||
// the regalloc.rs compatibility shim).
|
|
||||||
trace!("Unexpected mod {:?}", operand.vreg());
|
|
||||||
return Err(RegAllocError::SSA(operand.vreg(), iix));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user