public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
From: Richard Sandiford <richard.sandiford@arm.com>
To: "Andre Vieira \(lists\)" <andre.simoesdiasvieira@arm.com>
Cc: Jakub Jelinek <jakub@redhat.com>,
	 gcc-patches@gcc.gnu.org,  kyrylo.tkachov@arm.com
Subject: Re: [PATCH 2/2] aarch64: Add support for _BitInt
Date: Thu, 07 Mar 2024 17:59:57 +0000	[thread overview]
Message-ID: <mptedclapnm.fsf@arm.com> (raw)
In-Reply-To: <88b9a1f0-b0e2-4c61-9f5e-4cb380fa9a7c@arm.com> (Andre Vieira's message of "Tue, 27 Feb 2024 13:40:09 +0000")

"Andre Vieira (lists)" <andre.simoesdiasvieira@arm.com> writes:
> Hey,
>
> Dropped the first patch and dealt with the comments above, hopefully I 
> didn't miss any this time.
>
> ----------------------------------
>
> This patch adds support for C23's _BitInt for the AArch64 port when 
> compiling
> for little endianness.  Big Endianness requires further target-agnostic
> support and we therefor disable it for now.
>
> gcc/ChangeLog:
>
> 	* config/aarch64/aarch64.cc (TARGET_C_BITINT_TYPE_INFO): Declare MACRO.
> 	(aarch64_bitint_type_info): New function.
> 	(aarch64_return_in_memory_1): Return large _BitInt's in memory.
> 	(aarch64_function_arg_alignment): Adapt to correctly return the ABI
> 	mandated alignment of _BitInt(N) where N > 128 as the alignment of
> 	TImode.
> 	(aarch64_composite_type_p): Return true for _BitInt(N), where N > 128.
>
> libgcc/ChangeLog:
>
> 	* config/aarch64/t-softfp (softfp_extras): Add floatbitinthf,
> 	floatbitintbf, floatbitinttf and fixtfbitint.
> 	* config/aarch64/libgcc-softfp.ver (GCC_14.0.0): Add __floatbitinthf,
> 	__floatbitintbf, __floatbitinttf and __fixtfbitint.
>
> gcc/testsuite/ChangeLog:
>
> 	* gcc.target/aarch64/bitint-alignments.c: New test.
> 	* gcc.target/aarch64/bitint-args.c: New test.
> 	* gcc.target/aarch64/bitint-sizes.c: New test.
>
>
> On 02/02/2024 14:46, Jakub Jelinek wrote:
>> On Thu, Jan 25, 2024 at 05:45:01PM +0000, Andre Vieira wrote:
>>> This patch adds support for C23's _BitInt for the AArch64 port when compiling
>>> for little endianness.  Big Endianness requires further target-agnostic
>>> support and we therefor disable it for now.
>>>
>>> gcc/ChangeLog:
>>>
>>> 	* config/aarch64/aarch64.cc (TARGET_C_BITINT_TYPE_INFO): Declare MACRO.
>>> 	(aarch64_bitint_type_info): New function.
>>> 	(aarch64_return_in_memory_1): Return large _BitInt's in memory.
>>> 	(aarch64_function_arg_alignment): Adapt to correctly return the ABI
>>> 	mandated alignment of _BitInt(N) where N > 128 as the alignment of
>>> 	TImode.
>>> 	(aarch64_composite_type_p): Return true for _BitInt(N), where N > 128.
>>>
>>> libgcc/ChangeLog:
>>>
>>> 	* config/aarch64/t-softfp: Add fixtfbitint, floatbitinttf and
>>> 	floatbitinthf to the softfp_extras variable to ensure the
>>> 	runtime support is available for _BitInt.
>> 
>> I think this lacks some config/aarch64/t-whatever.ver
>> additions.
>> See PR113700 for some more details.
>> We want the support routines for binary floating point <-> _BitInt
>> conversions in both libgcc.a and libgcc_s.so.1 and exported from the latter
>> too at GCC_14.0.0 symver, while decimal floating point <-> _BitInt solely in
>> libgcc.a (as with all the huge dfp/bid stuff).
>> 
>> 	Jakub
>> 
>
> diff --git a/gcc/config/aarch64/aarch64.cc b/gcc/config/aarch64/aarch64.cc
> index 16318bf925883ecedf9345e53fc0824a553b2747..9bd8d22f6edd9f6c77907ec383f9e8bf055cfb8b 100644
> --- a/gcc/config/aarch64/aarch64.cc
> +++ b/gcc/config/aarch64/aarch64.cc
> @@ -6583,6 +6583,7 @@ aarch64_return_in_memory_1 (const_tree type)
>    int count;
>  
>    if (!AGGREGATE_TYPE_P (type)
> +      && TREE_CODE (type) != BITINT_TYPE
>        && TREE_CODE (type) != COMPLEX_TYPE
>        && TREE_CODE (type) != VECTOR_TYPE)
>      /* Simple scalar types always returned in registers.  */
> @@ -21895,6 +21896,11 @@ aarch64_composite_type_p (const_tree type,
>    if (type && (AGGREGATE_TYPE_P (type) || TREE_CODE (type) == COMPLEX_TYPE))
>      return true;
>  
> +  if (type
> +      && TREE_CODE (type) == BITINT_TYPE
> +      && int_size_in_bytes (type) > 16)
> +    return true;
> +

Think I probably said this before, but for the record: I don't think
the above code has any practical effect, but I agree it's probably better
to include it for completeness.

>    if (mode == BLKmode
>        || GET_MODE_CLASS (mode) == MODE_COMPLEX_FLOAT
>        || GET_MODE_CLASS (mode) == MODE_COMPLEX_INT)
> @@ -28400,6 +28406,42 @@ aarch64_excess_precision (enum excess_precision_type type)
>    return FLT_EVAL_METHOD_UNPREDICTABLE;
>  }
>  
> +/* Implement TARGET_C_BITINT_TYPE_INFO.
> +   Return true if _BitInt(N) is supported and fill its details into *INFO.  */
> +bool
> +aarch64_bitint_type_info (int n, struct bitint_info *info)
> +{
> +  if (TARGET_BIG_END)
> +    return false;
> +
> +  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
> +    /* The AAPCS for AArch64 defines _BitInt(N > 128) as an array with
> +       type {signed,unsigned} __int128[M] where M*128 >= N.  However, to be
> +       able to use libgcc's implementation to support large _BitInt's we need
> +       to use a LIMB_MODE that is no larger than 'long long'.  This is why we
> +       use DImode for our internal LIMB_MODE and we define the ABI_LIMB_MODE to
> +       be TImode to ensure we are ABI compliant.  */
> +    info->limb_mode = DImode;
> +
> +  if (n > 128)
> +    info->abi_limb_mode = TImode;
> +  else
> +    info->abi_limb_mode = info->limb_mode;
> +  info->big_endian = TARGET_BIG_END;
> +  info->extended = false;
> +  return true;
> +}
> +
>  /* Implement TARGET_SCHED_CAN_SPECULATE_INSN.  Return true if INSN can be
>     scheduled for speculative execution.  Reject the long-running division
>     and square-root instructions.  */
> @@ -30524,6 +30566,9 @@ aarch64_run_selftests (void)
>  #undef TARGET_C_EXCESS_PRECISION
>  #define TARGET_C_EXCESS_PRECISION aarch64_excess_precision
>  
> +#undef TARGET_C_BITINT_TYPE_INFO
> +#define TARGET_C_BITINT_TYPE_INFO aarch64_bitint_type_info
> +
>  #undef  TARGET_EXPAND_BUILTIN
>  #define TARGET_EXPAND_BUILTIN aarch64_expand_builtin
>  

OK for code bits.  I've got some comments about the tests though:

> diff --git a/gcc/testsuite/gcc.target/aarch64/bitint-alignments.c b/gcc/testsuite/gcc.target/aarch64/bitint-alignments.c
> new file mode 100644
> index 0000000000000000000000000000000000000000..4de31fe7ebd933247911c48ace01ab520fe194a3
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/aarch64/bitint-alignments.c
> @@ -0,0 +1,58 @@
> +/* { dg-do run } */
> +/* { dg-options "-std=c23" } */
> +
> +static long unsigned int
> +calc_size (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_size(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/aarch64/bitint-args.c b/gcc/testsuite/gcc.target/aarch64/bitint-args.c
> new file mode 100644
> index 0000000000000000000000000000000000000000..a6806ce609b3262c942e722918081ad466853910
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/aarch64/bitint-args.c
> @@ -0,0 +1,84 @@
> +/* { dg-do compile } */
> +/* { dg-options "-std=c23 -O -fno-stack-clash-protection -g" } */
> +/* { dg-final { check-function-bodies "**" "" } } */
> +
> +#define CHECK_ARG(N)		\
> +_BitInt(N) g##N;		\
> +void f##N(int x, _BitInt(N) y)	\
> +{				\
> +    g##N = y;			\
> +}
> +
> +
> +CHECK_ARG(2)
> +/*
> +** f2:
> +**	sbfiz	w1, w1, 6, 2
> +**	asr	w1, w1, 6
> +**	adrp	x0, .*
> +**	strb	w1, \[x0, [^\]]*\]
> +**	ret

There's no requirement for w1 or x0 to be used as the temporaries,
so everything except the incoming w1 should be escaped and captured.  E.g.:

> +**	sbfiz	(w[0-9]+), w1, 6, 2
> +**	asr	(w[0-9]+), \1, 6
> +**	adrp	(x[0-9]+), .*
> +**	strb	\2, \[\3, [^\]]*\]
> +**	ret

FWIW, passing a pointer a _BitInt(N) instead of x would avoid the need
for the adrp, and so make the tests more robust against code order.  E.g.:

void f##N(_BitInt(N) *ptr, _BitInt(N) y) \
{				\
    *ptr = y;			\
}

could be matched by:

> +**	sbfiz	(w[0-9]+), w1, 6, 2
> +**	asr	(w[0-9]+), \1, 6
> +**	strb	\2, \[x0\]
> +**	ret

Do you know why we don't use a single SBFX?  Probably worth filing a PR
if we don't have one already.

> +*/
> +CHECK_ARG(8)
> +/*
> +** f8:
> +**	adrp	x0, .*
> +**	strb	w1, \[x0, [^\]]*\]
> +**	ret
> +*/
> +CHECK_ARG(9)
> +/*
> +** f9:
> +**	sbfiz	w1, w1, 7, 9
> +**	asr	w1, w1, 7
> +**	adrp	x0, .*
> +**	strh	w1, \[x0, [^\]]*\]
> +**	ret
> +*/
> +CHECK_ARG(16)
> +/*
> +** f16:
> +**	adrp	x0, .*
> +**	strh	w1, \[x0, [^\]]*\]
> +**	ret
> +*/
> +CHECK_ARG(19)
> +/*
> +** f19:
> +**	sbfx	x1, x1, 0, 19
> +**	adrp	x0, .*
> +**	str	w1, \[x0, [^\]]*\]
> +**	ret
> +*/
> +CHECK_ARG(32)
> +/*
> +** f32:
> +**	adrp	x0, .*
> +**	str	w1, \[x0, [^\]]*\]
> +**	ret
> +*/
> +CHECK_ARG(42)
> +/*
> +** f42:
> +**	sbfx	x1, x1, 0, 42
> +**	adrp	x0, .*
> +**	str	x1, \[x0, [^\]]*\]
> +**	ret
> +*/
> +CHECK_ARG(64)
> +/*
> +** f64:
> +**	adrp	x0, .*
> +**	str	x1, \[x0, [^\]]*\]
> +**	ret
> +*/
> +CHECK_ARG(65)
> +/*
> +** f65:
> +**	extr	x3, x3, x2, 1
> +**	asr	x3, x3, 63
> +**	adrp	x0, .*
> +**	add	x0, x0, .*
> +**	stp	x2, x3, \[x0, [^\]]*\]
> +**	ret
> +*/

Can you add tests for 127, 128 and 129 too?

I think we should also have ABI tests for more exotic combinations, such as:

struct S1 {
    _BitInt(120) x1 : 120;
    _BitInt(8) x2 : 8;
};

struct S2 {
    _BitInt(120) x1 : 120;
    _BitInt(8) x2 : 8;
};

struct S3 {
    _BitInt(125) x1 : 63;
    unsigned _BitInt(125) x2 : 62;
};

struct S4 {
    _BitInt(5) x1 : 5;
    __attribute__((packed, aligned(2))) _BitInt(300) x2;
};

etc.

It'd also be good to have a version of
gcc.target/aarch64/bitfield-abi-warning.* that tests _BitInts rather
than plain integers --- not for the warning as such (which I guess we
shouldn't emit), but for the code generation.  It took Christophe and I
a lot of effort to untangle the brokenness captured in those tests, so
it would be good to preempt something similar happening here :)

It's also be good to make sure that the alignment on things like:

typedef _BitInt(100) bi1 __attribute__((aligned(1)));
typedef _BitInt(8) bi2 __attribute__((aligned(16)));

do not change how bi1 and bi2 are passed (which might be partly
covered by the bitfield warning tests, can't remember).

Thanks,
Richard

> diff --git a/gcc/testsuite/gcc.target/aarch64/bitint-sizes.c b/gcc/testsuite/gcc.target/aarch64/bitint-sizes.c
> new file mode 100644
> index 0000000000000000000000000000000000000000..bee9abfe91b0dcb1ec335ef9ed02f212f7aa34b7
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/aarch64/bitint-sizes.c
> @@ -0,0 +1,60 @@
> +/* { dg-do run } */
> +/* { dg-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/aarch64/libgcc-softfp.ver b/libgcc/config/aarch64/libgcc-softfp.ver
> index e73f5f9129776d39eb5020ed7398dc59aba2d197..9ba857036abef99913eebe56971eaaabf5e1952e 100644
> --- a/libgcc/config/aarch64/libgcc-softfp.ver
> +++ b/libgcc/config/aarch64/libgcc-softfp.ver
> @@ -39,3 +39,11 @@ GCC_13.0.0 {
>    __trunctfbf2
>    __trunchfbf2
>  }
> +
> +%inherit GCC_14.0.0 GCC_13.0.0
> +GCC_14.0.0 {
> +  __fixtfbitint
> +  __floatbitintbf
> +  __floatbitinthf
> +  __floatbitinttf
> +}
> diff --git a/libgcc/config/aarch64/t-softfp b/libgcc/config/aarch64/t-softfp
> index 2e32366f891361e2056c680b2e36edb1871c7670..80e7e77a545cc10eeccd84eea092871751c3e139 100644
> --- a/libgcc/config/aarch64/t-softfp
> +++ b/libgcc/config/aarch64/t-softfp
> @@ -4,7 +4,8 @@ softfp_extensions := sftf dftf hftf bfsf
>  softfp_truncations := tfsf tfdf tfhf tfbf dfbf sfbf hfbf
>  softfp_exclude_libgcc2 := n
>  softfp_extras += fixhfti fixunshfti floattihf floatuntihf \
> -		 floatdibf floatundibf floattibf floatuntibf
> +		 floatdibf floatundibf floattibf floatuntibf \
> +		 floatbitinthf floatbitintbf floatbitinttf fixtfbitint
>  
>  TARGET_LIBGCC2_CFLAGS += -Wno-missing-prototypes
>  

  parent reply	other threads:[~2024-03-07 18:00 UTC|newest]

Thread overview: 20+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-01-25 17:44 [PATCH 0/2] aarch64, bitint: Add support for _BitInt for AArch64 Little Endian Andre Vieira
2024-01-25 17:45 ` [PATCH 1/2] bitint: Use TARGET_ARRAY_MODE for large bitints where target supports it Andre Vieira
2024-02-02 15:18   ` Jakub Jelinek
2024-01-25 17:45 ` [PATCH 2/2] aarch64: Add support for _BitInt Andre Vieira
2024-01-25 19:40   ` Richard Sandiford
2024-02-02 14:46   ` Jakub Jelinek
2024-02-27 13:40     ` Andre Vieira (lists)
2024-02-28 11:19       ` Jakub Jelinek
2024-03-07 17:59       ` Richard Sandiford [this message]
2024-03-27 18:24 ` [PATCHv2 0/2] aarch64, bitint: Add support for _BitInt for AArch64 Little Endian Andre Vieira (lists)
2024-03-27 18:29   ` [PATCHv2 1/2] aarch64: Do not give ABI change diagnostics for _BitInt(N) Andre Vieira (lists)
2024-03-28 12:54     ` Richard Sandiford
2024-04-10  9:16       ` Andre Vieira (lists)
2024-04-10 10:24         ` Richard Sandiford
2024-03-27 18:31   ` [PATCHv2 2/2] aarch64: Add support for _BitInt Andre Vieira (lists)
2024-03-28 15:00     ` Richard Sandiford
2024-03-28 15:03       ` Jakub Jelinek
2024-03-28 15:21         ` Richard Sandiford
2024-04-10  9:17           ` [PATCHv3 " Andre Vieira (lists)
2024-04-10 10:27             ` Richard Sandiford

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=mptedclapnm.fsf@arm.com \
    --to=richard.sandiford@arm.com \
    --cc=andre.simoesdiasvieira@arm.com \
    --cc=gcc-patches@gcc.gnu.org \
    --cc=jakub@redhat.com \
    --cc=kyrylo.tkachov@arm.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).