RISC-V: Add support for _BitInt [PR117581]

This patch implements _BitInt support for RISC-V target by defining the
type layout and ABI requirements.  The limb mode selection is based on
the bit width, using appropriate integer modes from QImode to TImode.
The implementation also adds the necessary libgcc version symbols for
_BitInt runtime support functions.

Changes in v3:
- Require sync_char_short effective target for bitint-64.c, bitint-82.c
  and bitint-84.c tests since they use atomic operations.
- Add -fno-section-anchors to bitint-32-on-rv64.c and adjust expected
  assembly output patterns.

Changes in v2:
- limb_mode use up to XLEN when N > XLEN, which is different setting from
  the abi_limb_mode.
- Adding missing floatbitinthf in libgcc.

gcc/ChangeLog:

	PR target/117581
	* config/riscv/riscv.cc (riscv_bitint_type_info): New function.
	(TARGET_C_BITINT_TYPE_INFO): Define.

gcc/testsuite/ChangeLog:

	PR target/117581
	* gcc.dg/torture/bitint-64.c: Add sync_char_short effective target
	requirement.
	* gcc.dg/torture/bitint-82.c: Likewise.
	* gcc.dg/torture/bitint-84.c: Likewise.
	* gcc.target/riscv/bitint-32-on-rv64.c: New test.
	* gcc.target/riscv/bitint-alignments.c: New test.
	* gcc.target/riscv/bitint-args.c: New test.
	* gcc.target/riscv/bitint-sizes.c: New test.

libgcc/ChangeLog:

	PR target/117581
	* config/riscv/libgcc-riscv.ver: New file.
	* config/riscv/t-elf (SHLIB_MAPFILES): Add libgcc-riscv.ver.
	* config/riscv/t-softfp32 (softfp_extras): Add floatbitinttf and
	fixtfbitint.
This commit is contained in:
Kito Cheng
2026-01-12 21:31:11 +08:00
parent e6470a44a2
commit 808b684172
11 changed files with 326 additions and 1 deletions

View File

@@ -14786,6 +14786,37 @@ riscv_c_mode_for_floating_type (enum tree_index ti)
return default_mode_for_floating_type (ti);
}
/* Implement TARGET_C_BITINT_TYPE_INFO.
Return true if _BitInt(N) is supported and fill its details into *INFO. */
bool
riscv_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 && TARGET_64BIT)
info->limb_mode = TImode;
else
info->limb_mode = TARGET_64BIT ? DImode : SImode;
info->abi_limb_mode = info->limb_mode;
if (n > 64 && TARGET_64BIT)
info->abi_limb_mode = TImode;
if (n > 32 && !TARGET_64BIT)
info->abi_limb_mode = DImode;
info->big_endian = TARGET_BIG_ENDIAN;
info->extended = true;
return true;
}
/* This parses the version string STR and modifies the feature mask and
priority required to select those targets.
If LOC is nonnull, report diagnostics against *LOC, otherwise
@@ -16773,6 +16804,9 @@ riscv_prefetch_offset_address_p (rtx x, machine_mode mode)
#undef TARGET_C_MODE_FOR_FLOATING_TYPE
#define TARGET_C_MODE_FOR_FLOATING_TYPE riscv_c_mode_for_floating_type
#undef TARGET_C_BITINT_TYPE_INFO
#define TARGET_C_BITINT_TYPE_INFO riscv_bitint_type_info
#undef TARGET_USE_BY_PIECES_INFRASTRUCTURE_P
#define TARGET_USE_BY_PIECES_INFRASTRUCTURE_P riscv_use_by_pieces_infrastructure_p

View File

@@ -1,5 +1,6 @@
/* PR middle-end/114332 */
/* { dg-do run { target bitint } } */
/* { dg-require-effective-target sync_char_short } */
/* { dg-options "-std=c23 -fwrapv" } */
/* { dg-skip-if "" { ! run_expensive_tests } { "*" } { "-O0" "-O2" } } */
/* { dg-skip-if "" { ! run_expensive_tests } { "-flto" } { "" } } */

View File

@@ -1,4 +1,5 @@
/* { dg-do run { target bitint } } */
/* { dg-require-effective-target sync_char_short } */
/* { dg-options "-std=c23 -pedantic-errors" } */
/* { dg-skip-if "" { ! run_expensive_tests } { "*" } { "-O0" "-O2" } } */
/* { dg-skip-if "" { ! run_expensive_tests } { "-flto" } { "" } } */

View File

@@ -1,5 +1,6 @@
/* A simple variant of gcc.dg/torture/bitint-64.c */
/* { dg-do run { target bitint } } */
/* { dg-require-effective-target sync_char_short } */
/* { dg-options "-std=c23" } */
/* { dg-skip-if "" { ! run_expensive_tests } { "*" } { "-O0" "-O2" } } */
/* { dg-skip-if "" { ! run_expensive_tests } { "-flto" } { "" } } */

