Skip to content

Commit d900081

Browse files
committed
Format f16 values normally, rather than use the bit patterns
1 parent a904cce commit d900081

File tree

4 files changed

+20
-203
lines changed

4 files changed

+20
-203
lines changed

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

Lines changed: 2 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -38,11 +38,7 @@ std::ostream& operator<<(std::ostream& os, poly128_t value) {
3838
#endif
3939
4040
std::ostream& operator<<(std::ostream& os, float16_t value) {
41-
uint16_t temp = 0;
42-
memcpy(&temp, &value, sizeof(float16_t));
43-
std::stringstream ss;
44-
ss << "0x" << std::setfill('0') << std::setw(4) << std::hex << temp;
45-
os << ss.str();
41+
os << static_cast<float>(value);
4642
return os;
4743
}
4844
@@ -52,92 +48,7 @@ std::ostream& operator<<(std::ostream& os, uint8_t value) {
5248
}
5349
"#;
5450

55-
// Format f16 values (and vectors containing them) in a way that is consistent with C.
56-
pub const PLATFORM_RUST_DEFINITIONS: &str = r#"
57-
/// Used to continue `Debug`ging SIMD types as `MySimd(1, 2, 3, 4)`, as they
58-
/// were before moving to array-based simd.
59-
#[inline]
60-
fn debug_simd_finish<T: core::fmt::Debug, const N: usize>(
61-
formatter: &mut core::fmt::Formatter<'_>,
62-
type_name: &str,
63-
array: &[T; N],
64-
) -> core::fmt::Result {
65-
core::fmt::Formatter::debug_tuple_fields_finish(
66-
formatter,
67-
type_name,
68-
&core::array::from_fn::<&dyn core::fmt::Debug, N, _>(|i| &array[i]),
69-
)
70-
}
71-
72-
#[repr(transparent)]
73-
struct Hex<T>(T);
74-
75-
impl<T: DebugHexF16> core::fmt::Debug for Hex<T> {
76-
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
77-
<T as DebugHexF16>::fmt(&self.0, f)
78-
}
79-
}
80-
81-
fn debug_f16<T: DebugHexF16>(x: T) -> impl core::fmt::Debug {
82-
Hex(x)
83-
}
84-
85-
trait DebugHexF16 {
86-
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result;
87-
}
88-
89-
impl DebugHexF16 for f16 {
90-
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
91-
write!(f, "{:#06x?}", self.to_bits())
92-
}
93-
}
94-
95-
impl DebugHexF16 for float16x4_t {
96-
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
97-
let array = unsafe { core::mem::transmute::<_, [Hex<f16>; 4]>(*self) };
98-
debug_simd_finish(f, "float16x4_t", &array)
99-
}
100-
}
101-
102-
impl DebugHexF16 for float16x8_t {
103-
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
104-
let array = unsafe { core::mem::transmute::<_, [Hex<f16>; 8]>(*self) };
105-
debug_simd_finish(f, "float16x8_t", &array)
106-
}
107-
}
108-
109-
impl DebugHexF16 for float16x4x2_t {
110-
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
111-
debug_simd_finish(f, "float16x4x2_t", &[Hex(self.0), Hex(self.1)])
112-
}
113-
}
114-
impl DebugHexF16 for float16x4x3_t {
115-
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
116-
debug_simd_finish(f, "float16x4x3_t", &[Hex(self.0), Hex(self.1), Hex(self.2)])
117-
}
118-
}
119-
impl DebugHexF16 for float16x4x4_t {
120-
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
121-
debug_simd_finish(f, "float16x4x4_t", &[Hex(self.0), Hex(self.1), Hex(self.2), Hex(self.3)])
122-
}
123-
}
124-
125-
impl DebugHexF16 for float16x8x2_t {
126-
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
127-
debug_simd_finish(f, "float16x8x2_t", &[Hex(self.0), Hex(self.1)])
128-
}
129-
}
130-
impl DebugHexF16 for float16x8x3_t {
131-
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
132-
debug_simd_finish(f, "float16x8x3_t", &[Hex(self.0), Hex(self.1), Hex(self.2)])
133-
}
134-
}
135-
impl DebugHexF16 for float16x8x4_t {
136-
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
137-
debug_simd_finish(f, "float16x8x4_t", &[Hex(self.0), Hex(self.1), Hex(self.2), Hex(self.3)])
138-
}
139-
}
140-
"#;
51+
pub const PLATFORM_RUST_DEFINITIONS: &str = "";
14152

