NetBSD-Bugs archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Re: port-arm/56839: GCC emits wrong codes for compare_and_swap_1 bultins on armv5 (el & eb)



The following reply was made to PR port-arm/56839; it has been noted by GNATS.

From: Taylor R Campbell <riastradh%NetBSD.org@localhost>
To: Rin Okuyama <rokuyama.rk%gmail.com@localhost>,
	Nick Hudson <nick.hudson%gmx.co.uk@localhost>,
	Martin Husemann <martin%duskware.de@localhost>
Cc: gnats-bugs%NetBSD.org@localhost, netbsd-bugs%NetBSD.org@localhost
Subject: Re: port-arm/56839: GCC emits wrong codes for compare_and_swap_1 bultins on armv5 (el & eb)
Date: Thu, 13 Mar 2025 14:29:40 +0000

 It looks like gcc is _inconsistent_ about the signedness of the
 __sync_* builtins.  Here, for example, in gcc-14.2.0, it appears to
 use unsigned arguments in libgcc:
 
  134 typedef unsigned int UQItype __attribute__((mode (QI)));
  135 DEFINE (FN, 1, UQItype)
 ...
  139 typedef unsigned int UHItype __attribute__((mode (HI)));
  140 DEFINE (FN, 2, UHItype)
 ...
  144 typedef unsigned int USItype __attribute__((mode (SI)));
  145 DEFINE (FN, 4, USItype)
 ...
 
 https://gcc.gnu.org/git/?p=3Dgcc.git;a=3Dblob;f=3Dlibgcc/sync.c;h=3D6ffe88a=
 ac0f08d1adbc0b02f7f10d50d95d4c6eb;hb=3D04696df09633baf97cdbbdd6e9929b9d4721=
 61d3#l125
 
 And, for _FreeBSD_ on arm32, it also uses unsigned arguments:
 
  220 EMIT_ALL_OPS_N (1, unsigned char, "ldrb", "strb", "streqb")
  221 EMIT_ALL_OPS_N (2, unsigned short, "ldrh", "strh", "streqh")
  222 EMIT_ALL_OPS_N (4, unsigned int, "ldr", "str", "streq")
 
 https://gcc.gnu.org/git/?p=3Dgcc.git;a=3Dblob;f=3Dlibgcc/config/arm/freebsd=
 -atomic.c;h=3D7cf00b1e75d4759b983401797f0224764a2ce82d;hb=3D04696df09633baf=
 97cdbbdd6e9929b9d472161d3#l220
 
 But elsewhere, e.g. for _Linux_ on arm32, it uses signed arguments:
 
  249 SUBWORD_VAL_CAS (short,       2)
  250 SUBWORD_VAL_CAS (signed char, 1)
 
 https://gcc.gnu.org/git/?p=3Dgcc.git;a=3Dblob;f=3Dlibgcc/config/arm/linux-a=
 tomic.c;h=3D6d6683194aff0404967b28030bc7677b0f2e5949;hb=3D04696df09633baf97=
 cdbbdd6e9929b9d472161d3#l249
 
 And I have no idea about the code generation parts of things.
 
 We should file a bug upstream, perhaps.
 
 But until we do, I think it should be sufficient to write all of our
 __sync_* routines -- including both __sync_bool_* and __sync_val_*, of
 course -- with signed arguments and pass them to the unsigned
 _atomic_* functions, like Nick suggested.
 
 This should paper over the gcc issue, by forcing gcc to generate code
 that always zero-extends the subword when passing arguments in
 registers so the comparison will succeed (at least, for ABIs where
 that is relevant), without requiring changes to our _atomic_*
 definitions which are perfectly good for their signatures.
 
 I guess it is conceivable that there is an ABI where this will do the
 wrong thing but I doubt it.  Even on riscv64, where 8/16-bit units are
 type-extended to 32 bit and then sign-extended to 64 bits (no matter
 the signedness of the type), I think this will produce the correct
 result.  (Also I think these stubs won't be used on riscv anyway.)=20
 


Home | Main Index | Thread Index | Old Index