Jakub, Thanks for the helpful explanation! I wanted to add some perspective on the ABI side.
Setting the abi_limb_mode to 2 * XLEN is primarily for compatibility with existing ABI rules, where 2 * XLEN is passed via registers. For the parts exceeding that, they become an array of 2 * XLEN bit elements. This is a consideration for RV32 having Zilsd, and while RV64 doesn't support it yet, it might in the future. Jakub Jelinek <[email protected]> 於 2026年1月10日週六 上午6:09寫道: > > On Thu, Jan 08, 2026 at 08:50:35AM -0700, Jeffrey Law wrote: > > > +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; > > So I've never looked at how BitInt works, so if this is totally off-base > > just say so ;-) > > > > It seems a bit odd to have the limb_mode by DImode for rv32 when we don't > > have any DImode operations in rv32. Though we allow TImode for rv64, so > > perhaps we're just relying on widening capabilities in the expander > > interfaces under the hood? > > > > It also seems a bit odd that for n > 128 and TARGET_64BIT that we select > > DImode when we use TImode for sizes > 64, but <= 128. Similarly for > > !TARGET_64BIT we have SImode and DImode respectively. > > It depends on what the psABI says (if it says anything at all). > What Kito posted is quite usual thing (except for the abi_limb_mode != > limb_mode && extended = true case which still needs to have a few spots > in the generic handling tweaked (like for arm32). > > The above with that > + 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; > after it means that for TARGET_64BIT, up to _BitInt(128) those > are passed and handled like char/short/int/long long/__int128 (or unsigned > versions thereof) and for _BitInt(129) and above it is handled as > structure containing array of __int128 elements for passing/alignment, > but code emitted by compiler and libgcc handles it as array of long long > elements. > And similarly for !TARGET_64BIT ditto except the boundary is _BitInt(64) > and instead of __int128 in the above it is long long and instead of long > long elements int elements. > So, it will use 2 words only for the _BitInt(65) to _BitInt(128) > case (resp. _BitInt(33) to _BitInt(64)) and for larger stuff it will > use initially straight line code, then loops working on word-sized elements. > > Jakub >
