Skip to content

Commit ffa1235

Browse files
folkertdevAmanieu
authored andcommitted
in intrinsic-test, format f16 like C
1 parent 998a0ac commit ffa1235

File tree

2 files changed

+102
-1
lines changed

2 files changed

+102
-1
lines changed

crates/intrinsic-test/src/intrinsic.rs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,14 +121,25 @@ impl Intrinsic {
121121
constraints
122122
};
123123

124+
// the `intrinsic-test` crate compares the output of C and Rust intrinsics. Currently, It uses
125+
// a string representation of the output value to compare. In C, f16 values are currently printed
126+
// as hexadecimal integers. Since https://github.com/rust-lang/rust/pull/127013, rust does print
127+
// them as decimal floating point values. To keep the intrinsics tests working, for now, format
128+
// vectors containing f16 values like C prints them.
129+
let return_value = match self.results.kind() {
130+
TypeKind::Float if self.results.inner_size() == 16 => "debug_f16(__return_value)",
131+
_ => "format_args!(\"{__return_value:.150?}\")",
132+
};
133+
124134
let indentation2 = indentation.nested();
125135
let indentation3 = indentation2.nested();
136+
126137
format!(
127138
"{indentation}for i in 0..{passes} {{\n\
128139
{indentation2}unsafe {{\n\
129140
{loaded_args}\
130141
{indentation3}let __return_value = {intrinsic_call}{const}({args});\n\
131-
{indentation3}println!(\"Result {additional}-{{}}: {{:.150?}}\", i + 1, __return_value);\n\
142+
{indentation3}println!(\"Result {additional}-{{}}: {{:?}}\", i + 1, {return_value});\n\
132143
{indentation2}}}\n\
133144
{indentation}}}",
134145
loaded_args = self.arguments.load_values_rust(indentation3),

crates/intrinsic-test/src/main.rs

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,11 +190,99 @@ fn generate_rust_program(notices: &str, intrinsic: &Intrinsic, target: &str) ->
190190
.filter(|i| i.has_constraint())
191191
.collect_vec();
192192

193+
// Format f16 values (and vectors containing them) in a way that is consistent with C.
194+
let f16_formatting = r#"
195+
/// Used to continue `Debug`ging SIMD types as `MySimd(1, 2, 3, 4)`, as they
196+
/// were before moving to array-based simd.
197+
#[inline]
198+
fn debug_simd_finish<T: core::fmt::Debug, const N: usize>(
199+
formatter: &mut core::fmt::Formatter<'_>,
200+
type_name: &str,
201+
array: &[T; N],
202+
) -> core::fmt::Result {
203+
core::fmt::Formatter::debug_tuple_fields_finish(
204+
formatter,
205+
type_name,
206+
&core::array::from_fn::<&dyn core::fmt::Debug, N, _>(|i| &array[i]),
207+
)
208+
}
209+
210+
#[repr(transparent)]
211+
struct Hex<T>(T);
212+
213+
impl<T: DebugHexF16> core::fmt::Debug for Hex<T> {
214+
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
215+
<T as DebugHexF16>::fmt(&self.0, f)
216+
}
217+
}
218+
219+
fn debug_f16<T: DebugHexF16>(x: T) -> impl core::fmt::Debug {
220+
Hex(x)
221+
}
222+
223+
trait DebugHexF16 {
224+
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result;
225+
}
226+
227+
impl DebugHexF16 for f16 {
228+
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
229+
write!(f, "{:#06x?}", self.to_bits())
230+
}
231+
}
232+
233+
impl DebugHexF16 for float16x4_t {
234+
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
235+
let array = unsafe { core::mem::transmute::<_, [Hex<f16>; 4]>(*self) };
236+
debug_simd_finish(f, "float16x4_t", &array)
237+
}
238+
}
239+
240+
impl DebugHexF16 for float16x8_t {
241+
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
242+
let array = unsafe { core::mem::transmute::<_, [Hex<f16>; 8]>(*self) };
243+
debug_simd_finish(f, "float16x8_t", &array)
244+
}
245+
}
246+
247+
impl DebugHexF16 for float16x4x2_t {
248+
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
249+
debug_simd_finish(f, "float16x4x2_t", &[Hex(self.0), Hex(self.1)])
250+
}
251+
}
252+
impl DebugHexF16 for float16x4x3_t {
253+
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
254+
debug_simd_finish(f, "float16x4x3_t", &[Hex(self.0), Hex(self.1), Hex(self.2)])
255+
}
256+
}
257+
impl DebugHexF16 for float16x4x4_t {
258+
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
259+
debug_simd_finish(f, "float16x4x4_t", &[Hex(self.0), Hex(self.1), Hex(self.2), Hex(self.3)])
260+
}
261+
}
262+
263+
impl DebugHexF16 for float16x8x2_t {
264+
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
265+
debug_simd_finish(f, "float16x8x2_t", &[Hex(self.0), Hex(self.1)])
266+
}
267+
}
268+
impl DebugHexF16 for float16x8x3_t {
269+
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
270+
debug_simd_finish(f, "float16x8x3_t", &[Hex(self.0), Hex(self.1), Hex(self.2)])
271+
}
272+
}
273+
impl DebugHexF16 for float16x8x4_t {
274+
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
275+
debug_simd_finish(f, "float16x8x4_t", &[Hex(self.0), Hex(self.1), Hex(self.2), Hex(self.3)])
276+
}
277+
}
278+
"#;
279+
193280
let indentation = Indentation::default();
194281
format!(
195282
r#"{notices}#![feature(simd_ffi)]
196283
#![feature(link_llvm_intrinsics)]
197284
#![feature(f16)]
285+
#![feature(fmt_helpers_for_derive)]
198286
#![cfg_attr(target_arch = "arm", feature(stdarch_arm_neon_intrinsics))]
199287
#![cfg_attr(target_arch = "arm", feature(stdarch_aarch32_crc32))]
200288
#![cfg_attr(any(target_arch = "aarch64", target_arch = "arm64ec"), feature(stdarch_neon_fcma))]
@@ -207,6 +295,8 @@ fn generate_rust_program(notices: &str, intrinsic: &Intrinsic, target: &str) ->
207295
#![allow(non_upper_case_globals)]
208296
use core_arch::arch::{target_arch}::*;
209297
298+
{f16_formatting}
299+
210300
fn main() {{
211301
{arglists}
212302
{passes}

0 commit comments

Comments
 (0)