Make room for SpecialType in the value type numbering.
The value types are now classified into three groups: 1. Lane types are scalar types that can also be used to form vectors. 2. Vector types 2-256 copies of a lane type. 3. Special types. This is where the CPU flag types will go. The special types can't be used to form vectors. Change the numbering scheme for value types to make room for the special types and add `is_lane()` and `is_special()` classification methods. The VOID type still has number 0, but it can no longer appear as a vector lane. It classifies as special now.
This commit is contained in:
@@ -166,18 +166,15 @@ Concrete value types are represented as instances of :class:`ValueType`. There
|
||||
are subclasses to represent scalar and vector types.
|
||||
|
||||
.. autoclass:: ValueType
|
||||
.. inheritance-diagram:: ValueType LaneType VectorType IntType FloatType BoolType
|
||||
.. inheritance-diagram:: ValueType LaneType VectorType SpecialType IntType FloatType BoolType
|
||||
:parts: 1
|
||||
.. autoclass:: LaneType
|
||||
:members:
|
||||
.. autoclass:: VectorType
|
||||
:members:
|
||||
.. autoclass:: SpecialType
|
||||
.. autoclass:: IntType
|
||||
:members:
|
||||
.. autoclass:: FloatType
|
||||
:members:
|
||||
.. autoclass:: BoolType
|
||||
:members:
|
||||
|
||||
.. automodule:: base.types
|
||||
:members:
|
||||
|
||||
@@ -9,6 +9,18 @@ except ImportError:
|
||||
pass
|
||||
|
||||
|
||||
# Numbering scheme for value types:
|
||||
#
|
||||
# 0: Void
|
||||
# 0x01-0x6f: Special types
|
||||
# 0x70-0x7f: Lane types
|
||||
# 0x80-0xff: Vector types
|
||||
#
|
||||
# Vector types are encoded with the lane type in the low 4 bits and log2(lanes)
|
||||
# in the high 4 bits, giving a range of 2-256 lanes.
|
||||
LANE_BASE = 0x70
|
||||
|
||||
|
||||
# ValueType instances (i8, i32, ...) are provided in the `base.types` module.
|
||||
class ValueType(object):
|
||||
"""
|
||||
@@ -24,6 +36,9 @@ class ValueType(object):
|
||||
# List of all the lane types.
|
||||
all_lane_types = list() # type: List[LaneType]
|
||||
|
||||
# List of all the special types (neither lanes nor vectors).
|
||||
all_special_types = list() # type: List[SpecialType]
|
||||
|
||||
def __init__(self, name, membytes, doc):
|
||||
# type: (str, int, str) -> None
|
||||
self.name = name
|
||||
@@ -87,10 +102,11 @@ class LaneType(ValueType):
|
||||
# type: (str, int, str) -> None
|
||||
super(LaneType, self).__init__(name, membytes, doc)
|
||||
self._vectors = dict() # type: Dict[int, VectorType]
|
||||
# Assign numbers starting from 1. (0 is VOID).
|
||||
# Assign numbers starting from LANE_BASE.
|
||||
n = len(ValueType.all_lane_types)
|
||||
ValueType.all_lane_types.append(self)
|
||||
self.number = len(ValueType.all_lane_types)
|
||||
assert self.number < 16, 'Too many lane types'
|
||||
assert n < 16, 'Too many lane types'
|
||||
self.number = LANE_BASE + n
|
||||
|
||||
def __repr__(self):
|
||||
# type: () -> str
|
||||
@@ -132,6 +148,7 @@ class VectorType(ValueType):
|
||||
doc="""
|
||||
A SIMD vector with {} lanes containing a `{}` each.
|
||||
""".format(lanes, base.name))
|
||||
assert lanes <= 256, "Too many lanes"
|
||||
self.base = base
|
||||
self.lanes = lanes
|
||||
self.number = 16*int(math.log(lanes, 2)) + base.number
|
||||
@@ -152,6 +169,31 @@ class VectorType(ValueType):
|
||||
return self.base.lane_bits()
|
||||
|
||||
|
||||
class SpecialType(ValueType):
|
||||
"""
|
||||
A concrete scalar type that is neither a vector nor a lane type.
|
||||
|
||||
Special types cannot be used to form vectors.
|
||||
"""
|
||||
|
||||
def __init__(self, name, membytes, doc):
|
||||
# type: (str, int, str) -> None
|
||||
super(SpecialType, self).__init__(name, membytes, doc)
|
||||
# Assign numbers starting from 1. (0 is VOID)
|
||||
ValueType.all_special_types.append(self)
|
||||
self.number = len(ValueType.all_special_types)
|
||||
assert self.number < LANE_BASE, 'Too many special types'
|
||||
|
||||
def __repr__(self):
|
||||
# type: () -> str
|
||||
return 'SpecialType({})'.format(self.name)
|
||||
|
||||
def lane_count(self):
|
||||
# type: () -> int
|
||||
"""Return the number of lanes."""
|
||||
return 1
|
||||
|
||||
|
||||
class IntType(LaneType):
|
||||
"""A concrete scalar integer type."""
|
||||
|
||||
|
||||
@@ -30,6 +30,12 @@ pub struct Type(u8);
|
||||
/// a SIMD vector.
|
||||
pub const VOID: Type = Type(0);
|
||||
|
||||
// Start of the lane types. See also `meta/cdsl.types.py`.
|
||||
const LANE_BASE: u8 = 0x70;
|
||||
|
||||
// Start of the 2-lane vector types.
|
||||
const VECTOR_BASE: u8 = LANE_BASE + 16;
|
||||
|
||||
// Include code generated by `lib/cretonne/meta/gen_types.py`. This file contains constant
|
||||
// definitions for all the scalar types as well as common vector types for 64, 128, 256, and
|
||||
// 512-bit SIMD vectors.
|
||||
@@ -40,7 +46,11 @@ impl Type {
|
||||
///
|
||||
/// A lane type is the same as a SIMD vector type with one lane, so it returns itself.
|
||||
pub fn lane_type(self) -> Type {
|
||||
Type(self.0 & 0x0f)
|
||||
if self.0 < VECTOR_BASE {
|
||||
self
|
||||
} else {
|
||||
Type(LANE_BASE | (self.0 & 0x0f))
|
||||
}
|
||||
}
|
||||
|
||||
/// Get log_2 of the number of bits in a lane.
|
||||
@@ -78,6 +88,12 @@ impl Type {
|
||||
}
|
||||
}
|
||||
|
||||
/// Get a type with the same number of lanes as `self`, but using `lane` as the lane type.
|
||||
fn replace_lanes(self, lane: Type) -> Type {
|
||||
debug_assert!(lane.is_lane() && !self.is_special());
|
||||
Type((lane.0 & 0x0f) | (self.0 & 0xf0))
|
||||
}
|
||||
|
||||
/// Get a type with the same number of lanes as this type, but with the lanes replaced by
|
||||
/// booleans of the same size.
|
||||
///
|
||||
@@ -85,14 +101,13 @@ impl Type {
|
||||
/// boolean types.
|
||||
pub fn as_bool_pedantic(self) -> Type {
|
||||
// Replace the low 4 bits with the boolean version, preserve the high 4 bits.
|
||||
let lane = match self.lane_type() {
|
||||
self.replace_lanes(match self.lane_type() {
|
||||
B8 | I8 => B8,
|
||||
B16 | I16 => B16,
|
||||
B32 | I32 | F32 => B32,
|
||||
B64 | I64 | F64 => B64,
|
||||
_ => B1,
|
||||
};
|
||||
Type(lane.0 | (self.0 & 0xf0))
|
||||
})
|
||||
}
|
||||
|
||||
/// Get a type with the same number of lanes as this type, but with the lanes replaced by
|
||||
@@ -110,7 +125,7 @@ impl Type {
|
||||
/// Get a type with the same number of lanes as this type, but with lanes that are half the
|
||||
/// number of bits.
|
||||
pub fn half_width(self) -> Option<Type> {
|
||||
let lane = match self.lane_type() {
|
||||
Some(self.replace_lanes(match self.lane_type() {
|
||||
I16 => I8,
|
||||
I32 => I16,
|
||||
I64 => I32,
|
||||
@@ -119,14 +134,13 @@ impl Type {
|
||||
B32 => B16,
|
||||
B64 => B32,
|
||||
_ => return None,
|
||||
};
|
||||
Some(Type(lane.0 | (self.0 & 0xf0)))
|
||||
}))
|
||||
}
|
||||
|
||||
/// Get a type with the same number of lanes as this type, but with lanes that are twice the
|
||||
/// number of bits.
|
||||
pub fn double_width(self) -> Option<Type> {
|
||||
let lane = match self.lane_type() {
|
||||
Some(self.replace_lanes(match self.lane_type() {
|
||||
I8 => I16,
|
||||
I16 => I32,
|
||||
I32 => I64,
|
||||
@@ -135,8 +149,7 @@ impl Type {
|
||||
B16 => B32,
|
||||
B32 => B64,
|
||||
_ => return None,
|
||||
};
|
||||
Some(Type(lane.0 | (self.0 & 0xf0)))
|
||||
}))
|
||||
}
|
||||
|
||||
/// Is this the VOID type?
|
||||
@@ -144,6 +157,25 @@ impl Type {
|
||||
self == VOID
|
||||
}
|
||||
|
||||
/// Is this a special type?
|
||||
pub fn is_special(self) -> bool {
|
||||
self.0 < LANE_BASE
|
||||
}
|
||||
|
||||
/// Is this a lane type?
|
||||
///
|
||||
/// This is a scalar type that can also appear as the lane type of a SIMD vector.
|
||||
pub fn is_lane(self) -> bool {
|
||||
LANE_BASE <= self.0 && self.0 < VECTOR_BASE
|
||||
}
|
||||
|
||||
/// Is this a SIMD vector type?
|
||||
///
|
||||
/// A vector type has 2 or more lanes.
|
||||
pub fn is_vector(self) -> bool {
|
||||
self.0 >= VECTOR_BASE
|
||||
}
|
||||
|
||||
/// Is this a scalar boolean type?
|
||||
pub fn is_bool(self) -> bool {
|
||||
match self {
|
||||
@@ -175,14 +207,7 @@ impl Type {
|
||||
///
|
||||
/// A scalar type is the same as a SIMD vector type with one lane, so it returns 0.
|
||||
pub fn log2_lane_count(self) -> u8 {
|
||||
self.0 >> 4
|
||||
}
|
||||
|
||||
/// Is this a SIMD vector type?
|
||||
///
|
||||
/// A vector type has 2 or more lanes.
|
||||
pub fn is_vector(self) -> bool {
|
||||
self.log2_lane_count() > 0
|
||||
self.0.saturating_sub(LANE_BASE) >> 4
|
||||
}
|
||||
|
||||
/// Get the number of lanes in this SIMD vector type.
|
||||
@@ -214,7 +239,7 @@ impl Type {
|
||||
}
|
||||
let log2_lanes: u32 = n.trailing_zeros();
|
||||
let new_type = u32::from(self.0) + (log2_lanes << 4);
|
||||
if new_type < 0x90 {
|
||||
if new_type < 0x100 {
|
||||
Some(Type(new_type as u8))
|
||||
} else {
|
||||
None
|
||||
|
||||
Reference in New Issue
Block a user