diff --git a/cranelift/codegen/src/isa/x64/inst/emit.rs b/cranelift/codegen/src/isa/x64/inst/emit.rs index 2dec527723..4061df89b9 100644 --- a/cranelift/codegen/src/isa/x64/inst/emit.rs +++ b/cranelift/codegen/src/isa/x64/inst/emit.rs @@ -475,6 +475,16 @@ pub(crate) fn emit( info: &EmitInfo, state: &mut EmitState, ) { + if let Some(iset_requirement) = inst.isa_requirement() { + match iset_requirement { + // Cranelift assumes SSE2 at least. + InstructionSet::SSE | InstructionSet::SSE2 => {} + InstructionSet::SSSE3 => assert!(info.isa_flags.has_ssse3()), + InstructionSet::SSE41 => assert!(info.isa_flags.has_sse41()), + InstructionSet::SSE42 => assert!(info.isa_flags.has_sse42()), + } + } + match inst { Inst::AluRmiR { is_64, diff --git a/cranelift/codegen/src/isa/x64/inst/mod.rs b/cranelift/codegen/src/isa/x64/inst/mod.rs index d57c01ced5..02153ed11c 100644 --- a/cranelift/codegen/src/isa/x64/inst/mod.rs +++ b/cranelift/codegen/src/isa/x64/inst/mod.rs @@ -502,6 +502,71 @@ pub(crate) fn low32_will_sign_extend_to_64(x: u64) -> bool { xs == ((xs << 32) >> 32) } +impl Inst { + fn isa_requirement(&self) -> Option { + match self { + // These instructions are part of SSE2, which is a basic requirement in Cranelift, and + // don't have to be checked. + Inst::AluRmiR { .. } + | Inst::AtomicRmwSeq { .. } + | Inst::CallKnown { .. } + | Inst::CallUnknown { .. } + | Inst::CheckedDivOrRemSeq { .. } + | Inst::Cmove { .. } + | Inst::CmpRmiR { .. } + | Inst::CvtFloatToSintSeq { .. } + | Inst::CvtFloatToUintSeq { .. } + | Inst::CvtUint64ToFloatSeq { .. } + | Inst::Div { .. } + | Inst::EpiloguePlaceholder + | Inst::Fence { .. } + | Inst::Hlt + | Inst::Imm { .. } + | Inst::JmpCond { .. } + | Inst::JmpIf { .. } + | Inst::JmpKnown { .. } + | Inst::JmpTableSeq { .. } + | Inst::JmpUnknown { .. } + | Inst::LoadEffectiveAddress { .. } + | Inst::LoadExtName { .. } + | Inst::LockCmpxchg { .. } + | Inst::Mov64MR { .. } + | Inst::MovRM { .. } + | Inst::MovRR { .. } + | Inst::MovsxRmR { .. } + | Inst::MovzxRmR { .. } + | Inst::MulHi { .. } + | Inst::Neg { .. } + | Inst::Not { .. } + | Inst::Nop { .. } + | Inst::Pop64 { .. } + | Inst::Push64 { .. } + | Inst::Ret + | Inst::Setcc { .. } + | Inst::ShiftR { .. } + | Inst::SignExtendData { .. } + | Inst::TrapIf { .. } + | Inst::Ud2 { .. } + | Inst::UnaryRmR { .. } + | Inst::VirtualSPOffsetAdj { .. } + | Inst::XmmCmove { .. } + | Inst::XmmCmpRmR { .. } + | Inst::XmmLoadConstSeq { .. } + | Inst::XmmMinMaxSeq { .. } + | Inst::XmmUninitializedValue { .. } => None, + + // These use dynamic SSE opcodes. + Inst::GprToXmm { op, .. } + | Inst::XmmMovRM { op, .. } + | Inst::XmmRmiReg { opcode: op, .. } + | Inst::XmmRmR { op, .. } + | Inst::XmmRmRImm { op, .. } + | Inst::XmmToGpr { op, .. } + | Inst::XmmUnaryRmR { op, .. } => Some(op.available_from()), + } + } +} + // Handy constructors for Insts. impl Inst { diff --git a/cranelift/filetests/filetests/isa/x64/simd-lane-access-compile.clif b/cranelift/filetests/filetests/isa/x64/simd-lane-access-compile.clif index 5d397409ab..c6860433e6 100644 --- a/cranelift/filetests/filetests/isa/x64/simd-lane-access-compile.clif +++ b/cranelift/filetests/filetests/isa/x64/simd-lane-access-compile.clif @@ -1,6 +1,6 @@ test compile set enable_simd -target x86_64 +target x86_64 has_ssse3 has_sse41 feature "experimental_x64" ;; shuffle