core::num::f16b Rust's 16bit Brain Float - #160859
Conversation
|
Some changes occurred in compiler/rustc_attr_ir cc @jdonszelmann, @JonathanBrouwer This PR changes rustc_public cc @oli-obk, @celinval, @ouz-a, @makai410
|
|
r? @jieyouxu rustbot has assigned @jieyouxu. Use Why was this reviewer chosen?The reviewer was selected based on:
|
This comment has been minimized.
This comment has been minimized.
|
@rustbot reroll |
| } | ||
|
|
||
| fn type_f16b(&self) -> Type<'gcc> { | ||
| bug!("f16b is not supported by the GCC codegen backend") |
There was a problem hiding this comment.
I believe GCC actually supports this type: https://github.com/rust-lang/gccjit.rs/blob/master/src/context.rs#L1482
There was a problem hiding this comment.
Thanks 😄, I will aim to add it in a follow up PR 👍
There was a problem hiding this comment.
Actually, as @folkertdev pointed out, it was a doddle. So I've included the implementation in the PR 👍
bf10f8a to
01c5c1b
Compare
|
cc @bjorn3 |
There was a problem hiding this comment.
What is the calling convention of other targets?
There was a problem hiding this comment.
I believe only these files were changed because they have an exhaustive match on Float.
However, my version of abi-cafe found two interesting failures: GCC and Clang are inconsistent on aarch64 and armv7
// callee, compiled with GCC 12
#include <inttypes.h>
#include <string.h>
#include <stdio.h>
#include <stdbool.h>
typedef struct Many1 {
__bf16 f0;
} Many1;
void struct_in_1(Many1 arg0) {
printf("%d", arg0.f0);
}// caller, compiled with clang 23
#include <inttypes.h>
#include <string.h>
#include <stdio.h>
#include <stdbool.h>
typedef struct Many1 {
__bf16 f0;
} Many1;
void struct_in_1(Many1 arg0);
void do_test(void) {
{
Many1 arg0 = { .f0 = (((union { uint16_t bits; __bf16 value; }){ .bits = 49600 }).value) };
printf("%d", arg0.f0);
struct_in_1(arg0);
}
}hits
func struct_in_1's values differed
values (native-endian hex bytes):
expect: C0 C1
caller: C0 C1
callee: 04 00
the value was arg0.f0: rustarithmeticty(f16b)
whose arg was arg0: Many1
The current Rust implementation matches clang, and is hence incompatible with GCC
armv7 with hardware floats also runs into incompatibilities
[target.armv7-unknown-linux-gnueabihf."f16::conv_c::repr_c::clang-nightly_calls_distro-gcc"]
busted = "check"
[target.armv7-unknown-linux-gnueabihf."f16::conv_c::repr_c::distro-gcc_calls_clang-nightly"]
busted = "check"
[target.armv7-unknown-linux-gnueabihf."f16b::conv_c::repr_c::clang-nightly_calls_distro-gcc"]
busted = "check"
[target.armv7-unknown-linux-gnueabihf."f16b::conv_c::repr_c::distro-gcc_calls_clang-nightly"]
busted = "check"
Finally, you can let this ICE on many targets, e.g. mips, powerpc, s390x, sparc
There was a problem hiding this comment.
You can also (e.g. on loongarch64 https://godbolt.org/z/Y3hdhG4e6) emit a __truncsfbf2 libcall that is not provided (probably needs to be added to compiler-builtins).
I think the ICEs are probably a blocker? That needs a mechanism similar to has_reliable_f128.
There was a problem hiding this comment.
Yes I added it because of the exhaustive match statement in mips64.rs and sparc64.rs I've removed it; 40d3f6e and put in a panic!(...).
With regard to has_reliable_f128, are you envisaging a has_reliable_f16b entry on TargetConfig?
There was a problem hiding this comment.
With regard to
has_reliable_f128, are you envisaging ahas_reliable_f16bentry onTargetConfig?
Exactly
There was a problem hiding this comment.
What's your take on those ABI mismatches? We should track that somewhere.
There was a problem hiding this comment.
I'm not particularly certain what mips64 should do.
It doesn't, at least to my knowledge, have hardware support. Given we aren't implementing scalar arithmetic and an f16b can only be created through a bit pattern or vendor intrinsics, I can't immediately see a practical application? Hence a panic! seems like a pragmatic choice for the time being.
There was a problem hiding this comment.
No comment on whether this is the right approach, but always use span_bug! or at least bug! where possible in the compiler, rather than panic. It gives much more useful info.
There was a problem hiding this comment.
We can't use those custom macros in rustc_target because they are defined in rustc_middle, and that crate depends on rustc_target.
There was a problem hiding this comment.
It doesn't seem possible to use in compiler/rustc_target, however elsewhere I have strived to use it when available.
This comment has been minimized.
This comment has been minimized.
There was a problem hiding this comment.
I believe only these files were changed because they have an exhaustive match on Float.
However, my version of abi-cafe found two interesting failures: GCC and Clang are inconsistent on aarch64 and armv7
// callee, compiled with GCC 12
#include <inttypes.h>
#include <string.h>
#include <stdio.h>
#include <stdbool.h>
typedef struct Many1 {
__bf16 f0;
} Many1;
void struct_in_1(Many1 arg0) {
printf("%d", arg0.f0);
}// caller, compiled with clang 23
#include <inttypes.h>
#include <string.h>
#include <stdio.h>
#include <stdbool.h>
typedef struct Many1 {
__bf16 f0;
} Many1;
void struct_in_1(Many1 arg0);
void do_test(void) {
{
Many1 arg0 = { .f0 = (((union { uint16_t bits; __bf16 value; }){ .bits = 49600 }).value) };
printf("%d", arg0.f0);
struct_in_1(arg0);
}
}hits
func struct_in_1's values differed
values (native-endian hex bytes):
expect: C0 C1
caller: C0 C1
callee: 04 00
the value was arg0.f0: rustarithmeticty(f16b)
whose arg was arg0: Many1
The current Rust implementation matches clang, and is hence incompatible with GCC
armv7 with hardware floats also runs into incompatibilities
[target.armv7-unknown-linux-gnueabihf."f16::conv_c::repr_c::clang-nightly_calls_distro-gcc"]
busted = "check"
[target.armv7-unknown-linux-gnueabihf."f16::conv_c::repr_c::distro-gcc_calls_clang-nightly"]
busted = "check"
[target.armv7-unknown-linux-gnueabihf."f16b::conv_c::repr_c::clang-nightly_calls_distro-gcc"]
busted = "check"
[target.armv7-unknown-linux-gnueabihf."f16b::conv_c::repr_c::distro-gcc_calls_clang-nightly"]
busted = "check"
Finally, you can let this ICE on many targets, e.g. mips, powerpc, s390x, sparc
| }, | ||
| Primitive::Float(float) => match float { | ||
| Float::F16 | Float::F32 => "f32", | ||
| Float::F16 | Float::F16B | Float::F32 => "f32", |
There was a problem hiding this comment.
is that right? LLVM just crashes on bf16 right now, so it's probably at least untested?
There was a problem hiding this comment.
I could be mistaken, however I don't think WASM supports bf16? I've made it panic!(...) for now; 40d3f6e
53d3660 to
40d3f6e
Compare
This comment has been minimized.
This comment has been minimized.
da620d0 to
0ed984f
Compare
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
|
Some changes occurred in cfg and check-cfg configuration cc @Urgau
cc @rust-lang/miri |
This comment has been minimized.
This comment has been minimized.
|
I'm not a good reviewer for this change. Can somebody here pick it up rather than blindly rerolling? |
|
r? me |
|
💔 Test for 67e0d62 failed: CI. Failed job:
|
This comment has been minimized.
This comment has been minimized.
|
this might need escaping for the @bors try jobs=test-various,aarch64-apple-,-gnu-nopt-,x86_64-mingw-,aarch64-msvc-*,arm-android |
This comment has been minimized.
This comment has been minimized.
`core::num::f16b` Rust's 16bit Brain Float try-job: test-various try-job: aarch64-apple-* try-job: *-gnu-nopt-* try-job: x86_64-mingw-* try-job: aarch64-msvc-* try-job: arm-android
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
|
💔 Test for eb7a0f0 failed: CI. Failed jobs:
|
| //@ compile-flags: -O | ||
| //@ ignore-backends: gcc | ||
| //@ ignore-s390x | ||
| //@ ignore-wasm |
There was a problem hiding this comment.
apparently this also needs to be excluded on x86, because
https://triage.rust-lang.org/gha-logs/rust-lang/rust/96088718830
the __truncsfbf2 libcall is missing
There was a problem hiding this comment.
and we can't add that libcall without the type I think, unless f16 or u16 matches abi-wise on the relevant platforms.
There was a problem hiding this comment.
LLVM using __truncsfbf2 in to_bits is actually a LLVM miscompilation due to signalling NaNs - see llvm/llvm-project#97896 (comment).
There was a problem hiding this comment.
I've added //@ ignore-x86
There was a problem hiding this comment.
This is just a codegen test, why do we need to skip anything?
Please include comments so we're not confused in the future wondering why this test wasn't running...
There was a problem hiding this comment.
apparently this also needs to be excluded on x86, because
https://triage.rust-lang.org/gha-logs/rust-lang/rust/96088718830
That's the UI test, not this one. Codegen tests should be re-enabled.
That LLVM bug needs to disqualify reliable f16b on all platforms it affects, then the run-pass UI tests (and other runtime tests) should be gated on cfg_target_has_reliable_f16b rather than skipping individual platforms. We can't even implement the libcalls in compiler-builtins if LLVM is going to give us circular code when we try to bitcast.
There was a problem hiding this comment.
I see so you envisage something along the following?
#[cfg(has_reliable_f16b)] {
// do an actual test
} else {
// return 0;
}For GCC however, I don't understand how it decides whether the feature exists which was my original reluctance to include it in this PR. The call;
// compiler/rustc_codegen_gcc/src/base.rs
let f16b_type_supported = target_info.supports_target_dependent_type(CType::BFloat16);Seems to whittle down to the following snippet which I think would always return false. Yet somehow I don't think it does?
// compiler/rustc_codegen_gcc/src/lib.rs:128
fn supports_target_dependent_type(&self, typ: CType) -> bool {
match typ {
CType::UInt128t | CType::Int128t => {
if self.supports_128bit_integers.load(Ordering::SeqCst) {
return true;
}
}
_ => (),
}
false
}803ea00 to
7e193e5
Compare
|
@bors try jobs=test-various,aarch64-apple-,-gnu-nopt-,x86_64-mingw-,aarch64-msvc-*,arm-android |
This comment has been minimized.
This comment has been minimized.
`core::num::f16b` Rust's 16bit Brain Float try-job: test-various try-job: aarch64-apple- try-job: -gnu-nopt- try-job: x86_64-mingw- try-job: aarch64-msvc-* try-job: arm-android
|
💔 Test for c51a5dc failed: CI. Failed job:
|
This comment has been minimized.
This comment has been minimized.
|
@bors try jobs=test-various,aarch64-apple-,-gnu-nopt-,x86_64-mingw-,aarch64-msvc-*,arm-android |
This comment has been minimized.
This comment has been minimized.
`core::num::f16b` Rust's 16bit Brain Float try-job: test-various try-job: aarch64-apple-* try-job: *-gnu-nopt-* try-job: x86_64-mingw-* try-job: aarch64-msvc-* try-job: arm-android
This comment has been minimized.
This comment has been minimized.
|
💔 Test for db42cb7 failed: CI. Failed job:
|
|
@bors try jobs=test-various,aarch64-apple-,-gnu-nopt-,x86_64-mingw-,aarch64-msvc-*,arm-android |
This comment has been minimized.
This comment has been minimized.
`core::num::f16b` Rust's 16bit Brain Float try-job: test-various try-job: aarch64-apple-* try-job: *-gnu-nopt-* try-job: x86_64-mingw-* try-job: aarch64-msvc-* try-job: arm-android
View all comments
Implements the RFC: f16b type. Best reviewed commit by commit, happy to split into separate PRs if that is deemed easier to review. However the line count and surface area is, in my opinion, reasonably small.
Adds;
f16balong withbfloatlang item to work with LLVM, GCC is explicitlyunimplemented!(...)f16bfeature gate, page forf16bon libruscdoc and astruct bf16incore::numf16bas a scalar primitive for scalable vectorsIssues;