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