x64: match multiple ISA requirements before emitting
Because there are instructions that are present in more than one ISA feature set, we need to see if any of the ISA requirements match before emitting. This change includes the `VPABSQ` instruction as an example, which is present in both `AVX512F` and `AVX512VL`.
This commit is contained in:
@@ -10,6 +10,7 @@ use regalloc::{
|
||||
PrettyPrint, PrettyPrintSized, RealRegUniverse, Reg, RegClass, RegUsageCollector,
|
||||
RegUsageMapper, Writable,
|
||||
};
|
||||
use smallvec::{smallvec, SmallVec};
|
||||
use std::fmt;
|
||||
use std::string::String;
|
||||
|
||||
@@ -411,12 +412,12 @@ pub enum UnaryRmROpcode {
|
||||
}
|
||||
|
||||
impl UnaryRmROpcode {
|
||||
pub(crate) fn available_from(&self) -> Option<InstructionSet> {
|
||||
pub(crate) fn available_from(&self) -> SmallVec<[InstructionSet; 2]> {
|
||||
match self {
|
||||
UnaryRmROpcode::Bsr | UnaryRmROpcode::Bsf => None,
|
||||
UnaryRmROpcode::Lzcnt => Some(InstructionSet::Lzcnt),
|
||||
UnaryRmROpcode::Tzcnt => Some(InstructionSet::BMI1),
|
||||
UnaryRmROpcode::Popcnt => Some(InstructionSet::Popcnt),
|
||||
UnaryRmROpcode::Bsr | UnaryRmROpcode::Bsf => smallvec![],
|
||||
UnaryRmROpcode::Lzcnt => smallvec![InstructionSet::Lzcnt],
|
||||
UnaryRmROpcode::Tzcnt => smallvec![InstructionSet::BMI1],
|
||||
UnaryRmROpcode::Popcnt => smallvec![InstructionSet::Popcnt],
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -447,6 +448,7 @@ pub enum CmpOpcode {
|
||||
Test,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub(crate) enum InstructionSet {
|
||||
SSE,
|
||||
SSE2,
|
||||
@@ -458,6 +460,10 @@ pub(crate) enum InstructionSet {
|
||||
BMI1,
|
||||
#[allow(dead_code)] // never constructed (yet).
|
||||
BMI2,
|
||||
#[allow(dead_code)]
|
||||
AVX512F,
|
||||
#[allow(dead_code)]
|
||||
AVX512VL,
|
||||
}
|
||||
|
||||
/// Some SSE operations requiring 2 operands r/m and r.
|
||||
@@ -987,6 +993,37 @@ impl fmt::Display for SseOpcode {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub enum Avx512Opcode {
|
||||
#[allow(dead_code)]
|
||||
Vpabsq,
|
||||
}
|
||||
|
||||
impl Avx512Opcode {
|
||||
/// Which `InstructionSet`s support the opcode?
|
||||
#[allow(dead_code)]
|
||||
pub(crate) fn available_from(&self) -> SmallVec<[InstructionSet; 2]> {
|
||||
match self {
|
||||
Avx512Opcode::Vpabsq => smallvec![InstructionSet::AVX512F, InstructionSet::AVX512VL],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for Avx512Opcode {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
|
||||
let name = match self {
|
||||
Avx512Opcode::Vpabsq => "vpabsq",
|
||||
};
|
||||
write!(fmt, "{}", name)
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for Avx512Opcode {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
fmt::Debug::fmt(self, f)
|
||||
}
|
||||
}
|
||||
|
||||
/// This defines the ways a value can be extended: either signed- or zero-extension, or none for
|
||||
/// types that are not extended. Contrast with [ExtMode], which defines the widths from and to which
|
||||
/// values can be extended.
|
||||
|
||||
Reference in New Issue
Block a user