14253
pub const PLATFORM_RUST_CFGS: &str = r#"
14354
#![cfg_attr(target_arch = "arm", feature(stdarch_arm_neon_intrinsics))]

crates/intrinsic-test/src/common/intrinsic_helpers.rs

Lines changed: 1 addition & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -368,19 +368,8 @@ pub trait IntrinsicTypeDefinition: Deref<Target = IntrinsicType> {
368368
/// Generates a std::cout for the intrinsics results that will match the
369369
/// rust debug output format for the return type. The generated line assumes
370370
/// there is an int i in scope which is the current pass number.
371-
///
372-
/// The `intrinsic-test` crate compares the output of C and Rust intrinsics. Currently, It uses
373-
/// a string representation of the output value to compare. In C, f16 values are currently printed
374-
/// as hexadecimal integers. Since https://github.com/rust-lang/rust/pull/127013, rust does print
375-
/// them as decimal floating point values. To keep the intrinsics tests working, for now, format
376-
/// vectors containing f16 values like C prints them.
377371
fn print_result_rust(&self) -> String {
378-
let return_value = match self.kind() {
379-
TypeKind::Float if self.inner_size() == 16 => "debug_f16(__return_value)",
380-
_ => "format_args!(\"{__return_value:.150?}\")",
381-
};
382-
383-
String::from(return_value)
372+
String::from("format_args!(\"{__return_value:.150?}\")")
384373
}
385374

386375
/// To enable architecture-specific logic

crates/intrinsic-test/src/x86/config.rs

Lines changed: 2 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -142,71 +142,6 @@ fn debug_simd_finish<T: core::fmt::Debug, const N: usize>(
142142
)
143143
}
144144
145-
#[repr(transparent)]
146-
struct Hex<T>(T);
147-
148-
impl<T: DebugHexF16> core::fmt::Debug for Hex<T> {
149-
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
150-
<T as DebugHexF16>::fmt(&self.0, f)
151-
}
152-
}
153-
154-
fn debug_f16<T: DebugHexF16>(x: T) -> impl core::fmt::Debug {
155-
Hex(x)
156-
}
157-
158-
trait DebugHexF16 {
159-
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result;
160-
}
161-
162-
impl DebugHexF16 for f16 {
163-
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
164-
write!(f, "{:#06x?}", self.to_bits())
165-
}
166-
}
167-
168-
impl DebugHexF16 for __m128h {
169-
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
170-
let array = unsafe { core::mem::transmute::<_, [Hex<f16>; 8]>(*self) };
171-
debug_simd_finish(f, "__m128h", &array)
172-
}
173-
}
174-
175-
impl DebugHexF16 for __m128i {
176-
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
177-
let array = unsafe { core::mem::transmute::<_, [Hex<f16>; 8]>(*self) };
178-
debug_simd_finish(f, "__m128i", &array)
179-
}
180-
}
181-
182-
impl DebugHexF16 for __m256h {
183-
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
184-
let array = unsafe { core::mem::transmute::<_, [Hex<f16>; 16]>(*self) };
185-
debug_simd_finish(f, "__m256h", &array)
186-
}
187-
}
188-
189-
impl DebugHexF16 for __m256i {
190-
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
191-
let array = unsafe { core::mem::transmute::<_, [Hex<f16>; 16]>(*self) };
192-
debug_simd_finish(f, "__m256i", &array)
193-
}
194-
}
195-
196-
impl DebugHexF16 for __m512h {
197-
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
198-
let array = unsafe { core::mem::transmute::<_, [Hex<f16>; 32]>(*self) };
199-
debug_simd_finish(f, "__m512h", &array)
200-
}
201-
}
202-
203-
impl DebugHexF16 for __m512i {
204-
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
205-
let array = unsafe { core::mem::transmute::<_, [Hex<f16>; 32]>(*self) };
206-
debug_simd_finish(f, "__m512i", &array)
207-
}
208-
}
209-
210145
trait DebugAs<T> {
211146
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result;
212147
}
@@ -232,7 +167,7 @@ macro_rules! impl_debug_as {
232167
};
233168
}
234169
235-
impl_debug_as!(__m128i, "__m128i", 128, [u8, i8, u16, i16, u32, i32, u64, i64]);
170+
impl_debug_as!(__m128i, "__m128i", 128, [u8, i8, u16, i16, u32, i32, u64, i64, f16]);
236171
impl_debug_as!(__m256i, "__m256i", 256, [u8, i8, u16, i16, u32, i32, u64, i64]);
237172
impl_debug_as!(__m512i, "__m512i", 512, [u8, i8, u16, i16, u32, i32, u64, i64]);
238173
impl_debug_as!(__m128h, "__m128h", 128, [f32]);
@@ -336,11 +271,7 @@ pub const PLATFORM_C_FORWARD_DECLARATIONS: &str = r#"
336271
pub const PLATFORM_C_DEFINITIONS: &str = r#"
337272
338273
std::ostream& operator<<(std::ostream& os, _Float16 value) {
339-
uint16_t temp = 0;
340-
memcpy(&temp, &value, sizeof(_Float16));
341-
std::stringstream ss;
342-
ss << "0x" << std::setfill('0') << std::setw(4) << std::hex << temp;
343-
os << ss.str();
274+
os << static_cast<float>(value);
344275
return os;
345276
}
346277

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

