Hi!

Only __atomic_* builtins are meant to work on arbitrary _BitInt types
(if not supported in hw we emit a CAS loop which uses __atomic_load_*
in that case), the compatibility __sync_* builtins work only if there
is a corresponding normal integral type (for _BitInt on 32-bit ARM
we'll need to limit even that to no padding, because the padding bits
are well defined there and the hw or libatomic __sync_* APIs don't
guarantee that), IMHO people shouldn't mix very old APIs with very
new ones and I don't see a replacement for the __atomic_load_*.

For size > 16 that is how it already correctly behaves,
in the hunk shown in the patch it is immediately followed by

  if (fetch && !orig_format && TREE_CODE (type) == BITINT_TYPE)
    return -1;

which returns -1 for the __atomic_* builtins (i.e. !orig_format),
which causes caller to use atomic_bitint_fetch_using_cas_loop,
and otherwise does diagnostic and return 0 (which causes caller
to punt).  But for size == 16 if TImode isn't suipported (i.e.
mostly 32-bit arches), we return (correctly) -1 if !orig_format,
so again force atomic_bitint_fetch_using_cas_loop on those arches
for e.g. _BitInt(115), but for orig_format the function returns
16 as if it could do 16 byte __sync_*_and_* (which it can't
because TImode isn't supported; for 16 byte it can only do
(perhaps using libatomic) normal compare and swap).  So we need
to error and return 0, rather than return 16.

The following patch ensures that.

Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

2024-11-19  Jakub Jelinek  <ja...@redhat.com>

        PR c/117641
        * c-common.cc (sync_resolve_size): For size == 16 fetch of
        BITINT_TYPE if TImode isn't supported scalar mode diagnose
        and return 0 if orig_format instead of returning 16.

        * gcc.dg/bitint-115.c: New test.

--- gcc/c-family/c-common.cc.jj 2024-11-15 08:43:34.597097027 +0100
+++ gcc/c-family/c-common.cc    2024-11-18 16:21:06.306266787 +0100
@@ -7458,10 +7458,13 @@ sync_resolve_size (tree function, vec<tr
   size = tree_to_uhwi (TYPE_SIZE_UNIT (type));
   if (size == 16
       && fetch
-      && !orig_format
       && TREE_CODE (type) == BITINT_TYPE
       && !targetm.scalar_mode_supported_p (TImode))
-    return -1;
+    {
+      if (!orig_format)
+       return -1;
+      goto incompatible;
+    }
 
   if (size == 1 || size == 2 || size == 4 || size == 8 || size == 16)
     return size;
--- gcc/testsuite/gcc.dg/bitint-115.c.jj        2024-11-18 16:41:14.023399087 
+0100
+++ gcc/testsuite/gcc.dg/bitint-115.c   2024-11-18 16:42:38.515219036 +0100
@@ -0,0 +1,9 @@
+/* PR c/117641 */
+/* { dg-do compile { target bitint575 } } */
+/* { dg-options "-std=c23" } */
+
+void
+foo (_BitInt(128) *b)
+{
+  __sync_fetch_and_add (b, 1); /* { dg-error "incompatible" "" { target { ! 
int128 } } } */
+}

        Jakub

Reply via email to