On Thu, 14 Dec 2023, Jakub Jelinek wrote: > Hi! > > Given what I saw in the aarch64/arm psABIs for BITINT_TYPE, as I said > earlier I'm afraid we need to differentiate between the limb mode/precision > specified in the psABIs (what is used to decide how it is actually passed, > aligned or what size it has) vs. what limb mode/precision should be used > during bitint lowering and in the libgcc bitint APIs. > While in the x86_64 psABI a limb is 64-bit, which is perfect for both, > that is a wordsize which we can perform operations natively in, > e.g. aarch64 wants 128-bit limbs for alignment/sizing purposes, but > on the bitint lowering side I believe it would result in terribly bad code > and on the libgcc side wouldn't work at all (because it relies there on > longlong.h support). > > So, the following patch makes it possible for aarch64 to use TImode > as abi_limb_mode for _BitInt(129) and larger, while using DImode as > limb_mode. > > Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?
OK. Thanks, Richard. > 2023-12-14 Jakub Jelinek <ja...@redhat.com> > > * target.h (struct bitint_info): Add abi_limb_mode member, adjust > comment. > * target.def (bitint_type_info): Mention abi_limb_mode instead of > limb_mode. > * varasm.cc (output_constant): Use abi_limb_mode rather than > limb_mode. > * stor-layout.cc (finish_bitfield_representative): Likewise. Assert > that if precision is smaller or equal to abi_limb_mode precision or > if info.big_endian is different from WORDS_BIG_ENDIAN, info.limb_mode > must be the same as info.abi_limb_mode. > (layout_type): Use abi_limb_mode rather than limb_mode. > * gimple-fold.cc (clear_padding_bitint_needs_padding_p): Likewise. > (clear_padding_type): Likewise. > * config/i386/i386.cc (ix86_bitint_type_info): Also set > info->abi_limb_mode. > * doc/tm.texi: Regenerated. > > --- gcc/target.h.jj 2023-09-06 17:28:24.228977486 +0200 > +++ gcc/target.h 2023-12-14 14:26:48.490047206 +0100 > @@ -69,15 +69,23 @@ union cumulative_args_t { void *p; }; > #endif /* !CHECKING_P */ > > /* Target properties of _BitInt(N) type. _BitInt(N) is to be represented > - as series of limb_mode CEIL (N, GET_MODE_PRECISION (limb_mode)) limbs, > - ordered from least significant to most significant if !big_endian, > + as series of abi_limb_mode CEIL (N, GET_MODE_PRECISION (abi_limb_mode)) > + limbs, ordered from least significant to most significant if !big_endian, > otherwise from most significant to least significant. If extended is > false, the bits above or equal to N are undefined when stored in a > register > or memory, otherwise they are zero or sign extended depending on if > - it is unsigned _BitInt(N) or _BitInt(N) / signed _BitInt(N). */ > + it is unsigned _BitInt(N) or _BitInt(N) / signed _BitInt(N). > + limb_mode is either the same as abi_limb_mode, or some narrower mode > + in which _BitInt lowering should actually perform operations in and > + what libgcc _BitInt helpers should use. > + E.g. abi_limb_mode could be TImode which is something some processor > + specific ABI would specify to use, but it would be desirable to handle > + it as an array of DImode instead for efficiency. > + Note, abi_limb_mode can be different from limb_mode only if big_endian > + matches WORDS_BIG_ENDIAN. */ > > struct bitint_info { > - machine_mode limb_mode; > + machine_mode abi_limb_mode, limb_mode; > bool big_endian; > bool extended; > }; > --- gcc/target.def.jj 2023-12-08 08:28:23.644171016 +0100 > +++ gcc/target.def 2023-12-14 14:27:25.239537794 +0100 > @@ -6357,8 +6357,8 @@ DEFHOOK > (bitint_type_info, > "This target hook returns true if @code{_BitInt(@var{N})} is supported > and\n\ > provides details on it. @code{_BitInt(@var{N})} is to be represented as\n\ > -series of @code{info->limb_mode}\n\ > -@code{CEIL (@var{N}, GET_MODE_PRECISION (info->limb_mode))} limbs,\n\ > +series of @code{info->abi_limb_mode}\n\ > +@code{CEIL (@var{N}, GET_MODE_PRECISION (info->abi_limb_mode))} limbs,\n\ > ordered from least significant to most significant if\n\ > @code{!info->big_endian}, otherwise from most significant to least\n\ > significant. If @code{info->extended} is false, the bits above or equal > to\n\ > --- gcc/varasm.cc.jj 2023-12-01 08:10:44.504299177 +0100 > +++ gcc/varasm.cc 2023-12-14 14:55:45.821971713 +0100 > @@ -5315,7 +5315,8 @@ output_constant (tree exp, unsigned HOST > tree type = TREE_TYPE (exp); > bool ok = targetm.c.bitint_type_info (TYPE_PRECISION (type), &info); > gcc_assert (ok); > - scalar_int_mode limb_mode = as_a <scalar_int_mode> (info.limb_mode); > + scalar_int_mode limb_mode > + = as_a <scalar_int_mode> (info.abi_limb_mode); > if (TYPE_PRECISION (type) <= GET_MODE_PRECISION (limb_mode)) > { > cst = expand_expr (exp, NULL_RTX, VOIDmode, EXPAND_INITIALIZER); > --- gcc/stor-layout.cc.jj 2023-10-08 16:37:31.780273377 +0200 > +++ gcc/stor-layout.cc 2023-12-14 14:59:27.147904721 +0100 > @@ -2154,7 +2154,8 @@ finish_bitfield_representative (tree rep > unsigned prec = TYPE_PRECISION (TREE_TYPE (field)); > bool ok = targetm.c.bitint_type_info (prec, &info); > gcc_assert (ok); > - scalar_int_mode limb_mode = as_a <scalar_int_mode> (info.limb_mode); > + scalar_int_mode limb_mode > + = as_a <scalar_int_mode> (info.abi_limb_mode); > unsigned lprec = GET_MODE_PRECISION (limb_mode); > if (prec > lprec) > { > @@ -2416,16 +2417,20 @@ layout_type (tree type) > int cnt; > bool ok = targetm.c.bitint_type_info (TYPE_PRECISION (type), &info); > gcc_assert (ok); > - scalar_int_mode limb_mode = as_a <scalar_int_mode> (info.limb_mode); > + scalar_int_mode limb_mode > + = as_a <scalar_int_mode> (info.abi_limb_mode); > if (TYPE_PRECISION (type) <= GET_MODE_PRECISION (limb_mode)) > { > SET_TYPE_MODE (type, limb_mode); > + gcc_assert (info.abi_limb_mode == info.limb_mode); > cnt = 1; > } > else > { > SET_TYPE_MODE (type, BLKmode); > cnt = CEIL (TYPE_PRECISION (type), GET_MODE_PRECISION (limb_mode)); > + gcc_assert (info.abi_limb_mode == info.limb_mode > + || !info.big_endian == !WORDS_BIG_ENDIAN); > } > TYPE_SIZE (type) = bitsize_int (cnt * GET_MODE_BITSIZE (limb_mode)); > TYPE_SIZE_UNIT (type) = size_int (cnt * GET_MODE_SIZE (limb_mode)); > --- gcc/gimple-fold.cc.jj 2023-11-30 20:43:32.273640149 +0100 > +++ gcc/gimple-fold.cc 2023-12-14 14:52:13.363915817 +0100 > @@ -4604,7 +4604,7 @@ clear_padding_bitint_needs_padding_p (tr > gcc_assert (ok); > if (info.extended) > return false; > - scalar_int_mode limb_mode = as_a <scalar_int_mode> (info.limb_mode); > + scalar_int_mode limb_mode = as_a <scalar_int_mode> (info.abi_limb_mode); > if (TYPE_PRECISION (type) < GET_MODE_PRECISION (limb_mode)) > return true; > else if (TYPE_PRECISION (type) == GET_MODE_PRECISION (limb_mode)) > @@ -4881,7 +4881,8 @@ clear_padding_type (clear_padding_struct > struct bitint_info info; > bool ok = targetm.c.bitint_type_info (TYPE_PRECISION (type), &info); > gcc_assert (ok); > - scalar_int_mode limb_mode = as_a <scalar_int_mode> (info.limb_mode); > + scalar_int_mode limb_mode > + = as_a <scalar_int_mode> (info.abi_limb_mode); > if (TYPE_PRECISION (type) <= GET_MODE_PRECISION (limb_mode)) > { > gcc_assert ((size_t) sz <= clear_padding_unit); > --- gcc/config/i386/i386.cc.jj 2023-12-13 11:34:05.836511498 +0100 > +++ gcc/config/i386/i386.cc 2023-12-14 14:28:34.074583610 +0100 > @@ -25679,6 +25679,7 @@ ix86_bitint_type_info (int n, struct bit > info->limb_mode = SImode; > else > info->limb_mode = DImode; > + info->abi_limb_mode = info->limb_mode; > info->big_endian = false; > info->extended = false; > return true; > --- gcc/doc/tm.texi.jj 2023-12-08 08:28:23.520172768 +0100 > +++ gcc/doc/tm.texi 2023-12-14 14:58:12.643937150 +0100 > @@ -1032,8 +1032,8 @@ applied. > @deftypefn {Target Hook} bool TARGET_C_BITINT_TYPE_INFO (int @var{n}, struct > bitint_info *@var{info}) > This target hook returns true if @code{_BitInt(@var{N})} is supported and > provides details on it. @code{_BitInt(@var{N})} is to be represented as > -series of @code{info->limb_mode} > -@code{CEIL (@var{N}, GET_MODE_PRECISION (info->limb_mode))} limbs, > +series of @code{info->abi_limb_mode} > +@code{CEIL (@var{N}, GET_MODE_PRECISION (info->abi_limb_mode))} limbs, > ordered from least significant to most significant if > @code{!info->big_endian}, otherwise from most significant to least > significant. If @code{info->extended} is false, the bits above or equal to > > Jakub > > -- Richard Biener <rguent...@suse.de> SUSE Software Solutions Germany GmbH, Frankenstrasse 146, 90461 Nuernberg, Germany; GF: Ivo Totev, Andrew McDonald, Werner Knoblich; (HRB 36809, AG Nuernberg)