NetBSD-Bugs archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
Re: port-sh3/60773: sh3 __sync_val_compare_and_swap_1 test failures
The following reply was made to PR toolchain/60773; it has been noted by GNATS.
From: Taylor R Campbell <riastradh%NetBSD.org@localhost>
To: Valery Ushakov <uwe%stderr.spb.ru@localhost>
Cc: gnats-bugs%NetBSD.org@localhost, netbsd-bugs%NetBSD.org@localhost,
Nick Hudson <skrll%NetBSD.org@localhost>
Subject: Re: port-sh3/60773: sh3 __sync_val_compare_and_swap_1 test failures
Date: Fri, 25 Sep 2026 16:14:25 +0000
> Date: Fri, 25 Sep 2026 14:41:44 +0000
> From: Taylor R Campbell <riastradh%NetBSD.org@localhost>
>=20
> Note that main_s8 has an additional extu.b instruction in it! I'm
> guessing this means `extend unsigned byte', i.e., zero-extend result
> in r0 to printf argument in r6. So it looks like gcc treats
> __sync_val_compare_and_swap_1 as if it has the signed prototype:
> main__ matches main_u8, not main_s8.
> [...]
> Now I'm a little lost with the sh3 branch delay slot shenanigans (is
> that two comparisons fed into a single conditional branch with a delay
> slot??), but what I see here is that the _stored_ val is zero-extended
> with extu.b, but the _returned_ res is not! That's in stark contrast
> to the attached program I examined, where the returned result _is_
> zero-extended with extu.b.
Err, no, I just confused myself; it's consistent: in both cases gcc
treats __sync_val_compare_and_swap as if it returned uint8_t, not
int8_t, because so there's no extu.b instruction involved to convert
int8_t to uint8_t.
Here's how the builtin is declared:
209 DEF_SYNC_BUILTIN (BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_1,
210 "__sync_val_compare_and_swap_1",
211 BT_FN_I1_VPTR_I1_I1, ATTR_NOTHROWCALL_LEAF_LIST)
https://nxr.netbsd.org/xref/src/external/gpl3/gcc/dist/gcc/sync-builtins.de=
f?r=3D1.1.1.12#209
I'm a little fuzzy on what BT_FN_I1_VPTR_I1_I1 means. It appears to
be defined like this:
209 DEF_PRIMITIVE_TYPE (BT_I1, builtin_type_for_size (BITS_PER_UNIT*1, =
1))
...
787 DEF_FUNCTION_TYPE_3 (BT_FN_I1_VPTR_I1_I1, BT_I1, BT_VOLATILE_PTR, B=
T_I1, BT_I1)
https://nxr.netbsd.org/xref/src/external/gpl3/gcc/dist/gcc/builtin-types.de=
f?r=3D1.1.1.12#787
Note that BT_I1 is not clearly defined to be either int8_t _or_
uint8_t, for which there are BT_INT8 and BT_UINT8:
70 DEF_PRIMITIVE_TYPE (BT_INT8, signed_char_type_node)
...
72 DEF_PRIMITIVE_TYPE (BT_UINT8, unsigned_char_type_node)
But builtin_type_for_size is defined here and perhaps it illuminates:
7234 tree
7235 builtin_type_for_size (int size, bool unsignedp)
7236 {
7237 tree type =3D c_common_type_for_size (size, unsignedp);
7238 return type ? type : error_mark_node;
7239 }
https://nxr.netbsd.org/xref/src/external/gpl3/gcc/dist/gcc/c-family/c-commo=
n.cc?r=3D1.1.1.3#7228
2332 tree
2333 c_common_type_for_size (unsigned int bits, int unsignedp)
2334 {
...
2340 if (bits =3D=3D TYPE_PRECISION (signed_char_type_node))
2341 return unsignedp ? unsigned_char_type_node : signed_char_type_n=
ode;
https://nxr.netbsd.org/xref/src/external/gpl3/gcc/dist/gcc/c-family/c-commo=
n.cc?r=3D1.1.1.3#2328
That suggests to me that gcc will treat BT_I1 as unsigned char, and
thus always treat __sync_val_compare_and_swap_1 as if it had the
prototype
uint8_t __sync_val_compare_and_swap_1(volatile uint8_t *, uint8_t, uint8_t);
Which makes the arm bug of PR lib/56839 (GCC emits wrong codes for
compare_and_swap_1 bultins on armv5 (el & eb)) all the more puzzling!
However, I haven't connected the notation in sync-builtins.def to the
logic that gcc actually uses for code generation. So perhaps there is
more magic yet to be discovered down that path.
Home |
Main Index |
Thread Index |
Old Index