cranelift: Support bool vectors in trampoline

This commit is contained in:
Afonso Bordado
2021-09-06 20:25:23 +01:00
parent 37c094faf5
commit 9460a4fb16
2 changed files with 39 additions and 9 deletions

View File

@@ -127,6 +127,21 @@ impl Type {
} }
} }
/// Get a type with the same number of lanes as this type, but with the lanes replaced by
/// integers of the same size.
///
/// Scalar types follow this same rule, but `b1` is converted into `i8`
pub fn as_int(self) -> Self {
self.replace_lanes(match self.lane_type() {
B1 | B8 => I8,
B16 => I16,
B32 => I32,
B64 => I64,
B128 => I128,
_ => unimplemented!(),
})
}
/// Get a type with the same number of lanes as this type, but with lanes that are half the /// Get a type with the same number of lanes as this type, but with lanes that are half the
/// number of bits. /// number of bits.
pub fn half_width(self) -> Option<Self> { pub fn half_width(self) -> Option<Self> {
@@ -530,4 +545,13 @@ mod tests {
assert_eq!(I32X4.as_bool_pedantic(), B32X4); assert_eq!(I32X4.as_bool_pedantic(), B32X4);
assert_eq!(I32.as_bool_pedantic(), B32); assert_eq!(I32.as_bool_pedantic(), B32);
} }
#[test]
fn as_int() {
assert_eq!(B32X4.as_int(), I32X4);
assert_eq!(B8X8.as_int(), I8X8);
assert_eq!(B1.as_int(), I8);
assert_eq!(B8.as_int(), I8);
assert_eq!(B128.as_int(), I128);
}
} }

View File

@@ -2,7 +2,7 @@
use core::mem; use core::mem;
use cranelift_codegen::binemit::{NullRelocSink, NullStackMapSink, NullTrapSink}; use cranelift_codegen::binemit::{NullRelocSink, NullStackMapSink, NullTrapSink};
use cranelift_codegen::data_value::DataValue; use cranelift_codegen::data_value::DataValue;
use cranelift_codegen::ir::{condcodes::IntCC, Function, InstBuilder, Signature, Type}; use cranelift_codegen::ir::{condcodes::IntCC, Function, InstBuilder, Signature};
use cranelift_codegen::isa::{BackendVariant, TargetIsa}; use cranelift_codegen::isa::{BackendVariant, TargetIsa};
use cranelift_codegen::{ir, settings, CodegenError, Context}; use cranelift_codegen::{ir, settings, CodegenError, Context};
use cranelift_frontend::{FunctionBuilder, FunctionBuilderContext}; use cranelift_frontend::{FunctionBuilder, FunctionBuilderContext};
@@ -297,13 +297,16 @@ fn make_trampoline(signature: &ir::Signature, isa: &dyn TargetIsa) -> Function {
.enumerate() .enumerate()
.map(|(i, param)| { .map(|(i, param)| {
// Calculate the type to load from memory, using integers for booleans (no encodings). // Calculate the type to load from memory, using integers for booleans (no encodings).
let ty = if param.value_type.is_bool() { let is_scalar_bool = param.value_type.is_bool();
Type::int(max(param.value_type.bits(), 8)).expect( let is_vector_bool =
"to be able to convert any boolean type to its equal-width integer type", param.value_type.is_vector() && param.value_type.lane_type().is_bool();
)
let ty = if is_scalar_bool || is_vector_bool {
param.value_type.as_int()
} else { } else {
param.value_type param.value_type
}; };
// Load the value. // Load the value.
let loaded = builder.ins().load( let loaded = builder.ins().load(
ty, ty,
@@ -314,8 +317,12 @@ fn make_trampoline(signature: &ir::Signature, isa: &dyn TargetIsa) -> Function {
// For booleans, we want to type-convert the loaded integer into a boolean and ensure // For booleans, we want to type-convert the loaded integer into a boolean and ensure
// that we are using the architecture's canonical boolean representation (presumably // that we are using the architecture's canonical boolean representation (presumably
// comparison will emit this). // comparison will emit this).
if param.value_type.is_bool() { if is_scalar_bool {
builder.ins().icmp_imm(IntCC::NotEqual, loaded, 0) builder.ins().icmp_imm(IntCC::NotEqual, loaded, 0)
} else if is_vector_bool {
let zero_constant = builder.func.dfg.constants.insert(vec![0; 16].into());
let zero_vec = builder.ins().vconst(ty, zero_constant);
builder.ins().icmp(IntCC::NotEqual, loaded, zero_vec)
} else { } else {
loaded loaded
} }
@@ -332,9 +339,8 @@ fn make_trampoline(signature: &ir::Signature, isa: &dyn TargetIsa) -> Function {
let results = builder.func.dfg.inst_results(call).to_vec(); let results = builder.func.dfg.inst_results(call).to_vec();
for ((i, value), param) in results.iter().enumerate().zip(&signature.returns) { for ((i, value), param) in results.iter().enumerate().zip(&signature.returns) {
// Before storing return values, we convert booleans to their integer representation. // Before storing return values, we convert booleans to their integer representation.
let value = if param.value_type.is_bool() { let value = if param.value_type.lane_type().is_bool() {
let ty = Type::int(max(param.value_type.bits(), 8)) let ty = param.value_type.lane_type().as_int();
.expect("to be able to convert any boolean type to its equal-width integer type");
builder.ins().bint(ty, *value) builder.ins().bint(ty, *value)
} else { } else {
*value *value