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

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