Type::by() returns an Optional<Type>.

Don't use assertions to enforce the limits on SIMD lanes in a type, Type is too
fundamental for that. Instead, the Vector-forming by() method returns an
Optional<Type>, and None if the requested SIMD vector is not valid.

Same for Type::half_vector().
This commit is contained in:
Jakob Stoklund Olesen
2016-04-27 14:51:16 -07:00
parent c0f77f35c7
commit bbeafde243

View File

@@ -147,21 +147,26 @@ impl Type {
/// ///
/// If this is already a SIMD vector type, this produces a SIMD vector type with `n * /// If this is already a SIMD vector type, this produces a SIMD vector type with `n *
/// self.lane_count()` lanes. /// self.lane_count()` lanes.
pub fn by(self, n: u16) -> Type { pub fn by(self, n: u16) -> Option<Type> {
debug_assert!(self.lane_bits() > 0, if self.lane_bits() == 0 || !n.is_power_of_two() {
"Can't make SIMD vectors with void lanes."); return None;
debug_assert!(n.is_power_of_two(), }
"Number of SIMD lanes must be a power of two");
let log2_lanes: u32 = n.trailing_zeros(); let log2_lanes: u32 = n.trailing_zeros();
let new_type = self.0 as u32 + (log2_lanes << 4); let new_type = self.0 as u32 + (log2_lanes << 4);
assert!(new_type < 0x90, "No more than 256 SIMD lanes supported"); if new_type < 0x90 {
Type(new_type as u8) Some(Type(new_type as u8))
} else {
None
}
} }
/// Get a SIMD vector with half the number of lanes. /// Get a SIMD vector with half the number of lanes.
pub fn half_vector(self) -> Type { pub fn half_vector(self) -> Option<Type> {
assert!(!self.is_scalar(), "Expecting a proper SIMD vector type."); if self.is_scalar() {
Type(self.0 - 0x10) None
} else {
Some(Type(self.0 - 0x10))
}
} }
} }
@@ -320,13 +325,16 @@ mod tests {
#[test] #[test]
fn vectors() { fn vectors() {
let big = F64.by(256); let big = F64.by(256).unwrap();
assert_eq!(big.lane_bits(), 64); assert_eq!(big.lane_bits(), 64);
assert_eq!(big.lane_count(), 256); assert_eq!(big.lane_count(), 256);
assert_eq!(big.bits(), 64 * 256); assert_eq!(big.bits(), 64 * 256);
assert_eq!(format!("{}", big.half_vector()), "f64x128"); assert_eq!(format!("{}", big.half_vector().unwrap()), "f64x128");
assert_eq!(format!("{}", B1.by(2).half_vector()), "b1"); assert_eq!(format!("{}", B1.by(2).unwrap().half_vector().unwrap()),
"b1");
assert_eq!(I32.half_vector(), None);
assert_eq!(VOID.half_vector(), None);
} }
#[test] #[test]
@@ -347,13 +355,16 @@ mod tests {
#[test] #[test]
fn format_vectors() { fn format_vectors() {
assert_eq!(format!("{}", B1.by(8)), "b1x8"); assert_eq!(format!("{}", B1.by(8).unwrap()), "b1x8");
assert_eq!(format!("{}", B8.by(1)), "b8"); assert_eq!(format!("{}", B8.by(1).unwrap()), "b8");
assert_eq!(format!("{}", B16.by(256)), "b16x256"); assert_eq!(format!("{}", B16.by(256).unwrap()), "b16x256");
assert_eq!(format!("{}", B32.by(4).by(2)), "b32x8"); assert_eq!(format!("{}", B32.by(4).unwrap().by(2).unwrap()), "b32x8");
assert_eq!(format!("{}", B64.by(8)), "b64x8"); assert_eq!(format!("{}", B64.by(8).unwrap()), "b64x8");
assert_eq!(format!("{}", I8.by(64)), "i8x64"); assert_eq!(format!("{}", I8.by(64).unwrap()), "i8x64");
assert_eq!(format!("{}", F64.by(2)), "f64x2"); assert_eq!(format!("{}", F64.by(2).unwrap()), "f64x2");
assert_eq!(I8.by(3), None);
assert_eq!(I8.by(512), None);
assert_eq!(VOID.by(4), None);
} }
#[test] #[test]
@@ -374,7 +385,7 @@ mod tests {
assert_eq!(format!("{}", sig), "(i32)"); assert_eq!(format!("{}", sig), "(i32)");
sig.return_types.push(ArgumentType::new(F32)); sig.return_types.push(ArgumentType::new(F32));
assert_eq!(format!("{}", sig), "(i32) -> f32"); assert_eq!(format!("{}", sig), "(i32) -> f32");
sig.argument_types.push(ArgumentType::new(I32.by(4))); sig.argument_types.push(ArgumentType::new(I32.by(4).unwrap()));
assert_eq!(format!("{}", sig), "(i32, i32x4) -> f32"); assert_eq!(format!("{}", sig), "(i32, i32x4) -> f32");
sig.return_types.push(ArgumentType::new(B8)); sig.return_types.push(ArgumentType::new(B8));
assert_eq!(format!("{}", sig), "(i32, i32x4) -> f32, b8"); assert_eq!(format!("{}", sig), "(i32, i32x4) -> f32, b8");