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:
Trevor Elliott
2022-10-17 16:00:27 -07:00
committed by GitHub
parent 766ecb561e
commit 32a7593c94
242 changed files with 7695 additions and 10010 deletions

View File

@@ -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))

View File

@@ -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 = &copy.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());
}

View File

@@ -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("},");

View File

@@ -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")

View File

@@ -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");

View File

@@ -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(),
);

View File

@@ -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();