https://gcc.gnu.org/g:8079e96eb767851e8e061a13ecfb21aa1a2362de

commit r16-3176-g8079e96eb767851e8e061a13ecfb21aa1a2362de
Author: Yang Yujie <yangyu...@loongson.cn>
Date:   Sat Aug 2 17:16:23 2025 +0800

    LoongArch: Add support for _BitInt [PR117599]
    
    This patch adds support for C23's _BitInt for LoongArch.
    
    From the LoongArch psABI[1]:
    
    > _BitInt(N) objects are stored in little-endian order in memory
    > and are signed by default.
    >
    > For N ≤ 64, a _BitInt(N) object have the same size and alignment
    > of the smallest fundamental integral type that can contain it.
    > The unused high-order bits within this containing type are filled
    > with sign or zero extension of the N-bit value, depending on whether
    > the _BitInt(N) object is signed or unsigned. The _BitInt(N) object
    > propagates its signedness to the containing type and is laid out
    > in a register or memory as an object of this type.
    >
    > For N > 64, _BitInt(N) objects are implemented as structs of 64-bit
    > integer chunks. The number of chunks is the smallest even integer M
    > so that M * 64 ≥ N. These objects are of the same size of the struct
    > containing the chunks, but always have 16-byte alignment. If there
    > are unused bits in the highest-ordered chunk that contains used
    > bits, they are defined as the sign- or zero- extension of the used
    > bits depending on whether the _BitInt(N) object is signed or
    > unsigned. If an entire chunk is unused, its bits are undefined.
    
    [1] https://github.com/loongson/la-abi-specs
    
            PR target/117599
    
    gcc/ChangeLog:
    
            * config/loongarch/loongarch.h: Define a PROMOTE_MODE case for
            small _BitInts.
            * config/loongarch/loongarch.cc (loongarch_promote_function_mode):
            Same.
            (loongarch_bitint_type_info): New function.
            (TARGET_C_BITINT_TYPE_INFO): Declare.
    
    libgcc/ChangeLog:
    
            * config/loongarch/t-softfp-tf: Enable _BitInt helper functions.
            * config/loongarch/t-loongarch: Same.
            * config/loongarch/libgcc-loongarch.ver: New file.
    
    gcc/testsuite/ChangeLog:
    
            * gcc.target/loongarch/bitint-alignments.c: New test.
            * gcc.target/loongarch/bitint-args.c: New test.
            * gcc.target/loongarch/bitint-sizes.c: New test.

Diff:
---
 gcc/config/loongarch/loongarch.cc                  | 35 +++++++++-
 gcc/config/loongarch/loongarch.h                   |  4 +-
 .../gcc.target/loongarch/bitint-alignments.c       | 58 ++++++++++++++++
 gcc/testsuite/gcc.target/loongarch/bitint-args.c   | 81 ++++++++++++++++++++++
 gcc/testsuite/gcc.target/loongarch/bitint-sizes.c  | 60 ++++++++++++++++
 libgcc/config/loongarch/libgcc-loongarch.ver       | 28 ++++++++
 libgcc/config/loongarch/t-loongarch                |  2 +
 libgcc/config/loongarch/t-softfp-tf                |  1 +
 8 files changed, 266 insertions(+), 3 deletions(-)

diff --git a/gcc/config/loongarch/loongarch.cc 
b/gcc/config/loongarch/loongarch.cc
index 493f95e16191..b169d2ffcd06 100644
--- a/gcc/config/loongarch/loongarch.cc
+++ b/gcc/config/loongarch/loongarch.cc
@@ -10786,9 +10786,9 @@ loongarch_expand_vec_cmp (rtx operands[])
    to a fixed type.  */
 
 static machine_mode
