[machinst x64]: rename Inst::XmmUninitializedValue and document

This approach is not the best but avoids an extra instruction; perhaps at some point, as mentioned in https://github.com/bytecodealliance/wasmtime/pull/2248, we will add the extra instruction or refactor things in such a way that this `Inst` variant is unnecessary.
This commit is contained in:
Andrew Brown
2020-10-01 11:39:12 -07:00
parent 3d9f3bf728
commit 16a2538ecd
4 changed files with 26 additions and 16 deletions

View File

@@ -2003,7 +2003,7 @@ pub(crate) fn emit(
sink.bind_label(constant_end_label);
}
Inst::XmmFakeDef { .. } => {
Inst::XmmUninitializedValue { .. } => {
// This instruction format only exists to declare a register as a `def`; no code is
// emitted.
}

View File

@@ -342,10 +342,6 @@ pub enum Inst {
is64: bool,
},
/// Provides a way to tell the register allocator that the upcoming sequence of instructions
/// will overwrite `dst` so it should be considered as a `def`; use with care.
XmmFakeDef { dst: Writable<Reg> },
// =====================================
// Control flow instructions.
/// Direct call: call simm32.
@@ -486,6 +482,20 @@ pub enum Inst {
/// Marker, no-op in generated code: SP "virtual offset" is adjusted. This
/// controls how MemArg::NominalSPOffset args are lowered.
VirtualSPOffsetAdj { offset: i64 },
/// Provides a way to tell the register allocator that the upcoming sequence of instructions
/// will overwrite `dst` so it should be considered as a `def`; use this with care.
///
/// This is useful when we have a sequence of instructions whose register usages are nominally
/// `mod`s, but such that the combination of operations creates a result that is independent of
/// the initial register value. It's thus semantically a `def`, not a `mod`, when all the
/// instructions are taken together, so we want to ensure the register is defined (its
/// live-range starts) prior to the sequence to keep analyses happy.
///
/// One alternative would be a compound instruction that somehow encapsulates the others and
/// reports its own `def`s/`use`s/`mod`s; this adds complexity (the instruction list is no
/// longer flat) and requires knowledge about semantics and initial-value independence anyway.
XmmUninitializedValue { dst: Writable<Reg> },
}
pub(crate) fn low32_will_sign_extend_to_64(x: u64) -> bool {
@@ -644,9 +654,9 @@ impl Inst {
Inst::XMM_RM_R { op, src, dst }
}
pub(crate) fn xmm_fake_def(dst: Writable<Reg>) -> Self {
pub(crate) fn xmm_uninit_value(dst: Writable<Reg>) -> Self {
debug_assert!(dst.to_reg().get_class() == RegClass::V128);
Inst::XmmFakeDef { dst }
Inst::XmmUninitializedValue { dst }
}
pub(crate) fn xmm_mov_r_m(
@@ -1333,9 +1343,9 @@ impl ShowWithRRU for Inst {
dst.show_rru(mb_rru),
),
Inst::XmmFakeDef { dst } => format!(
Inst::XmmUninitializedValue { dst } => format!(
"{} {}",
ljustify("fake_def".into()),
ljustify("uninit".into()),
dst.show_rru(mb_rru),
),
@@ -1769,7 +1779,7 @@ fn x64_get_regs(inst: &Inst, collector: &mut RegUsageCollector) {
collector.add_mod(*dst);
}
}
Inst::XmmFakeDef { dst } => collector.add_def(*dst),
Inst::XmmUninitializedValue { dst } => collector.add_def(*dst),
Inst::XmmLoadConstSeq { dst, .. } => collector.add_def(*dst),
Inst::XmmMinMaxSeq { lhs, rhs_dst, .. } => {
collector.add_use(*lhs);
@@ -2104,7 +2114,7 @@ fn x64_map_regs<RUM: RegUsageMapper>(inst: &mut Inst, mapper: &RUM) {
src.map_uses(mapper);
map_mod(mapper, dst);
}
Inst::XmmFakeDef { ref mut dst, .. } => {
Inst::XmmUninitializedValue { ref mut dst, .. } => {
map_def(mapper, dst);
}
Inst::XmmLoadConstSeq { ref mut dst, .. } => {

View File

@@ -2995,7 +2995,7 @@ fn lower_insn_to_regs<C: LowerCtx<I = Inst>>(
// We know that splat will overwrite all of the lanes of `dst` but it takes several
// instructions to do so. Because of the multiple instructions, there is no good way to
// declare `dst` a `def` except with the following pseudo-instruction.
ctx.emit(Inst::xmm_fake_def(dst));
ctx.emit(Inst::xmm_uninit_value(dst));
match ty.lane_bits() {
8 => {
emit_insert_lane(ctx, src, dst, 0, ty.lane_type());