Skip to content

Commit f3f413d

Browse files
committed
Simplify scalable vector testing
1 parent fceaa1b commit f3f413d

3 files changed

Lines changed: 76 additions & 106 deletions

File tree

ci/intrinsic-test.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ case ${TARGET} in
5151
aarch64*)
5252
export CFLAGS="-I/usr/aarch64-linux-gnu/include/"
5353
ARCH=aarch64
54-
RUNTIME_RUSTFLAGS=-Ctarget-feature=+sve,+sve2
54+
RUNTIME_RUSTFLAGS="-Ctarget-feature=+sve,+sve2"
5555
;;
5656

5757
armv7*)

crates/intrinsic-test/src/arm/mod.rs

Lines changed: 61 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -233,72 +233,74 @@ const fn svprfop_from_i32(value: i32) -> svprfop {
233233
}
234234
}
235235
236-
macro_rules! debug_print_integral {
237-
($($name:ident => ($ty:ty, $svptrue_fn:ident, $svcnt_fn:ident, $svst_fn:ident)),*) => {
238-
$(
239-
#[inline]
240-
#[target_feature(enable = "sve")]
241-
#[cfg(all(any(target_arch = "aarch64", target_arch = "arm64ec"), target_endian = "little"))]
242-
pub fn $name(v: $ty) -> String {
243-
unsafe {
244-
let __pred = $svptrue_fn();
245-
let __num_elems = $svcnt_fn() as usize;
246-
let mut __buf = std::vec::Vec::with_capacity(__num_elems);
247-
$svst_fn(__pred, __buf.as_mut_ptr(), v);
248-
__buf.set_len(__num_elems);
249-
format!(
250-
"[{}]",
251-
__buf.iter().map(|el| el.to_string()).collect::<Vec<_>>().join(", ")
252-
)
253-
}
254-
}
255-
)*
236+
#[cfg(all(any(target_arch = "aarch64", target_arch = "arm64ec"), target_endian = "little"))]
237+
fn svint8_to_slice(a: &svint8_t) -> &[i8] {
238+
unsafe {
239+
core::slice::from_raw_parts(core::ptr::from_ref(a).cast(), svcntb() as usize)
256240
}
257241
}
258242
259-
debug_print_integral! {
260-
debug_print_f32 => (svfloat32_t, svptrue_b32, svcntw, svst1_f32),
261-
debug_print_f64 => (svfloat64_t, svptrue_b64, svcntd, svst1_f64),
262-
debug_print_s8 => (svint8_t, svptrue_b8, svcntb, svst1_s8),
263-
debug_print_s16 => (svint16_t, svptrue_b16, svcnth, svst1_s16),
264-
debug_print_s32 => (svint32_t, svptrue_b32, svcntw, svst1_s32),
265-
debug_print_s64 => (svint64_t, svptrue_b64, svcntd, svst1_s64),
266-
debug_print_u8 => (svuint8_t, svptrue_b8, svcntb, svst1_u8),
267-
debug_print_u16 => (svuint16_t, svptrue_b16, svcnth, svst1_u16),
268-
debug_print_u32 => (svuint32_t, svptrue_b32, svcntw, svst1_u32),
269-
debug_print_u64 => (svuint64_t, svptrue_b64, svcntd, svst1_u64)
243+
#[cfg(all(any(target_arch = "aarch64", target_arch = "arm64ec"), target_endian = "little"))]
244+
fn svuint8_to_slice(a: &svuint8_t) -> &[u8] {
245+
unsafe {
246+
core::slice::from_raw_parts(core::ptr::from_ref(a).cast(), svcntb() as usize)
247+
}
270248
}
271249
272-
macro_rules! debug_print_bool {
273-
($($name:ident => ($ty:ty, $svst_fn:ident, $svdup_fn:ident)),*) => {
274-
$(
275-
#[inline]
276-
#[target_feature(enable = "sve")]
277-
#[cfg(all(any(target_arch = "aarch64", target_arch = "arm64ec"), target_endian = "little"))]
278-
pub fn $name(v: $ty) -> String {
279-
unsafe {
280-
let __num_elems = svcntb() as usize;
281-
let mut __buf = std::vec::Vec::with_capacity(__num_elems);
282-
$svst_fn(v, __buf.as_mut_ptr(), $svdup_fn(1));
283-
__buf.set_len(__num_elems);
284-
format!(
285-
"[{}]",
286-
__buf.iter()
287-
.map(|el| *el == 1)
288-
.map(|el| el.to_string())
289-
.collect::<Vec<_>>()
290-
.join(", ")
291-
)
292-
}
293-
}
294-
)*
250+
#[cfg(all(any(target_arch = "aarch64", target_arch = "arm64ec"), target_endian = "little"))]
251+
fn svint16_to_slice(a: &svint16_t) -> &[i16] {
252+
unsafe {
253+
core::slice::from_raw_parts(core::ptr::from_ref(a).cast(), svcnth() as usize)
295254
}
296255
}
297256
298-
debug_print_bool! {
299-
debug_print_b8 => (svbool_t, svst1_u8, svdup_n_u8),
300-
debug_print_b16 => (svbool_t, svst1_u16, svdup_n_u16),
301-
debug_print_b32 => (svbool_t, svst1_u32, svdup_n_u32),
302-
debug_print_b64 => (svbool_t, svst1_u64, svdup_n_u64)
257+
#[cfg(all(any(target_arch = "aarch64", target_arch = "arm64ec"), target_endian = "little"))]
258+
fn svuint16_to_slice(a: &svuint16_t) -> &[u16] {
259+
unsafe {
260+
core::slice::from_raw_parts(core::ptr::from_ref(a).cast(), svcnth() as usize)
261+
}
303262
}
263+
264+
#[cfg(all(any(target_arch = "aarch64", target_arch = "arm64ec"), target_endian = "little"))]
265+
fn svint32_to_slice(a: &svint32_t) -> &[i32] {
266+
unsafe {
267+
core::slice::from_raw_parts(core::ptr::from_ref(a).cast(), svcntw() as usize)
268+
}
269+
}
270+
271+
#[cfg(all(any(target_arch = "aarch64", target_arch = "arm64ec"), target_endian = "little"))]
272+
fn svuint32_to_slice(a: &svuint32_t) -> &[u32] {
273+
unsafe {
274+
core::slice::from_raw_parts(core::ptr::from_ref(a).cast(), svcntw() as usize)
275+
}
276+
}
277+
278+
#[cfg(all(any(target_arch = "aarch64", target_arch = "arm64ec"), target_endian = "little"))]
279+
fn svint64_to_slice(a: &svint64_t) -> &[i64] {
280+
unsafe {
281+
core::slice::from_raw_parts(core::ptr::from_ref(a).cast(), svcntd() as usize)
282+
}
283+
}
284+
285+
#[cfg(all(any(target_arch = "aarch64", target_arch = "arm64ec"), target_endian = "little"))]
286+
fn svuint64_to_slice(a: &svuint64_t) -> &[u64] {
287+
unsafe {
288+
core::slice::from_raw_parts(core::ptr::from_ref(a).cast(), svcntd() as usize)
289+
}
290+
}
291+
292+
#[cfg(all(any(target_arch = "aarch64", target_arch = "arm64ec"), target_endian = "little"))]
293+
fn svfloat32_to_slice(a: &svfloat32_t) -> &[NanEqF32] {
294+
unsafe {
295+
core::slice::from_raw_parts(core::ptr::from_ref(a).cast(), svcntw() as usize)
296+
}
297+
}
298+
299+
#[cfg(all(any(target_arch = "aarch64", target_arch = "arm64ec"), target_endian = "little"))]
300+
fn svfloat64_to_slice(a: &svfloat64_t) -> &[NanEqF64] {
301+
unsafe {
302+
core::slice::from_raw_parts(core::ptr::from_ref(a).cast(), svcntd() as usize)
303+
}
304+
}
305+
304306
"#;

crates/intrinsic-test/src/arm/types.rs

Lines changed: 14 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -115,8 +115,7 @@ impl TypeDefinition for ArmType {
115115
}
116116

117117
if self.kind() == TypeKind::Bool {
118-
// There isn't a `svcmpeq` for `svbool_t` and there aren't `svboolxN_t` types, so just
119-
// do an XOR and test it is empty.
118+
// `svbool_t` layout is not an array of `bool`s, so we just do an XOR and test it is empty.
120119
return format!(
121120
r#"
122121
let __eq = sveor_b_z({PREDICATE_LOCAL}, __rust_return_value, __c_return_value);
@@ -142,53 +141,22 @@ assert!(!svptest_any({PREDICATE_LOCAL}, __eq), "{{}}", id);
142141
let n = self.num_vectors();
143142
(0..n)
144143
.format_with("\n", |i, fmt| {
145-
match self.kind() {
146-
TypeKind::Float | TypeKind::BFloat => {
147-
// Floats need special handling because `NaN != NaN` normally - this
148-
// effectively does `(rust == c) || (isnan(rust) && isnan(c))`
149-
fmt(&format_args!(
150-
r#"
144+
// Most types can just use `svcmpeq`
145+
fmt(&format_args!(
146+
r#"
151147
let __rust_eq_return_value = {rust_return_value};
152148
let __c_eq_return_value = {c_return_value};
153-
let __eq_sans_nan = svcmpeq_{ty}{bl}({PREDICATE_LOCAL}, __rust_eq_return_value, __c_eq_return_value);
154-
let __rust_nan = svcmpuo_{ty}{bl}({PREDICATE_LOCAL}, __rust_eq_return_value, __rust_eq_return_value);
155-
let __c_nan = svcmpuo_{ty}{bl}({PREDICATE_LOCAL}, __c_eq_return_value, __c_eq_return_value);
156-
let __both_nan = svand_b_z({PREDICATE_LOCAL}, __rust_nan, __c_nan);
157-
let __eq = svorr_b_z({PREDICATE_LOCAL}, __eq_sans_nan, __both_nan);
158-
if !svptest_any(__pred, __eq) {{
159-
let __rust_pretty = debug_print_{ty}{bl}(__rust_eq_return_value);
160-
let __c_pretty = debug_print_{ty}{bl}(__c_eq_return_value);
161-
panic!("{{}}-{i_plus_one}/{n}\nRust: {{__rust_pretty}}\nC: {{__c_pretty}}", id);
162-
}}
149+
assert_eq!(
150+
{prefix}_to_slice(&__rust_eq_return_value),
151+
{prefix}_to_slice(&__c_eq_return_value),
152+
"{{id}}-({i_plus_one}/{n})"
153+
);
163154
"#,
164-
ty = self.rust_intrinsic_name_prefix(),
165-
bl = self.inner_size(),
166-
rust_return_value = get(n, i, "__rust_return_value"),
167-
c_return_value = get(n, i, "__c_return_value"),
168-
i_plus_one = i + 1, // so that the output is "1/2" and "2/2"
169-
))
170-
}
171-
_ => {
172-
// Most types can just use `svcmpeq`
173-
fmt(&format_args!(
174-
r#"
175-
let __rust_eq_return_value = {rust_return_value};
176-
let __c_eq_return_value = {c_return_value};
177-
let __eq = svcmpeq_{ty}{bl}({PREDICATE_LOCAL}, __rust_eq_return_value, __c_eq_return_value);
178-
if !svptest_any(__pred, __eq) {{
179-
let __rust_pretty = debug_print_{ty}{bl}(__rust_eq_return_value);
180-
let __c_pretty = debug_print_{ty}{bl}(__c_eq_return_value);
181-
panic!("{{}}-{i_plus_one}/{n}\nRust: {{__rust_pretty}}\nC: {{__c_pretty}}", id);
182-
}}
183-
"#,
184-
ty = self.rust_intrinsic_name_prefix(),
185-
bl = self.inner_size(),
186-
rust_return_value = get(n, i, "__rust_return_value"),
187-
c_return_value = get(n, i, "__c_return_value"),
188-
i_plus_one = i + 1, // so that the output is "1/2" and "2/2"
189-
))
190-
}
191-
}
155+
rust_return_value = get(n, i, "__rust_return_value"),
156+
c_return_value = get(n, i, "__c_return_value"),
157+
prefix = format!("sv{}{}", self.kind.c_prefix(), self.inner_size()),
158+
i_plus_one = i + 1, // so that the output is "1/2" and "2/2"
159+
))
192160
})
193161
.to_string()
194162
}

0 commit comments

Comments
 (0)