-loongarch_promote_function_mode (const_tree type ATTRIBUTE_UNUSED,
+loongarch_promote_function_mode (const_tree type,
                                 machine_mode mode,
-                                int *punsignedp ATTRIBUTE_UNUSED,
+                                int *punsignedp,
                                 const_tree fntype ATTRIBUTE_UNUSED,
                                 int for_return ATTRIBUTE_UNUSED)
 {
@@ -11154,6 +11154,34 @@ loongarch_c_mode_for_suffix (char suffix)
   return VOIDmode;
 }
 
+/* Implement TARGET_C_BITINT_TYPE_INFO.
+   Return true if _BitInt(N) is supported and fill its details into *INFO.  */
+bool
+loongarch_bitint_type_info (int n, struct bitint_info *info)
+{
+  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
+    info->limb_mode = DImode;
+
+  info->abi_limb_mode = info->limb_mode;
+
+  if (n > 64)
+    info->abi_limb_mode = TImode;
+
+  info->big_endian = false;
+  info->extended = true;
+  return true;
+}
+
 /* Initialize the GCC target structure.  */
 #undef TARGET_ASM_ALIGNED_HI_OP
 #define TARGET_ASM_ALIGNED_HI_OP "\t.half\t"
@@ -11428,6 +11456,9 @@ loongarch_c_mode_for_suffix (char suffix)
 #undef TARGET_C_MODE_FOR_SUFFIX
 #define TARGET_C_MODE_FOR_SUFFIX loongarch_c_mode_for_suffix
 
+#undef TARGET_C_BITINT_TYPE_INFO
+#define TARGET_C_BITINT_TYPE_INFO loongarch_bitint_type_info
+
 struct gcc_target targetm = TARGET_INITIALIZER;
 
 #include "gt-loongarch.h"
diff --git a/gcc/config/loongarch/loongarch.h b/gcc/config/loongarch/loongarch.h
index 5fc86652f5f8..e8819bf14801 100644
--- a/gcc/config/loongarch/loongarch.h
+++ b/gcc/config/loongarch/loongarch.h
@@ -270,7 +270,9 @@ along with GCC; see the file COPYING3.  If not see
   if (GET_MODE_CLASS (MODE) == MODE_INT \
       && GET_MODE_SIZE (MODE) < UNITS_PER_WORD) \
     { \
-      if ((MODE) == SImode) \
+      if ((MODE) == SImode \
+         && !(TYPE && TREE_CODE (TYPE) == BITINT_TYPE \
+              && TYPE_PRECISION (TYPE) < 32)) \
        (UNSIGNEDP) = 0; \
       (MODE) = Pmode; \
     }
diff --git a/gcc/testsuite/gcc.target/loongarch/bitint-alignments.c 
b/gcc/testsuite/gcc.target/loongarch/bitint-alignments.c
new file mode 100644
index 000000000000..8592279b038b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/loongarch/bitint-alignments.c
@@ -0,0 +1,58 @@
+/* { dg-do run { target bitint } } */
+/* { dg-additional-options "-std=c23" } */
+
+static long unsigned int
+calc_alignof (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_alignof(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/loongarch/bitint-args.c 
b/gcc/testsuite/gcc.target/loongarch/bitint-args.c
new file mode 100644
index 000000000000..ceba1fb6e3af
--- /dev/null
+++ b/gcc/testsuite/gcc.target/loongarch/bitint-args.c
@@ -0,0 +1,81 @@
+/* { dg-do compile { target bitint } } */
+/* { dg-additional-options "-std=c23 -O -fno-stack-clash-protection -g" } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+#define CHECK_ARG(N)                           \
+void f##N(_BitInt(N) *ptr, _BitInt(N) y)       \
+{                                              \
+    *ptr = y;                                  \
+}
+
+
+CHECK_ARG(2)
+/*
+** f2:
+**     st.b    \$r5,\$r4,0
+**     jr      \$r1
+*/
+CHECK_ARG(8)
+/*
+** f8:
+**     st.b    \$r5,\$r4,0
+**     jr      \$r1
+*/
+CHECK_ARG(9)
+/*
+** f9:
+**     st.h    \$r5,\$r4,0
+**     jr      \$r1
+*/
+CHECK_ARG(16)
+/*
+** f16:
+**     st.h    \$r5,\$r4,0
+**     jr      \$r1
+*/
+CHECK_ARG(19)
+/*
+** f19:
+**     stptr.w \$r5,\$r4,0
+**     jr      \$r1
+*/
+CHECK_ARG(32)
+/*
+** f32:
+**     stptr.w \$r5,\$r4,0
+**     jr      \$r1
+*/
+CHECK_ARG(42)
+/*
+** f42:
+**     stptr.d \$r5,\$r4,0
+**     jr      \$r1
+*/
+CHECK_ARG(64)
+/*
+** f64:
+**     stptr.d \$r5,\$r4,0
+**     jr      \$r1
+*/
+CHECK_ARG(65)
+/*
+** f65:
+**     stptr.d \$r5,\$r4,0
+**     st.d    \$r6,\$r4,8
+**     jr      \$r1
+*/
+CHECK_ARG(127)
+/*
+** f127:
+**     stptr.d \$r5,\$r4,0
+**     st.d    \$r6,\$r4,8
+**     jr      \$r1
+*/
+
+CHECK_ARG(128)
+/*
+** f128:
+**     stptr.d \$r5,\$r4,0
+**     st.d    \$r6,\$r4,8
+**     jr      \$r1
+*/
diff --git a/gcc/testsuite/gcc.target/loongarch/bitint-sizes.c 
b/gcc/testsuite/gcc.target/loongarch/bitint-sizes.c
new file mode 100644
index 000000000000..7272f98acbb0
--- /dev/null
+++ b/gcc/testsuite/gcc.target/loongarch/bitint-sizes.c
@@ -0,0 +1,60 @@
+/* { dg-do run { target bitint } } */
+/* { dg-additional-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/loongarch/libgcc-loongarch.ver 
b/libgcc/config/loongarch/libgcc-loongarch.ver
new file mode 100644
index 000000000000..0a71f2ecca2f
--- /dev/null
+++ b/libgcc/config/loongarch/libgcc-loongarch.ver
@@ -0,0 +1,28 @@
+# Copyright (C) 2025 Free Software Foundation, Inc.
+#
+# This file is part of GCC.
+#
+# GCC is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GCC is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GCC; see the file COPYING3.  If not see
+# <http://www.gnu.org/licenses/>.
+
+GCC_16.0.0 {
+    __mulbitint3
+    __divmodbitint4
+    __fixsfbitint
+    __fixdfbitint
+    __fixtfbitint
+    __floatbitintsf
+    __floatbitintdf
+    __floatbitinttf
+}
diff --git a/libgcc/config/loongarch/t-loongarch 
b/libgcc/config/loongarch/t-loongarch
index 2a7dbf6ca83a..b9374fc70016 100644
--- a/libgcc/config/loongarch/t-loongarch
+++ b/libgcc/config/loongarch/t-loongarch
@@ -5,3 +5,5 @@ softfp_int_modes := si di
 softfp_extensions :=
 softfp_truncations :=
 softfp_exclude_libgcc2 := n
+
+SHLIB_MAPFILES += $(srcdir)/config/loongarch/libgcc-loongarch.ver
diff --git a/libgcc/config/loongarch/t-softfp-tf 
b/libgcc/config/loongarch/t-softfp-tf
index 306677b12554..be2b7302941c 100644
--- a/libgcc/config/loongarch/t-softfp-tf
+++ b/libgcc/config/loongarch/t-softfp-tf
@@ -1,3 +1,4 @@
 softfp_float_modes += tf
 softfp_extensions += sftf dftf
 softfp_truncations += tfsf tfdf
+softfp_extras += floatbitinttf fixtfbitint

Reply via email to