This patch adds support for C23's _BitInt for LoongArch.
Though there's not an official psABI definition, our plan
is to have 16-byte alignment for N > 64 and the padding bits
sign/zero-extended when passed between procedures.
One exception would be "unsigned _BitInt(32)". To match the
behavior of "unsigned int" in the current LP64 ABIs, it is
sign-extended when stored in a 64-bit GPR as a function
argument or return value.
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.
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.
---
gcc/config/loongarch/loongarch.cc | 31 ++++++-
gcc/config/loongarch/loongarch.h | 4 +-
.../gcc.target/loongarch/bitint-alignments.c | 58 ++++++++++++
.../gcc.target/loongarch/bitint-args.c | 93 +++++++++++++++++++
.../gcc.target/loongarch/bitint-sizes.c | 60 ++++++++++++
libgcc/config/loongarch/t-softfp-tf | 1 +
6 files changed, 244 insertions(+), 3 deletions(-)
create mode 100644 gcc/testsuite/gcc.target/loongarch/bitint-alignments.c
create mode 100644 gcc/testsuite/gcc.target/loongarch/bitint-args.c
create mode 100644 gcc/testsuite/gcc.target/loongarch/bitint-sizes.c
diff --git a/gcc/config/loongarch/loongarch.cc
b/gcc/config/loongarch/loongarch.cc
index 7533e53839f..f713d904b55 100644
--- a/gcc/config/loongarch/loongarch.cc
+++ b/gcc/config/loongarch/loongarch.cc
@@ -10852,9 +10852,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)
{
@@ -11216,6 +11216,30 @@ 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
+ 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"
@@ -11490,6 +11514,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 d8977634b71..73372df838e 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 00000000000..8592279b038
--- /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 00000000000..c23f152a558
--- /dev/null
+++ b/gcc/testsuite/gcc.target/loongarch/bitint-args.c
@@ -0,0 +1,93 @@
+/* { 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
+*/
+
+CHECK_ARG(129)
+/*
+** f129:
+** ldptr.d \$r12,\$r5,0
+** stptr.d \$r12,\$r4,0
+** ld.d \$r12,\$r5,8
+** st.d \$r12,\$r4,8
+** ld.d \$r12,\$r5,16
+** st.d \$r12,\$r4,16
+** 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 00000000000..7272f98acbb
--- /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/t-softfp-tf
b/libgcc/config/loongarch/t-softfp-tf
index 306677b1255..be2b7302941 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
--
2.34.1