Lines changed: 15 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -172,29 +172,7 @@ impl IntrinsicTypeDefinition for X86IntrinsicType {
172172
/// rust debug output format for the return type. The generated line assumes
173173
/// there is an int i in scope which is the current pass number.
174174
fn print_result_c(&self, indentation: Indentation, additional: &str) -> String {
175-
let lanes = if self.num_vectors() > 1 {
176-
(0..self.num_vectors())
177-
.map(|vector| {
178-
format!(
179-
r#""{ty}(" << {lanes} << ")""#,
180-
ty = self.c_single_vector_type(),
181-
lanes = (0..self.num_lanes())
182-
.map(move |idx| -> std::string::String {
183-
format!(
184-
"{cast}{lane_fn}(__return_value.val[{vector}], {lane})",
185-
cast = self.generate_final_type_cast(),
186-
lane_fn = self.get_lane_function(),
187-
lane = idx,
188-
vector = vector,
189-
)
190-
})
191-
.collect::<Vec<_>>()
192-
.join(r#" << ", " << "#)
193-
)
194-
})
195-
.collect::<Vec<_>>()
196-
.join(r#" << ", " << "#)
197-
} else if self.num_lanes() > 1 {
175+
let lanes = if self.num_lanes() > 1 {
198176
(0..self.num_lanes())
199177
.map(|idx| -> std::string::String {
200178
let cast_type = self.c_promotion();
@@ -283,12 +261,9 @@ impl IntrinsicTypeDefinition for X86IntrinsicType {
283261

284262
fn print_result_rust(&self) -> String {
285263
let return_value = match self.kind() {
286-
TypeKind::Float if self.inner_size() == 16 => "debug_f16(__return_value)".to_string(),
287-
TypeKind::Float
288-
if self.inner_size() == 32
289-
&& ["__m512h"].contains(&self.param.type_data.as_str()) =>
290-
{
291-
"debug_as::<_, f32>(__return_value)".to_string()
264+
// `_mm{256}_cvtps_ph` has return type __m128i but contains f16 values
265+
TypeKind::Float if self.param.type_data == "__m128i" => {
266+
"format_args!(\"{:.150?}\", debug_as::<_, f16>(__return_value))".to_string()
292267
}
293268
TypeKind::Int(_)
294269
if ["__m128i", "__m256i", "__m512i"].contains(&self.param.type_data.as_str()) =>
@@ -463,6 +438,17 @@ impl X86IntrinsicType {
463438
}
464439
}
465440

441+
// a few intrinsics have wrong `etype` field in the XML
442+
// - _mm512_reduce_add_ph
443+
// - _mm512_reduce_mul_ph
444+
// - _mm512_reduce_min_ph
445+
// - _mm512_reduce_max_ph
446+
// - _mm512_conj_pch
447+
if param.type_data == "__m512h" && param.etype == "FP32" {
448+
data.bit_len = Some(16);
449+
data.simd_len = Some(32);
450+
}
451+
466452
let mut result = X86IntrinsicType {
467453
data,
468454
param: param.clone(),

0 commit comments

Comments
 (0)