[machinst x64]: lower remaining lane operations--any_true, all_true, splat
This commit is contained in:
@@ -459,6 +459,7 @@ pub enum SseOpcode {
|
||||
Psubd,
|
||||
Psubq,
|
||||
Psubw,
|
||||
Ptest,
|
||||
Pxor,
|
||||
Rcpss,
|
||||
Roundss,
|
||||
@@ -606,6 +607,7 @@ impl SseOpcode {
|
||||
| SseOpcode::Pminuw
|
||||
| SseOpcode::Pminud
|
||||
| SseOpcode::Pmulld
|
||||
| SseOpcode::Ptest
|
||||
| SseOpcode::Roundss
|
||||
| SseOpcode::Roundsd => SSE41,
|
||||
|
||||
@@ -734,6 +736,7 @@ impl fmt::Debug for SseOpcode {
|
||||
SseOpcode::Psubd => "psubd",
|
||||
SseOpcode::Psubq => "psubq",
|
||||
SseOpcode::Psubw => "psubw",
|
||||
SseOpcode::Ptest => "ptest",
|
||||
SseOpcode::Pxor => "pxor",
|
||||
SseOpcode::Rcpss => "rcpss",
|
||||
SseOpcode::Roundss => "roundss",
|
||||
|
||||
@@ -2003,6 +2003,11 @@ pub(crate) fn emit(
|
||||
sink.bind_label(constant_end_label);
|
||||
}
|
||||
|
||||
Inst::XmmFakeDef { .. } => {
|
||||
// This instruction format only exists to declare a register as a `def`; no code is
|
||||
// emitted.
|
||||
}
|
||||
|
||||
Inst::Xmm_Mov_R_M {
|
||||
op,
|
||||
src,
|
||||
@@ -2087,19 +2092,20 @@ pub(crate) fn emit(
|
||||
|
||||
Inst::XMM_Cmp_RM_R { op, src, dst } => {
|
||||
let rex = RexFlags::clear_w();
|
||||
let (prefix, opcode) = match op {
|
||||
SseOpcode::Ucomisd => (LegacyPrefixes::_66, 0x0F2E),
|
||||
SseOpcode::Ucomiss => (LegacyPrefixes::None, 0x0F2E),
|
||||
let (prefix, opcode, len) = match op {
|
||||
SseOpcode::Ptest => (LegacyPrefixes::_66, 0x0F3817, 3),
|
||||
SseOpcode::Ucomisd => (LegacyPrefixes::_66, 0x0F2E, 2),
|
||||
SseOpcode::Ucomiss => (LegacyPrefixes::None, 0x0F2E, 2),
|
||||
_ => unimplemented!("Emit xmm cmp rm r"),
|
||||
};
|
||||
|
||||
match src {
|
||||
RegMem::Reg { reg } => {
|
||||
emit_std_reg_reg(sink, prefix, opcode, 2, *dst, *reg, rex);
|
||||
emit_std_reg_reg(sink, prefix, opcode, len, *dst, *reg, rex);
|
||||
}
|
||||
RegMem::Mem { addr } => {
|
||||
let addr = &addr.finalize(state);
|
||||
emit_std_reg_mem(sink, prefix, opcode, 2, *dst, addr, rex);
|
||||
emit_std_reg_mem(sink, prefix, opcode, len, *dst, addr, rex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -342,6 +342,10 @@ 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.
|
||||
@@ -640,6 +644,11 @@ impl Inst {
|
||||
Inst::XMM_RM_R { op, src, dst }
|
||||
}
|
||||
|
||||
pub(crate) fn xmm_fake_def(dst: Writable<Reg>) -> Self {
|
||||
debug_assert!(dst.to_reg().get_class() == RegClass::V128);
|
||||
Inst::XmmFakeDef { dst }
|
||||
}
|
||||
|
||||
pub(crate) fn xmm_mov_r_m(
|
||||
op: SseOpcode,
|
||||
src: Reg,
|
||||
@@ -1324,6 +1333,12 @@ impl ShowWithRRU for Inst {
|
||||
dst.show_rru(mb_rru),
|
||||
),
|
||||
|
||||
Inst::XmmFakeDef { dst } => format!(
|
||||
"{} {}",
|
||||
ljustify("fake_def".into()),
|
||||
dst.show_rru(mb_rru),
|
||||
),
|
||||
|
||||
Inst::XmmLoadConstSeq { val, dst, .. } => {
|
||||
format!("load_const ${:?}, {}", val, dst.show_rru(mb_rru),)
|
||||
}
|
||||
@@ -1754,6 +1769,7 @@ fn x64_get_regs(inst: &Inst, collector: &mut RegUsageCollector) {
|
||||
collector.add_mod(*dst);
|
||||
}
|
||||
}
|
||||
Inst::XmmFakeDef { dst } => collector.add_def(*dst),
|
||||
Inst::XmmLoadConstSeq { dst, .. } => collector.add_def(*dst),
|
||||
Inst::XmmMinMaxSeq { lhs, rhs_dst, .. } => {
|
||||
collector.add_use(*lhs);
|
||||
@@ -2088,6 +2104,9 @@ fn x64_map_regs<RUM: RegUsageMapper>(inst: &mut Inst, mapper: &RUM) {
|
||||
src.map_uses(mapper);
|
||||
map_mod(mapper, dst);
|
||||
}
|
||||
Inst::XmmFakeDef { ref mut dst, .. } => {
|
||||
map_def(mapper, dst);
|
||||
}
|
||||
Inst::XmmLoadConstSeq { ref mut dst, .. } => {
|
||||
map_def(mapper, dst);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user