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

@@ -20,7 +20,7 @@ pub trait Value: Clone + From<DataValue> {
fn into_float(self) -> ValueResult<f64>;
fn is_float(&self) -> bool;
fn is_nan(&self) -> ValueResult<bool>;
fn bool(b: bool, ty: Type) -> ValueResult<Self>;
fn bool(b: bool, vec_elem: bool, ty: Type) -> ValueResult<Self>;
fn into_bool(self) -> ValueResult<bool>;
fn vector(v: [u8; 16], ty: Type) -> ValueResult<Self>;
fn into_array(&self) -> ValueResult<[u8; 16]>;
@@ -152,6 +152,8 @@ pub enum ValueConversionKind {
/// Converts an integer into a boolean, zero integers are converted into a
/// `false`, while other integers are converted into `true`. Booleans are passed through.
ToBoolean,
/// Converts an integer into either -1 or zero.
Mask(Type),
}
/// Helper for creating match expressions over [DataValue].
@@ -268,14 +270,39 @@ impl Value for DataValue {
}
}
fn bool(b: bool, ty: Type) -> ValueResult<Self> {
assert!(ty.is_bool());
Ok(DataValue::B(b))
fn bool(b: bool, vec_elem: bool, ty: Type) -> ValueResult<Self> {
assert!(ty.is_int());
macro_rules! make_bool {
($ty:ident) => {
Ok(DataValue::$ty(if b {
if vec_elem {
-1
} else {
1
}
} else {
0
}))
};
}
match ty {
types::I8 => make_bool!(I8),
types::I16 => make_bool!(I16),
types::I32 => make_bool!(I32),
types::I64 => make_bool!(I64),
types::I128 => make_bool!(I128),
_ => Err(ValueError::InvalidType(ValueTypeClass::Integer, ty)),
}
}
fn into_bool(self) -> ValueResult<bool> {
match self {
DataValue::B(b) => Ok(b),
DataValue::I8(b) => Ok(b != 0),
DataValue::I16(b) => Ok(b != 0),
DataValue::I32(b) => Ok(b != 0),
DataValue::I64(b) => Ok(b != 0),
DataValue::I128(b) => Ok(b != 0),
_ => Err(ValueError::InvalidType(ValueTypeClass::Boolean, self.ty())),
}
}
@@ -316,16 +343,6 @@ impl Value for DataValue {
(DataValue::F32(n), types::I32) => DataValue::I32(n.bits() as i32),
(DataValue::F64(n), types::I64) => DataValue::I64(n.bits() as i64),
(DataValue::F32(n), types::F64) => DataValue::F64((n.as_f32() as f64).into()),
(DataValue::B(b), t) if t.is_bool() => DataValue::B(b),
(DataValue::B(b), t) if t.is_int() => {
// Bools are represented in memory as all 1's
let val = match (b, t) {
(true, types::I128) => -1,
(true, t) => (1i128 << t.bits()) - 1,
_ => 0,
};
DataValue::int(val, t)?
}
(dv, t) if (t.is_int() || t.is_float()) && dv.ty() == t => dv,
(dv, _) => unimplemented!("conversion: {} -> {:?}", dv.ty(), kind),
},
@@ -432,10 +449,13 @@ impl Value for DataValue {
(s, _) => unimplemented!("conversion: {} -> {:?}", s.ty(), kind),
},
ValueConversionKind::ToBoolean => match self.ty() {
ty if ty.is_bool() => DataValue::B(self.into_bool()?),
ty if ty.is_int() => DataValue::B(self.into_int()? != 0),
ty if ty.is_int() => DataValue::I8(if self.into_int()? != 0 { 1 } else { 0 }),
ty => unimplemented!("conversion: {} -> {:?}", ty, kind),
},
ValueConversionKind::Mask(ty) => {
let b = self.into_bool()?;
Self::bool(b, true, ty).unwrap()
}
})
}
@@ -662,11 +682,11 @@ impl Value for DataValue {
}
fn and(self, other: Self) -> ValueResult<Self> {
binary_match!(&(self, other); [B, I8, I16, I32, I64, I128, F32, F64])
binary_match!(&(self, other); [I8, I16, I32, I64, I128, F32, F64])
}
fn or(self, other: Self) -> ValueResult<Self> {
binary_match!(|(self, other); [B, I8, I16, I32, I64, I128, F32, F64])
binary_match!(|(self, other); [I8, I16, I32, I64, I128, F32, F64])
}
fn xor(self, other: Self) -> ValueResult<Self> {
@@ -674,7 +694,7 @@ impl Value for DataValue {
}
fn not(self) -> ValueResult<Self> {
unary_match!(!(self); [B, I8, I16, I32, I64, I128, F32, F64])
unary_match!(!(self); [I8, I16, I32, I64, I128, F32, F64])
}
fn count_ones(self) -> ValueResult<Self> {