View File

@@ -0,0 +1,47 @@
/* { dg-do compile { target bitint } } */
/* { dg-additional-options "-march=rv64gc -mabi=lp64d -std=c23 -O -fno-stack-clash-protection -g -fpie -mcmodel=medlow -fno-section-anchors" } */
/* { dg-skip-if "" { *-*-* } { "-flto" "-O0"} } */
/* { dg-final { check-function-bodies "**" "" } } */
signed _BitInt(32) a;
unsigned _BitInt(32) b;
signed _BitInt(16) c;
unsigned _BitInt(16) d;
signed _BitInt(32) f1(void) {
/*
** f1:
** ...
** lw a0,a
** ret
*/
return a;
}
unsigned _BitInt(32) f2(void) {
/*
** f2:
** ...
** lw a0,b
** ret
*/
return b;
}
signed _BitInt(16) f3(void) {
/*
** f3:
** ...
** lh a0,c
** ret
*/
return c;
}
unsigned _BitInt(16) f4(void) {
/*
** f4:
** ...
** lhu a0,d
** ret
*/
return d;
}

View File

@@ -0,0 +1,60 @@
/* { dg-do run { target bitint } } */
/* { dg-additional-options "-std=c23" } */
static long unsigned int
calc_alignof (int n)
{
#if __riscv_xlen == 64
if (n > 64)
return alignof(__int128_t);
#endif
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);
}

View File

@@ -0,0 +1,82 @@
/* { dg-do compile { target bitint } } */
/* { dg-additional-options "-march=rv64gc -mabi=lp64d -std=c23 -O -fno-stack-clash-protection -g" } */
/* { dg-skip-if "" { *-*-* } { "-flto" "-O0"} } */
/* { dg-final { check-function-bodies "**" "" } } */
#define CHECK_ARG(N) \
void f##N(_BitInt(N) *ptr, _BitInt(N) y) \
{ \
*ptr = y; \
}
CHECK_ARG(2)
/*
** f2:
** sb a1,0\(a0\)
** ret
*/
CHECK_ARG(8)
/*
** f8:
** sb a1,0\(a0\)
** ret
*/
CHECK_ARG(9)
/*
** f9:
** sh a1,0\(a0\)
** ret
*/
CHECK_ARG(16)
/*
** f16:
** sh a1,0\(a0\)
** ret
*/
CHECK_ARG(19)
/*
** f19:
** sw a1,0\(a0\)
** ret
*/
CHECK_ARG(32)
/*
** f32:
** sw a1,0\(a0\)
** ret
*/
CHECK_ARG(42)
/*
** f42:
** sd a1,0\(a0\)
** ret
*/
CHECK_ARG(64)
/*
** f64:
** sd a1,0\(a0\)
** ret
*/
CHECK_ARG(65)
/*
** f65:
** sd a1,0\(a0\)
** sd a2,8\(a0\)
** ret
*/
CHECK_ARG(127)
/*
** f127:
** sd a1,0\(a0\)
** sd a2,8\(a0\)
** ret
*/
CHECK_ARG(128)
/*
** f128:
** sd a1,0\(a0\)
** sd a2,8\(a0\)
** ret
*/

View File

@@ -0,0 +1,65 @@
/* { dg-do run { target bitint } } */
/* { dg-additional-options "-std=c23" } */
static long unsigned int
calc_size (int n)
{
#if __riscv_xlen == 64
if (n > 128)
return ((n - 1)/128 + 1) * sizeof(__int128_t);
if (n > 64)
return sizeof(__int128_t);
#elif __riscv_xlen == 32
if (n > 64)
return ((n - 1)/64 + 1) * sizeof(long long);
#endif
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);
}

View File

@@ -0,0 +1,29 @@
# 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
__floatbitinthf
__floatbitintsf
__floatbitintdf
__floatbitinttf
}

View File

@@ -7,3 +7,5 @@ LIB2ADD += $(srcdir)/config/riscv/save-restore.S \
# Avoid the full unwinder being pulled along with the division libcalls.
LIB2_DIVMOD_EXCEPTION_FLAGS := -fasynchronous-unwind-tables
SHLIB_MAPFILES += $(srcdir)/config/riscv/libgcc-riscv.ver

View File

@@ -34,6 +34,8 @@ endif
endif
softfp_extras += floatbitinttf fixtfbitint
else
# ABI_QUAD
@@ -49,4 +51,5 @@ softfp_truncations += tfhf dfhf sfhf \
hfbf bfhf
softfp_extras += fixhfsi fixhfdi fixunshfsi fixunshfdi \
floatsihf floatdihf floatunsihf floatundihf \
floatsibf floatdibf floatunsibf floatundibf
floatsibf floatdibf floatunsibf floatundibf \
floatbitinthf