Hey,

Dropped the first patch and dealt with the comments above, hopefully I didn't miss any this time.

----------------------------------

This patch adds support for C23's _BitInt for the AArch64 port when compiling
for little endianness.  Big Endianness requires further target-agnostic
support and we therefor disable it for now.

gcc/ChangeLog:

        * config/aarch64/aarch64.cc (TARGET_C_BITINT_TYPE_INFO): Declare MACRO.
        (aarch64_bitint_type_info): New function.
        (aarch64_return_in_memory_1): Return large _BitInt's in memory.
        (aarch64_function_arg_alignment): Adapt to correctly return the ABI
        mandated alignment of _BitInt(N) where N > 128 as the alignment of
        TImode.
        (aarch64_composite_type_p): Return true for _BitInt(N), where N > 128.

libgcc/ChangeLog:

        * config/aarch64/t-softfp (softfp_extras): Add floatbitinthf,
        floatbitintbf, floatbitinttf and fixtfbitint.
        * config/aarch64/libgcc-softfp.ver (GCC_14.0.0): Add __floatbitinthf,
        __floatbitintbf, __floatbitinttf and __fixtfbitint.

gcc/testsuite/ChangeLog:

        * gcc.target/aarch64/bitint-alignments.c: New test.
        * gcc.target/aarch64/bitint-args.c: New test.
        * gcc.target/aarch64/bitint-sizes.c: New test.


On 02/02/2024 14:46, Jakub Jelinek wrote:
On Thu, Jan 25, 2024 at 05:45:01PM +0000, Andre Vieira wrote:
This patch adds support for C23's _BitInt for the AArch64 port when compiling
for little endianness.  Big Endianness requires further target-agnostic
support and we therefor disable it for now.

gcc/ChangeLog:

        * config/aarch64/aarch64.cc (TARGET_C_BITINT_TYPE_INFO): Declare MACRO.
        (aarch64_bitint_type_info): New function.
        (aarch64_return_in_memory_1): Return large _BitInt's in memory.
        (aarch64_function_arg_alignment): Adapt to correctly return the ABI
        mandated alignment of _BitInt(N) where N > 128 as the alignment of
        TImode.
        (aarch64_composite_type_p): Return true for _BitInt(N), where N > 128.

libgcc/ChangeLog:

        * config/aarch64/t-softfp: Add fixtfbitint, floatbitinttf and
        floatbitinthf to the softfp_extras variable to ensure the
        runtime support is available for _BitInt.

I think this lacks some config/aarch64/t-whatever.ver
additions.
See PR113700 for some more details.
We want the support routines for binary floating point <-> _BitInt
conversions in both libgcc.a and libgcc_s.so.1 and exported from the latter
too at GCC_14.0.0 symver, while decimal floating point <-> _BitInt solely in
libgcc.a (as with all the huge dfp/bid stuff).

        Jakub
diff --git a/gcc/config/aarch64/aarch64.cc b/gcc/config/aarch64/aarch64.cc
index 
16318bf925883ecedf9345e53fc0824a553b2747..9bd8d22f6edd9f6c77907ec383f9e8bf055cfb8b
 100644
--- a/gcc/config/aarch64/aarch64.cc
+++ b/gcc/config/aarch64/aarch64.cc
@@ -6583,6 +6583,7 @@ aarch64_return_in_memory_1 (const_tree type)
   int count;
 
   if (!AGGREGATE_TYPE_P (type)
+      && TREE_CODE (type) != BITINT_TYPE
       && TREE_CODE (type) != COMPLEX_TYPE
       && TREE_CODE (type) != VECTOR_TYPE)
     /* Simple scalar types always returned in registers.  */
