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:
@@ -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
|
||||||
|
|||||||
@@ -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):
|
||||||
|
|||||||
@@ -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:
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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.
|
||||||
|
|||||||
Reference in New Issue
Block a user