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