@@ -21895,6 +21896,11 @@ aarch64_composite_type_p (const_tree type,
   if (type && (AGGREGATE_TYPE_P (type) || TREE_CODE (type) == COMPLEX_TYPE))
     return true;
 
+  if (type
+      && TREE_CODE (type) == BITINT_TYPE
+      && int_size_in_bytes (type) > 16)
+    return true;
+
   if (mode == BLKmode
       || GET_MODE_CLASS (mode) == MODE_COMPLEX_FLOAT
       || GET_MODE_CLASS (mode) == MODE_COMPLEX_INT)
@@ -28400,6 +28406,42 @@ aarch64_excess_precision (enum excess_precision_type 
type)
   return FLT_EVAL_METHOD_UNPREDICTABLE;
 }
 
+/* Implement TARGET_C_BITINT_TYPE_INFO.
+   Return true if _BitInt(N) is supported and fill its details into *INFO.  */
+bool
+aarch64_bitint_type_info (int n, struct bitint_info *info)
+{
+  if (TARGET_BIG_END)
+    return false;
+
+  if (n <= 8)
+    info->limb_mode = QImode;
+  else if (n <= 16)
+    info->limb_mode = HImode;
+  else if (n <= 32)
+    info->limb_mode = SImode;
+  else if (n <= 64)
+    info->limb_mode = DImode;
+  else if (n <= 128)
+    info->limb_mode = TImode;
+  else
+    /* The AAPCS for AArch64 defines _BitInt(N > 128) as an array with
+       type {signed,unsigned} __int128[M] where M*128 >= N.  However, to be
+       able to use libgcc's implementation to support large _BitInt's we need
+       to use a LIMB_MODE that is no larger than 'long long'.  This is why we
+       use DImode for our internal LIMB_MODE and we define the ABI_LIMB_MODE to
+       be TImode to ensure we are ABI compliant.  */
+    info->limb_mode = DImode;
+
+  if (n > 128)
+    info->abi_limb_mode = TImode;
+  else
+    info->abi_limb_mode = info->limb_mode;
+  info->big_endian = TARGET_BIG_END;
+  info->extended = false;
+  return true;
+}
+
 /* Implement TARGET_SCHED_CAN_SPECULATE_INSN.  Return true if INSN can be
    scheduled for speculative execution.  Reject the long-running division
    and square-root instructions.  */
@@ -30524,6 +30566,9 @@ aarch64_run_selftests (void)
 #undef TARGET_C_EXCESS_PRECISION
 #define TARGET_C_EXCESS_PRECISION aarch64_excess_precision
 
+#undef TARGET_C_BITINT_TYPE_INFO
+#define TARGET_C_BITINT_TYPE_INFO aarch64_bitint_type_info
+
 #undef  TARGET_EXPAND_BUILTIN
 #define TARGET_EXPAND_BUILTIN aarch64_expand_builtin
 
