Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 4 additions & 49 deletions crates/intrinsic-test/src/common/argument.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
use itertools::Itertools;

use crate::common::intrinsic_helpers::TypeKind;
use crate::common::values::test_values_array_name;

use super::PASSES;
use super::constraint::Constraint;
use super::gen_rust::PASSES;
use super::intrinsic_helpers::IntrinsicTypeDefinition;

/// An argument for the intrinsic.
Expand Down Expand Up @@ -52,17 +53,6 @@ where
self.constraint.is_some()
}

/// Returns a string with the name of the static variable containing test values for intrinsic
/// arguments of this type.
pub(crate) fn rust_vals_array_name(&self) -> impl std::fmt::Display {
let loads = crate::common::gen_rust::PASSES;
format!(
"{ty}_{load_size}",
ty = self.ty.rust_scalar_type().to_uppercase(),
load_size = self.ty.num_lanes() * self.ty.num_vectors() + loads - 1,
)
}

/// Should this argument be passed by reference in C wrapper function declarations?
///
/// SIMD types and `f16` are currently passed by reference.
Expand Down Expand Up @@ -165,41 +155,6 @@ where
.join("")
}

/// Returns a string defining a static variable with test values used for all intrinsics with
/// arguments of `arg`'s type.
///
/// e.g.
/// ```rust,ignore
/// static U8_20: [u8; 20] = [
/// 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0xf0,
/// 0x80, 0x3b, 0xff,
/// ];
/// ```
///
/// `num_lanes * num_vectors + loads - 1` elements are present in the array, which is sufficient
/// for a `loads` number of `num_lanes * num_vectors` windows into the array to be loaded:
///
/// ```text
/// [0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0xf0, 0x80, 0x3b, 0xff]
/// ^^^^^^^^^^^^^^^^^^^ first window of `num_lanes * num_vectors` elements (e.g. four elements)
/// ^^^^^^^^^^^^^^^^^^ second window
/// `loads`th window ^^^^^^^^^^^^^^^^^^^^^^
/// ```
pub fn gen_arg_rust(
arg: &Argument<T>,
w: &mut impl std::io::Write,
loads: u32,
) -> std::io::Result<()> {
writeln!(
w,
"static {name}: [{ty}; {load_size}] = {values};\n",
name = arg.rust_vals_array_name(),
ty = arg.ty.rust_scalar_type(),
load_size = arg.ty.num_lanes() * arg.ty.num_vectors() + loads - 1,
values = arg.ty.populate_random(loads)
)
}

/// Returns a string defining a local variable for each argument and loading a value into each
/// using a load intrinsic.
///
Expand All @@ -226,14 +181,14 @@ where
format!(
"let {name} = {load}({vals_name}.as_ptr().add((i+{idx}) % {PASSES}) as _);\n",
name = arg.generate_name(),
vals_name = arg.rust_vals_array_name(),
vals_name = test_values_array_name(&arg.ty),
load = arg.ty.get_load_function(),
)
} else {
format!(
"let {name} = {vals_name}[(i+{idx}) % {PASSES}];\n",
name = arg.generate_name(),
vals_name = arg.rust_vals_array_name(),
vals_name = test_values_array_name(&arg.ty),
)
}
})
Expand Down
16 changes: 6 additions & 10 deletions crates/intrinsic-test/src/common/gen_rust.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,10 @@ use std::process::Command;
use itertools::Itertools;

use super::intrinsic_helpers::IntrinsicTypeDefinition;
use crate::common::argument::ArgumentList;
use crate::common::PASSES;
use crate::common::intrinsic::Intrinsic;
use crate::common::intrinsic_helpers::TypeKind;

// The number of times each intrinsic will be called - influences the generation of the
// test arrays to minimise repeated testing of the same test values.
pub(crate) const PASSES: u32 = 20;
use crate::common::values::{test_values_array_name, test_values_array_static};

