Remove IFLAGS/FFLAGS types (#5406)
All instructions using the CPU flags types (IFLAGS/FFLAGS) were already removed. This patch completes the cleanup by removing all remaining instructions that define values of CPU flags types, as well as the types themselves. Specifically, the following features are removed: - The IFLAGS and FFLAGS types and the SpecialType category. - Special handling of IFLAGS and FFLAGS in machinst/isle.rs and machinst/lower.rs. - The ifcmp, ifcmp_imm, ffcmp, iadd_ifcin, iadd_ifcout, iadd_ifcarry, isub_ifbin, isub_ifbout, and isub_ifborrow instructions. - The writes_cpu_flags instruction property. - The flags verifier pass. - Flags handling in the interpreter. All of these features are currently unused; no functional change intended by this patch. This addresses https://github.com/bytecodealliance/wasmtime/issues/3249.
This commit is contained in:
@@ -73,8 +73,6 @@ pub(crate) struct InstructionContent {
|
||||
pub can_trap: bool,
|
||||
/// Does this instruction have other side effects besides can_* flags?
|
||||
pub other_side_effects: bool,
|
||||
/// Does this instruction write to CPU flags?
|
||||
pub writes_cpu_flags: bool,
|
||||
}
|
||||
|
||||
impl InstructionContent {
|
||||
@@ -240,9 +238,6 @@ impl InstructionBuilder {
|
||||
let polymorphic_info =
|
||||
verify_polymorphic(&operands_in, &operands_out, &self.format, &value_opnums);
|
||||
|
||||
// Infer from output operands whether an instruction clobbers CPU flags or not.
|
||||
let writes_cpu_flags = operands_out.iter().any(|op| op.is_cpu_flags());
|
||||
|
||||
let camel_name = camel_case(&self.name);
|
||||
|
||||
Rc::new(InstructionContent {
|
||||
@@ -264,7 +259,6 @@ impl InstructionBuilder {
|
||||
can_store: self.can_store,
|
||||
can_trap: self.can_trap,
|
||||
other_side_effects: self.other_side_effects,
|
||||
writes_cpu_flags,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -87,17 +87,6 @@ impl Operand {
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_cpu_flags(&self) -> bool {
|
||||
match &self.kind.fields {
|
||||
OperandKindFields::TypeVar(type_var)
|
||||
if type_var.name == "iflags" || type_var.name == "fflags" =>
|
||||
{
|
||||
true
|
||||
}
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub type EnumValues = HashMap<&'static str, &'static str>;
|
||||
|
||||
@@ -18,7 +18,6 @@ static RUST_NAME_PREFIX: &str = "ir::types::";
|
||||
pub(crate) enum ValueType {
|
||||
Lane(LaneType),
|
||||
Reference(ReferenceType),
|
||||
Special(SpecialType),
|
||||
Vector(VectorType),
|
||||
DynamicVector(DynamicVectorType),
|
||||
}
|
||||
@@ -29,11 +28,6 @@ impl ValueType {
|
||||
LaneTypeIterator::new()
|
||||
}
|
||||
|
||||
/// Iterate through all of the special types (neither lanes nor vectors).
|
||||
pub fn all_special_types() -> SpecialTypeIterator {
|
||||
SpecialTypeIterator::new()
|
||||
}
|
||||
|
||||
pub fn all_reference_types() -> ReferenceTypeIterator {
|
||||
ReferenceTypeIterator::new()
|
||||
}
|
||||
@@ -43,7 +37,6 @@ impl ValueType {
|
||||
match *self {
|
||||
ValueType::Lane(l) => l.doc(),
|
||||
ValueType::Reference(r) => r.doc(),
|
||||
ValueType::Special(s) => s.doc(),
|
||||
ValueType::Vector(ref v) => v.doc(),
|
||||
ValueType::DynamicVector(ref v) => v.doc(),
|
||||
}
|
||||
@@ -54,7 +47,6 @@ impl ValueType {
|
||||
match *self {
|
||||
ValueType::Lane(l) => l.lane_bits(),
|
||||
ValueType::Reference(r) => r.lane_bits(),
|
||||
ValueType::Special(s) => s.lane_bits(),
|
||||
ValueType::Vector(ref v) => v.lane_bits(),
|
||||
ValueType::DynamicVector(ref v) => v.lane_bits(),
|
||||
}
|
||||
@@ -78,7 +70,6 @@ impl ValueType {
|
||||
match *self {
|
||||
ValueType::Lane(l) => l.number(),
|
||||
ValueType::Reference(r) => r.number(),
|
||||
ValueType::Special(s) => s.number(),
|
||||
ValueType::Vector(ref v) => v.number(),
|
||||
ValueType::DynamicVector(ref v) => v.number(),
|
||||
}
|
||||
@@ -100,7 +91,6 @@ impl fmt::Display for ValueType {
|
||||
match *self {
|
||||
ValueType::Lane(l) => l.fmt(f),
|
||||
ValueType::Reference(r) => r.fmt(f),
|
||||
ValueType::Special(s) => s.fmt(f),
|
||||
ValueType::Vector(ref v) => v.fmt(f),
|
||||
ValueType::DynamicVector(ref v) => v.fmt(f),
|
||||
}
|
||||
@@ -121,13 +111,6 @@ impl From<ReferenceType> for ValueType {
|
||||
}
|
||||
}
|
||||
|
||||
/// Create a ValueType from a given special type.
|
||||
impl From<SpecialType> for ValueType {
|
||||
fn from(spec: SpecialType) -> Self {
|
||||
ValueType::Special(spec)
|
||||
}
|
||||
}
|
||||
|
||||
/// Create a ValueType from a given vector type.
|
||||
impl From<VectorType> for ValueType {
|
||||
fn from(vector: VectorType) -> Self {
|
||||
@@ -436,91 +419,6 @@ impl fmt::Debug for DynamicVectorType {
|
||||
}
|
||||
}
|
||||
|
||||
/// A concrete scalar type that is neither a vector nor a lane type.
|
||||
///
|
||||
/// Special types cannot be used to form vectors.
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Hash)]
|
||||
pub(crate) enum SpecialType {
|
||||
Flag(shared_types::Flag),
|
||||
}
|
||||
|
||||
impl SpecialType {
|
||||
/// Return a string containing the documentation comment for this special type.
|
||||
pub fn doc(self) -> String {
|
||||
match self {
|
||||
SpecialType::Flag(shared_types::Flag::IFlags) => String::from(
|
||||
"CPU flags representing the result of an integer comparison. These flags
|
||||
can be tested with an :type:`intcc` condition code.",
|
||||
),
|
||||
SpecialType::Flag(shared_types::Flag::FFlags) => String::from(
|
||||
"CPU flags representing the result of a floating point comparison. These
|
||||
flags can be tested with a :type:`floatcc` condition code.",
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
/// Return the number of bits in a lane.
|
||||
pub fn lane_bits(self) -> u64 {
|
||||
match self {
|
||||
SpecialType::Flag(_) => 0,
|
||||
}
|
||||
}
|
||||
|
||||
/// Find the unique number associated with this special type.
|
||||
pub fn number(self) -> u16 {
|
||||
match self {
|
||||
SpecialType::Flag(shared_types::Flag::IFlags) => 1,
|
||||
SpecialType::Flag(shared_types::Flag::FFlags) => 2,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for SpecialType {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match *self {
|
||||
SpecialType::Flag(shared_types::Flag::IFlags) => write!(f, "iflags"),
|
||||
SpecialType::Flag(shared_types::Flag::FFlags) => write!(f, "fflags"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for SpecialType {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(
|
||||
f,
|
||||
"{}",
|
||||
match *self {
|
||||
SpecialType::Flag(_) => format!("FlagsType({})", self),
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<shared_types::Flag> for SpecialType {
|
||||
fn from(f: shared_types::Flag) -> Self {
|
||||
SpecialType::Flag(f)
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) struct SpecialTypeIterator {
|
||||
flag_iter: shared_types::FlagIterator,
|
||||
}
|
||||
|
||||
impl SpecialTypeIterator {
|
||||
fn new() -> Self {
|
||||
Self {
|
||||
flag_iter: shared_types::FlagIterator::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Iterator for SpecialTypeIterator {
|
||||
type Item = SpecialType;
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
self.flag_iter.next().map(SpecialType::from)
|
||||
}
|
||||
}
|
||||
|
||||
/// Reference type is scalar type, but not lane type.
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Hash)]
|
||||
pub(crate) struct ReferenceType(pub shared_types::Reference);
|
||||
|
||||
@@ -6,7 +6,7 @@ use std::iter::FromIterator;
|
||||
use std::ops;
|
||||
use std::rc::Rc;
|
||||
|
||||
use crate::cdsl::types::{LaneType, ReferenceType, SpecialType, ValueType};
|
||||
use crate::cdsl::types::{LaneType, ReferenceType, ValueType};
|
||||
|
||||
const MAX_LANES: u16 = 256;
|
||||
const MAX_BITS: u16 = 128;
|
||||
@@ -57,9 +57,6 @@ impl TypeVar {
|
||||
let mut builder = TypeSetBuilder::new();
|
||||
|
||||
let (scalar_type, num_lanes) = match value_type {
|
||||
ValueType::Special(special_type) => {
|
||||
return TypeVar::new(name, doc, builder.specials(vec![special_type]).build());
|
||||
}
|
||||
ValueType::Reference(ReferenceType(reference_type)) => {
|
||||
let bits = reference_type as RangeBound;
|
||||
return TypeVar::new(name, doc, builder.refs(bits..bits).build());
|
||||
@@ -156,7 +153,6 @@ impl TypeVar {
|
||||
let ts = self.get_typeset();
|
||||
|
||||
// Safety checks to avoid over/underflows.
|
||||
assert!(ts.specials.is_empty(), "can't derive from special types");
|
||||
match derived_func {
|
||||
DerivedFunc::HalfWidth => {
|
||||
assert!(
|
||||
@@ -364,9 +360,6 @@ pub(crate) struct TypeVarParent {
|
||||
/// - The permitted range of boolean types.
|
||||
///
|
||||
/// The ranges are inclusive from smallest bit-width to largest bit-width.
|
||||
///
|
||||
/// Finally, a type set can contain special types (derived from `SpecialType`)
|
||||
/// which can't appear as lane types.
|
||||
|
||||
type RangeBound = u16;
|
||||
type Range = ops::Range<RangeBound>;
|
||||
@@ -385,7 +378,6 @@ pub(crate) struct TypeSet {
|
||||
pub ints: NumSet,
|
||||
pub floats: NumSet,
|
||||
pub refs: NumSet,
|
||||
pub specials: Vec<SpecialType>,
|
||||
}
|
||||
|
||||
impl TypeSet {
|
||||
@@ -395,7 +387,6 @@ impl TypeSet {
|
||||
ints: NumSet,
|
||||
floats: NumSet,
|
||||
refs: NumSet,
|
||||
specials: Vec<SpecialType>,
|
||||
) -> Self {
|
||||
Self {
|
||||
lanes,
|
||||
@@ -403,7 +394,6 @@ impl TypeSet {
|
||||
ints,
|
||||
floats,
|
||||
refs,
|
||||
specials,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -411,7 +401,6 @@ impl TypeSet {
|
||||
pub fn size(&self) -> usize {
|
||||
self.lanes.len() * (self.ints.len() + self.floats.len() + self.refs.len())
|
||||
+ self.dynamic_lanes.len() * (self.ints.len() + self.floats.len() + self.refs.len())
|
||||
+ self.specials.len()
|
||||
}
|
||||
|
||||
/// Return the image of self across the derived function func.
|
||||
@@ -450,7 +439,6 @@ impl TypeSet {
|
||||
let mut copy = self.clone();
|
||||
copy.ints = NumSet::from_iter(self.ints.iter().filter(|&&x| x > 8).map(|&x| x / 2));
|
||||
copy.floats = NumSet::from_iter(self.floats.iter().filter(|&&x| x > 32).map(|&x| x / 2));
|
||||
copy.specials = Vec::new();
|
||||
copy
|
||||
}
|
||||
|
||||
@@ -464,7 +452,6 @@ impl TypeSet {
|
||||
.filter(|&&x| x < MAX_FLOAT_BITS)
|
||||
.map(|&x| x * 2),
|
||||
);
|
||||
copy.specials = Vec::new();
|
||||
copy
|
||||
}
|
||||
|
||||
@@ -472,7 +459,6 @@ impl TypeSet {
|
||||
fn half_vector(&self) -> TypeSet {
|
||||
let mut copy = self.clone();
|
||||
copy.lanes = NumSet::from_iter(self.lanes.iter().filter(|&&x| x > 1).map(|&x| x / 2));
|
||||
copy.specials = Vec::new();
|
||||
copy
|
||||
}
|
||||
|
||||
@@ -485,7 +471,6 @@ impl TypeSet {
|
||||
.filter(|&&x| x < MAX_LANES)
|
||||
.map(|&x| x * 2),
|
||||
);
|
||||
copy.specials = Vec::new();
|
||||
copy
|
||||
}
|
||||
|
||||
@@ -497,7 +482,6 @@ impl TypeSet {
|
||||
.filter(|&&x| x < MAX_LANES)
|
||||
.map(|&x| x),
|
||||
);
|
||||
copy.specials = Vec::new();
|
||||
copy.dynamic_lanes = NumSet::new();
|
||||
copy
|
||||
}
|
||||
@@ -523,9 +507,6 @@ impl TypeSet {
|
||||
ret.push(LaneType::float_from_bits(bits).to_dynamic(num_lanes));
|
||||
}
|
||||
}
|
||||
for &special in &self.specials {
|
||||
ret.push(special.into());
|
||||
}
|
||||
ret
|
||||
}
|
||||
|
||||
@@ -572,12 +553,6 @@ impl fmt::Debug for TypeSet {
|
||||
Vec::from_iter(self.refs.iter().map(|x| x.to_string())).join(", ")
|
||||
));
|
||||
}
|
||||
if !self.specials.is_empty() {
|
||||
subsets.push(format!(
|
||||
"specials={{{}}}",
|
||||
Vec::from_iter(self.specials.iter().map(|x| x.to_string())).join(", ")
|
||||
));
|
||||
}
|
||||
|
||||
write!(fmt, "{})", subsets.join(", "))?;
|
||||
Ok(())
|
||||
@@ -591,7 +566,6 @@ pub(crate) struct TypeSetBuilder {
|
||||
includes_scalars: bool,
|
||||
simd_lanes: Interval,
|
||||
dynamic_simd_lanes: Interval,
|
||||
specials: Vec<SpecialType>,
|
||||
}
|
||||
|
||||
impl TypeSetBuilder {
|
||||
@@ -603,7 +577,6 @@ impl TypeSetBuilder {
|
||||
includes_scalars: true,
|
||||
simd_lanes: Interval::None,
|
||||
dynamic_simd_lanes: Interval::None,
|
||||
specials: Vec::new(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -636,11 +609,6 @@ impl TypeSetBuilder {
|
||||
self.dynamic_simd_lanes = interval.into();
|
||||
self
|
||||
}
|
||||
pub fn specials(mut self, specials: Vec<SpecialType>) -> Self {
|
||||
assert!(self.specials.is_empty());
|
||||
self.specials = specials;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn build(self) -> TypeSet {
|
||||
let min_lanes = if self.includes_scalars { 1 } else { 2 };
|
||||
@@ -651,7 +619,6 @@ impl TypeSetBuilder {
|
||||
range_to_set(self.ints.to_range(8..MAX_BITS, None)),
|
||||
range_to_set(self.floats.to_range(32..64, None)),
|
||||
range_to_set(self.refs.to_range(32..64, None)),
|
||||
self.specials,
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -721,13 +688,11 @@ fn test_typevar_builder() {
|
||||
assert_eq!(type_set.lanes, num_set![1]);
|
||||
assert!(type_set.floats.is_empty());
|
||||
assert_eq!(type_set.ints, num_set![8, 16, 32, 64, 128]);
|
||||
assert!(type_set.specials.is_empty());
|
||||
|
||||
let type_set = TypeSetBuilder::new().floats(Interval::All).build();
|
||||
assert_eq!(type_set.lanes, num_set![1]);
|
||||
assert_eq!(type_set.floats, num_set![32, 64]);
|
||||
assert!(type_set.ints.is_empty());
|
||||
assert!(type_set.specials.is_empty());
|
||||
|
||||
let type_set = TypeSetBuilder::new()
|
||||
.floats(Interval::All)
|
||||
@@ -737,7 +702,6 @@ fn test_typevar_builder() {
|
||||
assert_eq!(type_set.lanes, num_set![2, 4, 8, 16, 32, 64, 128, 256]);
|
||||
assert_eq!(type_set.floats, num_set![32, 64]);
|
||||
assert!(type_set.ints.is_empty());
|
||||
assert!(type_set.specials.is_empty());
|
||||
|
||||
let type_set = TypeSetBuilder::new()
|
||||
.floats(Interval::All)
|
||||
@@ -747,7 +711,6 @@ fn test_typevar_builder() {
|
||||
assert_eq!(type_set.lanes, num_set![1, 2, 4, 8, 16, 32, 64, 128, 256]);
|
||||
assert_eq!(type_set.floats, num_set![32, 64]);
|
||||
assert!(type_set.ints.is_empty());
|
||||
assert!(type_set.specials.is_empty());
|
||||
|
||||
let type_set = TypeSetBuilder::new()
|
||||
.floats(Interval::All)
|
||||
@@ -758,7 +721,6 @@ fn test_typevar_builder() {
|
||||
assert_eq!(type_set.floats, num_set![32, 64]);
|
||||
assert!(type_set.dynamic_lanes.is_empty());
|
||||
assert!(type_set.ints.is_empty());
|
||||
assert!(type_set.specials.is_empty());
|
||||
|
||||
let type_set = TypeSetBuilder::new()
|
||||
.ints(Interval::All)
|
||||
@@ -773,7 +735,6 @@ fn test_typevar_builder() {
|
||||
assert_eq!(type_set.ints, num_set![8, 16, 32, 64, 128]);
|
||||
assert_eq!(type_set.floats, num_set![32, 64]);
|
||||
assert_eq!(type_set.lanes, num_set![1]);
|
||||
assert!(type_set.specials.is_empty());
|
||||
|
||||
let type_set = TypeSetBuilder::new()
|
||||
.floats(Interval::All)
|
||||
@@ -787,13 +748,11 @@ fn test_typevar_builder() {
|
||||
assert_eq!(type_set.floats, num_set![32, 64]);
|
||||
assert_eq!(type_set.lanes, num_set![1]);
|
||||
assert!(type_set.ints.is_empty());
|
||||
assert!(type_set.specials.is_empty());
|
||||
|
||||
let type_set = TypeSetBuilder::new().ints(16..64).build();
|
||||
assert_eq!(type_set.lanes, num_set![1]);
|
||||
assert_eq!(type_set.ints, num_set![16, 32, 64]);
|
||||
assert!(type_set.floats.is_empty());
|
||||
assert!(type_set.specials.is_empty());
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -979,7 +938,6 @@ fn test_typevar_singleton() {
|
||||
assert_eq!(typevar.name, "i32");
|
||||
assert_eq!(typevar.type_set.ints, num_set![32]);
|
||||
assert!(typevar.type_set.floats.is_empty());
|
||||
assert!(typevar.type_set.specials.is_empty());
|
||||
assert_eq!(typevar.type_set.lanes, num_set![1]);
|
||||
|
||||
// Test f32x4.
|
||||
@@ -991,5 +949,4 @@ fn test_typevar_singleton() {
|
||||
assert!(typevar.type_set.ints.is_empty());
|
||||
assert_eq!(typevar.type_set.floats, num_set![32]);
|
||||
assert_eq!(typevar.type_set.lanes, num_set![4]);
|
||||
assert!(typevar.type_set.specials.is_empty());
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user