Rename ScalarType to LaneType.

The word "scalar" is a bit vague and tends to mean "non-vector". Since
we are about to add new CPU flag value types that can't appear as vector
lanes, make the distinction clear: LaneType represents value types that
can appear as a vector lane.

Also replace the Type::is_scalar() method with an is_vector() method.
This commit is contained in:
Jakob Stoklund Olesen
2017-10-12 10:39:12 -07:00
parent 994af598f5
commit 89a24b2f13
9 changed files with 45 additions and 48 deletions

View File

@@ -166,9 +166,9 @@ Concrete value types are represented as instances of :class:`ValueType`. There
are subclasses to represent scalar and vector types. are subclasses to represent scalar and vector types.
.. autoclass:: ValueType .. autoclass:: ValueType
.. inheritance-diagram:: ValueType ScalarType VectorType IntType FloatType BoolType .. inheritance-diagram:: ValueType LaneType VectorType IntType FloatType BoolType
:parts: 1 :parts: 1
.. autoclass:: ScalarType .. autoclass:: LaneType
:members: :members:
.. autoclass:: VectorType .. autoclass:: VectorType
:members: :members:
@@ -183,7 +183,7 @@ are subclasses to represent scalar and vector types.
:members: :members:
There are no predefined vector types, but they can be created as needed with There are no predefined vector types, but they can be created as needed with
the :func:`ScalarType.by` function. the :func:`LaneType.by` function.
.. module:: cdsl.operands .. module:: cdsl.operands

View File