/// Rust definitions that are included verbatim in the generated source. In particular, defines
/// a wrapper around float types that defines `NaN`s to be equal reflexively to enable
Expand Down Expand Up @@ -134,10 +131,10 @@ pub fn write_lib_rs<T: IntrinsicTypeDefinition>(
for intrinsic in intrinsics {
for arg in &intrinsic.arguments.args {
if !arg.has_constraint() {
let name = arg.rust_vals_array_name().to_string();
let name = test_values_array_name(&arg.ty);

if seen.insert(name) {
ArgumentList::gen_arg_rust(arg, w, PASSES)?;
test_values_array_static(w, &arg.ty)?;
}
}
}
Expand All @@ -162,7 +159,6 @@ pub fn write_lib_rs<T: IntrinsicTypeDefinition>(
fn generate_rust_test_loop<T: IntrinsicTypeDefinition>(
w: &mut impl std::io::Write,
intrinsic: &Intrinsic<T>,
passes: u32,
) -> std::io::Result<()> {
let intrinsic_name = &intrinsic.name;

Expand Down Expand Up @@ -246,7 +242,7 @@ fn generate_rust_test_loop<T: IntrinsicTypeDefinition>(
loaded_args = intrinsic.arguments.load_values_rust(),
rust_args = intrinsic.arguments.as_call_param_rust(),
c_args = intrinsic.arguments.as_c_call_param_rust(),
passes = passes,
passes = PASSES,
cast_prefix = cast_prefix,
cast_suffix = cast_suffix,
)
Expand All @@ -266,7 +262,7 @@ fn create_rust_test<T: IntrinsicTypeDefinition>(
intrinsic_name = intrinsic.name,
)?;

generate_rust_test_loop(w, intrinsic, PASSES)?;
generate_rust_test_loop(w, intrinsic)?;

writeln!(w, "}}")?;

Expand Down
90 changes: 0 additions & 90 deletions crates/intrinsic-test/src/common/intrinsic_helpers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,6 @@ use std::fmt;
use std::ops::Deref;
use std::str::FromStr;

use itertools::Itertools as _;

use super::values::value_for_array;

#[derive(Debug, PartialEq, Copy, Clone)]
pub enum Sign {
Signed,
Expand Down Expand Up @@ -197,92 +193,6 @@ impl IntrinsicType {
pub fn is_ptr(&self) -> bool {
self.ptr
}

/// Returns the elements used in the test value arrays in `gen_arg_rust`. Uses the same
/// `num_lanes * num_vectors + loads - 1` arithmetic to produce the number of values that
/// `ArgumentList::gen_arg_rust` expects and `ArgumentList::load_values_rust` needs.
///
/// Each value in the array starts as a bit pattern from `common::values::value_from_array`
/// which is then printed as a hex value in the generated code (and if identified as a negative
/// value, with the appropriate minus and corrected hex pattern). Calls to `fN::from_bits` are
/// generated for floats.
pub fn populate_random(&self, loads: u32) -> String {
match self {
IntrinsicType {
bit_len: Some(bit_len @ (1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 16 | 32 | 64)),
kind:
kind @ (TypeKind::Int(_) | TypeKind::Poly | TypeKind::Char(_) | TypeKind::Mask),
vec_len,
..
} => {
format!(
"[\n{body}\n]",
body = (0..(self.num_lanes() * vec_len.unwrap_or(1) + loads - 1)).format_with(
",\n",
|i, fmt| {
let src = value_for_array(*bit_len, i);
assert!(src == 0 || src.ilog2() < *bit_len);
if *kind == TypeKind::Int(Sign::Signed) && (src >> (*bit_len - 1)) != 0
{
// `src` is a two's complement representation of a negative value.
let mask = !0u64 >> (64 - *bit_len);
let ones_compl = src ^ mask;
let twos_compl = ones_compl + 1;
fmt(&format_args!("-{twos_compl:#x}"))
} else {
fmt(&format_args!("{src:#x}"))
}
}
)
)
}
IntrinsicType {
kind: TypeKind::Float,
bit_len: Some(bit_len @ (16 | 32 | 64)),
vec_len,
..
} => {
format!(
"[\n{body}\n]",
body = (0..(self.num_lanes() * vec_len.unwrap_or(1) + loads - 1)).format_with(
",\n",
|i, fmt| fmt(&format_args!(
"f{bit_len}::from_bits({src:#x})",
src = value_for_array(*bit_len, i)
))
)
)
}
IntrinsicType {
kind: TypeKind::Vector,
bit_len: Some(128 | 256 | 512),
vec_len,
..
} => {
let effective_bit_len = 32;
format!(
"[\n{body}\n]",
body = (0..(vec_len.unwrap_or(1) * self.num_lanes() + loads - 1)).format_with(
",\n",
|i, fmt| {
let src = value_for_array(effective_bit_len, i);
assert!(src == 0 || src.ilog2() < effective_bit_len);
if (src >> (effective_bit_len - 1)) != 0 {
// `src` is a two's complement representation of a negative value.
let mask = !0u64 >> (64 - effective_bit_len);
let ones_compl = src ^ mask;
let twos_compl = ones_compl + 1;
fmt(&format_args!("-{twos_compl:#x}"))
} else {
fmt(&format_args!("{src:#x}"))
}
}
)
)
}
_ => unimplemented!("populate random: {self:#?}"),
}
}
}

pub trait IntrinsicTypeDefinition: Deref<Target = IntrinsicType> {
Expand Down
4 changes: 4 additions & 0 deletions crates/intrinsic-test/src/common/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@ mod gen_c;
mod gen_rust;
mod values;

// The number of times each intrinsic will be called - influences the generation of the
// test arrays to minimise repeated testing of the same test values.
pub(crate) const PASSES: u32 = 20;

/// Architectures must support this trait
/// to be successfully tested.
pub trait SupportedArchitectureTest {
Expand Down
Loading
Loading