diff --git a/gcc/testsuite/gcc.target/aarch64/bitint-alignments.c 
b/gcc/testsuite/gcc.target/aarch64/bitint-alignments.c
new file mode 100644
index 
0000000000000000000000000000000000000000..4de31fe7ebd933247911c48ace01ab520fe194a3
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/bitint-alignments.c
@@ -0,0 +1,58 @@
+/* { dg-do run } */
+/* { dg-options "-std=c23" } */
+
+static long unsigned int
+calc_size (int n)
+{
+  if (n > 64)
+    return alignof(__int128_t);
+  if (n > 32)
+    return alignof(long long);
+  if (n > 16)
+    return alignof(int);
+  if (n > 8)
+    return alignof(short);
+  else
+    return alignof(char);
+}
+
+#define CHECK_ALIGNMENT(N) \
+  if (alignof(_BitInt(N)) != calc_size(N)) \
+    __builtin_abort ();
+
+int main (void)
+{
+  CHECK_ALIGNMENT(2);
+  CHECK_ALIGNMENT(3);
+  CHECK_ALIGNMENT(7);
+  CHECK_ALIGNMENT(8);
+  CHECK_ALIGNMENT(9);
+  CHECK_ALIGNMENT(13);
+  CHECK_ALIGNMENT(15);
+  CHECK_ALIGNMENT(16);
+  CHECK_ALIGNMENT(17);
+  CHECK_ALIGNMENT(24);
+  CHECK_ALIGNMENT(31);
+  CHECK_ALIGNMENT(32);
+  CHECK_ALIGNMENT(33);
+  CHECK_ALIGNMENT(42);
+  CHECK_ALIGNMENT(53);
+  CHECK_ALIGNMENT(63);
+  CHECK_ALIGNMENT(64);
+  CHECK_ALIGNMENT(65);
+  CHECK_ALIGNMENT(79);
+  CHECK_ALIGNMENT(96);
+  CHECK_ALIGNMENT(113);
+  CHECK_ALIGNMENT(127);
+  CHECK_ALIGNMENT(128);
+  CHECK_ALIGNMENT(129);
+  CHECK_ALIGNMENT(153);
+  CHECK_ALIGNMENT(255);
+  CHECK_ALIGNMENT(256);
+  CHECK_ALIGNMENT(257);
+  CHECK_ALIGNMENT(353);
+  CHECK_ALIGNMENT(512);
+  CHECK_ALIGNMENT(620);
+  CHECK_ALIGNMENT(1024);
+  CHECK_ALIGNMENT(30000);
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/bitint-args.c 
b/gcc/testsuite/gcc.target/aarch64/bitint-args.c
new file mode 100644
index 
0000000000000000000000000000000000000000..a6806ce609b3262c942e722918081ad466853910
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/bitint-args.c
@@ -0,0 +1,84 @@
+/* { dg-do compile } */
+/* { dg-options "-std=c23 -O -fno-stack-clash-protection -g" } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+#define CHECK_ARG(N)           \
+_BitInt(N) g##N;               \
+void f##N(int x, _BitInt(N) y) \
+{                              \
+    g##N = y;                  \
+}
+
+
+CHECK_ARG(2)
+/*
+** f2:
+**     sbfiz   w1, w1, 6, 2
+**     asr     w1, w1, 6
+**     adrp    x0, .*
+**     strb    w1, \[x0, [^\]]*\]
+**     ret
+*/
+CHECK_ARG(8)
+/*
+** f8:
+**     adrp    x0, .*
+**     strb    w1, \[x0, [^\]]*\]
+**     ret
+*/
+CHECK_ARG(9)
+/*
+** f9:
+**     sbfiz   w1, w1, 7, 9
+**     asr     w1, w1, 7
+**     adrp    x0, .*
+**     strh    w1, \[x0, [^\]]*\]
+**     ret
+*/
+CHECK_ARG(16)
+/*
+** f16:
+**     adrp    x0, .*
+**     strh    w1, \[x0, [^\]]*\]
+**     ret
+*/
+CHECK_ARG(19)
+/*
+** f19:
+**     sbfx    x1, x1, 0, 19
+**     adrp    x0, .*
+**     str     w1, \[x0, [^\]]*\]
+**     ret
+*/
+CHECK_ARG(32)
+/*
+** f32:
+**     adrp    x0, .*
+**     str     w1, \[x0, [^\]]*\]
+**     ret
+*/
+CHECK_ARG(42)
+/*
+** f42:
+**     sbfx    x1, x1, 0, 42
+**     adrp    x0, .*
+**     str     x1, \[x0, [^\]]*\]
+**     ret
+*/
+CHECK_ARG(64)
+/*
+** f64:
+**     adrp    x0, .*
+**     str     x1, \[x0, [^\]]*\]
+**     ret
+*/
+CHECK_ARG(65)
+/*
+** f65:
+**     extr    x3, x3, x2, 1
+**     asr     x3, x3, 63
+**     adrp    x0, .*
+**     add     x0, x0, .*
+**     stp     x2, x3, \[x0, [^\]]*\]
+**     ret
+*/
diff --git a/gcc/testsuite/gcc.target/aarch64/bitint-sizes.c 
b/gcc/testsuite/gcc.target/aarch64/bitint-sizes.c
new file mode 100644
index 
0000000000000000000000000000000000000000..bee9abfe91b0dcb1ec335ef9ed02f212f7aa34b7
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/bitint-sizes.c
@@ -0,0 +1,60 @@
+/* { dg-do run } */
+/* { dg-options "-std=c23" } */
+
+static long unsigned int
+calc_size (int n)
+{
+  if (n > 128)
+    return ((n - 1)/128 + 1)  * sizeof(__int128_t);
+  if (n > 64)
+    return sizeof(__int128_t);
+  if (n > 32)
+    return sizeof(long long);
+  if (n > 16)
+    return sizeof(int);
+  if (n > 8)
+    return sizeof(short);
+  else
+    return sizeof(char);
+}
+
+#define CHECK_SIZE(N) \
+  if (sizeof(_BitInt(N)) != calc_size(N)) \
+    __builtin_abort ();
+
+int main (void)
+{
+  CHECK_SIZE(2);
+  CHECK_SIZE(3);
+  CHECK_SIZE(7);
+  CHECK_SIZE(8);
+  CHECK_SIZE(9);
+  CHECK_SIZE(13);
+  CHECK_SIZE(15);
+  CHECK_SIZE(16);
+  CHECK_SIZE(17);
+  CHECK_SIZE(24);
+  CHECK_SIZE(31);
+  CHECK_SIZE(32);
+  CHECK_SIZE(33);
+  CHECK_SIZE(42);
+  CHECK_SIZE(53);
+  CHECK_SIZE(63);
+  CHECK_SIZE(64);
+  CHECK_SIZE(65);
+  CHECK_SIZE(79);
+  CHECK_SIZE(96);
+  CHECK_SIZE(113);
+  CHECK_SIZE(127);
+  CHECK_SIZE(128);
+  CHECK_SIZE(129);
+  CHECK_SIZE(153);
+  CHECK_SIZE(255);
+  CHECK_SIZE(256);
+  CHECK_SIZE(257);
+  CHECK_SIZE(353);
+  CHECK_SIZE(512);
+  CHECK_SIZE(620);
+  CHECK_SIZE(1024);
+  CHECK_SIZE(30000);
+}
diff --git a/libgcc/config/aarch64/libgcc-softfp.ver 
b/libgcc/config/aarch64/libgcc-softfp.ver
index 
e73f5f9129776d39eb5020ed7398dc59aba2d197..9ba857036abef99913eebe56971eaaabf5e1952e
 100644
--- a/libgcc/config/aarch64/libgcc-softfp.ver
+++ b/libgcc/config/aarch64/libgcc-softfp.ver
@@ -39,3 +39,11 @@ GCC_13.0.0 {
   __trunctfbf2
   __trunchfbf2
 }
+
+%inherit GCC_14.0.0 GCC_13.0.0
+GCC_14.0.0 {
+  __fixtfbitint
+  __floatbitintbf
+  __floatbitinthf
+  __floatbitinttf
+}
diff --git a/libgcc/config/aarch64/t-softfp b/libgcc/config/aarch64/t-softfp
index 
2e32366f891361e2056c680b2e36edb1871c7670..80e7e77a545cc10eeccd84eea092871751c3e139
 100644
--- a/libgcc/config/aarch64/t-softfp
+++ b/libgcc/config/aarch64/t-softfp
@@ -4,7 +4,8 @@ softfp_extensions := sftf dftf hftf bfsf
 softfp_truncations := tfsf tfdf tfhf tfbf dfbf sfbf hfbf
 softfp_exclude_libgcc2 := n
 softfp_extras += fixhfti fixunshfti floattihf floatuntihf \
-                floatdibf floatundibf floattibf floatuntibf
+                floatdibf floatundibf floattibf floatuntibf \
+                floatbitinthf floatbitintbf floatbitinttf fixtfbitint
 
 TARGET_LIBGCC2_CFLAGS += -Wno-missing-prototypes
 

Reply via email to