@@ -9,7 +9,7 @@ except ImportError:
pass pass
# ValueType instances (i8, i32, ...) are provided in the cretonne.types module. # ValueType instances (i8, i32, ...) are provided in the `base.types` module.
class ValueType(object): class ValueType(object):
""" """
A concrete SSA value type. A concrete SSA value type.
@@ -21,8 +21,8 @@ class ValueType(object):
# Map name -> ValueType. # Map name -> ValueType.
_registry = dict() # type: Dict[str, ValueType] _registry = dict() # type: Dict[str, ValueType]
# List of all the scalar types. # List of all the lane types.
all_scalars = list() # type: List[ScalarType] all_lane_types = list() # type: List[LaneType]
def __init__(self, name, membytes, doc): def __init__(self, name, membytes, doc):
# type: (str, int, str) -> None # type: (str, int, str) -> None
@@ -75,9 +75,9 @@ class ValueType(object):
self.lane_bits() >= other.lane_bits()) self.lane_bits() >= other.lane_bits())
class ScalarType(ValueType): class LaneType(ValueType):
""" """
A concrete scalar (not vector) type. A concrete scalar type that can appear as a vector lane too.
Also tracks a unique set of :py:class:`VectorType` instances with this type Also tracks a unique set of :py:class:`VectorType` instances with this type
as the lane type. as the lane type.
@@ -85,16 +85,16 @@ class ScalarType(ValueType):
def __init__(self, name, membytes, doc): def __init__(self, name, membytes, doc):
# type: (str, int, str) -> None # type: (str, int, str) -> None
super(ScalarType, self).__init__(name, membytes, doc) super(LaneType, self).__init__(name, membytes, doc)
self._vectors = dict() # type: Dict[int, VectorType] self._vectors = dict() # type: Dict[int, VectorType]
# Assign numbers starting from 1. (0 is VOID). # Assign numbers starting from 1. (0 is VOID).
ValueType.all_scalars.append(self) ValueType.all_lane_types.append(self)
self.number = len(ValueType.all_scalars) self.number = len(ValueType.all_lane_types)
assert self.number < 16, 'Too many scalar types' assert self.number < 16, 'Too many lane types'
def __repr__(self): def __repr__(self):
# type: () -> str # type: () -> str
return 'ScalarType({})'.format(self.name) return 'LaneType({})'.format(self.name)
def by(self, lanes): def by(self, lanes):
# type: (int) -> VectorType # type: (int) -> VectorType
@@ -120,13 +120,12 @@ class VectorType(ValueType):
""" """
A concrete SIMD vector type. A concrete SIMD vector type.
A vector type has a lane type which is an instance of :class:`ScalarType`, A vector type has a lane type which is an instance of :class:`LaneType`,
and a positive number of lanes. and a positive number of lanes.
""" """
def __init__(self, base, lanes): def __init__(self, base, lanes):
# type: (ScalarType, int) -> None # type: (LaneType, int) -> None
assert isinstance(base, ScalarType), 'SIMD lanes must be scalar types'
super(VectorType, self).__init__( super(VectorType, self).__init__(
name='{}x{}'.format(base.name, lanes), name='{}x{}'.format(base.name, lanes),
membytes=lanes*base.membytes, membytes=lanes*base.membytes,
@@ -153,7 +152,7 @@ class VectorType(ValueType):
return self.base.lane_bits() return self.base.lane_bits()
class IntType(ScalarType): class IntType(LaneType):
"""A concrete scalar integer type.""" """A concrete scalar integer type."""
def __init__(self, bits): def __init__(self, bits):
@@ -184,7 +183,7 @@ class IntType(ScalarType):
return self.bits return self.bits
class FloatType(ScalarType): class FloatType(LaneType):
"""A concrete scalar floating point type.""" """A concrete scalar floating point type."""
def __init__(self, bits, doc): def __init__(self, bits, doc):
@@ -215,7 +214,7 @@ class FloatType(ScalarType):
return self.bits return self.bits
class BoolType(ScalarType): class BoolType(LaneType):
"""A concrete scalar boolean type.""" """A concrete scalar boolean type."""
def __init__(self, bits): def __init__(self, bits):

View File

@@ -487,7 +487,7 @@ class TypeSet(object):
def concrete_types(self): def concrete_types(self):
# type: () -> Iterable[types.ValueType] # type: () -> Iterable[types.ValueType]
def by(scalar, lanes): def by(scalar, lanes):
# type: (types.ScalarType, int) -> types.ValueType # type: (types.LaneType, int) -> types.ValueType
if (lanes == 1): if (lanes == 1):
return scalar return scalar
else: else:
@@ -577,7 +577,7 @@ class TypeVar(object):
if isinstance(typ, types.VectorType): if isinstance(typ, types.VectorType):
scalar = typ.base scalar = typ.base
lanes = (typ.lanes, typ.lanes) lanes = (typ.lanes, typ.lanes)
elif isinstance(typ, types.ScalarType): elif isinstance(typ, types.LaneType):
scalar = typ scalar = typ
lanes = (1, 1) lanes = (1, 1)
else: else:

View File

@@ -36,7 +36,7 @@ def emit_vectors(bits, fmt):
Emit definition for all vector types with `bits` total size. Emit definition for all vector types with `bits` total size.
""" """
size = bits // 8 size = bits // 8
for ty in ValueType.all_scalars: for ty in ValueType.all_lane_types:
mb = ty.membytes mb = ty.membytes
if mb == 0 or mb >= size: if mb == 0 or mb >= size:
continue continue
@@ -45,7 +45,7 @@ def emit_vectors(bits, fmt):
def emit_types(fmt): def emit_types(fmt):
# type: (srcgen.Formatter) -> None # type: (srcgen.Formatter) -> None
for ty in ValueType.all_scalars: for ty in ValueType.all_lane_types:
emit_type(ty, fmt) emit_type(ty, fmt)
# Emit vector definitions for common SIMD sizes. # Emit vector definitions for common SIMD sizes.
emit_vectors(64, fmt) emit_vectors(64, fmt)

View File

@@ -164,21 +164,19 @@ pub fn legalize_abi_value(have: Type, arg: &ArgumentType) -> ValueConversion {
Ordering::Equal => { Ordering::Equal => {
// This must be an integer vector that is split and then extended. // This must be an integer vector that is split and then extended.
assert!(arg.value_type.is_int()); assert!(arg.value_type.is_int());
assert!(!have.is_scalar()); assert!(have.is_vector());
ValueConversion::VectorSplit ValueConversion::VectorSplit
} }
// We have more bits than the argument. // We have more bits than the argument.
Ordering::Greater => { Ordering::Greater => {
if have.is_scalar() { if have.is_vector() {
if have.is_float() {
// Convert a float to int so it can be split the next time.
// ARM would do this to pass an `f64` in two registers.
ValueConversion::IntBits
} else {
ValueConversion::IntSplit
}
} else {
ValueConversion::VectorSplit ValueConversion::VectorSplit
} else if have.is_float() {
// Convert a float to int so it can be split the next time.
// ARM would do this to pass an `f64` in two registers.
ValueConversion::IntBits
} else {
ValueConversion::IntSplit
} }
} }
} }

View File

@@ -38,7 +38,7 @@ include!(concat!(env!("OUT_DIR"), "/types.rs"));
impl Type { impl Type {
/// Get the lane type of this SIMD vector type. /// Get the lane type of this SIMD vector type.
/// ///
/// A scalar type is the same as a SIMD vector type with one lane, so it returns itself. /// A lane type is the same as a SIMD vector type with one lane, so it returns itself.
pub fn lane_type(self) -> Type { pub fn lane_type(self) -> Type {
Type(self.0 & 0x0f) Type(self.0 & 0x0f)
} }
@@ -100,7 +100,7 @@ impl Type {
/// ///
/// Scalar types are all converted to `b1` which is usually what you want. /// Scalar types are all converted to `b1` which is usually what you want.
pub fn as_bool(self) -> Type { pub fn as_bool(self) -> Type {
if self.is_scalar() { if !self.is_vector() {
B1 B1
} else { } else {
self.as_bool_pedantic() self.as_bool_pedantic()
@@ -173,16 +173,16 @@ impl Type {
/// All SIMD types have a lane count that is a power of two and no larger than 256, so this /// All SIMD types have a lane count that is a power of two and no larger than 256, so this
/// will be a number in the range 0-8. /// will be a number in the range 0-8.
/// ///
/// A scalar type is the same as a SIMD vector type with one lane, so it return 0. /// 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 { pub fn log2_lane_count(self) -> u8 {
self.0 >> 4 self.0 >> 4
} }
/// Is this a scalar type? (That is, not a SIMD vector type). /// Is this a SIMD vector type?
/// ///
/// A scalar type is the same as a SIMD vector type with one lane. /// A vector type has 2 or more lanes.
pub fn is_scalar(self) -> bool { pub fn is_vector(self) -> bool {
self.log2_lane_count() == 0 self.log2_lane_count() > 0
} }
/// Get the number of lanes in this SIMD vector type. /// Get the number of lanes in this SIMD vector type.
@@ -225,10 +225,10 @@ impl Type {
/// ///
/// There is no `double_vector()` method. Use `t.by(2)` instead. /// There is no `double_vector()` method. Use `t.by(2)` instead.
pub fn half_vector(self) -> Option<Type> { pub fn half_vector(self) -> Option<Type> {
if self.is_scalar() { if self.is_vector() {
None
} else {
Some(Type(self.0 - 0x10)) Some(Type(self.0 - 0x10))
} else {
None
} }
} }
@@ -255,7 +255,7 @@ impl Display for Type {
write!(f, "i{}", self.lane_bits()) write!(f, "i{}", self.lane_bits())
} else if self.is_float() { } else if self.is_float() {
write!(f, "f{}", self.lane_bits()) write!(f, "f{}", self.lane_bits())
} else if !self.is_scalar() { } else if self.is_vector() {
write!(f, "{}x{}", self.lane_type(), self.lane_count()) write!(f, "{}x{}", self.lane_type(), self.lane_count())
} else { } else {
panic!("Invalid Type(0x{:x})", self.0) panic!("Invalid Type(0x{:x})", self.0)
@@ -273,7 +273,7 @@ impl Debug for Type {
write!(f, "types::I{}", self.lane_bits()) write!(f, "types::I{}", self.lane_bits())
} else if self.is_float() { } else if self.is_float() {
write!(f, "types::F{}", self.lane_bits()) write!(f, "types::F{}", self.lane_bits())
} else if !self.is_scalar() { } else if self.is_vector() {
write!(f, "{:?}X{}", self.lane_type(), self.lane_count()) write!(f, "{:?}X{}", self.lane_type(), self.lane_count())
} else { } else {
write!(f, "Type(0x{:x})", self.0) write!(f, "Type(0x{:x})", self.0)

View File

@@ -46,7 +46,7 @@ impl ArgAssigner for Args {
// Check for a legal type. // Check for a legal type.
// We don't support SIMD yet, so break all vectors down. // We don't support SIMD yet, so break all vectors down.
if !ty.is_scalar() { if ty.is_vector() {
return ValueConversion::VectorSplit.into(); return ValueConversion::VectorSplit.into();
} }

View File

@@ -45,7 +45,7 @@ impl ArgAssigner for Args {
// Check for a legal type. // Check for a legal type.
// RISC-V doesn't have SIMD at all, so break all vectors down. // RISC-V doesn't have SIMD at all, so break all vectors down.
if !ty.is_scalar() { if ty.is_vector() {
return ValueConversion::VectorSplit.into(); return ValueConversion::VectorSplit.into();
} }

View File

@@ -217,7 +217,7 @@ fn expand_select(inst: ir::Inst, func: &mut ir::Function, cfg: &mut ControlFlowG
/// Expand illegal `f32const` and `f64const` instructions. /// Expand illegal `f32const` and `f64const` instructions.
fn expand_fconst(inst: ir::Inst, func: &mut ir::Function, _cfg: &mut ControlFlowGraph) { fn expand_fconst(inst: ir::Inst, func: &mut ir::Function, _cfg: &mut ControlFlowGraph) {
let ty = func.dfg.value_type(func.dfg.first_result(inst)); let ty = func.dfg.value_type(func.dfg.first_result(inst));
assert!(ty.is_scalar(), "Only scalar fconst supported: {}", ty); assert!(!ty.is_vector(), "Only scalar fconst supported: {}", ty);
// In the future, we may want to generate constant pool entries for these constants, but for // In the future, we may want to generate constant pool entries for these constants, but for
// now use an `iconst` and a bit cast. // now use an `iconst` and a bit cast.