cranelift: Remove booleans (#5031)
Remove the boolean types from cranelift, and the associated instructions breduce, bextend, bconst, and bint. Standardize on using 1/0 for the return value from instructions that produce scalar boolean results, and -1/0 for boolean vector elements. Fixes #3205 Co-authored-by: Afonso Bordado <afonso360@users.noreply.github.com> Co-authored-by: Ulrich Weigand <ulrich.weigand@de.ibm.com> Co-authored-by: Chris Fallin <chris@cfallin.org>
This commit is contained in:
@@ -145,7 +145,6 @@ impl From<DynamicVectorType> for ValueType {
|
||||
/// A concrete scalar type that can appear as a vector lane too.
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Hash)]
|
||||
pub(crate) enum LaneType {
|
||||
Bool(shared_types::Bool),
|
||||
Float(shared_types::Float),
|
||||
Int(shared_types::Int),
|
||||
}
|
||||
@@ -154,7 +153,6 @@ impl LaneType {
|
||||
/// Return a string containing the documentation comment for this lane type.
|
||||
pub fn doc(self) -> String {
|
||||
match self {
|
||||
LaneType::Bool(_) => format!("A boolean type with {} bits.", self.lane_bits()),
|
||||
LaneType::Float(shared_types::Float::F32) => String::from(
|
||||
"A 32-bit floating point type represented in the IEEE 754-2008
|
||||
*binary32* interchange format. This corresponds to the :c:type:`float`
|
||||
@@ -178,7 +176,6 @@ impl LaneType {
|
||||
/// Return the number of bits in a lane.
|
||||
pub fn lane_bits(self) -> u64 {
|
||||
match self {
|
||||
LaneType::Bool(ref b) => *b as u64,
|
||||
LaneType::Float(ref f) => *f as u64,
|
||||
LaneType::Int(ref i) => *i as u64,
|
||||
}
|
||||
@@ -188,12 +185,6 @@ impl LaneType {
|
||||
pub fn number(self) -> u16 {
|
||||
constants::LANE_BASE
|
||||
+ match self {
|
||||
LaneType::Bool(shared_types::Bool::B1) => 0,
|
||||
LaneType::Bool(shared_types::Bool::B8) => 1,
|
||||
LaneType::Bool(shared_types::Bool::B16) => 2,
|
||||
LaneType::Bool(shared_types::Bool::B32) => 3,
|
||||
LaneType::Bool(shared_types::Bool::B64) => 4,
|
||||
LaneType::Bool(shared_types::Bool::B128) => 5,
|
||||
LaneType::Int(shared_types::Int::I8) => 6,
|
||||
LaneType::Int(shared_types::Int::I16) => 7,
|
||||
LaneType::Int(shared_types::Int::I32) => 8,
|
||||
@@ -204,18 +195,6 @@ impl LaneType {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn bool_from_bits(num_bits: u16) -> LaneType {
|
||||
LaneType::Bool(match num_bits {
|
||||
1 => shared_types::Bool::B1,
|
||||
8 => shared_types::Bool::B8,
|
||||
16 => shared_types::Bool::B16,
|
||||
32 => shared_types::Bool::B32,
|
||||
64 => shared_types::Bool::B64,
|
||||
128 => shared_types::Bool::B128,
|
||||
_ => unreachable!("unxpected num bits for bool"),
|
||||
})
|
||||
}
|
||||
|
||||
pub fn int_from_bits(num_bits: u16) -> LaneType {
|
||||
LaneType::Int(match num_bits {
|
||||
8 => shared_types::Int::I8,
|
||||
@@ -251,7 +230,6 @@ impl LaneType {
|
||||
impl fmt::Display for LaneType {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match *self {
|
||||
LaneType::Bool(_) => write!(f, "b{}", self.lane_bits()),
|
||||
LaneType::Float(_) => write!(f, "f{}", self.lane_bits()),
|
||||
LaneType::Int(_) => write!(f, "i{}", self.lane_bits()),
|
||||
}
|
||||
@@ -265,7 +243,6 @@ impl fmt::Debug for LaneType {
|
||||
f,
|
||||
"{}",
|
||||
match *self {
|
||||
LaneType::Bool(_) => format!("BoolType({})", inner_msg),
|
||||
LaneType::Float(_) => format!("FloatType({})", inner_msg),
|
||||
LaneType::Int(_) => format!("IntType({})", inner_msg),
|
||||
}
|
||||
@@ -273,13 +250,6 @@ impl fmt::Debug for LaneType {
|
||||
}
|
||||
}
|
||||
|
||||
/// Create a LaneType from a given bool variant.
|
||||
impl From<shared_types::Bool> for LaneType {
|
||||
fn from(b: shared_types::Bool) -> Self {
|
||||
LaneType::Bool(b)
|
||||
}
|
||||
}
|
||||
|
||||
/// Create a LaneType from a given float variant.
|
||||
impl From<shared_types::Float> for LaneType {
|
||||
fn from(f: shared_types::Float) -> Self {
|
||||
@@ -296,7 +266,6 @@ impl From<shared_types::Int> for LaneType {
|
||||
|
||||
/// An iterator for different lane types.
|
||||
pub(crate) struct LaneTypeIterator {
|
||||
bool_iter: shared_types::BoolIterator,
|
||||
int_iter: shared_types::IntIterator,
|
||||
float_iter: shared_types::FloatIterator,
|
||||
}
|
||||
@@ -305,7 +274,6 @@ impl LaneTypeIterator {
|
||||
/// Create a new lane type iterator.
|
||||
fn new() -> Self {
|
||||
Self {
|
||||
bool_iter: shared_types::BoolIterator::new(),
|
||||
int_iter: shared_types::IntIterator::new(),
|
||||
float_iter: shared_types::FloatIterator::new(),
|
||||
}
|
||||
@@ -315,9 +283,7 @@ impl LaneTypeIterator {
|
||||
impl Iterator for LaneTypeIterator {
|
||||
type Item = LaneType;
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
if let Some(b) = self.bool_iter.next() {
|
||||
Some(LaneType::from(b))
|
||||
} else if let Some(i) = self.int_iter.next() {
|
||||
if let Some(i) = self.int_iter.next() {
|
||||
Some(LaneType::from(i))
|
||||
} else if let Some(f) = self.float_iter.next() {
|
||||
Some(LaneType::from(f))
|
||||
|
||||
@@ -90,10 +90,6 @@ impl TypeVar {
|
||||
let bits = float_type as RangeBound;
|
||||
builder.floats(bits..bits)
|
||||
}
|
||||
LaneType::Bool(bool_type) => {
|
||||
let bits = bool_type as RangeBound;
|
||||
builder.bools(bits..bits)
|
||||
}
|
||||
};
|
||||
TypeVar::new(name, doc, builder.build())
|
||||
}
|
||||
@@ -171,10 +167,6 @@ impl TypeVar {
|
||||
ts.floats.is_empty() || *ts.floats.iter().min().unwrap() > 32,
|
||||
"can't halve all float types"
|
||||
);
|
||||
assert!(
|
||||
ts.bools.is_empty() || *ts.bools.iter().min().unwrap() > 8,
|
||||
"can't halve all boolean types"
|
||||
);
|
||||
}
|
||||
DerivedFunc::DoubleWidth => {
|
||||
assert!(
|
||||
@@ -185,10 +177,6 @@ impl TypeVar {
|
||||
ts.floats.is_empty() || *ts.floats.iter().max().unwrap() < MAX_FLOAT_BITS,
|
||||
"can't double all float types"
|
||||
);
|
||||
assert!(
|
||||
ts.bools.is_empty() || *ts.bools.iter().max().unwrap() < MAX_BITS,
|
||||
"can't double all boolean types"
|
||||
);
|
||||
}
|
||||
DerivedFunc::HalfVector => {
|
||||
assert!(
|
||||
@@ -211,10 +199,6 @@ impl TypeVar {
|
||||
ts.floats.is_empty() || *ts.floats.iter().min().unwrap() > 32,
|
||||
"can't halve all float types"
|
||||
);
|
||||
assert!(
|
||||
ts.bools.is_empty() || *ts.bools.iter().min().unwrap() > 8,
|
||||
"can't halve all boolean types"
|
||||
);
|
||||
assert!(
|
||||
*ts.lanes.iter().max().unwrap() < MAX_LANES,
|
||||
"can't double 256 lanes"
|
||||
@@ -229,10 +213,6 @@ impl TypeVar {
|
||||
ts.floats.is_empty() || *ts.floats.iter().max().unwrap() < MAX_FLOAT_BITS,
|
||||
"can't double all float types"
|
||||
);
|
||||
assert!(
|
||||
ts.bools.is_empty() || *ts.bools.iter().max().unwrap() < MAX_BITS,
|
||||
"can't double all boolean types"
|
||||
);
|
||||
assert!(
|
||||
*ts.lanes.iter().min().unwrap() > 1,
|
||||
"can't halve a scalar type"
|
||||
@@ -404,7 +384,6 @@ pub(crate) struct TypeSet {
|
||||
pub dynamic_lanes: NumSet,
|
||||
pub ints: NumSet,
|
||||
pub floats: NumSet,
|
||||
pub bools: NumSet,
|
||||
pub refs: NumSet,
|
||||
pub specials: Vec<SpecialType>,
|
||||
}
|
||||
@@ -415,7 +394,6 @@ impl TypeSet {
|
||||
dynamic_lanes: NumSet,
|
||||
ints: NumSet,
|
||||
floats: NumSet,
|
||||
bools: NumSet,
|
||||
refs: NumSet,
|
||||
specials: Vec<SpecialType>,
|
||||
) -> Self {
|
||||
@@ -424,7 +402,6 @@ impl TypeSet {
|
||||
dynamic_lanes,
|
||||
ints,
|
||||
floats,
|
||||
bools,
|
||||
refs,
|
||||
specials,
|
||||
}
|
||||
@@ -432,10 +409,8 @@ impl TypeSet {
|
||||
|
||||
/// Return the number of concrete types represented by this typeset.
|
||||
pub fn size(&self) -> usize {
|
||||
self.lanes.len()
|
||||
* (self.ints.len() + self.floats.len() + self.bools.len() + self.refs.len())
|
||||
+ self.dynamic_lanes.len()
|
||||
* (self.ints.len() + self.floats.len() + self.bools.len() + self.refs.len())
|
||||
self.lanes.len() * (self.ints.len() + self.floats.len() + self.refs.len())
|
||||
+ self.dynamic_lanes.len() * (self.ints.len() + self.floats.len() + self.refs.len())
|
||||
+ self.specials.len()
|
||||
}
|
||||
|
||||
@@ -467,13 +442,6 @@ impl TypeSet {
|
||||
copy.ints = NumSet::new();
|
||||
copy.floats = NumSet::new();
|
||||
copy.refs = NumSet::new();
|
||||
if !(&self.lanes - &num_set![1]).is_empty() {
|
||||
copy.bools = &self.ints | &self.floats;
|
||||
copy.bools = ©.bools | &self.bools;
|
||||
}
|
||||
if self.lanes.contains(&1) {
|
||||
copy.bools.insert(1);
|
||||
}
|
||||
copy
|
||||
}
|
||||
|
||||
@@ -482,7 +450,6 @@ impl TypeSet {
|
||||
let mut copy = self.clone();
|
||||
copy.ints = NumSet::from_iter(self.ints.iter().filter(|&&x| x > 8).map(|&x| x / 2));
|
||||
copy.floats = NumSet::from_iter(self.floats.iter().filter(|&&x| x > 32).map(|&x| x / 2));
|
||||
copy.bools = NumSet::from_iter(self.bools.iter().filter(|&&x| x > 8).map(|&x| x / 2));
|
||||
copy.specials = Vec::new();
|
||||
copy
|
||||
}
|
||||
@@ -497,13 +464,6 @@ impl TypeSet {
|
||||
.filter(|&&x| x < MAX_FLOAT_BITS)
|
||||
.map(|&x| x * 2),
|
||||
);
|
||||
copy.bools = NumSet::from_iter(
|
||||
self.bools
|
||||
.iter()
|
||||
.filter(|&&x| x < MAX_BITS)
|
||||
.map(|&x| x * 2)
|
||||
.filter(|x| legal_bool(*x)),
|
||||
);
|
||||
copy.specials = Vec::new();
|
||||
copy
|
||||
}
|
||||
@@ -551,9 +511,6 @@ impl TypeSet {
|
||||
for &bits in &self.floats {
|
||||
ret.push(LaneType::float_from_bits(bits).by(num_lanes));
|
||||
}
|
||||
for &bits in &self.bools {
|
||||
ret.push(LaneType::bool_from_bits(bits).by(num_lanes));
|
||||
}
|
||||
for &bits in &self.refs {
|
||||
ret.push(ReferenceType::ref_from_bits(bits).into());
|
||||
}
|
||||
@@ -565,9 +522,6 @@ impl TypeSet {
|
||||
for &bits in &self.floats {
|
||||
ret.push(LaneType::float_from_bits(bits).to_dynamic(num_lanes));
|
||||
}
|
||||
for &bits in &self.bools {
|
||||
ret.push(LaneType::bool_from_bits(bits).to_dynamic(num_lanes));
|
||||
}
|
||||
}
|
||||
for &special in &self.specials {
|
||||
ret.push(special.into());
|
||||
@@ -612,12 +566,6 @@ impl fmt::Debug for TypeSet {
|
||||
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.refs.is_empty() {
|
||||
subsets.push(format!(
|
||||
"refs={{{}}}",
|
||||
@@ -639,7 +587,6 @@ impl fmt::Debug for TypeSet {
|
||||
pub(crate) struct TypeSetBuilder {
|
||||
ints: Interval,
|
||||
floats: Interval,
|
||||
bools: Interval,
|
||||
refs: Interval,
|
||||
includes_scalars: bool,
|
||||
simd_lanes: Interval,
|
||||
@@ -652,7 +599,6 @@ impl TypeSetBuilder {
|
||||
Self {
|
||||
ints: Interval::None,
|
||||
floats: Interval::None,
|
||||
bools: Interval::None,
|
||||
refs: Interval::None,
|
||||
includes_scalars: true,
|
||||
simd_lanes: Interval::None,
|
||||
@@ -671,11 +617,6 @@ impl TypeSetBuilder {
|
||||
self.floats = interval.into();
|
||||
self
|
||||
}
|
||||
pub fn bools(mut self, interval: impl Into<Interval>) -> Self {
|
||||
assert!(self.bools == Interval::None);
|
||||
self.bools = interval.into();
|
||||
self
|
||||
}
|
||||
pub fn refs(mut self, interval: impl Into<Interval>) -> Self {
|
||||
assert!(self.refs == Interval::None);
|
||||
self.refs = interval.into();
|
||||
@@ -704,17 +645,11 @@ impl TypeSetBuilder {
|
||||
pub fn build(self) -> TypeSet {
|
||||
let min_lanes = if self.includes_scalars { 1 } else { 2 };
|
||||
|
||||
let bools = range_to_set(self.bools.to_range(1..MAX_BITS, None))
|
||||
.into_iter()
|
||||
.filter(|x| legal_bool(*x))
|
||||
.collect();
|
||||
|
||||
TypeSet::new(
|
||||
range_to_set(self.simd_lanes.to_range(min_lanes..MAX_LANES, Some(1))),
|
||||
range_to_set(self.dynamic_simd_lanes.to_range(2..MAX_LANES, None)),
|
||||
range_to_set(self.ints.to_range(8..MAX_BITS, None)),
|
||||
range_to_set(self.floats.to_range(32..64, None)),
|
||||
bools,
|
||||
range_to_set(self.refs.to_range(32..64, None)),
|
||||
self.specials,
|
||||
)
|
||||
@@ -760,11 +695,6 @@ impl Into<Interval> for Range {
|
||||
}
|
||||
}
|
||||
|
||||
fn legal_bool(bits: RangeBound) -> bool {
|
||||
// Only allow legal bit widths for bool types.
|
||||
bits == 1 || (bits >= 8 && bits <= MAX_BITS && bits.is_power_of_two())
|
||||
}
|
||||
|
||||
/// Generates a set with all the powers of two included in the range.
|
||||
fn range_to_set(range: Option<Range>) -> NumSet {
|
||||
let mut set = NumSet::new();
|
||||
@@ -791,21 +721,12 @@ fn test_typevar_builder() {
|
||||
assert_eq!(type_set.lanes, num_set![1]);
|
||||
assert!(type_set.floats.is_empty());
|
||||
assert_eq!(type_set.ints, num_set![8, 16, 32, 64, 128]);
|
||||
assert!(type_set.bools.is_empty());
|
||||
assert!(type_set.specials.is_empty());
|
||||
|
||||
let type_set = TypeSetBuilder::new().bools(Interval::All).build();
|
||||
assert_eq!(type_set.lanes, num_set![1]);
|
||||
assert!(type_set.floats.is_empty());
|
||||
assert!(type_set.ints.is_empty());
|
||||
assert_eq!(type_set.bools, num_set![1, 8, 16, 32, 64, 128]);
|
||||
assert!(type_set.specials.is_empty());
|
||||
|
||||
let type_set = TypeSetBuilder::new().floats(Interval::All).build();
|
||||
assert_eq!(type_set.lanes, num_set![1]);
|
||||
assert_eq!(type_set.floats, num_set![32, 64]);
|
||||
assert!(type_set.ints.is_empty());
|
||||
assert!(type_set.bools.is_empty());
|
||||
assert!(type_set.specials.is_empty());
|
||||
|
||||
let type_set = TypeSetBuilder::new()
|
||||
@@ -816,7 +737,6 @@ fn test_typevar_builder() {
|
||||
assert_eq!(type_set.lanes, num_set![2, 4, 8, 16, 32, 64, 128, 256]);
|
||||
assert_eq!(type_set.floats, num_set![32, 64]);
|
||||
assert!(type_set.ints.is_empty());
|
||||
assert!(type_set.bools.is_empty());
|
||||
assert!(type_set.specials.is_empty());
|
||||
|
||||
let type_set = TypeSetBuilder::new()
|
||||
@@ -827,7 +747,6 @@ fn test_typevar_builder() {
|
||||
assert_eq!(type_set.lanes, num_set![1, 2, 4, 8, 16, 32, 64, 128, 256]);
|
||||
assert_eq!(type_set.floats, num_set![32, 64]);
|
||||
assert!(type_set.ints.is_empty());
|
||||
assert!(type_set.bools.is_empty());
|
||||
assert!(type_set.specials.is_empty());
|
||||
|
||||
let type_set = TypeSetBuilder::new()
|
||||
@@ -839,12 +758,10 @@ fn test_typevar_builder() {
|
||||
assert_eq!(type_set.floats, num_set![32, 64]);
|
||||
assert!(type_set.dynamic_lanes.is_empty());
|
||||
assert!(type_set.ints.is_empty());
|
||||
assert!(type_set.bools.is_empty());
|
||||
assert!(type_set.specials.is_empty());
|
||||
|
||||
let type_set = TypeSetBuilder::new()
|
||||
.ints(Interval::All)
|
||||
.bools(Interval::All)
|
||||
.floats(Interval::All)
|
||||
.dynamic_simd_lanes(Interval::All)
|
||||
.includes_scalars(false)
|
||||
@@ -854,7 +771,6 @@ fn test_typevar_builder() {
|
||||
num_set![2, 4, 8, 16, 32, 64, 128, 256]
|
||||
);
|
||||
assert_eq!(type_set.ints, num_set![8, 16, 32, 64, 128]);
|
||||
assert_eq!(type_set.bools, num_set![1, 8, 16, 32, 64, 128]);
|
||||
assert_eq!(type_set.floats, num_set![32, 64]);
|
||||
assert_eq!(type_set.lanes, num_set![1]);
|
||||
assert!(type_set.specials.is_empty());
|
||||
@@ -871,14 +787,12 @@ fn test_typevar_builder() {
|
||||
assert_eq!(type_set.floats, num_set![32, 64]);
|
||||
assert_eq!(type_set.lanes, num_set![1]);
|
||||
assert!(type_set.ints.is_empty());
|
||||
assert!(type_set.bools.is_empty());
|
||||
assert!(type_set.specials.is_empty());
|
||||
|
||||
let type_set = TypeSetBuilder::new().ints(16..64).build();
|
||||
assert_eq!(type_set.lanes, num_set![1]);
|
||||
assert_eq!(type_set.ints, num_set![16, 32, 64]);
|
||||
assert!(type_set.floats.is_empty());
|
||||
assert!(type_set.bools.is_empty());
|
||||
assert!(type_set.specials.is_empty());
|
||||
}
|
||||
|
||||
@@ -897,17 +811,6 @@ fn test_dynamic_to_vector() {
|
||||
.ints(Interval::All)
|
||||
.build()
|
||||
);
|
||||
assert_eq!(
|
||||
TypeSetBuilder::new()
|
||||
.dynamic_simd_lanes(Interval::All)
|
||||
.bools(Interval::All)
|
||||
.build()
|
||||
.dynamic_to_vector(),
|
||||
TypeSetBuilder::new()
|
||||
.simd_lanes(2..128)
|
||||
.bools(Interval::All)
|
||||
.build()
|
||||
);
|
||||
assert_eq!(
|
||||
TypeSetBuilder::new()
|
||||
.dynamic_simd_lanes(Interval::All)
|
||||
@@ -944,20 +847,6 @@ fn test_as_bool() {
|
||||
a.lane_of(),
|
||||
TypeSetBuilder::new().ints(8..8).floats(32..32).build()
|
||||
);
|
||||
|
||||
// Test as_bool with disjoint intervals.
|
||||
let mut a_as_bool = TypeSetBuilder::new().simd_lanes(2..8).build();
|
||||
a_as_bool.bools = num_set![8, 32];
|
||||
assert_eq!(a.as_bool(), a_as_bool);
|
||||
|
||||
let b = TypeSetBuilder::new()
|
||||
.simd_lanes(1..8)
|
||||
.ints(8..8)
|
||||
.floats(32..32)
|
||||
.build();
|
||||
let mut b_as_bool = TypeSetBuilder::new().simd_lanes(1..8).build();
|
||||
b_as_bool.bools = num_set![1, 8, 32];
|
||||
assert_eq!(b.as_bool(), b_as_bool);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -1002,14 +891,6 @@ fn test_forward_images() {
|
||||
TypeSetBuilder::new().floats(32..64).build().half_width(),
|
||||
TypeSetBuilder::new().floats(32..32).build()
|
||||
);
|
||||
assert_eq!(
|
||||
TypeSetBuilder::new().bools(1..8).build().half_width(),
|
||||
empty_set
|
||||
);
|
||||
assert_eq!(
|
||||
TypeSetBuilder::new().bools(1..32).build().half_width(),
|
||||
TypeSetBuilder::new().bools(8..16).build()
|
||||
);
|
||||
|
||||
// Double width.
|
||||
assert_eq!(
|
||||
@@ -1028,14 +909,6 @@ fn test_forward_images() {
|
||||
TypeSetBuilder::new().floats(32..64).build().double_width(),
|
||||
TypeSetBuilder::new().floats(64..64).build()
|
||||
);
|
||||
assert_eq!(
|
||||
TypeSetBuilder::new().bools(1..16).build().double_width(),
|
||||
TypeSetBuilder::new().bools(16..32).build()
|
||||
);
|
||||
assert_eq!(
|
||||
TypeSetBuilder::new().bools(32..64).build().double_width(),
|
||||
TypeSetBuilder::new().bools(64..128).build()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -1069,10 +942,6 @@ fn test_typeset_singleton() {
|
||||
TypeSetBuilder::new().floats(64..64).build().get_singleton(),
|
||||
ValueType::Lane(shared_types::Float::F64.into())
|
||||
);
|
||||
assert_eq!(
|
||||
TypeSetBuilder::new().bools(1..1).build().get_singleton(),
|
||||
ValueType::Lane(shared_types::Bool::B1.into())
|
||||
);
|
||||
assert_eq!(
|
||||
TypeSetBuilder::new()
|
||||
.simd_lanes(4..4)
|
||||
@@ -1110,7 +979,6 @@ fn test_typevar_singleton() {
|
||||
assert_eq!(typevar.name, "i32");
|
||||
assert_eq!(typevar.type_set.ints, num_set![32]);
|
||||
assert!(typevar.type_set.floats.is_empty());
|
||||
assert!(typevar.type_set.bools.is_empty());
|
||||
assert!(typevar.type_set.specials.is_empty());
|
||||
assert_eq!(typevar.type_set.lanes, num_set![1]);
|
||||
|
||||
@@ -1123,6 +991,5 @@ fn test_typevar_singleton() {
|
||||
assert!(typevar.type_set.ints.is_empty());
|
||||
assert_eq!(typevar.type_set.floats, num_set![32]);
|
||||
assert_eq!(typevar.type_set.lanes, num_set![4]);
|
||||
assert!(typevar.type_set.bools.is_empty());
|
||||
assert!(typevar.type_set.specials.is_empty());
|
||||
}
|
||||
|
||||
@@ -769,9 +769,6 @@ fn typeset_to_string(ts: &TypeSet) -> String {
|
||||
if !ts.floats.is_empty() {
|
||||
result += &format!(", floats={}", iterable_to_string(&ts.floats));
|
||||
}
|
||||
if !ts.bools.is_empty() {
|
||||
result += &format!(", bools={}", iterable_to_string(&ts.bools));
|
||||
}
|
||||
if !ts.specials.is_empty() {
|
||||
result += &format!(", specials=[{}]", iterable_to_string(&ts.specials));
|
||||
}
|
||||
@@ -804,7 +801,6 @@ pub(crate) fn gen_typesets_table(type_sets: &UniqueTable<TypeSet>, fmt: &mut For
|
||||
gen_bitset(&ts.dynamic_lanes, "dynamic_lanes", 16, fmt);
|
||||
gen_bitset(&ts.ints, "ints", 8, fmt);
|
||||
gen_bitset(&ts.floats, "floats", 8, fmt);
|
||||
gen_bitset(&ts.bools, "bools", 8, fmt);
|
||||
gen_bitset(&ts.refs, "refs", 8, fmt);
|
||||
});
|
||||
fmt.line("},");
|
||||
|
||||
@@ -43,7 +43,6 @@ pub(crate) struct Formats {
|
||||
pub(crate) ternary_imm8: Rc<InstructionFormat>,
|
||||
pub(crate) trap: Rc<InstructionFormat>,
|
||||
pub(crate) unary: Rc<InstructionFormat>,
|
||||
pub(crate) unary_bool: Rc<InstructionFormat>,
|
||||
pub(crate) unary_const: Rc<InstructionFormat>,
|
||||
pub(crate) unary_global_value: Rc<InstructionFormat>,
|
||||
pub(crate) unary_ieee32: Rc<InstructionFormat>,
|
||||
@@ -62,8 +61,6 @@ impl Formats {
|
||||
|
||||
unary_ieee64: Builder::new("UnaryIeee64").imm(&imm.ieee64).build(),
|
||||
|
||||
unary_bool: Builder::new("UnaryBool").imm(&imm.boolean).build(),
|
||||
|
||||
unary_const: Builder::new("UnaryConst").imm(&imm.pool_constant).build(),
|
||||
|
||||
unary_global_value: Builder::new("UnaryGlobalValue")
|
||||
|
||||
@@ -44,11 +44,6 @@ pub(crate) struct Immediates {
|
||||
/// IEEE 754-2008 binary64 interchange format.
|
||||
pub ieee64: OperandKind,
|
||||
|
||||
/// An immediate boolean operand.
|
||||
///
|
||||
/// This type of immediate boolean can interact with SSA values with any BoolType type.
|
||||
pub boolean: OperandKind,
|
||||
|
||||
/// A condition code for comparing integer values.
|
||||
///
|
||||
/// This enumerated operand kind is used for the `icmp` instruction and corresponds to the
|
||||
@@ -142,7 +137,6 @@ impl Immediates {
|
||||
"ir::immediates::Ieee64",
|
||||
"A 64-bit immediate floating point number.",
|
||||
),
|
||||
boolean: new_imm("imm", "bool", "An immediate boolean."),
|
||||
intcc: {
|
||||
let mut intcc_values = HashMap::new();
|
||||
intcc_values.insert("eq", "Equal");
|
||||
|
||||
@@ -37,17 +37,14 @@ fn define_control_flow(
|
||||
.is_branch(true),
|
||||
);
|
||||
|
||||
let Testable = &TypeVar::new(
|
||||
"Testable",
|
||||
"A scalar boolean or integer type",
|
||||
TypeSetBuilder::new()
|
||||
.ints(Interval::All)
|
||||
.bools(Interval::All)
|
||||
.build(),
|
||||
let ScalarTruthy = &TypeVar::new(
|
||||
"ScalarTruthy",
|
||||
"A scalar truthy type",
|
||||
TypeSetBuilder::new().ints(Interval::All).build(),
|
||||
);
|
||||
|
||||
{
|
||||
let c = &Operand::new("c", Testable).with_doc("Controlling value to test");
|
||||
let c = &Operand::new("c", ScalarTruthy).with_doc("Controlling value to test");
|
||||
|
||||
ig.push(
|
||||
Inst::new(
|
||||
@@ -55,8 +52,7 @@ fn define_control_flow(
|
||||
r#"
|
||||
Branch when zero.
|
||||
|
||||
If ``c`` is a `b1` value, take the branch when ``c`` is false. If
|
||||
``c`` is an integer value, take the branch when ``c = 0``.
|
||||
Take the branch when ``c = 0``.
|
||||
"#,
|
||||
&formats.branch,
|
||||
)
|
||||
@@ -70,8 +66,7 @@ fn define_control_flow(
|
||||
r#"
|
||||
Branch when non-zero.
|
||||
|
||||
If ``c`` is a `b1` value, take the branch when ``c`` is true. If
|
||||
``c`` is an integer value, take the branch when ``c != 0``.
|
||||
Take the branch when ``c != 0``.
|
||||
"#,
|
||||
&formats.branch,
|
||||
)
|
||||
@@ -226,7 +221,7 @@ fn define_control_flow(
|
||||
.is_terminator(true),
|
||||
);
|
||||
|
||||
let c = &Operand::new("c", Testable).with_doc("Controlling value to test");
|
||||
let c = &Operand::new("c", ScalarTruthy).with_doc("Controlling value to test");
|
||||
ig.push(
|
||||
Inst::new(
|
||||
"trapz",
|
||||
@@ -255,7 +250,7 @@ fn define_control_flow(
|
||||
.can_trap(true),
|
||||
);
|
||||
|
||||
let c = &Operand::new("c", Testable).with_doc("Controlling value to test");
|
||||
let c = &Operand::new("c", ScalarTruthy).with_doc("Controlling value to test");
|
||||
ig.push(
|
||||
Inst::new(
|
||||
"trapnz",
|
||||
@@ -412,7 +407,6 @@ fn define_simd_lane_access(
|
||||
TypeSetBuilder::new()
|
||||
.ints(Interval::All)
|
||||
.floats(Interval::All)
|
||||
.bools(Interval::All)
|
||||
.simd_lanes(Interval::All)
|
||||
.dynamic_simd_lanes(Interval::All)
|
||||
.includes_scalars(false)
|
||||
@@ -685,7 +679,7 @@ pub(crate) fn define(
|
||||
let iflags: &TypeVar = &ValueType::Special(types::Flag::IFlags.into()).into();
|
||||
let fflags: &TypeVar = &ValueType::Special(types::Flag::FFlags.into()).into();
|
||||
|
||||
let b1: &TypeVar = &ValueType::from(LaneType::from(types::Bool::B1)).into();
|
||||
let i8: &TypeVar = &ValueType::from(LaneType::from(types::Int::I8)).into();
|
||||
let f32_: &TypeVar = &ValueType::from(LaneType::from(types::Float::F32)).into();
|
||||
let f64_: &TypeVar = &ValueType::from(LaneType::from(types::Float::F64)).into();
|
||||
|
||||
@@ -700,19 +694,10 @@ pub(crate) fn define(
|
||||
.build(),
|
||||
);
|
||||
|
||||
let Bool = &TypeVar::new(
|
||||
"Bool",
|
||||
"A scalar or vector boolean type",
|
||||
TypeSetBuilder::new()
|
||||
.bools(Interval::All)
|
||||
.simd_lanes(Interval::All)
|
||||
.build(),
|
||||
);
|
||||
|
||||
let ScalarBool = &TypeVar::new(
|
||||
"ScalarBool",
|
||||
"A scalar boolean type",
|
||||
TypeSetBuilder::new().bools(Interval::All).build(),
|
||||
let ScalarTruthy = &TypeVar::new(
|
||||
"ScalarTruthy",
|
||||
"A scalar truthy type",
|
||||
TypeSetBuilder::new().ints(Interval::All).build(),
|
||||
);
|
||||
|
||||
let iB = &TypeVar::new(
|
||||
@@ -733,33 +718,22 @@ pub(crate) fn define(
|
||||
TypeSetBuilder::new().refs(Interval::All).build(),
|
||||
);
|
||||
|
||||
let Testable = &TypeVar::new(
|
||||
"Testable",
|
||||
"A scalar boolean or integer type",
|
||||
TypeSetBuilder::new()
|
||||
.ints(Interval::All)
|
||||
.bools(Interval::All)
|
||||
.build(),
|
||||
);
|
||||
|
||||
let TxN = &TypeVar::new(
|
||||
"TxN",
|
||||
"A SIMD vector type",
|
||||
TypeSetBuilder::new()
|
||||
.ints(Interval::All)
|
||||
.floats(Interval::All)
|
||||
.bools(Interval::All)
|
||||
.simd_lanes(Interval::All)
|
||||
.includes_scalars(false)
|
||||
.build(),
|
||||
);
|
||||
let Any = &TypeVar::new(
|
||||
"Any",
|
||||
"Any integer, float, boolean, or reference scalar or vector type",
|
||||
"Any integer, float, or reference scalar or vector type",
|
||||
TypeSetBuilder::new()
|
||||
.ints(Interval::All)
|
||||
.floats(Interval::All)
|
||||
.bools(Interval::All)
|
||||
.refs(Interval::All)
|
||||
.simd_lanes(Interval::All)
|
||||
.includes_scalars(true)
|
||||
@@ -1419,24 +1393,6 @@ pub(crate) fn define(
|
||||
.operands_out(vec![a]),
|
||||
);
|
||||
|
||||
let N = &Operand::new("N", &imm.boolean);
|
||||
let a = &Operand::new("a", Bool).with_doc("A constant boolean scalar or vector value");
|
||||
|
||||
ig.push(
|
||||
Inst::new(
|
||||
"bconst",
|
||||
r#"
|
||||
Boolean constant.
|
||||
|
||||
Create a scalar boolean SSA value with an immediate constant value, or
|
||||
a boolean vector where all the lanes have the same value.
|
||||
"#,
|
||||
&formats.unary_bool,
|
||||
)
|
||||
.operands_in(vec![N])
|
||||
.operands_out(vec![a]),
|
||||
);
|
||||
|
||||
let N = &Operand::new("N", &imm.pool_constant)
|
||||
.with_doc("The 16 immediate bytes of a 128-bit vector");
|
||||
let a = &Operand::new("a", TxN).with_doc("A constant vector value");
|
||||
@@ -1463,7 +1419,6 @@ pub(crate) fn define(
|
||||
lane counts and widths",
|
||||
TypeSetBuilder::new()
|
||||
.ints(8..8)
|
||||
.bools(8..8)
|
||||
.simd_lanes(16..16)
|
||||
.includes_scalars(false)
|
||||
.build(),
|
||||
@@ -1513,7 +1468,7 @@ pub(crate) fn define(
|
||||
&formats.nullary,
|
||||
));
|
||||
|
||||
let c = &Operand::new("c", Testable).with_doc("Controlling value to test");
|
||||
let c = &Operand::new("c", ScalarTruthy).with_doc("Controlling value to test");
|
||||
let x = &Operand::new("x", Any).with_doc("Value to use when `c` is true");
|
||||
let y = &Operand::new("y", Any).with_doc("Value to use when `c` is false");
|
||||
let a = &Operand::new("a", Any);
|
||||
@@ -1640,7 +1595,6 @@ pub(crate) fn define(
|
||||
TypeSetBuilder::new()
|
||||
.ints(Interval::All)
|
||||
.floats(Interval::All)
|
||||
.bools(Interval::All)
|
||||
.simd_lanes(1..128)
|
||||
.includes_scalars(true)
|
||||
.build(),
|
||||
@@ -1680,7 +1634,7 @@ pub(crate) fn define(
|
||||
r#"
|
||||
Vector lane select.
|
||||
|
||||
Select lanes from ``x`` or ``y`` controlled by the lanes of the boolean
|
||||
Select lanes from ``x`` or ``y`` controlled by the lanes of the truthy
|
||||
vector ``c``.
|
||||
"#,
|
||||
&formats.ternary,
|
||||
@@ -1689,7 +1643,7 @@ pub(crate) fn define(
|
||||
.operands_out(vec![a]),
|
||||
);
|
||||
|
||||
let s = &Operand::new("s", b1);
|
||||
let s = &Operand::new("s", i8);
|
||||
|
||||
ig.push(
|
||||
Inst::new(
|
||||
@@ -1760,8 +1714,8 @@ pub(crate) fn define(
|
||||
| sgt | ugt | Greater than |
|
||||
| sle | ule | Less than or equal |
|
||||
|
||||
When this instruction compares integer vectors, it returns a boolean
|
||||
vector of lane-wise comparisons.
|
||||
When this instruction compares integer vectors, it returns a vector of
|
||||
lane-wise comparisons.
|
||||
"#,
|
||||
&formats.int_compare,
|
||||
)
|
||||
@@ -1769,7 +1723,7 @@ pub(crate) fn define(
|
||||
.operands_out(vec![a]),
|
||||
);
|
||||
|
||||
let a = &Operand::new("a", b1);
|
||||
let a = &Operand::new("a", i8);
|
||||
let x = &Operand::new("x", iB);
|
||||
let Y = &Operand::new("Y", &imm.imm64);
|
||||
|
||||
@@ -2158,10 +2112,10 @@ pub(crate) fn define(
|
||||
let x = &Operand::new("x", iB);
|
||||
let y = &Operand::new("y", iB);
|
||||
|
||||
let c_in = &Operand::new("c_in", b1).with_doc("Input carry flag");
|
||||
let c_out = &Operand::new("c_out", b1).with_doc("Output carry flag");
|
||||
let b_in = &Operand::new("b_in", b1).with_doc("Input borrow flag");
|
||||
let b_out = &Operand::new("b_out", b1).with_doc("Output borrow flag");
|
||||
let c_in = &Operand::new("c_in", i8).with_doc("Input carry flag");
|
||||
let c_out = &Operand::new("c_out", i8).with_doc("Output carry flag");
|
||||
let b_in = &Operand::new("b_in", i8).with_doc("Input borrow flag");
|
||||
let b_out = &Operand::new("b_out", i8).with_doc("Output borrow flag");
|
||||
|
||||
let c_if_in = &Operand::new("c_in", iflags);
|
||||
let c_if_out = &Operand::new("c_out", iflags);
|
||||
@@ -2430,11 +2384,10 @@ pub(crate) fn define(
|
||||
|
||||
let bits = &TypeVar::new(
|
||||
"bits",
|
||||
"Any integer, float, or boolean scalar or vector type",
|
||||
"Any integer, float, or vector type",
|
||||
TypeSetBuilder::new()
|
||||
.ints(Interval::All)
|
||||
.floats(Interval::All)
|
||||
.bools(Interval::All)
|
||||
.simd_lanes(Interval::All)
|
||||
.includes_scalars(true)
|
||||
.build(),
|
||||
@@ -2916,7 +2869,7 @@ pub(crate) fn define(
|
||||
floating point comparisons of the same name.
|
||||
|
||||
When this instruction compares floating point vectors, it returns a
|
||||
boolean vector with the results of lane-wise comparisons.
|
||||
vector with the results of lane-wise comparisons.
|
||||
"#,
|
||||
&formats.float_compare,
|
||||
)
|
||||
@@ -3195,7 +3148,7 @@ pub(crate) fn define(
|
||||
.operands_out(vec![a]),
|
||||
);
|
||||
|
||||
let a = &Operand::new("a", b1);
|
||||
let a = &Operand::new("a", i8);
|
||||
let x = &Operand::new("x", Ref);
|
||||
|
||||
ig.push(
|
||||
@@ -3213,7 +3166,7 @@ pub(crate) fn define(
|
||||
.operands_out(vec![a]),
|
||||
);
|
||||
|
||||
let a = &Operand::new("a", b1);
|
||||
let a = &Operand::new("a", i8);
|
||||
let x = &Operand::new("x", Ref);
|
||||
|
||||
ig.push(
|
||||
@@ -3233,7 +3186,7 @@ pub(crate) fn define(
|
||||
|
||||
let Cond = &Operand::new("Cond", &imm.intcc);
|
||||
let f = &Operand::new("f", iflags);
|
||||
let a = &Operand::new("a", b1);
|
||||
let a = &Operand::new("a", i8);
|
||||
|
||||
ig.push(
|
||||
Inst::new(
|
||||
@@ -3329,80 +3282,11 @@ pub(crate) fn define(
|
||||
.operands_out(vec![a]),
|
||||
);
|
||||
|
||||
let Bool = &TypeVar::new(
|
||||
"Bool",
|
||||
"A scalar boolean type",
|
||||
TypeSetBuilder::new().bools(Interval::All).build(),
|
||||
);
|
||||
|
||||
let BoolTo = &TypeVar::new(
|
||||
"BoolTo",
|
||||
"A smaller boolean type",
|
||||
TypeSetBuilder::new().bools(Interval::All).build(),
|
||||
);
|
||||
|
||||
let x = &Operand::new("x", Bool);
|
||||
let a = &Operand::new("a", BoolTo);
|
||||
|
||||
ig.push(
|
||||
Inst::new(
|
||||
"breduce",
|
||||
r#"
|
||||
Convert `x` to a smaller boolean type by discarding the most significant bits.
|
||||
"#,
|
||||
&formats.unary,
|
||||
)
|
||||
.operands_in(vec![x])
|
||||
.operands_out(vec![a]),
|
||||
);
|
||||
|
||||
let BoolTo = &TypeVar::new(
|
||||
"BoolTo",
|
||||
"A larger boolean type",
|
||||
TypeSetBuilder::new().bools(Interval::All).build(),
|
||||
);
|
||||
let x = &Operand::new("x", Bool);
|
||||
let a = &Operand::new("a", BoolTo);
|
||||
|
||||
ig.push(
|
||||
Inst::new(
|
||||
"bextend",
|
||||
r#"
|
||||
Convert `x` to a larger boolean type
|
||||
"#,
|
||||
&formats.unary,
|
||||
)
|
||||
.operands_in(vec![x])
|
||||
.operands_out(vec![a]),
|
||||
);
|
||||
|
||||
let IntTo = &TypeVar::new(
|
||||
"IntTo",
|
||||
"A scalar integer type",
|
||||
TypeSetBuilder::new().ints(Interval::All).build(),
|
||||
);
|
||||
let x = &Operand::new("x", ScalarBool);
|
||||
let a = &Operand::new("a", IntTo);
|
||||
|
||||
ig.push(
|
||||
Inst::new(
|
||||
"bint",
|
||||
r#"
|
||||
Convert `x` to an integer.
|
||||
|
||||
True maps to 1 and false maps to 0.
|
||||
"#,
|
||||
&formats.unary,
|
||||
)
|
||||
.operands_in(vec![x])
|
||||
.operands_out(vec![a]),
|
||||
);
|
||||
|
||||
let Bool = &TypeVar::new(
|
||||
"Bool",
|
||||
"A scalar or vector boolean type",
|
||||
let Truthy = &TypeVar::new(
|
||||
"Truthy",
|
||||
"A scalar or vector whose values are truthy",
|
||||
TypeSetBuilder::new()
|
||||
.bools(Interval::All)
|
||||
.ints(Interval::All)
|
||||
.simd_lanes(Interval::All)
|
||||
.build(),
|
||||
);
|
||||
@@ -3414,7 +3298,7 @@ pub(crate) fn define(
|
||||
.simd_lanes(Interval::All)
|
||||
.build(),
|
||||
);
|
||||
let x = &Operand::new("x", Bool);
|
||||
let x = &Operand::new("x", Truthy);
|
||||
let a = &Operand::new("a", IntTo);
|
||||
|
||||
ig.push(
|
||||
@@ -4136,7 +4020,6 @@ pub(crate) fn define(
|
||||
TypeSetBuilder::new()
|
||||
.ints(Interval::All)
|
||||
.floats(Interval::All)
|
||||
.bools(Interval::All)
|
||||
.dynamic_simd_lanes(Interval::All)
|
||||
.build(),
|
||||
);
|
||||
|
||||
@@ -1,49 +1,5 @@
|
||||
//! This module predefines all the Cranelift scalar types.
|
||||
|
||||
#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
|
||||
pub(crate) enum Bool {
|
||||
/// 1-bit bool.
|
||||
B1 = 1,
|
||||
/// 8-bit bool.
|
||||
B8 = 8,
|
||||
/// 16-bit bool.
|
||||
B16 = 16,
|
||||
/// 32-bit bool.
|
||||
B32 = 32,
|
||||
/// 64-bit bool.
|
||||
B64 = 64,
|
||||
/// 128-bit bool.
|
||||
B128 = 128,
|
||||
}
|
||||
|
||||
/// This provides an iterator through all of the supported bool variants.
|
||||
pub(crate) struct BoolIterator {
|
||||
index: u8,
|
||||
}
|
||||
|
||||
impl BoolIterator {
|
||||
pub fn new() -> Self {
|
||||
Self { index: 0 }
|
||||
}
|
||||
}
|
||||
|
||||
impl Iterator for BoolIterator {
|
||||
type Item = Bool;
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
let res = match self.index {
|
||||
0 => Some(Bool::B1),
|
||||
1 => Some(Bool::B8),
|
||||
2 => Some(Bool::B16),
|
||||
3 => Some(Bool::B32),
|
||||
4 => Some(Bool::B64),
|
||||
5 => Some(Bool::B128),
|
||||
_ => return None,
|
||||
};
|
||||
self.index += 1;
|
||||
res
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
|
||||
pub(crate) enum Int {
|
||||
/// 8-bit int.
|
||||
@@ -187,18 +143,6 @@ impl Iterator for ReferenceIterator {
|
||||
mod iter_tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn bool_iter_works() {
|
||||
let mut bool_iter = BoolIterator::new();
|
||||
assert_eq!(bool_iter.next(), Some(Bool::B1));
|
||||
assert_eq!(bool_iter.next(), Some(Bool::B8));
|
||||
assert_eq!(bool_iter.next(), Some(Bool::B16));
|
||||
assert_eq!(bool_iter.next(), Some(Bool::B32));
|
||||
assert_eq!(bool_iter.next(), Some(Bool::B64));
|
||||
assert_eq!(bool_iter.next(), Some(Bool::B128));
|
||||
assert_eq!(bool_iter.next(), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn int_iter_works() {
|
||||
let mut int_iter = IntIterator::new();
|
||||
|
||||
Reference in New Issue
Block a user