cbe: workaround GCC miscompilation

This was causing a zig2 miscomp, which emitted slightly broken debug
information, which caused extremely slow stack unwinding. We're working
on fixing or reporting this upstream, but we can use this workaround for
now, because GCC guarantees arithmetic signed shift.
This commit is contained in:
mlugg 2025-09-24 00:36:17 +01:00
parent dbda011ae6
commit 3f84b6c80e
No known key found for this signature in database
GPG key ID: 3F5B7DCCBF4AF02E
2 changed files with 16 additions and 0 deletions

View file

@ -1510,8 +1510,16 @@ static inline zig_u128 zig_shl_u128(zig_u128 lhs, uint8_t rhs) {
}
static inline zig_i128 zig_shr_i128(zig_i128 lhs, uint8_t rhs) {
// This works around a GCC miscompilation, but it has the side benefit of
// emitting better code. It is behind the `#if` because it depends on
// arithmetic right shift, which is implementation-defined in C, but should
// be guaranteed on any GCC-compatible compiler.
#if defined(zig_gnuc)
return lhs >> rhs;
#else
zig_i128 sign_mask = lhs < zig_make_i128(0, 0) ? -zig_make_i128(0, 1) : zig_make_i128(0, 0);
return ((lhs ^ sign_mask) >> rhs) ^ sign_mask;
#endif
}
static inline zig_i128 zig_shl_i128(zig_i128 lhs, uint8_t rhs) {

View file

@ -1510,8 +1510,16 @@ static inline zig_u128 zig_shl_u128(zig_u128 lhs, uint8_t rhs) {
}
static inline zig_i128 zig_shr_i128(zig_i128 lhs, uint8_t rhs) {
// This works around a GCC miscompilation, but it has the side benefit of
// emitting better code. It is behind the `#if` because it depends on
// arithmetic right shift, which is implementation-defined in C, but should
// be guaranteed on any GCC-compatible compiler.
#if defined(zig_gnuc)
return lhs >> rhs;
#else
zig_i128 sign_mask = lhs < zig_make_i128(0, 0) ? -zig_make_i128(0, 1) : zig_make_i128(0, 0);
return ((lhs ^ sign_mask) >> rhs) ^ sign_mask;
#endif
}
static inline zig_i128 zig_shl_i128(zig_i128 lhs, uint8_t rhs) {