aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorYang Yujie <yangyujie@loongson.cn>2025-08-02 17:16:23 +0800
committerLulu Cheng <chenglulu@loongson.cn>2025-08-13 11:01:55 +0800
commit8079e96eb767851e8e061a13ecfb21aa1a2362de (patch)
tree02fee192423bdee21c8d8edc7f798a2342fc850e /gcc
parent8a7a433e86f32871f56095434cc85eb2da1b550b (diff)
downloadgcc-8079e96eb767851e8e061a13ecfb21aa1a2362de.zip
gcc-8079e96eb767851e8e061a13ecfb21aa1a2362de.tar.gz
gcc-8079e96eb767851e8e061a13ecfb21aa1a2362de.tar.bz2
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.
Diffstat (limited to 'gcc')
-rw-r--r--gcc/config/loongarch/loongarch.cc35
-rw-r--r--gcc/config/loongarch/loongarch.h4
-rw-r--r--gcc/testsuite/gcc.target/loongarch/bitint-alignments.c58
-rw-r--r--gcc/testsuite/gcc.target/loongarch/bitint-args.c81
-rw-r--r--gcc/testsuite/gcc.target/loongarch/bitint-sizes.c60
5 files changed, 235 insertions, 3 deletions
diff --git a/gcc/config/loongarch/loongarch.cc b/gcc/config/loongarch/loongarch.cc
index 493f95e..b169d2f 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 5fc8665..e8819bf 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 0000000..8592279
--- /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 0000000..ceba1fb
--- /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 0000000..7272f98
--- /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);
+}