[meta] Add helper methods and tests to TypeSet;
This commit is contained in:
@@ -1,4 +1,7 @@
|
|||||||
use std::collections::BTreeSet;
|
use std::cell::RefCell;
|
||||||
|
use std::collections::{BTreeSet, HashSet};
|
||||||
|
use std::fmt;
|
||||||
|
use std::hash;
|
||||||
use std::iter::FromIterator;
|
use std::iter::FromIterator;
|
||||||
use std::ops;
|
use std::ops;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
@@ -301,7 +304,7 @@ macro_rules! num_set {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
#[derive(Clone, PartialEq, Eq, Hash)]
|
||||||
pub struct TypeSet {
|
pub struct TypeSet {
|
||||||
pub lanes: NumSet,
|
pub lanes: NumSet,
|
||||||
pub ints: NumSet,
|
pub ints: NumSet,
|
||||||
@@ -331,7 +334,7 @@ impl TypeSet {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Return the number of concrete types represented by this typeset.
|
/// Return the number of concrete types represented by this typeset.
|
||||||
fn size(&self) -> usize {
|
pub fn size(&self) -> usize {
|
||||||
self.lanes.len()
|
self.lanes.len()
|
||||||
* (self.ints.len() + self.floats.len() + self.bools.len() + self.bitvecs.len())
|
* (self.ints.len() + self.floats.len() + self.bools.len() + self.bitvecs.len())
|
||||||
+ self.specials.len()
|
+ self.specials.len()
|
||||||
@@ -486,6 +489,175 @@ impl TypeSet {
|
|||||||
assert_eq!(types.len(), 1);
|
assert_eq!(types.len(), 1);
|
||||||
return types.remove(0);
|
return types.remove(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Return the inverse image of self across the derived function func.
|
||||||
|
fn preimage(&self, func: DerivedFunc) -> TypeSet {
|
||||||
|
if self.size() == 0 {
|
||||||
|
// The inverse of the empty set is itself.
|
||||||
|
return self.clone();
|
||||||
|
}
|
||||||
|
|
||||||
|
match func {
|
||||||
|
DerivedFunc::LaneOf => {
|
||||||
|
let mut copy = self.clone();
|
||||||
|
copy.bitvecs = NumSet::new();
|
||||||
|
copy.lanes =
|
||||||
|
NumSet::from_iter((0..MAX_LANES.trailing_zeros() + 1).map(|i| u16::pow(2, i)));
|
||||||
|
copy
|
||||||
|
}
|
||||||
|
DerivedFunc::AsBool => {
|
||||||
|
let mut copy = self.clone();
|
||||||
|
copy.bitvecs = NumSet::new();
|
||||||
|
if self.bools.contains(&1) {
|
||||||
|
copy.ints = NumSet::from_iter(vec![8, 16, 32, 64]);
|
||||||
|
copy.floats = NumSet::from_iter(vec![32, 64]);
|
||||||
|
} else {
|
||||||
|
copy.ints = &self.bools - &NumSet::from_iter(vec![1]);
|
||||||
|
copy.floats = &self.bools & &NumSet::from_iter(vec![32, 64]);
|
||||||
|
// If b1 is not in our typeset, than lanes=1 cannot be in the pre-image, as
|
||||||
|
// as_bool() of scalars is always b1.
|
||||||
|
copy.lanes = &self.lanes - &NumSet::from_iter(vec![1]);
|
||||||
|
}
|
||||||
|
copy
|
||||||
|
}
|
||||||
|
DerivedFunc::HalfWidth => self.double_width(),
|
||||||
|
DerivedFunc::DoubleWidth => self.half_width(),
|
||||||
|
DerivedFunc::HalfVector => self.double_vector(),
|
||||||
|
DerivedFunc::DoubleVector => self.half_vector(),
|
||||||
|
DerivedFunc::ToBitVec => {
|
||||||
|
let all_lanes = range_to_set(Some(1..MAX_LANES));
|
||||||
|
let all_ints = range_to_set(Some(8..MAX_BITS));
|
||||||
|
let all_floats = range_to_set(Some(32..64));
|
||||||
|
let all_bools = range_to_set(Some(1..MAX_BITS));
|
||||||
|
|
||||||
|
let mut lanes = range_to_set(Some(1..MAX_LANES));
|
||||||
|
let mut ints = range_to_set(Some(8..MAX_BITS));
|
||||||
|
let mut floats = range_to_set(Some(32..64));
|
||||||
|
let mut bools = range_to_set(Some(1..MAX_BITS));
|
||||||
|
|
||||||
|
for &l in &all_lanes {
|
||||||
|
for &i in &all_ints {
|
||||||
|
if self.bitvecs.contains(&(i * l)) {
|
||||||
|
lanes.insert(l);
|
||||||
|
ints.insert(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for &f in &all_floats {
|
||||||
|
if self.bitvecs.contains(&(f * l)) {
|
||||||
|
lanes.insert(l);
|
||||||
|
floats.insert(f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for &b in &all_bools {
|
||||||
|
if self.bitvecs.contains(&(b * l)) {
|
||||||
|
lanes.insert(l);
|
||||||
|
bools.insert(b);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let bitvecs = NumSet::new();
|
||||||
|
let specials = Vec::new();
|
||||||
|
TypeSet::new(lanes, ints, floats, bools, bitvecs, specials)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn inplace_intersect_with(&mut self, other: &TypeSet) {
|
||||||
|
self.lanes = &self.lanes & &other.lanes;
|
||||||
|
self.ints = &self.ints & &other.ints;
|
||||||
|
self.floats = &self.floats & &other.floats;
|
||||||
|
self.bools = &self.bools & &other.bools;
|
||||||
|
self.bitvecs = &self.bitvecs & &other.bitvecs;
|
||||||
|
|
||||||
|
let mut new_specials = Vec::new();
|
||||||
|
for spec in &self.specials {
|
||||||
|
if let Some(spec) = other.specials.iter().find(|&other_spec| other_spec == spec) {
|
||||||
|
new_specials.push(*spec);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
self.specials = new_specials;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_subset(&self, other: &TypeSet) -> bool {
|
||||||
|
self.lanes.is_subset(&other.lanes)
|
||||||
|
&& self.ints.is_subset(&other.ints)
|
||||||
|
&& self.floats.is_subset(&other.floats)
|
||||||
|
&& self.bools.is_subset(&other.bools)
|
||||||
|
&& self.bitvecs.is_subset(&other.bitvecs)
|
||||||
|
&& {
|
||||||
|
let specials: HashSet<SpecialType> = HashSet::from_iter(self.specials.clone());
|
||||||
|
let other_specials = HashSet::from_iter(other.specials.clone());
|
||||||
|
specials.is_subset(&other_specials)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_wider_or_equal(&self, other: &TypeSet) -> bool {
|
||||||
|
set_wider_or_equal(&self.ints, &other.ints)
|
||||||
|
&& set_wider_or_equal(&self.floats, &other.floats)
|
||||||
|
&& set_wider_or_equal(&self.bools, &other.bools)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_narrower(&self, other: &TypeSet) -> bool {
|
||||||
|
set_narrower(&self.ints, &other.ints)
|
||||||
|
&& set_narrower(&self.floats, &other.floats)
|
||||||
|
&& set_narrower(&self.bools, &other.bools)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_wider_or_equal(s1: &NumSet, s2: &NumSet) -> bool {
|
||||||
|
s1.len() > 0 && s2.len() > 0 && s1.iter().min() >= s2.iter().max()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_narrower(s1: &NumSet, s2: &NumSet) -> bool {
|
||||||
|
s1.len() > 0 && s2.len() > 0 && s1.iter().min() < s2.iter().max()
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Debug for TypeSet {
|
||||||
|
fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
|
||||||
|
write!(fmt, "TypeSet(")?;
|
||||||
|
|
||||||
|
let mut subsets = Vec::new();
|
||||||
|
if !self.lanes.is_empty() {
|
||||||
|
subsets.push(format!(
|
||||||
|
"lanes={{{}}}",
|
||||||
|
Vec::from_iter(self.lanes.iter().map(|x| x.to_string())).join(", ")
|
||||||
|
));
|
||||||
|
}
|
||||||
|
if !self.ints.is_empty() {
|
||||||
|
subsets.push(format!(
|
||||||
|
"ints={{{}}}",
|
||||||
|
Vec::from_iter(self.ints.iter().map(|x| x.to_string())).join(", ")
|
||||||
|
));
|
||||||
|
}
|
||||||
|
if !self.floats.is_empty() {
|
||||||
|
subsets.push(format!(
|
||||||
|
"floats={{{}}}",
|
||||||
|
Vec::from_iter(self.floats.iter().map(|x| x.to_string())).join(", ")
|
||||||
|
));
|
||||||
|
}
|
||||||
|
if !self.bools.is_empty() {
|
||||||
|
subsets.push(format!(
|
||||||
|
"bools={{{}}}",
|
||||||
|
Vec::from_iter(self.bools.iter().map(|x| x.to_string())).join(", ")
|
||||||
|
));
|
||||||
|
}
|
||||||
|
if !self.bitvecs.is_empty() {
|
||||||
|
subsets.push(format!(
|
||||||
|
"bitvecs={{{}}}",
|
||||||
|
Vec::from_iter(self.bitvecs.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(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct TypeSetBuilder {
|
pub struct TypeSetBuilder {
|
||||||
@@ -805,6 +977,136 @@ fn test_forward_images() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_backward_images() {
|
||||||
|
let empty_set = TypeSetBuilder::new().finish();
|
||||||
|
|
||||||
|
// LaneOf.
|
||||||
|
assert_eq!(
|
||||||
|
TypeSetBuilder::new()
|
||||||
|
.simd_lanes(1..1)
|
||||||
|
.ints(8..8)
|
||||||
|
.floats(32..32)
|
||||||
|
.finish()
|
||||||
|
.preimage(DerivedFunc::LaneOf),
|
||||||
|
TypeSetBuilder::new()
|
||||||
|
.simd_lanes(Interval::All)
|
||||||
|
.ints(8..8)
|
||||||
|
.floats(32..32)
|
||||||
|
.finish()
|
||||||
|
);
|
||||||
|
assert_eq!(empty_set.preimage(DerivedFunc::LaneOf), empty_set);
|
||||||
|
|
||||||
|
// AsBool.
|
||||||
|
assert_eq!(
|
||||||
|
TypeSetBuilder::new()
|
||||||
|
.simd_lanes(1..4)
|
||||||
|
.bools(1..64)
|
||||||
|
.finish()
|
||||||
|
.preimage(DerivedFunc::AsBool),
|
||||||
|
TypeSetBuilder::new()
|
||||||
|
.simd_lanes(1..4)
|
||||||
|
.ints(Interval::All)
|
||||||
|
.bools(Interval::All)
|
||||||
|
.floats(Interval::All)
|
||||||
|
.finish()
|
||||||
|
);
|
||||||
|
|
||||||
|
// Double vector.
|
||||||
|
assert_eq!(
|
||||||
|
TypeSetBuilder::new()
|
||||||
|
.simd_lanes(1..1)
|
||||||
|
.ints(8..8)
|
||||||
|
.finish()
|
||||||
|
.preimage(DerivedFunc::DoubleVector)
|
||||||
|
.size(),
|
||||||
|
0
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
TypeSetBuilder::new()
|
||||||
|
.simd_lanes(1..16)
|
||||||
|
.ints(8..16)
|
||||||
|
.floats(32..32)
|
||||||
|
.finish()
|
||||||
|
.preimage(DerivedFunc::DoubleVector),
|
||||||
|
TypeSetBuilder::new()
|
||||||
|
.simd_lanes(1..8)
|
||||||
|
.ints(8..16)
|
||||||
|
.floats(32..32)
|
||||||
|
.finish(),
|
||||||
|
);
|
||||||
|
|
||||||
|
// Half vector.
|
||||||
|
assert_eq!(
|
||||||
|
TypeSetBuilder::new()
|
||||||
|
.simd_lanes(256..256)
|
||||||
|
.ints(8..8)
|
||||||
|
.finish()
|
||||||
|
.preimage(DerivedFunc::HalfVector)
|
||||||
|
.size(),
|
||||||
|
0
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
TypeSetBuilder::new()
|
||||||
|
.simd_lanes(64..128)
|
||||||
|
.bools(1..32)
|
||||||
|
.finish()
|
||||||
|
.preimage(DerivedFunc::HalfVector),
|
||||||
|
TypeSetBuilder::new()
|
||||||
|
.simd_lanes(128..256)
|
||||||
|
.bools(1..32)
|
||||||
|
.finish(),
|
||||||
|
);
|
||||||
|
|
||||||
|
// Half width.
|
||||||
|
assert_eq!(
|
||||||
|
TypeSetBuilder::new()
|
||||||
|
.ints(64..64)
|
||||||
|
.floats(64..64)
|
||||||
|
.bools(64..64)
|
||||||
|
.finish()
|
||||||
|
.preimage(DerivedFunc::HalfWidth)
|
||||||
|
.size(),
|
||||||
|
0
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
TypeSetBuilder::new()
|
||||||
|
.simd_lanes(64..256)
|
||||||
|
.bools(1..64)
|
||||||
|
.finish()
|
||||||
|
.preimage(DerivedFunc::HalfWidth),
|
||||||
|
TypeSetBuilder::new()
|
||||||
|
.simd_lanes(64..256)
|
||||||
|
.bools(16..64)
|
||||||
|
.finish(),
|
||||||
|
);
|
||||||
|
|
||||||
|
// Double width.
|
||||||
|
assert_eq!(
|
||||||
|
TypeSetBuilder::new()
|
||||||
|
.ints(8..8)
|
||||||
|
.floats(32..32)
|
||||||
|
.bools(1..8)
|
||||||
|
.finish()
|
||||||
|
.preimage(DerivedFunc::DoubleWidth)
|
||||||
|
.size(),
|
||||||
|
0
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
TypeSetBuilder::new()
|
||||||
|
.simd_lanes(1..16)
|
||||||
|
.ints(8..16)
|
||||||
|
.floats(32..64)
|
||||||
|
.finish()
|
||||||
|
.preimage(DerivedFunc::DoubleWidth),
|
||||||
|
TypeSetBuilder::new()
|
||||||
|
.simd_lanes(1..16)
|
||||||
|
.ints(8..8)
|
||||||
|
.floats(32..32)
|
||||||
|
.finish()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[should_panic]
|
#[should_panic]
|
||||||
fn test_typeset_singleton_panic_nonsingleton_types() {
|
fn test_typeset_singleton_panic_nonsingleton_types() {
|
||||||
|
|||||||
Reference in New Issue
Block a user