-
Notifications
You must be signed in to change notification settings - Fork 179
ABI for _BitInt #419
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
ABI for _BitInt #419
Conversation
|
Plan to putting more table for the code gen among 3 different options, I was too optimistic that I could have time to doing that...:( anyway will put that once I have one. |
|
I just realized I didn't have enough bandwidth on this, so I asked my colleague @BeMg to help on this. We plan to did few more comparison and analysis for moving this forward. |
|
Here is a comparison of three strategies for how to deal with unused bits for bitInt:
This table shows the number of instructions for common operations between different strategies.
And the following table shows the number of instructions for each operation.
Also, here is the doc that includes the detailed assembly and the C source code for reference. cc @kito-cheng |
What if we use sign-extend strategy for signed BitInts and zero-extend strategy for unsigned BitInts as suggested here #419 (comment) This would match what we do for uint16_t/uint8_t/int16_t/uint16_t. That should give the shortest sequence for shift_right, div, mod, and compares. |
|
Updated with more combination code generation results There are four kinds of configurations for BitInt with three different ABI policies: And here is the table summarizing the number of assembly instructions
The details of the sheet can be found here cc @kito-cheng |
Update: Add mix type extend BitInt(65)
And detail instruction count sheet |
|
According to @BeMg's experiments, doing the same kind of extension as the original data type gives the best code gen performance, so I'm prefer that. The only issue is that BitInt(32) on RV64 wouldn’t match the behavior of a normal unsigned/uint32_t. and there are two options:
Let me know if anyone has any preferecne or comment, otherwise we will decide that in next psABI meeting and moving forward :) |
|
Here is an example implementation for four different styles. |
|
It was raised at the psabi tg that special casing N=32 might make the libgcc/compiler-rt implementations more difficult, as they would need to be implemented differently. I asked whether there were separate implementations for different N, or a shared implementation. According to the docs, it seems the answer is there is a shared implementation: https://gcc.gnu.org/onlinedocs/gccint/Integer-library-routines.html#Bit-precise-integer-arithmetic-functions This also does not use the conventional ABI, it uses a buffer+length encoding, which avoids the "does this fit into a register" questions usually present. We probably still need to agree on |
|
Changes:
|
|
Changes:
|
|
Also some survey on GCC implementation:
|
|
Where are you testing _BitInt for s390x? I can't get it to work on godbolt.org, so I'm not sure where you're getting the information that it orders the chunks from most to least significant. Is that only in trunk or something? |
|
As for which makes more sense, least to most significant is the sensible ordering for the chunks, as if you're doing, say, addition, you need to iterate from least to most significant chunk, no? |
|
Am 9. Oktober 2025 19:50:04 MESZ schrieb Jessica Clarke ***@***.***>:
jrtc27 left a comment (riscv-non-isa/riscv-elf-psabi-doc#419)
As for which makes more sense, least to most significant is the sensible ordering for the chunks, as if you're doing, say, addition, you need to iterate from least to most significant chunk, no?
Loops with decrements are trivial.
If you order the bytes in native sequence, you don't have to worry about chunk sizes at all.
Data stored by as 32-bit chunks will be ordered in the same sequence as when using 128-bit chunks. This makes storage to file easy.
Best regards
Heinrich
|
Implement riscv-non-isa/riscv-elf-psabi-doc#419. This patch makes the type extension based on the variable type for BIGINT, rather than using sign extension for all cases.
Implement riscv-non-isa/riscv-elf-psabi-doc#419. This patch makes the type extension based on the variable type for BIGINT, rather than using sign extension for all cases.
Implement riscv-non-isa/riscv-elf-psabi-doc#419. This patch makes the type extension based on the variable type for BIGINT, rather than using sign extension for all cases.
`_BitInt (N)` is the type defined in C23, allow user to define an arbitrary-sized integer type, where N is a postive integer larger than zero. This proposal defined the size and alignment of _BitInt, and define the unused bits as unspecified which is same as x86-64 and AArch64. For the calling convention part, we keep unused bits as unspecified. Ref: - ISO/IEC WG14 N2763: https://www.open-std.org/jtc1/sc22/wg14/www/docs/n2763.pdf - [AArch64] Rationale Document for ABI related to the C23 _BitInt type. https://github.com/ARM-software/abi-aa/tree/main/design-documents/bit-precise-types.rst - AAPCS64 for _BitInt(N) ARM-software/abi-aa@d621417 - x86-64 ABI for _BitInt(N) https://gitlab.com/x86-psABIs/x86-64-ABI/-/commit/8ca45392570e96920f8a15d903d6122f6d263cd0 Fix #300
Changed _BitInt(N) unused bits from undefined to use sign/zero extension based on the type's signedness. This makes the behavior more predictable and consistent with the type semantics. - Signed _BitInt(N): unused bits are sign-extended - Unsigned _BitInt(N): unused bits are zero-extended - Added note clarifying that _BitInt defaults to signed per C spec - Clarified passing rules for different sized _BitInt types
Updated _BitInt(N) endianness rules to be more precise: - N ≤ 2×XLEN: follows standard scalar endianness - N > 2×XLEN: divided into 2×XLEN chunks, each chunk follows scalar endianness, but chunks are always stored lower-first regardless of system endianness
- Clarify that little-endian chunk ordering is specified explicitly - Move big-endian behavior to a separate NOTE section - Document that big-endian ABI is experimental and may change
- Chunk ordering now follows system endianness consistently - Little-endian: lower-addressed chunks contain less significant bits - Big-endian: lower-addressed chunks contain more significant bits - Retain note that big-endian ABI is experimental
|
Changes:
|
_BitInt (N)is the type defined in C23, allow user to define an arbitrary-sized integer type, where N is a postive integer larger than zero.This proposal defined the size and alignment of _BitInt, and define the unused bits as unspecified which is same as x86-64 and AArch64.
For the calling convention part, we keep unused bits as unspecified.
Ref:
ISO/IEC WG14 N2763: https://www.open-std.org/jtc1/sc22/wg14/www/docs/n2763.pdf
[AArch64] Rationale Document for ABI related to the C23 _BitInt type. https://github.com/ARM-software/abi-aa/tree/main/design-documents/bit-precise-types.rst
AAPCS64 for _BitInt(N) ARM-software/abi-aa@d621417
x86-64 ABI for _BitInt(N) https://gitlab.com/x86-psABIs/x86-64-ABI/-/commit/8ca45392570e96920f8a15d903d6122f6d263cd0
Fix #300