https://gcc.gnu.org/bugzilla/show_bug.cgi?id=102989
--- Comment #45 from Jakub Jelinek <jakub at gcc dot gnu.org> --- Let's consider some simple testcase (where one doesn't really mix different _BitInt sizes etc.). _BitInt(512) foo (_BitInt(512) a, _BitInt(512) b, _BitInt(512) c, _BitInt(512) d) { return (a + b) - (c + d); } With the patch, this now ICEs during expansion, because while we can handle copying of even the larger _BitInt vars, we don't handle (nor plan to) +/- etc. during expansion for that, it would be in the earlier lowering pass. If I'd emit straight line code here, I suppose I could use BIT_FIELD_REFs/BIT_INSERT_EXPRs, but if I want loopy code, as you wrote perhaps ARRAY_REF on VCE could work fine for the input operands, but dunno what to use for the result of the operation, forcing it into a VAR_DECL I'm afraid will mean we can't coalesce it much, the above would force the 2 + results and 1 - result into VAR_DECLs. Could we e.g. allow BIT_INSERT_EXPRs or have some new ref for this purpose to update a single limb in a BITTYPE_INT SSA_NAME? Now, looking what we do right now, detailed expand dump before emergency dump shows: Partition map Partition 0 (_1 - 1 ) Partition 1 (_2 - 2 ) Partition 2 (_3 - 3 ) Partition 3 (a_4(D) - 4 ) Partition 4 (b_5(D) - 5 ) Partition 5 (c_6(D) - 6 ) Partition 6 (d_7(D) - 7 ) which I believe means it didn't actually coalesce anything at all. For the larger BITINT_TYPEs it will be very much desirable to coalesce as much as possible, given that none of the default def SSA_NAMEs are really use I'd think ideally we'd do a += b c += d result = a - c For at least multiplication/division and I assume conversions to/from floating point (and decimal), we'll need some library calls. One question is what ABI to use for them, whether to e.g. pass pointer to the limbs (and when -fbuilding-libgcc predefine macros on what mode is the limb mode, whether the limbs are ordered from least significant to most or vice versa, etc.) and in addition to that precision in bits for each argument and whether it is zero or sign extended from that, so that we could e.g. handle more efficiently _BitInt(16384) foo (unsigned _BitInt(2048) a, _BitInt(1024) b) { return (_BitInt(16384) a) * b; } by passing e.g. _mulwhatever (&res, 16384, &a, 2048, &b, -1024) where -1024 would mean 1024 bits sign extended, 2048 2048 bits zero extended, result is 16384 bits. And for GIMPLE a question is how to express it before expansion, whether we use some ifn that is then lowered.