Hi!

I'd like to see in C2Y I/O support for _BitInt, so
something like
https://www.open-std.org/jtc1/sc22/wg14/www/docs/n2858.pdf
with obvious updates for the recent C2Y changes
(signed _BitInt(1) support).
Now, there are two obstackles in supporting say
  printf ("%wb575u\n", 
112041924188967982740577128258454371281147745286925175670933304406883025453800257407817937118400087623607194547157147451911301069533401837411803352174766773116684201492387419uwb);
or
  _BitInt(575) x;
  scanf ("%wb575d", &x);
One is a dependency of building the C library on a compiler
which supports _BitInt (with the right ABI), and another one
is that there are way too many different _BitInt types.
It is UB to use va_arg with a type which doesn't match the actually
passed types with a couple of exceptions.
If BITINT_MAXWIDTH is very small, say 64, one can just use next to
  if (is_ll)
    val = va_arg (ap, long long);
  else if (is_l)
    val = va_arg (ap, long);
  else if (is_i)
    val = va_arg (ap, int);
also
  else if (is_wb)
    switch (wb_val)
      {
#define V(N) case N: val = va_arg (ap, _BitInt(N)); break;
        V(1) V(2) V(3) V(4) V(5) V(6) V(7) V(8) V(9)
#define W(N) V(N##0) V(N##1) V(N##2) V(N##3) V(N##4) \
             V(N##5) V(N##6) V(N##7) V(N##8) V(N##9)
        W(1) W(2) W(3) W(4) W(5) V(60) V(61) V(62) V(63) V(64)
        default: whatever;
      }
but if BITINT_MAXWIDTH is 65535 as in GCC or 8388608 in Clang, this
doesn't really scale (not to mention that it is needed at least, twice,
once for signed _BitInt and once for unsigned _BitInt).

The following WIP patch attempts to deal with both of these problems.

The goal is to add 3 new type-generic builtins, where one can be used
in a new stdarg.h macro (or two), and the other ones in a few new
stdbit.h macros.  The former one would be something like
va_arg_bitint(va_list ap, size_t n, type *ptr, bool endian, bool uns)
or
va_arg_bitint_le(va_list ap, size_t n, type *ptr, bool uns)
va_arg_bitint_be(va_list ap, size_t n, type *ptr, bool uns)
where type is a standard or extended integer type other than bool, and
then in stdbit.h
stdc_store_bitint_le(const void *bitintptr, size_t n, type *ptr, bool uns)
stdc_store_bitint_be(const void *bitintptr, size_t n, type *ptr, bool uns)
stdc_load_bitint_le(void *bitintptr, size_t n, const type *ptr, bool uns)
stdc_load_bitint_be(void *bitintptr, size_t n, const type *ptr, bool uns)
The va_arg_bitint_le macro would work as if
  if (uns)
    switch (n)
      {
      case 1: stdc_store_bitint_le(&(_BitInt(1)){va_arg(ap, unsigned 
_BitInt(1))}, 1, ptr, uns); break;
      case 2: stdc_store_bitint_le(&(_BitInt(2)){va_arg(ap, unsigned 
_BitInt(2))}, 2, ptr, uns); break;
...
      case BITINT_MAXWIDTH: 
stdc_store_bitint_le(&(_BitInt(BITINT_MAXWIDTH)){va_arg(ap, unsigned 
_BitInt(BITINT_MAXWIDTH))}, BITINT_MAXWIDTH, ptr, uns); break;
      }
  else
    switch (n)
      {
      case 1: stdc_store_bitint_le(&(_BitInt(1)){va_arg(ap, _BitInt(1))}, 1, 
ptr, uns); break;
      case 2: stdc_store_bitint_le(&(_BitInt(2)){va_arg(ap, _BitInt(2))}, 2, 
ptr, uns); break;
...
      case BITINT_MAXWIDTH: 
stdc_store_bitint_le(&(_BitInt(BITINT_MAXWIDTH)){va_arg(ap, 
_BitInt(BITINT_MAXWIDTH))}, BITINT_MAXWIDTH, ptr, uns); break;
      }
so as if using va_arg with _BitInt(N) where n == N and invoking
stdc_store_bitint_le (or for _be _be) on it.
Let W be the width of the standard or extended integer type type.
The stdc_store_bitint_le macro would store to ptr[0] the least
significant W bits of the _BitInt(N) where n == N value, to ptr[1]
the W bits above that up to ptr[(n + W - 1) / W - 1], which would
get the most significant of _BitInt(N) pointed by bitintptr.  If
(n % W) != 0, with the remaining bits sign extended if !uns and
zero extended if uns.  The be variant with the different limb
ordering in the array.

And stdc_load_bitint_{l,b}e would do the reverse operation, intended
for scanf etc., where user pass as va_arg pointer to some _BitInt(N)
and we'd want to store there value from the sum of the limbs passed
to the macro.

This way, the C library (but also C users which want to implement
something similar in their code) can use these macros to easily
implement the vaargs _BitInt I/O support, and for the case where
the C library needs to be buildable by compilers which don't support
_BitInt yet or do support it, but don't support these macros/intrinsics yet,
one possibility is compile e.g.
[[gnu::noipa]] void
__libc_va_arg_bitint_le (va_list *ap, size_t n, unsigned long *ptr, bool uns)
{
  __builtin_va_arg_bitint (*ap, n, ptr, false, uns);
}
by a newer compiler into assembly and use that assembly file as fallback
if the compiler used to build libc doesn't support those.

The following patch is a WIP, __builtin_bitint_pack is not really
implemented, and __builtin_va_arg_bitint/__builtin_bitint_unpack
don't support avr/msp430 due to __int20/__int24 types (but those
don't support _BitInt yet so not an issue that needs immediate
solving) and one needs to write the target hook for __builtin_va_arg_bitint
(currently implemented just the generic version for char * va_list targets
and x86).

Thoughts on this?

2026-07-06  Jakub Jelinek  <[email protected]>

gcc/
        * builtin-types.def (BT_FN_VOID_PTR_VAR): New.
        * builtins.def (BUILT_IN_VA_ARG_BITINT,
        BUILT_IN_BITINT_UNPACK, BUILT_IN_BITINT_PACK): New builtins.
        * builtins.cc (fold_builtin_bitint_pack): New function.
        (fold_builtin_varargs): Use it for BUILT_IN_VA_ARG_BITINT,
        BUILT_IN_BITINT_UNPACK and BUILT_IN_BITINT_PACK.
        * target.def (gimplify_va_arg_expr): Tweak description and
        comment.
        (gimplify_va_arg_bitint): New target hook.
        * doc/tm.texi.in: Add TARGET_GIMPLIFY_VA_ARG_BITINT.
        * doc/tm.texi: Regenerate.
        * targhooks.h (std_gimplify_va_arg_bitint): Declare.
        * targhooks.cc (std_gimplify_va_arg_bitint): New function.
        * passes.def (pass_all_optimizations_g): Add pass_stdarg.
        * tree-stdarg.cc (expand_ifn_va_arg_1): Expand also
        BUILT_IN_VA_ARG_BITINT.  Fix comment typo, inbetween
        -> in between.
        (pass_stdarg::clone): New method.
        * gimplify.cc (gimplify_call_expr): Handle
        BUILT_IN_VA_ARG_BITINT, BUILT_IN_BITINT_UNPACK and
        BUILT_IN_BITINT_PACK.
        * function.h (struct function): Add has_bitint_pack bitfield.
        * tree-inline.cc (expand_call_inline): Or in has_bitint_pack.
        * gimple-lower-bitint.cc (struct bitint_large_huge): Declare
        add_mult and lower_pack_unpack methods.
        (bitint_large_huge::add_mult): New method.
        (bitint_large_huge::lower_pack_unpack): New method.
        (bitint_large_huge::lower_call): Handle
        BUILT_IN_BITINT_UNPACK and BUILT_IN_BITINT_PACK using
        lower_pack_unpack.
        (gimple_lower_bitint): Don't ignore functions with no
        _BitInt SSA_NAMEs if cfun->has_bitint_pack is set, arrange
        in that case for limb_prec etc. being computed.  Pretend
        BUILT_IN_BITINT_UNPACK and BUILT_IN_BITINT_PACK calls have
        kind bitint_prec_large.
        * lto-streamer-in.cc (input_struct_function_base): Stream in
        has_bitint_pack.
        * lto-streamer-out.cc (output_struct_function_base): Stream out
        has_bitint_pack.
        * config/i386/i386.cc (ix86_gimplify_va_arg_bitint): New function.
        (TARGET_GIMPLIFY_VA_ARG_BITINT): Redefine.
gcc/c-family/
        * c-common.cc (check_builtin_function_arguments): Handle
        BUILT_IN_VA_ARG_BITINT, BUILT_IN_BITINT_UNPACK and
        BUILT_IN_BITINT_PACK.
gcc/testsuite/
        * gcc.dg/bitint-138.c: New test.
        * gcc.dg/bitint-139.c: New test.
        * gcc.dg/bitint-140.c: New test.
        * gcc.dg/bitint-141.c: New test.
        * gcc.dg/bitint-142.c: New test.
        * gcc.dg/bitint-143.c: New test.
        * gcc.dg/bitint-144.c: New test.
        * gcc.dg/bitint-145.c: New test.
        * gcc.dg/bitint-146.c: New test.
        * gcc.dg/bitint-147.c: New test.
        * gcc.dg/bitint-148.c: New test.
        * gcc.dg/bitint-149.c: New test.
        * gcc.dg/bitint-150.c: New test.
        * gcc.dg/bitint-151.c: New test.
        * gcc.dg/bitint-152.c: New test.
        * gcc.dg/bitint-153.c: New test.
        * gcc.dg/bitint-154.c: New test.
        * gcc.dg/bitint-155.c: New test.

--- gcc/builtin-types.def.jj    2026-07-03 20:39:18.971958769 +0200
+++ gcc/builtin-types.def       2026-07-04 09:55:05.395610572 +0200
@@ -1046,6 +1046,7 @@ DEF_FUNCTION_TYPE_VAR_1 (BT_FN_I2_I2_VAR
 DEF_FUNCTION_TYPE_VAR_1 (BT_FN_I4_I4_VAR, BT_I4, BT_I4)
 DEF_FUNCTION_TYPE_VAR_1 (BT_FN_I8_I8_VAR, BT_I8, BT_I8)
 DEF_FUNCTION_TYPE_VAR_1 (BT_FN_I16_I16_VAR, BT_I16, BT_I16)
+DEF_FUNCTION_TYPE_VAR_1 (BT_FN_VOID_PTR_VAR, BT_VOID, BT_PTR)
 
 DEF_FUNCTION_TYPE_VAR_2 (BT_FN_INT_FILEPTR_CONST_STRING_VAR,
                         BT_INT, BT_FILEPTR, BT_CONST_STRING)
--- gcc/builtins.def.jj 2026-07-03 20:39:18.973958745 +0200
+++ gcc/builtins.def    2026-07-04 09:55:05.396657381 +0200
@@ -1157,6 +1157,9 @@ DEF_GCC_BUILTIN        (BUILT_IN_VA_END,
 DEF_GCC_BUILTIN        (BUILT_IN_VA_START, "va_start", 
BT_FN_VOID_VALIST_REF_VAR, ATTR_NOTHROW_LEAF_LIST)
 DEF_GCC_BUILTIN        (BUILT_IN_VA_ARG_PACK, "va_arg_pack", BT_FN_INT, 
ATTR_PURE_NOTHROW_LEAF_LIST)
 DEF_GCC_BUILTIN        (BUILT_IN_VA_ARG_PACK_LEN, "va_arg_pack_len", 
BT_FN_INT, ATTR_PURE_NOTHROW_LEAF_LIST)
+DEF_GCC_BUILTIN        (BUILT_IN_VA_ARG_BITINT, "va_arg_bitint", 
BT_FN_VOID_VALIST_REF_VAR, ATTR_NULL)
+DEF_GCC_BUILTIN        (BUILT_IN_BITINT_UNPACK, "bitint_unpack", 
BT_FN_VOID_CONST_PTR_VAR, ATTR_NULL)
+DEF_GCC_BUILTIN        (BUILT_IN_BITINT_PACK, "bitint_pack", 
BT_FN_VOID_PTR_VAR, ATTR_NULL)
 DEF_EXT_LIB_BUILTIN    (BUILT_IN__EXIT, "_exit", BT_FN_VOID_INT, 
ATTR_NORETURN_NOTHROW_LEAF_LIST)
 DEF_C99_BUILTIN        (BUILT_IN__EXIT2, "_Exit", BT_FN_VOID_INT, 
ATTR_NORETURN_NOTHROW_LEAF_LIST)
 
--- gcc/builtins.cc.jj  2026-07-03 20:39:18.973958745 +0200
+++ gcc/builtins.cc     2026-07-06 10:59:18.374406272 +0200
@@ -10636,6 +10636,26 @@ fold_builtin_addc_subc (location_t loc,
   return build2_loc (loc, COMPOUND_EXPR, type, store, intres);
 }
 
+/* Adjust __builtin_va_arg_bitint, __builtin_bitint_pack or
+   __builtin_bitint_unpack calls, if they have 5 arguments, to remember
+   the type of the 3rd argument in new 6th argument.  Pointer conversions
+   in GIMPLE are useless, so we can't rely on TREE_TYPE of the 3rd
+   argument later on.  */
+
+static tree
+fold_builtin_bitint_pack (location_t loc, enum built_in_function fcode,
+                         tree *args, int nargs)
+{
+  if (nargs != 5)
+    return NULL_TREE;
+  nargs = fcode == BUILT_IN_VA_ARG_BITINT ? 7 : 6;
+  return build_call_expr_loc (loc, builtin_decl_explicit (fcode), nargs,
+                             args[0], args[1], args[2], args[3], args[4],
+                             build_zero_cst (TREE_TYPE (args[2])),
+                             nargs == 7 ? build_zero_cst (TREE_TYPE (args[0]))
+                             : NULL_TREE);
+}
+
 /* Fold a call to __builtin_FILE to a constant string.  */
 
 static inline tree
@@ -11957,6 +11977,11 @@ fold_builtin_varargs (location_t loc, tr
     case BUILT_IN_SUBCLL:
       return fold_builtin_addc_subc (loc, fcode, args);
 
+    case BUILT_IN_VA_ARG_BITINT:
+    case BUILT_IN_BITINT_UNPACK:
+    case BUILT_IN_BITINT_PACK:
+      return fold_builtin_bitint_pack (loc, fcode, args, nargs);
+
     default:
       break;
     }
--- gcc/target.def.jj   2026-07-03 20:39:18.999958429 +0200
+++ gcc/target.def      2026-07-04 09:55:05.396060299 +0200
@@ -4469,16 +4469,29 @@ DEFHOOK_UNDOC
 "Expand the @code{__builtin_va_start} builtin.",
  void, (tree valist, rtx nextarg), NULL)
 
-/* Gimplifies a VA_ARG_EXPR.  */
+/* Gimplifies an IFN_VA_ARG call.  */
 DEFHOOK
 (gimplify_va_arg_expr,
  "This hook performs target-specific gimplification of\n\
-@code{VA_ARG_EXPR}.  The first two parameters correspond to the\n\
+@code{IFN_VA_ARG} call.  The first two parameters correspond to the\n\
 arguments to @code{va_arg}; the latter two are as in\n\
 @code{gimplify.cc:gimplify_expr}.",
  tree, (tree valist, tree type, gimple_seq *pre_p, gimple_seq *post_p),
  std_gimplify_va_arg_expr)
 
+/* Gimplifies an __builtin_va_arg_bitint call except the
+   __builtin_bitint_unpack part.  */
+DEFHOOK
+(gimplify_va_arg_bitint,
+ "This hook performs target-specific gimplification of\n\
+@code{__builtin_va_arg_bitint} call except the\n\
+@code{__builtin_bitint_unpack} part.  The first two\n\
+parameters correspond to the first two arguments to\n\
+@code{__builtin_va_arg_bitint}; the latter two are as in\n\
+@code{gimplify.cc:gimplify_expr}.",
+ tree, (tree valist, tree type, gimple_seq *pre_p, gimple_seq *post_p),
+ std_gimplify_va_arg_bitint)
+
 /* Validity-checking routines for PCH files, target-specific.
    get_pch_validity returns a pointer to the data to be stored,
    and stores the size in its argument.  pch_valid_p gets the same
--- gcc/doc/tm.texi.in.jj       2026-07-03 20:39:18.984958611 +0200
+++ gcc/doc/tm.texi.in  2026-07-04 09:55:05.392708803 +0200
@@ -3498,6 +3498,8 @@ stack.
 
 @hook TARGET_GIMPLIFY_VA_ARG_EXPR
 
+@hook TARGET_GIMPLIFY_VA_ARG_BITINT
+
 @hook TARGET_VALID_POINTER_MODE
 
 @hook TARGET_REF_MAY_ALIAS_ERRNO
--- gcc/doc/tm.texi.jj  2026-07-03 20:39:18.983958623 +0200
+++ gcc/doc/tm.texi     2026-07-04 09:55:05.393756717 +0200
@@ -4574,11 +4574,20 @@ type of @var{type}. If @var{type} is not
 
 @deftypefn {Target Hook} tree TARGET_GIMPLIFY_VA_ARG_EXPR (tree @var{valist}, 
tree @var{type}, gimple_seq *@var{pre_p}, gimple_seq *@var{post_p})
 This hook performs target-specific gimplification of
-@code{VA_ARG_EXPR}.  The first two parameters correspond to the
+@code{IFN_VA_ARG} call.  The first two parameters correspond to the
 arguments to @code{va_arg}; the latter two are as in
 @code{gimplify.cc:gimplify_expr}.
 @end deftypefn
 
+@deftypefn {Target Hook} tree TARGET_GIMPLIFY_VA_ARG_BITINT (tree 
@var{valist}, tree @var{type}, gimple_seq *@var{pre_p}, gimple_seq 
*@var{post_p})
+This hook performs target-specific gimplification of
+@code{__builtin_va_arg_bitint} call except the
+@code{__builtin_bitint_unpack} part.  The first two
+parameters correspond to the first two arguments to
+@code{__builtin_va_arg_bitint}; the latter two are as in
+@code{gimplify.cc:gimplify_expr}.
+@end deftypefn
+
 @deftypefn {Target Hook} bool TARGET_VALID_POINTER_MODE (scalar_int_mode 
@var{mode})
 Define this to return nonzero if the port can handle pointers
 with machine mode @var{mode}.  The default version of this
--- gcc/targhooks.h.jj  2026-07-03 20:39:19.002958392 +0200
+++ gcc/targhooks.h     2026-07-04 09:55:05.395417423 +0200
@@ -289,6 +289,8 @@ extern bool default_member_type_forces_b
 extern void default_atomic_assign_expand_fenv (tree *, tree *, tree *);
 extern tree build_va_arg_indirect_ref (tree);
 extern tree std_gimplify_va_arg_expr (tree, tree, gimple_seq *, gimple_seq *);
+extern tree std_gimplify_va_arg_bitint (tree, tree, gimple_seq *,
+                                       gimple_seq *);
 extern bool can_use_doloop_if_innermost (const widest_int &,
                                         const widest_int &,
                                         unsigned int, bool);
--- gcc/targhooks.cc.jj 2026-07-03 20:39:19.001958405 +0200
+++ gcc/targhooks.cc    2026-07-04 09:55:05.394886423 +0200
@@ -2706,6 +2706,173 @@ std_gimplify_va_arg_expr (tree valist, t
   return build_va_arg_indirect_ref (addr);
 }
 
+/* The "standard" implementation of __builtin_va_arg_bitint: read the
+   _BitInt(n) value from the current (padded) address and increment
+   by the (padded) size and return its address, so that
+   __builtin_bitint_unpack can be called on that address.  */
+
+tree
+std_gimplify_va_arg_bitint (tree valist, tree n, gimple_seq *pre_p,
+                           gimple_seq *post_p)
+{
+  /* All of the alignment and movement below is for args-grow-up machines.  */
+  gcc_assert (!ARGS_GROW_DOWNWARD);
+
+  scalar_int_mode last_limb_mode = QImode;
+  struct bitint_info info;
+  tree ptr = create_tmp_var (const_ptr_type_node, "bitint_ptr");
+  tree labend = create_artificial_label (input_location);
+  int i;
+  for (i = 1; i <= 256; ++i)
+    {
+      bool ok = targetm.c.bitint_type_info (i, &info);
+      gcc_assert (ok);
+      scalar_int_mode limb_mode
+       = as_a <scalar_int_mode> (info.abi_limb_mode);
+      if (i > GET_MODE_PRECISION (limb_mode)
+         || (i != 1 && limb_mode != last_limb_mode))
+       {
+         tree type = build_bitint_type (i - 1, 1);
+         gimple_seq post_seq = NULL;
+         tree labtrue = create_artificial_label (input_location);
+         tree labfalse = create_artificial_label (input_location);
+         gcond *cond_stmt
+           = gimple_build_cond (LE_EXPR, n,
+                                build_int_cst (TREE_TYPE (n), i - 1),
+                                labtrue, labfalse);
+         gimple_seq_add_stmt (pre_p, cond_stmt);
+         gimple_seq_add_stmt (pre_p, gimple_build_label (labtrue));
+         tree mem_ref
+           = std_gimplify_va_arg_expr (unshare_expr (valist), type, pre_p,
+                                       &post_seq);
+         gcc_assert (TREE_CODE (mem_ref) == MEM_REF);
+         gimplify_assign (ptr, build_fold_addr_expr (mem_ref), pre_p);
+         if (post_seq)
+           gimple_seq_add_seq (pre_p, post_seq);
+         gimple_seq_add_stmt (pre_p, gimple_build_goto (labend));
+         gimple_seq_add_stmt (pre_p, gimple_build_label (labfalse));
+         if (i > GET_MODE_PRECISION (limb_mode))
+           break;
+       }
+      last_limb_mode = limb_mode;
+      /* Optimize for the common case where N 1-8 use QImode,
+        9-16 use HImode, 17-32 use SImode etc.  */
+      int j = -1;
+      switch (i)
+       {
+       case 1: j = 8; break;
+       case 9: j = 16; break;
+       case 17: j = 32; break;
+       case 33: j = 64; break;
+       case 65: j = 128; break;
+       default: break;
+       }
+      if (j != -1)
+       {
+         ok = targetm.c.bitint_type_info (j, &info);
+         gcc_assert (ok);
+         scalar_int_mode limb_mode
+           = as_a <scalar_int_mode> (info.abi_limb_mode);
+         if (limb_mode == last_limb_mode)
+           i = j - 1;
+       }
+    }
+
+  tree type = build_bitint_type (i, 1);
+  bool indirect = pass_va_arg_by_reference (type);
+  if (indirect)
+    type = build_pointer_type (type);
+  scalar_int_mode limb_mode = as_a <scalar_int_mode> (info.abi_limb_mode);
+  int abi_limb_prec = GET_MODE_PRECISION (limb_mode);
+
+  unsigned HOST_WIDE_INT align = PARM_BOUNDARY / BITS_PER_UNIT;
+  unsigned HOST_WIDE_INT boundary
+    = targetm.calls.function_arg_boundary (TYPE_MODE (type), type);
+
+  /* When we align parameter on stack for caller, if the parameter
+     alignment is beyond MAX_SUPPORTED_STACK_ALIGNMENT, it will be
+     aligned at MAX_SUPPORTED_STACK_ALIGNMENT.  We will match callee
+     here with caller.  */
+  if (boundary > MAX_SUPPORTED_STACK_ALIGNMENT)
+    boundary = MAX_SUPPORTED_STACK_ALIGNMENT;
+
+  boundary /= BITS_PER_UNIT;
+
+  tree valist_tmp = get_initialized_tmp_var (valist, pre_p);
+
+  /* va_list pointer is aligned to PARM_BOUNDARY.  If argument actually
+     requires greater alignment, we must perform dynamic alignment.  */
+  if (boundary > align)
+    {
+      tree t = build2 (MODIFY_EXPR, TREE_TYPE (valist), valist_tmp,
+                      fold_build_pointer_plus_hwi (valist_tmp, boundary - 1));
+      gimplify_and_add (t, pre_p);
+
+      t = build2 (MODIFY_EXPR, TREE_TYPE (valist), valist_tmp,
+                 fold_build2 (BIT_AND_EXPR, TREE_TYPE (valist),
+                              valist_tmp,
+                              build_int_cst (TREE_TYPE (valist), -boundary)));
+      gimplify_and_add (t, pre_p);
+    }
+  else
+    boundary = align;
+
+  /* If the actual alignment is less than the alignment of the type,
+     adjust the type accordingly so that we don't assume strict alignment
+     when dereferencing the pointer.  */
+  boundary *= BITS_PER_UNIT;
+  if (boundary < TYPE_ALIGN (type))
+    {
+      type = build_variant_type_copy (type);
+      SET_TYPE_ALIGN (type, boundary);
+    }
+
+  /* Compute the rounded size of the type.  */
+  tree type_size;
+  if (indirect)
+    type_size = arg_size_in_bytes (type);
+  else
+    {
+      tree t = fold_convert (sizetype, n);
+      t = size_binop (PLUS_EXPR, t, size_int (abi_limb_prec - 1));
+      t = size_binop (TRUNC_DIV_EXPR, t, size_int (abi_limb_prec));
+      type_size = size_binop (MULT_EXPR, t,
+                             size_int (GET_MODE_SIZE (limb_mode)));
+    }
+  tree rounded_size = round_up (type_size, align);
+
+  /* Reduce rounded_size so it's sharable with the postqueue.  */
+  gimplify_expr (&rounded_size, pre_p, post_p, is_gimple_val, fb_rvalue);
+
+  /* Get AP.  */
+  tree addr = valist_tmp;
+  if (PAD_VARARGS_DOWN)
+    {
+      /* Small args are padded downward.  */
+      tree t = fold_build2_loc (input_location, GT_EXPR, sizetype,
+                               rounded_size, size_int (align));
+      t = fold_build3 (COND_EXPR, sizetype, t, size_zero_node,
+                      size_binop (MINUS_EXPR, rounded_size, type_size));
+      addr = fold_build_pointer_plus (addr, t);
+    }
+
+  /* Compute new value for AP.  */
+  tree t = fold_build_pointer_plus (valist_tmp, rounded_size);
+  t = build2 (MODIFY_EXPR, TREE_TYPE (valist), valist, t);
+  gimplify_and_add (t, pre_p);
+
+  addr = fold_convert (build_pointer_type (type), addr);
+
+  if (indirect)
+    addr = build_va_arg_indirect_ref (addr);
+
+  gimplify_assign (ptr, addr, pre_p);
+
+  gimple_seq_add_stmt (pre_p, gimple_build_label (labend));
+
+  return ptr;
+}
+
 /* An implementation of TARGET_CAN_USE_DOLOOP_P for targets that do
    not support nested low-overhead loops.  */
 
--- gcc/passes.def.jj   2026-07-03 20:39:18.998958441 +0200
+++ gcc/passes.def      2026-07-04 09:55:05.396906713 +0200
@@ -397,6 +397,7 @@ along with GCC; see the file COPYING3.
         passes and all optimization work is done early.  */
       NEXT_PASS (pass_remove_cgraph_callee_edges);
       NEXT_PASS (pass_strip_predict_hints, false /* early_p */);
+      NEXT_PASS (pass_stdarg);
       /* Lower remaining pieces of GIMPLE.  */
       NEXT_PASS (pass_lower_complex);
       NEXT_PASS (pass_lower_bitint);
--- gcc/tree-stdarg.cc.jj       2026-07-03 20:39:19.006958344 +0200
+++ gcc/tree-stdarg.cc  2026-07-06 13:28:28.256424506 +0200
@@ -1003,17 +1003,17 @@ expand_ifn_va_arg_1 (function *fun)
     for (i = gsi_start_bb (bb); !gsi_end_p (i); gsi_next (&i))
       {
        gimple *stmt = gsi_stmt (i);
-       tree ap, aptype, expr, lhs, type;
+       tree ap, aptype;
        gimple_seq pre = NULL, post = NULL;
-
-       if (!gimple_call_internal_p (stmt, IFN_VA_ARG))
+       bool ifn_va_arg = gimple_call_internal_p (stmt, IFN_VA_ARG);
+       if (!ifn_va_arg
+           && !gimple_call_builtin_p (stmt, BUILT_IN_VA_ARG_BITINT))
          continue;
 
        modified = true;
 
-       type = TREE_TYPE (TREE_TYPE (gimple_call_arg (stmt, 1)));
        ap = gimple_call_arg (stmt, 0);
-       aptype = TREE_TYPE (gimple_call_arg (stmt, 2));
+       aptype = TREE_TYPE (gimple_call_arg (stmt, ifn_va_arg ? 2 : 6));
        gcc_assert (POINTER_TYPE_P (aptype));
 
        /* Balanced out the &ap, usually added by build_va_arg.  */
@@ -1028,30 +1028,54 @@ expand_ifn_va_arg_1 (function *fun)
           from multiple evaluations.  */
        gimplify_expr (&ap, &pre, &post, is_gimple_min_lval, fb_lvalue);
 
-       expr = targetm.gimplify_va_arg_expr (ap, type, &pre, &post);
-
-       lhs = gimple_call_lhs (stmt);
-       if (lhs != NULL_TREE)
+       if (ifn_va_arg)
          {
-           unsigned int nargs = gimple_call_num_args (stmt);
-           gcc_assert (useless_type_conversion_p (TREE_TYPE (lhs), type));
+           tree type = TREE_TYPE (TREE_TYPE (gimple_call_arg (stmt, 1)));
+           tree expr = targetm.gimplify_va_arg_expr (ap, type, &pre, &post);
 
-           if (nargs == 4)
+           tree lhs = gimple_call_lhs (stmt);
+           if (lhs != NULL_TREE)
              {
-               /* We've transported the size of with WITH_SIZE_EXPR here as
-                  the last argument of the internal fn call.  Now reinstate
-                  it.  */
-               tree size = gimple_call_arg (stmt, nargs - 1);
-               expr = build2 (WITH_SIZE_EXPR, TREE_TYPE (expr), expr, size);
-             }
+               unsigned int nargs = gimple_call_num_args (stmt);
+               gcc_assert (useless_type_conversion_p (TREE_TYPE (lhs), type));
 
-           /* We use gimplify_assign here, rather than gimple_build_assign,
-              because gimple_assign knows how to deal with variable-sized
-              types.  */
-           gimplify_assign (lhs, expr, &pre);
+               if (nargs == 4)
+                 {
+                   /* We've transported the size of with WITH_SIZE_EXPR here
+                      as the last argument of the internal fn call.  Now
+                      reinstate it.  */
+                   tree size = gimple_call_arg (stmt, nargs - 1);
+                   expr = build2 (WITH_SIZE_EXPR, TREE_TYPE (expr), expr,
+                                  size);
+                 }
+
+               /* We use gimplify_assign here, rather than
+                  gimple_build_assign, because gimple_assign knows how to deal
+                  with variable-sized types.  */
+               gimplify_assign (lhs, expr, &pre);
+             }
+           else
+             gimplify_and_add (expr, &pre);
          }
        else
-         gimplify_and_add (expr, &pre);
+         {
+           tree n = gimple_call_arg (stmt, 1);
+           tree dptr = gimple_call_arg (stmt, 2);
+           tree endian = gimple_call_arg (stmt, 3);
+           tree uns = gimple_call_arg (stmt, 4);
+           tree dptr_type = gimple_call_arg (stmt, 5);
+           tree sptr = targetm.gimplify_va_arg_bitint (ap, n, &pre, &post);
+
+           /* Emit
+              __builtin_bitint_unpack (sptr, n, dptr, endian, uns);
+              call that bitint lowering lowers later on (with original
+              pointer type of dptr as an extra argument of NULL pointer).  */
+           tree fn = builtin_decl_explicit (BUILT_IN_BITINT_UNPACK);
+           gimple *g = gimple_build_call (fn, 6, sptr, n, dptr, endian, uns,
+                                          dptr_type);
+           gimple_seq_add_stmt (&pre, g);
+           cfun->has_bitint_pack = 1;
+         }
 
        input_location = saved_location;
        pop_gimplify_context (NULL);
@@ -1061,7 +1085,7 @@ expand_ifn_va_arg_1 (function *fun)
 
        /* Add the sequence after IFN_VA_ARG.  This splits the bb right
           after IFN_VA_ARG, and adds the sequence in one or more new bbs
-          inbetween.  */
+          in between.  */
        gimple_find_sub_bbs (pre, &i);
 
        /* Remove the IFN_VA_ARG gimple_call.  It's the last stmt in the
@@ -1126,6 +1150,11 @@ public:
   {}
 
   /* opt_pass methods: */
+  opt_pass * clone () final override
+    {
+      return new pass_stdarg (m_ctxt);
+    }
+
   bool gate (function *) final override
     {
       /* Always run this pass, in order to expand va_arg internal_fns.  We
--- gcc/gimplify.cc.jj  2026-07-03 20:39:18.992958514 +0200
+++ gcc/gimplify.cc     2026-07-04 09:55:05.397828605 +0200
@@ -4669,6 +4669,17 @@ gimplify_call_expr (tree *expr_p, gimple
          }
        break;
 
+      case BUILT_IN_VA_ARG_BITINT:
+       /* Clear the tentatively set PROP_gimple_lva, to indicate that
+          __builtin_va_arg_bitint needs to be expanded.  */
+       cfun->curr_properties &= ~PROP_gimple_lva;
+       break;
+
+      case BUILT_IN_BITINT_PACK:
+      case BUILT_IN_BITINT_UNPACK:
+       cfun->has_bitint_pack = 1;
+       break;
+
       default:
         ;
       }
--- gcc/function.h.jj   2026-07-03 20:39:18.987958575 +0200
+++ gcc/function.h      2026-07-04 09:55:05.398938619 +0200
@@ -456,6 +456,9 @@ struct GTY(()) function {
 
   /* Nonzero if reload will have to split basic blocks.  */
   unsigned int split_basic_blocks_after_reload : 1;
+
+  /* Nonzero if function has any __builtin_bitint_{,un}pack calls.  */
+  unsigned int has_bitint_pack : 1;
 };
 
 /* Add the decl D to the local_decls list of FUN.  */
--- gcc/tree-inline.cc.jj       2026-07-03 20:39:19.003958380 +0200
+++ gcc/tree-inline.cc  2026-07-04 09:55:05.399280058 +0200
@@ -5097,6 +5097,7 @@ expand_call_inline (basic_block bb, gimp
   if (src_properties != prop_mask)
     dst_cfun->curr_properties &= src_properties | ~prop_mask;
   dst_cfun->calls_eh_return |= id->src_cfun->calls_eh_return;
+  dst_cfun->has_bitint_pack |= id->src_cfun->has_bitint_pack;
   id->dst_node->has_omp_variant_constructs
     |= id->src_node->has_omp_variant_constructs;
 
--- gcc/gimple-lower-bitint.cc.jj       2026-07-03 20:39:18.989958551 +0200
+++ gcc/gimple-lower-bitint.cc  2026-07-06 13:15:49.312372924 +0200
@@ -452,6 +452,7 @@ struct bitint_large_huge
   tree handle_operand (tree, tree);
   tree prepare_data_in_out (tree, tree, tree *, tree = NULL_TREE);
   tree add_cast (tree, tree);
+  gimple *add_mult (tree, tree, unsigned HOST_WIDE_INT);
   tree handle_plus_minus (tree_code, tree, tree, tree);
   tree handle_lshift (tree, tree, tree);
   tree handle_cast (tree, tree, tree);
@@ -475,6 +476,7 @@ struct bitint_large_huge
   void lower_complexexpr_stmt (gimple *);
   void lower_bit_query (gimple *);
   void lower_bswap_bitreverse (tree, gimple *);
+  void lower_pack_unpack (gimple *);
   void lower_call (tree, gimple *);
   void lower_asm (gimple *);
   void lower_stmt (gimple *);
@@ -1202,6 +1204,24 @@ bitint_large_huge::add_cast (tree type,
   return lhs;
 }
 
+/* Emit a stmt to set dest = src * m; before the current location.  */
+
+gimple *
+bitint_large_huge::add_mult (tree dest, tree src, unsigned HOST_WIDE_INT m)
+{
+  gimple *g;
+  if (m == 1)
+    g = gimple_build_assign (dest, src);
+  else if (pow2p_hwi (m))
+    g = gimple_build_assign (dest, LSHIFT_EXPR, src,
+                            build_int_cst (unsigned_type_node,
+                                           exact_log2 (m)));
+  else
+    g = gimple_build_assign (dest, MULT_EXPR, src, size_int (m));
+  insert_before (g);
+  return g;
+}
+
 /* Helper of handle_stmt method, handle PLUS_EXPR or MINUS_EXPR.  */
 
 tree
@@ -6284,6 +6304,587 @@ bitint_large_huge::lower_bswap_bitrevers
     }
 }
 
+/* Lower a __builtin_bitint_{,un}pack call.  */
+
+void
+bitint_large_huge::lower_pack_unpack (gimple *stmt)
+{
+  bool pack_p = gimple_call_builtin_p (stmt, BUILT_IN_BITINT_PACK);
+  location_t loc = gimple_location (stmt);
+  tree bitint_ptr = gimple_call_arg (stmt, 0);
+  tree n = gimple_call_arg (stmt, 1);
+  tree limb_ptr = gimple_call_arg (stmt, 2);
+  tree big_endian_p = gimple_call_arg (stmt, 3);
+  tree uns_p = gimple_call_arg (stmt, 4);
+  tree limb_ptr_type = TREE_TYPE (gimple_call_arg (stmt, 5));
+  gcc_assert (POINTER_TYPE_P (limb_ptr_type));
+  tree limb_type = TYPE_MAIN_VARIANT (TREE_TYPE (limb_ptr_type));
+  gcc_assert (TREE_CODE (limb_type) == INTEGER_TYPE);
+  /* When _BitInt support is added for avr or msp430 or if some
+     target chooses to use some non power-of-two limb_prec, this might
+     need to change and add full-blown support for arbitrary
+     TYPE_PRECISION (limb_type) (for avr this could be 24 and for msp430
+     20) and limb_prec combinations.  Until then, we just support
+     the cases where TYPE_PRECISION (limb_prec) and limb_prec are
+     power-of-two and one of them is divisible by the other one.
+     And for the case where limb_type is wider than limb_prec, only
+     support when limb_type has precision limb_prec * 2.  */
+  if ((TYPE_PRECISION (limb_type) > limb_prec
+       && TYPE_PRECISION (limb_type) != 2 * limb_prec)
+      || (TYPE_PRECISION (limb_type) < limb_prec
+         && (limb_prec % TYPE_PRECISION (limb_type)) != 0))
+    {
+      sorry_at (loc, "currently unsupported combination of requested limb "
+                    "type %qT and internal %<_BitInt%> limb type %qT",
+               limb_type, m_limb_type);
+      return;
+    }
+
+  scalar_int_mode last_limb_mode = QImode;
+  struct bitint_info info;
+  auto_vec <tree, 10> small_types;
+  int i;
+  for (i = 1; i <= 256; ++i)
+    {
+      bool ok = targetm.c.bitint_type_info (i, &info);
+      gcc_assert (ok);
+      scalar_int_mode limb_mode
+       = as_a <scalar_int_mode> (info.abi_limb_mode);
+      if (i > GET_MODE_PRECISION (limb_mode)
+         || (i != 1 && limb_mode != last_limb_mode))
+       {
+         small_types.safe_push (build_bitint_type (i - 1, 1));
+         if (i > GET_MODE_PRECISION (limb_mode))
+           break;
+       }
+      last_limb_mode = limb_mode;
+      /* Optimize for the common case where N 1-8 use QImode,
+        9-16 use HImode, 17-32 use SImode etc.  */
+      int j = -1;
+      switch (i)
+       {
+       case 1: j = 8; break;
+       case 9: j = 16; break;
+       case 17: j = 32; break;
+       case 33: j = 64; break;
+       case 65: j = 128; break;
+       default: break;
+       }
+      if (j != -1)
+       {
+         ok = targetm.c.bitint_type_info (j, &info);
+         gcc_assert (ok);
+         scalar_int_mode limb_mode
+           = as_a <scalar_int_mode> (info.abi_limb_mode);
+         if (limb_mode == last_limb_mode)
+           i = j - 1;
+       }
+    }
+  if (TYPE_PRECISION (small_types.last ()) < TYPE_PRECISION (limb_type))
+    small_types.safe_push (build_bitint_type (TYPE_PRECISION (limb_type), 1));
+  if (!pack_p)
+    {
+      int prec = TYPE_PRECISION (small_types.last ());
+      tree itype = build_nonstandard_integer_type (prec, 1), type, val;
+      edge edge_small, edge_next = NULL, edge_large;
+      if_then_else (gimple_build_cond (LE_EXPR, n,
+                                      size_int (prec),
+                                      NULL_TREE,
+                                      NULL_TREE),
+                   profile_probability::unlikely (),
+                   edge_small, edge_large);
+      unsigned j;
+      FOR_EACH_VEC_ELT (small_types, j, type)
+       {
+         if (TYPE_PRECISION (type) < prec)
+           if_then_else (gimple_build_cond (LE_EXPR, n,
+                                            size_int (TYPE_PRECISION (type)),
+                                            NULL_TREE,
+                                            NULL_TREE),
+                         profile_probability::even (),
+                         edge_small, edge_next);
+         tree mem = build2 (MEM_REF, type, bitint_ptr,
+                            build_int_cst (ptr_type_node, 0));
+         gimple *g = gimple_build_assign (make_ssa_name (type), mem);
+         insert_before (g);
+         g = gimple_build_assign (make_ssa_name (itype), NOP_EXPR,
+                                  gimple_assign_lhs (g));
+         insert_before (g);
+         small_types[j] = gimple_assign_lhs (g);
+         if (TYPE_PRECISION (type) < prec)
+           m_gsi = gsi_after_labels (edge_next->src);
+       }
+      tree v = small_types.last ();
+      edge e;
+      do
+       {
+         e = single_succ_edge (gimple_bb (SSA_NAME_DEF_STMT (v)));
+         if (e->dest == edge_large->dest)
+           {
+             m_gsi = gsi_after_labels (e->src);
+             break;
+           }
+         gphi *phi = create_phi_node (make_ssa_name (TREE_TYPE (v)), e->dest);
+         add_phi_arg (phi, v, e, UNKNOWN_LOCATION);
+         v = gimple_phi_result (phi);
+       }
+      while (1);
+      FOR_EACH_VEC_ELT (small_types, j, val)
+       if (val == small_types.last ())
+         break;
+       else
+         {
+           e = single_succ_edge (gimple_bb (SSA_NAME_DEF_STMT (val)));
+           gphi_iterator gsi = gsi_start_phis (e->dest);
+           add_phi_arg (gsi.phi (), val, e, UNKNOWN_LOCATION);
+         }
+      if (TYPE_PRECISION (limb_type) > prec)
+       v = add_cast (limb_type, v);
+      e = single_succ_edge (gsi_bb (m_gsi));
+      gphi *phiv = create_phi_node (make_ssa_name (TREE_TYPE (v)), e->dest);
+      add_phi_arg (phiv, v, e, UNKNOWN_LOCATION);
+      gphi *phin = create_phi_node (make_ssa_name (sizetype), e->dest);
+      add_phi_arg (phin, n, e, UNKNOWN_LOCATION);
+      gphi *phip = create_phi_node (make_ssa_name (TREE_TYPE (limb_ptr)),
+                                   e->dest);
+      add_phi_arg (phip, limb_ptr, e, UNKNOWN_LOCATION);
+
+      m_gsi = gsi_after_labels (edge_large->src);
+      tree ndiv = make_ssa_name (sizetype);
+      tree nmod = make_ssa_name (sizetype);
+      int p = MAX (TYPE_PRECISION (limb_type), limb_prec);
+      gimple *g;
+      if (pow2p_hwi (p))
+       {
+         g = gimple_build_assign (ndiv, RSHIFT_EXPR, n,
+                                  build_int_cst (unsigned_type_node,
+                                                 exact_log2 (p)));
+         insert_before (g);
+         g = gimple_build_assign (nmod, BIT_AND_EXPR, n, size_int (p - 1));
+         insert_before (g);
+       }
+      else
+       {
+         g = gimple_build_assign (ndiv, TRUNC_DIV_EXPR, n, size_int (p));
+         insert_before (g);
+         g = gimple_build_assign (nmod, TRUNC_MOD_EXPR, n, size_int (p));
+         insert_before (g);
+       }
+      g = gimple_build_assign (make_ssa_name (boolean_type_node),
+                              EQ_EXPR, nmod, size_zero_node);
+      insert_before (g);
+      g = gimple_build_assign (make_ssa_name (sizetype), NOP_EXPR,
+                              gimple_assign_lhs (g));
+      insert_before (g);
+      tree ndivm = make_ssa_name (sizetype);
+      g = gimple_build_assign (ndivm, MINUS_EXPR, ndiv, gimple_assign_lhs (g));
+      insert_before (g);
+      tree ndiv2 = NULL_TREE, nmod2 = NULL_TREE, ndivm2 = NULL_TREE;
+      if (TYPE_PRECISION (limb_type) < limb_prec)
+       {
+         ndiv2 = make_ssa_name (sizetype);
+         nmod2 = make_ssa_name (sizetype);
+         p = TYPE_PRECISION (limb_type);
+         if (pow2p_hwi (p))
+           {
+             g = gimple_build_assign (ndiv2, RSHIFT_EXPR, n,
+                                      build_int_cst (unsigned_type_node,
+                                                     exact_log2 (p)));
+             insert_before (g);
+             g = gimple_build_assign (nmod2, BIT_AND_EXPR, n,
+                                      size_int (p - 1));
+             insert_before (g);
+           }
+         else
+           {
+             g = gimple_build_assign (ndiv2, TRUNC_DIV_EXPR, n, size_int (p));
+             insert_before (g);
+             g = gimple_build_assign (nmod2, TRUNC_MOD_EXPR, n, size_int (p));
+             insert_before (g);
+           }
+         g = gimple_build_assign (make_ssa_name (boolean_type_node),
+                                  EQ_EXPR, nmod2, size_zero_node);
+         insert_before (g);
+         g = gimple_build_assign (make_ssa_name (sizetype), NOP_EXPR,
+                                  gimple_assign_lhs (g));
+         insert_before (g);
+         g = gimple_build_assign (make_ssa_name (sizetype), MINUS_EXPR,
+                                  ndiv2, gimple_assign_lhs (g));
+         insert_before (g);
+         ndivm2 = make_ssa_name (sizetype);
+         add_mult (ndivm2, gimple_assign_lhs (g),
+                   tree_to_uhwi (TYPE_SIZE_UNIT (limb_type)));
+       }
+      tree idx_next;
+      tree idx = create_loop (size_zero_node, &idx_next);
+      tree t;
+      if (bitint_big_endian)
+       {
+         g = gimple_build_assign (make_ssa_name (sizetype),
+                                  MINUS_EXPR, ndivm, idx);
+         insert_before (g);
+         t = gimple_assign_lhs (g);
+       }
+      else
+       t = idx;
+      bool double_sz = TYPE_PRECISION (limb_type) > limb_prec;
+      tree ptr = make_ssa_name (TREE_TYPE (bitint_ptr));
+      g = add_mult (make_ssa_name (sizetype), t,
+                   m_limb_size * (double_sz + 1));
+      g = gimple_build_assign (ptr, POINTER_PLUS_EXPR, bitint_ptr,
+                              gimple_assign_lhs (g));
+      insert_before (g);
+      tree mem = build2 (MEM_REF, m_limb_type, ptr,
+                        build_int_cst (ptr_type_node, 0));
+      g = gimple_build_assign (make_ssa_name (m_limb_type), mem);
+      insert_before (g);
+      auto_vec<tree, 16> parts;
+      tree idxtimessize = NULL_TREE;
+      if (TYPE_PRECISION (limb_type) >= limb_prec)
+       {
+         if (TYPE_PRECISION (limb_type) > limb_prec)
+           {
+             t = add_cast (limb_type, gimple_assign_lhs (g));
+             mem = build2 (MEM_REF, m_limb_type, ptr,
+                           build_int_cst (ptr_type_node,
+                                          bitint_big_endian
+                                          ? -m_limb_size : m_limb_size));
+             g = gimple_build_assign (make_ssa_name (m_limb_type), mem);
+             insert_before (g);
+             tree t2 = add_cast (limb_type, gimple_assign_lhs (g));
+             if (bitint_big_endian)
+               std::swap (t, t2);
+             g = gimple_build_assign (make_ssa_name (limb_type),
+                                      LSHIFT_EXPR, t2,
+                                      build_int_cst (unsigned_type_node,
+                                                     limb_prec));
+             insert_before (g);
+             g = gimple_build_assign (make_ssa_name (limb_type),
+                                      BIT_IOR_EXPR, t, gimple_assign_lhs (g));
+             insert_before (g);
+             parts.safe_push (gimple_assign_lhs (g));
+           }
+         else if (useless_type_conversion_p (limb_type, m_limb_type))
+           parts.safe_push (gimple_assign_lhs (g));
+         else
+           parts.safe_push (add_cast (limb_type, gimple_assign_lhs (g)));
+       }
+      else
+       {
+         tree l = gimple_assign_lhs (g);
+         parts.safe_push (add_cast (limb_type, l));
+         for (p = TYPE_PRECISION (limb_type); p < limb_prec;
+              p += TYPE_PRECISION (limb_type))
+           {
+             g = gimple_build_assign (make_ssa_name (m_limb_type),
+                                      RSHIFT_EXPR, l,
+                                      build_int_cst (unsigned_type_node, p));
+             insert_before (g);
+             parts.safe_push (add_cast (limb_type, gimple_assign_lhs (g)));
+           }
+         idxtimessize = make_ssa_name (sizetype);
+         add_mult (idxtimessize, idx,
+                   tree_to_uhwi (TYPE_SIZE_UNIT (limb_type))
+                   * (limb_prec / TYPE_PRECISION (limb_type)));
+       }
+      if_then_else (gimple_build_cond (NE_EXPR, big_endian_p,
+                                      boolean_false_node,
+                                      NULL_TREE, NULL_TREE),
+                   profile_probability::even (),
+                   edge_small, edge_next);
+      if (TYPE_PRECISION (limb_type) >= limb_prec)
+       {
+         g = gimple_build_assign (make_ssa_name (sizetype),
+                                  MINUS_EXPR, ndivm, idx);
+         insert_before (g);
+         tree tbe = gimple_assign_lhs (g);
+         m_gsi = gsi_after_labels (edge_next->dest);
+         gphi *phi = create_phi_node (make_ssa_name (sizetype),
+                                      gsi_bb (m_gsi));
+         add_phi_arg (phi, tbe, edge_small, UNKNOWN_LOCATION);
+         add_phi_arg (phi, idx, edge_next, UNKNOWN_LOCATION);
+         g = add_mult (make_ssa_name (sizetype), gimple_phi_result (phi),
+                       tree_to_uhwi (TYPE_SIZE_UNIT (limb_type)));
+         g = gimple_build_assign (make_ssa_name (TREE_TYPE (limb_ptr)),
+                                  POINTER_PLUS_EXPR, limb_ptr,
+                                  gimple_assign_lhs (g));
+         insert_before (g);
+         mem = build2 (MEM_REF, limb_type, gimple_assign_lhs (g),
+                       build_int_cst (limb_ptr_type, 0));
+         g = gimple_build_assign (mem, parts[0]);
+         insert_before (g);
+       }
+      else
+       {
+         g = gimple_build_assign (make_ssa_name (sizetype), MINUS_EXPR,
+                                  ndivm2, idxtimessize);
+         insert_before (g);
+         g = gimple_build_assign (make_ssa_name (TREE_TYPE (limb_ptr)),
+                                  POINTER_PLUS_EXPR, limb_ptr,
+                                  gimple_assign_lhs (g));
+         insert_before (g);
+         tree base = gimple_assign_lhs (g);
+         int sz = tree_to_uhwi (TYPE_SIZE_UNIT (limb_type));
+         unsigned int j;
+         FOR_EACH_VEC_ELT (parts, j, t)
+           {
+             mem = build2 (MEM_REF, limb_type, base,
+                           build_int_cst (limb_ptr_type,
+                                          (- (int) j) * sz));
+             g = gimple_build_assign (mem, t);
+             insert_before (g);
+           }
+         m_gsi = gsi_after_labels (edge_next->src);
+         g = gimple_build_assign (make_ssa_name (TREE_TYPE (limb_ptr)),
+                                  POINTER_PLUS_EXPR, limb_ptr,
+                                  idxtimessize);
+         insert_before (g);
+         base = gimple_assign_lhs (g);
+         FOR_EACH_VEC_ELT (parts, j, t)
+           {
+             mem = build2 (MEM_REF, limb_type, base,
+                           build_int_cst (limb_ptr_type, j * sz));
+             g = gimple_build_assign (mem, t);
+             insert_before (g);
+           }
+         m_gsi = gsi_after_labels (edge_next->dest);
+       }
+      g = gimple_build_assign (idx_next, PLUS_EXPR, idx, size_one_node);
+      insert_before (g);
+      g = gimple_build_cond (NE_EXPR, idx_next, ndiv, NULL_TREE,
+                            NULL_TREE);
+      insert_before (g);
+
+      m_gsi = gsi_after_labels (edge_large->src);
+      if_then (gimple_build_cond (NE_EXPR, nmod, size_zero_node,
+                                 NULL_TREE, NULL_TREE),
+              profile_probability::even (), edge_small, e);
+      if (bitint_big_endian)
+       t = bitint_ptr;
+      else
+       {
+         g = add_mult (make_ssa_name (sizetype), ndivm,
+                       m_limb_size * (double_sz + 1));
+         g = gimple_build_assign (make_ssa_name (TREE_TYPE (bitint_ptr)),
+                                  POINTER_PLUS_EXPR, bitint_ptr,
+                                  gimple_assign_lhs (g));
+         insert_before (g);
+         t = gimple_assign_lhs (g);
+       }
+      mem = build2 (MEM_REF, m_limb_type, t,
+                   build_int_cst (ptr_type_node, 0));
+      g = gimple_build_assign (make_ssa_name (m_limb_type), mem);
+      insert_before (g);
+      t = gimple_assign_lhs (g);
+      if (double_sz)
+       {
+         t = add_cast (TREE_TYPE (v), t);
+         if_then (gimple_build_cond (GT_EXPR, nmod, size_int (limb_prec),
+                                     NULL_TREE, NULL_TREE),
+                  profile_probability::even (),
+                  edge_small, edge_next);
+         mem = build2 (MEM_REF, m_limb_type, TREE_OPERAND (mem, 0),
+                       build_int_cst (ptr_type_node, m_limb_size));
+         g = gimple_build_assign (make_ssa_name (m_limb_type), mem);
+         insert_before (g);
+         tree t2 = add_cast (TREE_TYPE (v), gimple_assign_lhs (g));
+         tree t3 = t;
+         if (bitint_big_endian)
+           std::swap (t2, t3);
+         g = gimple_build_assign (make_ssa_name (TREE_TYPE (v)),
+                                  LSHIFT_EXPR, t2,
+                                  build_int_cst (unsigned_type_node,
+                                                 limb_prec));
+         insert_before (g);
+         g = gimple_build_assign (make_ssa_name (TREE_TYPE (v)),
+                                  BIT_IOR_EXPR, t3, gimple_assign_lhs (g));
+         insert_before (g);
+         gphi *phi = create_phi_node (make_ssa_name (TREE_TYPE (v)),
+                                      edge_small->dest);
+         add_phi_arg (phi, gimple_assign_lhs (g), edge_small,
+                      UNKNOWN_LOCATION);
+         add_phi_arg (phi, t, edge_next, UNKNOWN_LOCATION);
+         t = gimple_phi_result (phi);
+         m_gsi = gsi_after_labels (edge_next->dest);
+       }
+      else if (!useless_type_conversion_p (TREE_TYPE (v), m_limb_type))
+       t = add_cast (TREE_TYPE (v), t);
+      if_then_else (gimple_build_cond (NE_EXPR, big_endian_p,
+                                      boolean_false_node,
+                                      NULL_TREE, NULL_TREE),
+                   profile_probability::even (),
+                   edge_small, edge_next);
+      m_gsi = gsi_after_labels (edge_next->src);
+      p = tree_to_uhwi (TYPE_SIZE_UNIT (limb_type));
+      if (TYPE_PRECISION (limb_type) < limb_prec)
+       p *= limb_prec / TYPE_PRECISION (limb_type);
+      g = add_mult (make_ssa_name (sizetype), ndiv, p);
+      g = gimple_build_assign (make_ssa_name (TREE_TYPE (limb_ptr)),
+                              POINTER_PLUS_EXPR, limb_ptr,
+                              gimple_assign_lhs (g));
+      insert_before (g);
+      gphi *phip3 = create_phi_node (make_ssa_name (TREE_TYPE (limb_ptr)),
+                                    edge_next->dest);
+      add_phi_arg (phip3, limb_ptr, edge_small, UNKNOWN_LOCATION);
+      add_phi_arg (phip3, gimple_assign_lhs (g), edge_next, UNKNOWN_LOCATION);
+      edge_next = single_succ_edge (edge_next->dest);
+      gphi *phiv2 = create_phi_node (make_ssa_name (TREE_TYPE (v)), e->dest);
+      add_phi_arg (phiv2, build_zero_cst (TREE_TYPE (v)), e, UNKNOWN_LOCATION);
+      add_phi_arg (phiv2, t, edge_next, UNKNOWN_LOCATION);
+      gphi *phip2 = create_phi_node (make_ssa_name (TREE_TYPE (limb_ptr)),
+                                    e->dest);
+      add_phi_arg (phip2, limb_ptr, e, UNKNOWN_LOCATION);
+      add_phi_arg (phip2, gimple_phi_result (phip3), edge_next,
+                  UNKNOWN_LOCATION);
+
+      add_phi_arg (phiv, gimple_phi_result (phiv2), edge_large,
+                  UNKNOWN_LOCATION);
+      add_phi_arg (phin, nmod, edge_large, UNKNOWN_LOCATION);
+      add_phi_arg (phip, gimple_phi_result (phip2), edge_large,
+                  UNKNOWN_LOCATION);
+      m_gsi = gsi_after_labels (edge_large->dest);
+      if_then (gimple_build_cond (NE_EXPR, gimple_phi_result (phin),
+                                 size_zero_node, NULL_TREE, NULL_TREE),
+              profile_probability::even (), edge_small, e);
+      if_then (gimple_build_cond (NE_EXPR, gimple_phi_result (phin),
+                                 size_int (TYPE_PRECISION (TREE_TYPE (v))),
+                                 NULL_TREE, NULL_TREE),
+              profile_probability::even (), e, edge_large);
+      tree shift = make_ssa_name (sizetype);
+      g = gimple_build_assign (shift, MINUS_EXPR,
+                              size_int (TYPE_PRECISION (TREE_TYPE (v))),
+                              gimple_phi_result (phin));
+      insert_before (g);
+      if (!useless_type_conversion_p (unsigned_type_node, sizetype))
+       shift = add_cast (unsigned_type_node, shift);
+      v = make_ssa_name (TREE_TYPE (v));
+      g = gimple_build_assign (v, LSHIFT_EXPR, gimple_phi_result (phiv),
+                              shift);
+      insert_before (g);
+      if_then_else (gimple_build_cond (NE_EXPR, uns_p, boolean_false_node,
+                                      NULL_TREE, NULL_TREE),
+                   profile_probability::even (),
+                   edge_next, e);
+      g = gimple_build_assign (make_ssa_name (TREE_TYPE (v)), RSHIFT_EXPR,
+                              v, shift);
+      insert_before (g);
+      gphi *phi = create_phi_node (make_ssa_name (TREE_TYPE (v)), e->dest);
+      add_phi_arg (phi, gimple_assign_lhs (g), edge_next, UNKNOWN_LOCATION);
+      m_gsi = gsi_after_labels (e->src);
+      tree stype = signed_type_for (TREE_TYPE (v));
+      g = gimple_build_assign (make_ssa_name (stype), RSHIFT_EXPR,
+                              add_cast (stype, v), shift);
+      insert_before (g);
+      add_phi_arg (phi, add_cast (TREE_TYPE (v), gimple_assign_lhs (g)),
+                  e, UNKNOWN_LOCATION);
+      gphi *phi2 = create_phi_node (make_ssa_name (TREE_TYPE (v)),
+                                   edge_large->dest);
+      add_phi_arg (phi2, gimple_phi_result (phiv), edge_large,
+                  UNKNOWN_LOCATION);
+      add_phi_arg (phi2, gimple_phi_result (phi), single_succ_edge (e->dest),
+                  UNKNOWN_LOCATION);
+      m_gsi = gsi_after_labels (edge_large->dest);
+      t = gimple_phi_result (phi2);
+      if (TYPE_PRECISION (limb_type) >= TYPE_PRECISION (TREE_TYPE (v)))
+       {
+         if (!useless_type_conversion_p (limb_type, TREE_TYPE (v)))
+           t = add_cast (limb_type, t);
+         mem = build2 (MEM_REF, limb_type, gimple_phi_result (phip),
+                       build_int_cst (limb_ptr_type, 0));
+         g = gimple_build_assign (mem, t);
+         insert_before (g);
+       }
+      else
+       {
+         if_then_else (gimple_build_cond (NE_EXPR, big_endian_p,
+                                          boolean_false_node, NULL_TREE,
+                                          NULL_TREE),
+                       profile_probability::even (),
+                       edge_next, e);
+         p = TYPE_PRECISION (limb_type);
+         g = gimple_build_assign (make_ssa_name (sizetype), PLUS_EXPR,
+                                  gimple_phi_result (phin), size_int (p - 1));
+         insert_before (g);
+         if (pow2p_hwi (p))
+           g = gimple_build_assign (make_ssa_name (sizetype), RSHIFT_EXPR,
+                                    gimple_assign_lhs (g),
+                                    build_int_cst (unsigned_type_node,
+                                                   exact_log2 (p)));
+         else
+           g = gimple_build_assign (make_ssa_name (sizetype), TRUNC_DIV_EXPR,
+                                    gimple_assign_lhs (g), size_int (p));
+         insert_before (g);
+         g = add_mult (make_ssa_name (sizetype), gimple_assign_lhs (g),
+                       tree_to_uhwi (TYPE_SIZE_UNIT (limb_type)));
+         g = gimple_build_assign (make_ssa_name (TREE_TYPE (limb_ptr)),
+                                  POINTER_PLUS_EXPR, gimple_phi_result (phip),
+                                  gimple_assign_lhs (g));
+         insert_before (g);
+         idx = create_loop (size_zero_node, &idx_next);
+         phi = create_phi_node (make_ssa_name (TREE_TYPE (limb_ptr)), m_bb);
+         add_phi_arg (phi, gimple_assign_lhs (g),
+                      find_edge (m_preheader_bb, m_bb), UNKNOWN_LOCATION);
+         g = gimple_build_assign (make_ssa_name (TREE_TYPE (v)),
+                                  RSHIFT_EXPR, t,
+                                  add_cast (unsigned_type_node, idx));
+         insert_before (g);
+         tree minuslimbsz
+           = fold_unary (NEGATE_EXPR, sizetype, TYPE_SIZE_UNIT (limb_type));
+         mem = build2 (MEM_REF, limb_type, gimple_phi_result (phi),
+                       fold_convert (limb_ptr_type, minuslimbsz));
+         g = gimple_build_assign (mem, add_cast (limb_type,
+                                                 gimple_assign_lhs (g)));
+         insert_before (g);
+         g = gimple_build_assign (idx_next, PLUS_EXPR, idx,
+                                  size_int (TYPE_PRECISION (limb_type)));
+         insert_before (g);
+         g = gimple_build_assign (make_ssa_name (TREE_TYPE (limb_ptr)),
+                                  POINTER_PLUS_EXPR, gimple_phi_result (phi),
+                                  minuslimbsz);
+         insert_before (g);
+         add_phi_arg (phi, gimple_assign_lhs (g), find_edge (m_bb, m_bb),
+                      UNKNOWN_LOCATION);
+         g = gimple_build_cond (LT_EXPR, idx_next, gimple_phi_result (phin),
+                                NULL_TREE, NULL_TREE);
+         insert_before (g);
+
+         m_gsi = gsi_after_labels (e->src);
+         idx = create_loop (size_zero_node, &idx_next);
+         phi = create_phi_node (make_ssa_name (TREE_TYPE (limb_ptr)), m_bb);
+         add_phi_arg (phi, gimple_phi_result (phip),
+                      find_edge (m_preheader_bb, m_bb), UNKNOWN_LOCATION);
+         g = gimple_build_assign (make_ssa_name (TREE_TYPE (v)),
+                                  RSHIFT_EXPR, t,
+                                  add_cast (unsigned_type_node, idx));
+         insert_before (g);
+         mem = build2 (MEM_REF, limb_type, gimple_phi_result (phi),
+                       build_int_cst (limb_ptr_type, 0));
+         g = gimple_build_assign (mem, add_cast (limb_type,
+                                                 gimple_assign_lhs (g)));
+         insert_before (g);
+         g = gimple_build_assign (idx_next, PLUS_EXPR, idx,
+                                  size_int (TYPE_PRECISION (limb_type)));
+         insert_before (g);
+         g = gimple_build_assign (make_ssa_name (TREE_TYPE (limb_ptr)),
+                                  POINTER_PLUS_EXPR, gimple_phi_result (phi),
+                                  TYPE_SIZE_UNIT (limb_type));
+         insert_before (g);
+         add_phi_arg (phi, gimple_assign_lhs (g), find_edge (m_bb, m_bb),
+                      UNKNOWN_LOCATION);
+         g = gimple_build_cond (LT_EXPR, idx_next, gimple_phi_result (phin),
+                                NULL_TREE, NULL_TREE);
+         insert_before (g);
+       }
+    }
+  else
+    sorry_at (gimple_location (stmt),
+             "%<__builtin_bitint_pack%> not supported yet");
+  m_gsi = gsi_for_stmt (stmt);
+  unlink_stmt_vdef (stmt);
+  release_ssa_name (gimple_vdef (stmt));
+  gsi_remove (&m_gsi, true);
+}
+
 /* Lower a call statement with one or more large/huge _BitInt
    arguments or large/huge _BitInt return value.  */
 
@@ -6320,6 +6921,12 @@ bitint_large_huge::lower_call (tree obj,
       default:
        break;
       }
+  if (gimple_call_builtin_p (stmt, BUILT_IN_BITINT_PACK)
+      || gimple_call_builtin_p (stmt, BUILT_IN_BITINT_UNPACK))
+    {
+      lower_pack_unpack (stmt);
+      return;
+    }
   bool returns_twice = (gimple_call_flags (stmt) & ECF_RETURNS_TWICE) != 0;
   for (unsigned int i = 0; i < nargs; ++i)
     {
@@ -7274,7 +7881,7 @@ gimple_lower_bitint (void)
            }
        }
     }
-  if (i == num_ssa_names)
+  if (i == num_ssa_names && !cfun->has_bitint_pack)
     return 0;
 
   basic_block bb;
@@ -7973,8 +8580,20 @@ gimple_lower_bitint (void)
        }
     }
 
-  if (large_huge.m_names || has_large_huge)
+  if (large_huge.m_names || has_large_huge || cfun->has_bitint_pack)
     {
+      if (cfun->has_bitint_pack && !limb_prec)
+       {
+         struct bitint_info info;
+         for (int i = 64; i < WIDE_INT_MAX_PRECISION - 1; i *= 2)
+           {
+             if (!targetm.c.bitint_type_info (i, &info))
+               return 0;
+             if (bitint_precision_kind (i) >= bitint_prec_large)
+               break;
+           }
+         gcc_assert (limb_prec);
+       }
       ret = TODO_update_ssa_only_virtuals | TODO_cleanup_cfg;
       calculate_dominance_info (CDI_DOMINATORS);
       if (optimize)
@@ -8112,6 +8731,9 @@ gimple_lower_bitint (void)
                      kind = MAX (kind, this_kind);
                    }
                }
+             if (gimple_call_builtin_p (stmt, BUILT_IN_BITINT_PACK)
+                 || gimple_call_builtin_p (stmt, BUILT_IN_BITINT_UNPACK))
+               kind = bitint_prec_large;
            }
          if (kind == bitint_prec_small)
            continue;
@@ -8453,7 +9075,7 @@ gimple_lower_bitint (void)
        }
     }
 
-  if (large_huge.m_names || has_large_huge)
+  if (large_huge.m_names || has_large_huge || cfun->has_bitint_pack)
     {
       gimple *nop = NULL;
       for (i = 0; i < num_ssa_names; ++i)
--- gcc/lto-streamer-in.cc.jj   2026-07-03 20:39:18.995958477 +0200
+++ gcc/lto-streamer-in.cc      2026-07-04 09:55:05.400650265 +0200
@@ -1329,6 +1329,7 @@ input_struct_function_base (struct funct
   fn->has_musttail = bp_unpack_value (&bp, 1);
   fn->has_unroll = bp_unpack_value (&bp, 1);
   fn->assume_function = bp_unpack_value (&bp, 1);
+  fn->has_bitint_pack = bp_unpack_value (&bp, 1);
   fn->va_list_fpr_size = bp_unpack_value (&bp, 8);
   fn->va_list_gpr_size = bp_unpack_value (&bp, 8);
   fn->last_clique = bp_unpack_value (&bp, sizeof (short) * 8);
--- gcc/lto-streamer-out.cc.jj  2026-07-03 20:39:18.995958477 +0200
+++ gcc/lto-streamer-out.cc     2026-07-04 09:55:05.400960499 +0200
@@ -2319,6 +2319,7 @@ output_struct_function_base (struct outp
   bp_pack_value (&bp, fn->has_musttail, 1);
   bp_pack_value (&bp, fn->has_unroll, 1);
   bp_pack_value (&bp, fn->assume_function, 1);
+  bp_pack_value (&bp, fn->has_bitint_pack, 1);
   bp_pack_value (&bp, fn->va_list_fpr_size, 8);
   bp_pack_value (&bp, fn->va_list_gpr_size, 8);
   bp_pack_value (&bp, fn->last_clique, sizeof (short) * 8);
--- gcc/config/i386/i386.cc.jj  2026-07-04 09:52:04.479188874 +0200
+++ gcc/config/i386/i386.cc     2026-07-04 09:55:05.390728140 +0200
@@ -5271,6 +5271,83 @@ ix86_gimplify_va_arg (tree valist, tree
     addr = build_va_arg_indirect_ref (addr);
   return build_va_arg_indirect_ref (addr);
 }
+
+/* Implement __builtin_va_arg_bitint.  */
+
+static tree
+ix86_gimplify_va_arg_bitint (tree valist, tree n, gimple_seq *pre_p,
+                            gimple_seq *post_p)
+{
+  /* Only 64bit target needs something special.  */
+  if (is_va_list_char_pointer (TREE_TYPE (valist)))
+    return std_gimplify_va_arg_bitint (valist, n, pre_p, post_p);
+
+  tree f_gpr = TYPE_FIELDS (TREE_TYPE (sysv_va_list_type_node));
+  tree f_fpr = DECL_CHAIN (f_gpr);
+  tree f_ovf = DECL_CHAIN (f_fpr);
+
+  tree ovf = build3 (COMPONENT_REF, TREE_TYPE (f_ovf), valist, f_ovf,
+                    NULL_TREE);
+
+  tree ptr = create_tmp_var (const_ptr_type_node, "bitint_ptr");
+  tree labend = create_artificial_label (input_location);
+  for (int i = BITS_PER_UNIT; i <= BITS_PER_WORD * 2; i <<= 1)
+    {
+      tree type = build_bitint_type (i, 1);
+      gimple_seq post_seq = NULL;
+      tree labtrue = create_artificial_label (input_location);
+      tree labfalse = create_artificial_label (input_location);
+      gcond *cond_stmt
+       = gimple_build_cond (LE_EXPR, n,
+                            build_int_cst (TREE_TYPE (n), i),
+                            labtrue, labfalse);
+      gimple_seq_add_stmt (pre_p, cond_stmt);
+      gimple_seq_add_stmt (pre_p, gimple_build_label (labtrue));
+      tree mem_ref
+       = ix86_gimplify_va_arg (unshare_expr (valist), type, pre_p, &post_seq);
+      gcc_assert (TREE_CODE (mem_ref) == MEM_REF);
+      gimplify_assign (ptr, build_fold_addr_expr (mem_ref), pre_p);
+      if (post_seq)
+       gimple_seq_add_seq (pre_p, post_seq);
+      gimple_seq_add_stmt (pre_p, gimple_build_goto (labend));
+      gimple_seq_add_stmt (pre_p, gimple_build_label (labfalse));
+    }
+
+  tree type = build_bitint_type (BITS_PER_WORD * 4, 1);
+  bool indirect_p = pass_va_arg_by_reference (type);
+  int size = 0, rsize = 0;
+  tree type_size = NULL_TREE;
+  if (indirect_p)
+    {
+      type = build_pointer_type (type);
+      size = arg_int_size_in_bytes (type);
+      rsize = CEIL (size, UNITS_PER_WORD);
+    }
+  else
+    {
+      tree t = fold_convert (sizetype, n);
+      t = size_binop (PLUS_EXPR, t, size_int (BITS_PER_WORD - 1));
+      t = size_binop (TRUNC_DIV_EXPR, t, size_int (BITS_PER_WORD));
+      type_size = size_binop (MULT_EXPR, t,
+                             size_int (UNITS_PER_WORD));
+    }
+
+  tree t = ovf;
+  gimplify_expr (&t, pre_p, NULL, is_gimple_val, fb_rvalue);
+  if (indirect_p)
+    gimplify_assign (ptr, build_va_arg_indirect_ref (t), pre_p);
+  else
+    gimplify_assign (ptr, t, pre_p);
+
+  if (indirect_p)
+    t = fold_build_pointer_plus_hwi (t, rsize * UNITS_PER_WORD);
+  else
+    t = fold_build_pointer_plus (t, type_size);
+  gimplify_assign (unshare_expr (ovf), t, pre_p);
+
+  gimple_seq_add_stmt (pre_p, gimple_build_label (labend));
+  return ptr;
+}
 
 /* Return true if OPNUM's MEM should be matched
    in movabs* patterns.  */
@@ -28586,6 +28663,9 @@ static const scoped_attribute_specs *con
 #undef TARGET_GIMPLIFY_VA_ARG_EXPR
 #define TARGET_GIMPLIFY_VA_ARG_EXPR ix86_gimplify_va_arg
 
+#undef TARGET_GIMPLIFY_VA_ARG_BITINT
+#define TARGET_GIMPLIFY_VA_ARG_BITINT ix86_gimplify_va_arg_bitint
+
 #undef TARGET_SCALAR_MODE_SUPPORTED_P
 #define TARGET_SCALAR_MODE_SUPPORTED_P ix86_scalar_mode_supported_p
 
--- gcc/c-family/c-common.cc.jj 2026-07-03 20:39:18.977958696 +0200
+++ gcc/c-family/c-common.cc    2026-07-04 09:55:05.388954104 +0200
@@ -6972,6 +6972,103 @@ check_builtin_function_arguments (locati
        }
       return true;
 
+    case BUILT_IN_VA_ARG_BITINT:
+    case BUILT_IN_BITINT_UNPACK:
+    case BUILT_IN_BITINT_PACK:
+      if (!builtin_function_validate_nargs (loc, fndecl, nargs, 5, complain))
+       return false;
+      if (!INTEGRAL_TYPE_P (TREE_TYPE (args[1])))
+       {
+         if (complain)
+           error_at (ARG_LOCATION (1),
+                     "argument %u in call to function "
+                     "%qE does not have integral type",
+                     2, fndecl);
+         return false;
+       }
+      if (TREE_CODE (TREE_TYPE (args[2])) != POINTER_TYPE)
+       {
+         if (complain)
+           error_at (ARG_LOCATION (2),
+                     "argument %u in call to function "
+                     "%qE does not have pointer type",
+                     3, fndecl);
+         return false;
+       }
+      if (TREE_CODE (TREE_TYPE (TREE_TYPE (args[2]))) != INTEGER_TYPE)
+       {
+         if (complain)
+           error_at (ARG_LOCATION (2),
+                     "argument %u in call to function "
+                     "%qE does not have pointer to integer type",
+                     3, fndecl);
+         return false;
+       }
+      if (DECL_FUNCTION_CODE (fndecl) != BUILT_IN_BITINT_PACK
+         && TYPE_READONLY (TREE_TYPE (TREE_TYPE (args[2]))))
+       {
+         if (complain)
+           error_at (ARG_LOCATION (2),
+                     "argument %u in call to function "
+                     "%qE is a pointer to %<const%> integer type",
+                     3, fndecl);
+         return false;
+       }
+      if (!INTEGRAL_TYPE_P (TREE_TYPE (args[3])))
+       {
+         if (complain)
+           error_at (ARG_LOCATION (3),
+                     "argument %u in call to function "
+                     "%qE does not have integral type",
+                     4, fndecl);
+         return false;
+       }
+      if (!INTEGRAL_TYPE_P (TREE_TYPE (args[4])))
+       {
+         if (complain)
+           error_at (ARG_LOCATION (4),
+                     "argument %u in call to function "
+                     "%qE does not have integral type",
+                     5, fndecl);
+         return false;
+       }
+      args[1] = fold_convert (sizetype, args[1]);
+      if (TREE_CODE (TREE_TYPE (args[3])) != BOOLEAN_TYPE)
+       {
+         if (TREE_CODE (args[3]) == INTEGER_CST)
+           args[3] = constant_boolean_node (integer_nonzerop (args[3]),
+                                            boolean_type_node);
+         else
+           args[3] = build2 (NE_EXPR, boolean_type_node,
+                             args[3], build_zero_cst (TREE_TYPE (args[3])));
+       }
+      if (TREE_CODE (TREE_TYPE (args[4])) != BOOLEAN_TYPE)
+       {
+         if (TREE_CODE (args[4]) == INTEGER_CST)
+           args[4] = constant_boolean_node (integer_nonzerop (args[4]),
+                                            boolean_type_node);
+         else
+           args[4] = build2 (NE_EXPR, boolean_type_node,
+                             args[4], build_zero_cst (TREE_TYPE (args[4])));
+       }
+      {
+       if (c_dialect_cxx ())
+         {
+           sorry_at (loc, "%qD used when %<_BitInt(N)%> is not supported "
+                          "in C++", fndecl);
+           return false;
+         }
+       struct bitint_info info;
+       if (!targetm.c.bitint_type_info (256, &info))
+         {
+           sorry_at (loc, "%qD used when %<_BitInt(N)%> is not supported "
+                          "on this target", fndecl);
+           return false;
+         }
+      }
+
+      return true;
+
     default:
       return true;
     }
--- gcc/testsuite/gcc.dg/bitint-138.c.jj        2026-07-04 09:55:05.394614638 
+0200
+++ gcc/testsuite/gcc.dg/bitint-138.c   2026-07-04 16:56:27.065444577 +0200
@@ -0,0 +1,219 @@
+/* { dg-do run { target bitint } } */
+/* { dg-options "-O2" } */
+
+#include <stdarg.h>
+
+#ifndef T
+#define T long
+#endif
+
+[[gnu::noipa]] void
+foo (va_list *ap, int n, unsigned T *p, bool e, bool u)
+{
+  __builtin_va_arg_bitint (*ap, n, p, e, u);
+}
+
+#if __BITINT_MAXWIDTH__ >= 837
+#define W (sizeof (T) * __CHAR_BIT__)
+
+[[gnu::noipa]] _BitInt(837)
+bar (int n, ...)
+{
+  va_list ap;
+  unsigned T a[(837 + W - 1) / W + 1]; 
+  va_start (ap);
+  a[(n + W - 1) / W] = 42;
+  foo (&ap, n, a, false, true);
+  if (a[(n + W - 1) / W] != 42)
+    __builtin_abort ();
+  if (va_arg (ap, int) != 42)
+    __builtin_abort ();
+  va_end (ap);
+  _BitInt(837) r = 0;
+  int i = 0;
+  for (int j = 0; i < n; i += W, ++j)
+    r += ((_BitInt(837)) a[j]) << i;
+  return r;
+}
+
+[[gnu::noipa]] _BitInt(837)
+baz (int n, ...)
+{
+  va_list ap;
+  unsigned T a[(837 + W - 1) / W + 1]; 
+  va_start (ap);
+  a[(n + W - 1) / W] = 42;
+  foo (&ap, n, a, true, true);
+  if (a[(n + W - 1) / W] != 42)
+    __builtin_abort ();
+  if (va_arg (ap, int) != 42)
+    __builtin_abort ();
+  va_end (ap);
+  _BitInt(837) r = 0;
+  int i = 0;
+  for (int j = 0; i < n; i += W, ++j)
+    r += ((_BitInt(837)) a[(n + W - 1) / W - 1 - j]) << i;
+  return r;
+}
+#endif
+
+[[gnu::noipa]] void
+qux (void *b, int n, unsigned T *p, bool e, bool u)
+{
+  __builtin_bitint_unpack (b, n, p, e, u);
+}
+
+#if __BITINT_MAXWIDTH__ >= 837
+[[gnu::noipa]] _BitInt(837)
+corge (int n, void *b)
+{
+  unsigned T a[(837 + W - 1) / W + 1]; 
+  a[(n + W - 1) / W] = 42;
+  qux (b, n, a, false, true);
+  if (a[(n + W - 1) / W] != 42)
+    __builtin_abort ();
+  _BitInt(837) r = 0;
+  int i = 0;
+  for (int j = 0; i < n; i += W, ++j)
+    r += ((_BitInt(837)) a[j]) << i;
+  return r;
+}
+
+[[gnu::noipa]] _BitInt(837)
+garply (int n, void *b)
+{
+  unsigned T a[(837 + W - 1) / W + 1]; 
+  a[(n + W - 1) / W] = 42;
+  qux (b, n, a, true, true);
+  if (a[(n + W - 1) / W] != 42)
+    __builtin_abort ();
+  _BitInt(837) r = 0;
+  int i = 0;
+  for (int j = 0; i < n; i += W, ++j)
+    r += ((_BitInt(837)) a[(n + W - 1) / W - 1 - j]) << i;
+  return r;
+}
+#endif
+
+int
+main ()
+{
+#if __BITINT_MAXWIDTH__ >= 837
+  if (bar (1, 0uwb, 42) != 0uwb)
+    __builtin_abort ();
+  if (bar (1, 1uwb, 42) != 1uwb)
+    __builtin_abort ();
+  if (bar (5, 19uwb, 42) != 19uwb)
+    __builtin_abort ();
+  if (bar (8, 206uwb, 42) != 206uwb)
+    __builtin_abort ();
+  if (bar (13, 7570uwb, 42) != 7570uwb)
+    __builtin_abort ();
+  if (bar (16, 38151uwb, 42) != 38151uwb)
+    __builtin_abort ();
+  if (bar (27, 85311871uwb, 42) != 85311871uwb)
+    __builtin_abort ();
+  if (bar (32, 2918365024uwb, 42) != 2918365024uwb)
+    __builtin_abort ();
+  if (bar (52, 2418319599906367uwb, 42) != 2418319599906367uwb)
+    __builtin_abort ();
+  if (bar (64, 10324453899960610638uwb, 42) != 10324453899960610638uwb)
+    __builtin_abort ();
+  if (bar (115, 35493143902794610347964586515544041uwb, 42)
+      != 35493143902794610347964586515544041uwb)
+    __builtin_abort ();
+  if (bar (128, 242619899432347503858857658506928415851uwb, 42)
+      != 242619899432347503858857658506928415851uwb)
+    __builtin_abort ();
+  if (bar (526, 
180194070356886021255857914345126405999398316757939019056773385284724305086631574185580484256183791238681315262210197901922727810824312479861470581236057569742uwb,
 42)
+      != 
180194070356886021255857914345126405999398316757939019056773385284724305086631574185580484256183791238681315262210197901922727810824312479861470581236057569742uwb)
+    __builtin_abort ();
+  if (bar (817, 
873989987746428259412194333913416701987357762822590714399458303903535888835232670878457161432636363996257309241302481691723537010408733419813385804491106555801784494262060916206872597091033287849274902594962928694944169726768114734355431735427071uwb,
 42)
+      != 
873989987746428259412194333913416701987357762822590714399458303903535888835232670878457161432636363996257309241302481691723537010408733419813385804491106555801784494262060916206872597091033287849274902594962928694944169726768114734355431735427071uwb)
+    __builtin_abort ();
+  if (bar (832, 
23594434241796262031251233318841235347130683007441570017128772622267774079572850334920487667606346508713826956600386054750426773544457159868730626269255744559973640839812924189319711235173267236738614098413184882928609457627967564162746003214826547541uwb,
 42)
+      != 
23594434241796262031251233318841235347130683007441570017128772622267774079572850334920487667606346508713826956600386054750426773544457159868730626269255744559973640839812924189319711235173267236738614098413184882928609457627967564162746003214826547541uwb)
+    __builtin_abort ();
+  if (baz (1, 0uwb, 42) != 0uwb)
+    __builtin_abort ();
+  if (baz (1, 1uwb, 42) != 1uwb)
+    __builtin_abort ();
+  if (baz (5, 19uwb, 42) != 19uwb)
+    __builtin_abort ();
+  if (baz (8, 206uwb, 42) != 206uwb)
+    __builtin_abort ();
+  if (baz (13, 7570uwb, 42) != 7570uwb)
+    __builtin_abort ();
+  if (baz (16, 38151uwb, 42) != 38151uwb)
+    __builtin_abort ();
+  if (baz (27, 85311871uwb, 42) != 85311871uwb)
+    __builtin_abort ();
+  if (baz (32, 2918365024uwb, 42) != 2918365024uwb)
+    __builtin_abort ();
+  if (baz (52, 2418319599906367uwb, 42) != 2418319599906367uwb)
+    __builtin_abort ();
+  if (baz (64, 10324453899960610638uwb, 42) != 10324453899960610638uwb)
+    __builtin_abort ();
+  if (baz (115, 35493143902794610347964586515544041uwb, 42)
+      != 35493143902794610347964586515544041uwb)
+    __builtin_abort ();
+  if (baz (128, 242619899432347503858857658506928415851uwb, 42)
+      != 242619899432347503858857658506928415851uwb)
+    __builtin_abort ();
+  if (baz (526, 
180194070356886021255857914345126405999398316757939019056773385284724305086631574185580484256183791238681315262210197901922727810824312479861470581236057569742uwb,
 42)
+      != 
180194070356886021255857914345126405999398316757939019056773385284724305086631574185580484256183791238681315262210197901922727810824312479861470581236057569742uwb)
+    __builtin_abort ();
+  if (baz (817, 
873989987746428259412194333913416701987357762822590714399458303903535888835232670878457161432636363996257309241302481691723537010408733419813385804491106555801784494262060916206872597091033287849274902594962928694944169726768114734355431735427071uwb,
 42)
+      != 
873989987746428259412194333913416701987357762822590714399458303903535888835232670878457161432636363996257309241302481691723537010408733419813385804491106555801784494262060916206872597091033287849274902594962928694944169726768114734355431735427071uwb)
+    __builtin_abort ();
+  if (baz (832, 
23594434241796262031251233318841235347130683007441570017128772622267774079572850334920487667606346508713826956600386054750426773544457159868730626269255744559973640839812924189319711235173267236738614098413184882928609457627967564162746003214826547541uwb,
 42)
+      != 
23594434241796262031251233318841235347130683007441570017128772622267774079572850334920487667606346508713826956600386054750426773544457159868730626269255744559973640839812924189319711235173267236738614098413184882928609457627967564162746003214826547541uwb)
+    __builtin_abort ();
+#define corge(n, v) \
+  do                                   \
+    {                                  \
+      unsigned _BitInt(n) w = v;       \
+      if ((corge) (n, &w) != v)                \
+       __builtin_abort ();             \
+    }                                  \
+  while (0)
+#define garply(n, v) \
+  do                                   \
+    {                                  \
+      unsigned _BitInt(n) w = v;       \
+      if ((garply) (n, &w) != v)       \
+       __builtin_abort ();             \
+    }                                  \
+  while (0)
+  corge (1, 0uwb);
+  corge (1, 1uwb);
+  corge (5, 19uwb);
+  corge (8, 206uwb);
+  corge (13, 7570uwb);
+  corge (16, 38151uwb);
+  corge (27, 85311871uwb);
+  corge (32, 2918365024uwb);
+  corge (52, 2418319599906367uwb);
+  corge (64, 10324453899960610638uwb);
+  corge (115, 35493143902794610347964586515544041uwb);
+  corge (128, 242619899432347503858857658506928415851uwb);
+  corge (526, 
180194070356886021255857914345126405999398316757939019056773385284724305086631574185580484256183791238681315262210197901922727810824312479861470581236057569742uwb);
+  corge (817, 
873989987746428259412194333913416701987357762822590714399458303903535888835232670878457161432636363996257309241302481691723537010408733419813385804491106555801784494262060916206872597091033287849274902594962928694944169726768114734355431735427071uwb);
+  corge (832, 
23594434241796262031251233318841235347130683007441570017128772622267774079572850334920487667606346508713826956600386054750426773544457159868730626269255744559973640839812924189319711235173267236738614098413184882928609457627967564162746003214826547541uwb);
+  garply (1, 0uwb);
+  garply (1, 1uwb);
+  garply (5, 19uwb);
+  garply (8, 206uwb);
+  garply (13, 7570uwb);
+  garply (16, 38151uwb);
+  garply (27, 85311871uwb);
+  garply (32, 2918365024uwb);
+  garply (52, 2418319599906367uwb);
+  garply (64, 10324453899960610638uwb);
+  garply (115, 35493143902794610347964586515544041uwb);
+  garply (128, 242619899432347503858857658506928415851uwb);
+  garply (526, 
180194070356886021255857914345126405999398316757939019056773385284724305086631574185580484256183791238681315262210197901922727810824312479861470581236057569742uwb);
+  garply (817, 
873989987746428259412194333913416701987357762822590714399458303903535888835232670878457161432636363996257309241302481691723537010408733419813385804491106555801784494262060916206872597091033287849274902594962928694944169726768114734355431735427071uwb);
+  garply (832, 
23594434241796262031251233318841235347130683007441570017128772622267774079572850334920487667606346508713826956600386054750426773544457159868730626269255744559973640839812924189319711235173267236738614098413184882928609457627967564162746003214826547541uwb);
+#endif
+}
--- gcc/testsuite/gcc.dg/bitint-139.c.jj        2026-07-04 14:04:26.330909315 
+0200
+++ gcc/testsuite/gcc.dg/bitint-139.c   2026-07-04 16:55:49.494939690 +0200
@@ -0,0 +1,227 @@
+/* { dg-do run { target bitint } } */
+/* { dg-options "-std=c2y -O2" } */
+
+#include <stdarg.h>
+
+#ifndef T
+#define T long
+#endif
+
+[[gnu::noipa]] void
+foo (va_list *ap, int n, unsigned T *p, bool e, bool u)
+{
+  __builtin_va_arg_bitint (*ap, n, p, e, u);
+}
+
+#if __BITINT_MAXWIDTH__ >= 837
+#define W (sizeof (T) * __CHAR_BIT__)
+
+[[gnu::noipa]] _BitInt(837)
+bar (int n, ...)
+{
+  va_list ap;
+  unsigned T a[(837 + W - 1) / W + 1]; 
+  va_start (ap);
+  a[(n + W - 1) / W] = 42;
+  foo (&ap, n, a, false, false);
+  if (a[(n + W - 1) / W] != 42)
+    __builtin_abort ();
+  if (va_arg (ap, int) != 42)
+    __builtin_abort ();
+  va_end (ap);
+  _BitInt(837) r = 0;
+  int i = 0, j;
+  for (j = 0; i < n; i += W, ++j)
+    r += ((_BitInt(837)) a[j]) << i;
+  if ((signed T) a[j - 1] < 0)
+    r += ((_BitInt(837)) -1) << i;
+  return r;
+}
+
+[[gnu::noipa]] _BitInt(837)
+baz (int n, ...)
+{
+  va_list ap;
+  unsigned T a[(837 + W - 1) / W + 1]; 
+  va_start (ap);
+  a[(n + W - 1) / W] = 42;
+  foo (&ap, n, a, true, false);
+  if (a[(n + W - 1) / W] != 42)
+    __builtin_abort ();
+  if (va_arg (ap, int) != 42)
+    __builtin_abort ();
+  va_end (ap);
+  _BitInt(837) r = 0;
+  int i = 0;
+  for (int j = 0; i < n; i += W, ++j)
+    r += ((_BitInt(837)) a[(n + W - 1) / W - 1 - j]) << i;
+  if ((signed T) a[0] < 0)
+    r += ((_BitInt(837)) -1) << i;
+  return r;
+}
+#endif
+
+[[gnu::noipa]] void
+qux (void *b, int n, unsigned T *p, bool e, bool u)
+{
+  __builtin_bitint_unpack (b, n, p, e, u);
+}
+
+#if __BITINT_MAXWIDTH__ >= 837
+[[gnu::noipa]] _BitInt(837)
+corge (int n, void *b)
+{
+  unsigned T a[(837 + W - 1) / W + 1]; 
+  a[(n + W - 1) / W] = 42;
+  qux (b, n, a, false, false);
+  if (a[(n + W - 1) / W] != 42)
+    __builtin_abort ();
+  _BitInt(837) r = 0;
+  int i = 0, j;
+  for (j = 0; i < n; i += W, ++j)
+    r += ((_BitInt(837)) a[j]) << i;
+  if ((signed T) a[j - 1] < 0)
+    r += ((_BitInt(837)) -1) << i;
+  return r;
+}
+
+[[gnu::noipa]] _BitInt(837)
+garply (int n, void *b)
+{
+  unsigned T a[(837 + W - 1) / W + 1]; 
+  a[(n + W - 1) / W] = 42;
+  qux (b, n, a, true, false);
+  if (a[(n + W - 1) / W] != 42)
+    __builtin_abort ();
+  _BitInt(837) r = 0;
+  int i = 0;
+  for (int j = 0; i < n; i += W, ++j)
+    r += ((_BitInt(837)) a[(n + W - 1) / W - 1 - j]) << i;
+  if ((signed T) a[0] < 0)
+    r += ((_BitInt(837)) -1) << i;
+  return r;
+}
+#endif
+
+int
+main ()
+{
+#if __BITINT_MAXWIDTH__ >= 837
+  if (bar (1, 0wb, 42) != 0wb)
+    __builtin_abort ();
+  if (bar (1, (_BitInt(1)) -1wb, 42) != -1)
+    __builtin_abort ();
+  if (bar (5, -12wb, 42) != -12wb)
+    __builtin_abort ();
+  if (bar (8, 107wb, 42) != 107wb)
+    __builtin_abort ();
+  if (bar (13, -3412wb, 42) != -3412wb)
+    __builtin_abort ();
+  if (bar (16, 24476wb, 42) != 24476wb)
+    __builtin_abort ();
+  if (bar (27, 62759870wb, 42) != 62759870wb)
+    __builtin_abort ();
+  if (bar (32, -1940906384wb, 42) != -1940906384wb)
+    __builtin_abort ();
+  if (bar (52, 1858183038390462wb, 42) != 1858183038390462wb)
+    __builtin_abort ();
+  if (bar (64, -8256680225559468133wb, 42) != -8256680225559468133wb)
+    __builtin_abort ();
+  if (bar (115, -19567690694941323284865986666034440wb, 42)
+      != -19567690694941323284865986666034440wb)
+    __builtin_abort ();
+  if (bar (128, 161295407943090171995441423582245738873wb, 42)
+      != 161295407943090171995441423582245738873wb)
+    __builtin_abort ();
+  if (bar (526, 
-74271886962589044440447868575290160981240275268510476349065102288448110495100787566581815991681080970045571964341005744164492099577970625349715415120434591551wb,
 42)
+      != 
-74271886962589044440447868575290160981240275268510476349065102288448110495100787566581815991681080970045571964341005744164492099577970625349715415120434591551wb)
+    __builtin_abort ();
+  if (bar (817, 
334564236539647801894756601387982526099412299271253169952919468031421908511714389453640635282951515192153648697545656682447892978128484511111304249912088833406530236950518222889146208703714474459832662825296577861528390922881280570442885198821395wb,
 42)
+      != 
334564236539647801894756601387982526099412299271253169952919468031421908511714389453640635282951515192153648697545656682447892978128484511111304249912088833406530236950518222889146208703714474459832662825296577861528390922881280570442885198821395wb)
+    __builtin_abort ();
+  if (bar (832, 
-10126372172398046441720587244981184637120620339348885338829980023036886270537721600610561760907517491635974396689410675687310513034165727511443880739391604187139125794232654654443819264830956682943559210170711510767483980557257583148651885937914964439wb,
 42)
+      != 
-10126372172398046441720587244981184637120620339348885338829980023036886270537721600610561760907517491635974396689410675687310513034165727511443880739391604187139125794232654654443819264830956682943559210170711510767483980557257583148651885937914964439wb)
+    __builtin_abort ();
+  if (baz (1, 0wb, 42) != 0wb)
+    __builtin_abort ();
+  if (baz (1, (_BitInt(1)) -1wb, 42) != -1)
+    __builtin_abort ();
+  if (baz (5, 12wb, 42) != 12wb)
+    __builtin_abort ();
+  if (baz (8, -107wb, 42) != -107wb)
+    __builtin_abort ();
+  if (baz (13, 3412wb, 42) != 3412wb)
+    __builtin_abort ();
+  if (baz (16, -24476wb, 42) != -24476wb)
+    __builtin_abort ();
+  if (baz (27, -62759870wb, 42) != -62759870wb)
+    __builtin_abort ();
+  if (baz (32, 1940906384wb, 42) != 1940906384wb)
+    __builtin_abort ();
+  if (baz (52, -1858183038390462wb, 42) != -1858183038390462wb)
+    __builtin_abort ();
+  if (baz (64, 8256680225559468133wb, 42) != 8256680225559468133wb)
+    __builtin_abort ();
+  if (baz (115, 19567690694941323284865986666034440wb, 42)
+      != 19567690694941323284865986666034440wb)
+    __builtin_abort ();
+  if (baz (128, -161295407943090171995441423582245738873wb, 42)
+      != -161295407943090171995441423582245738873wb)
+    __builtin_abort ();
+  if (baz (526, 
74271886962589044440447868575290160981240275268510476349065102288448110495100787566581815991681080970045571964341005744164492099577970625349715415120434591551wb,
 42)
+      != 
74271886962589044440447868575290160981240275268510476349065102288448110495100787566581815991681080970045571964341005744164492099577970625349715415120434591551wb)
+    __builtin_abort ();
+  if (baz (817, 
-334564236539647801894756601387982526099412299271253169952919468031421908511714389453640635282951515192153648697545656682447892978128484511111304249912088833406530236950518222889146208703714474459832662825296577861528390922881280570442885198821395wb,
 42)
+      != 
-334564236539647801894756601387982526099412299271253169952919468031421908511714389453640635282951515192153648697545656682447892978128484511111304249912088833406530236950518222889146208703714474459832662825296577861528390922881280570442885198821395wb)
+    __builtin_abort ();
+  if (baz (832, 
10126372172398046441720587244981184637120620339348885338829980023036886270537721600610561760907517491635974396689410675687310513034165727511443880739391604187139125794232654654443819264830956682943559210170711510767483980557257583148651885937914964439wb,
 42)
+      != 
10126372172398046441720587244981184637120620339348885338829980023036886270537721600610561760907517491635974396689410675687310513034165727511443880739391604187139125794232654654443819264830956682943559210170711510767483980557257583148651885937914964439wb)
+    __builtin_abort ();
+#define corge(n, v) \
+  do                                   \
+    {                                  \
+      unsigned _BitInt(n) w = v;       \
+      if ((corge) (n, &w) != v)                \
+       __builtin_abort ();             \
+    }                                  \
+  while (0)
+#define garply(n, v) \
+  do                                   \
+    {                                  \
+      unsigned _BitInt(n) w = v;       \
+      if ((garply) (n, &w) != v)       \
+       __builtin_abort ();             \
+    }                                  \
+  while (0)
+  corge (1, 0wb);
+  corge (1, (_BitInt(1)) -1wb);
+  corge (5, -12wb);
+  corge (8, 107wb);
+  corge (13, -3412wb);
+  corge (16, 24476wb);
+  corge (27, 62759870wb);
+  corge (32, -1940906384wb);
+  corge (52, 1858183038390462wb);
+  corge (64, -8256680225559468133wb);
+  corge (115, -19567690694941323284865986666034440wb);
+  corge (128, 161295407943090171995441423582245738873wb);
+  corge (526, 
-74271886962589044440447868575290160981240275268510476349065102288448110495100787566581815991681080970045571964341005744164492099577970625349715415120434591551wb);
+  corge (817, 
334564236539647801894756601387982526099412299271253169952919468031421908511714389453640635282951515192153648697545656682447892978128484511111304249912088833406530236950518222889146208703714474459832662825296577861528390922881280570442885198821395wb);
+  corge (832, 
-10126372172398046441720587244981184637120620339348885338829980023036886270537721600610561760907517491635974396689410675687310513034165727511443880739391604187139125794232654654443819264830956682943559210170711510767483980557257583148651885937914964439wb);
+  garply (1, 0wb);
+  garply (1, (_BitInt(1)) -1wb);
+  garply (5, 12wb);
+  garply (8, -107wb);
+  garply (13, 3412wb);
+  garply (16, -24476wb);
+  garply (27, -62759870wb);
+  garply (32, 1940906384wb);
+  garply (52, -1858183038390462wb);
+  garply (64, 8256680225559468133wb);
+  garply (115, 19567690694941323284865986666034440wb);
+  garply (128, -161295407943090171995441423582245738873wb);
+  garply (526, 
74271886962589044440447868575290160981240275268510476349065102288448110495100787566581815991681080970045571964341005744164492099577970625349715415120434591551wb);
+  garply (817, 
-334564236539647801894756601387982526099412299271253169952919468031421908511714389453640635282951515192153648697545656682447892978128484511111304249912088833406530236950518222889146208703714474459832662825296577861528390922881280570442885198821395wb);
+  garply (832, 
10126372172398046441720587244981184637120620339348885338829980023036886270537721600610561760907517491635974396689410675687310513034165727511443880739391604187139125794232654654443819264830956682943559210170711510767483980557257583148651885937914964439wb);
+#endif
+}
--- gcc/testsuite/gcc.dg/bitint-140.c.jj        2026-07-04 16:53:11.388023264 
+0200
+++ gcc/testsuite/gcc.dg/bitint-140.c   2026-07-04 16:56:53.846091756 +0200
@@ -0,0 +1,7 @@
+/* { dg-do run { target bitint } } */
+/* { dg-options "-O2" } */
+
+#include <stdarg.h>
+
+#define T short
+#include "bitint-138.c"
--- gcc/testsuite/gcc.dg/bitint-141.c.jj        2026-07-06 10:09:51.894338823 
+0200
+++ gcc/testsuite/gcc.dg/bitint-141.c   2026-07-06 10:10:04.340173989 +0200
@@ -0,0 +1,7 @@
+/* { dg-do run { target bitint } } */
+/* { dg-options "-std=c2y -O2" } */
+
+#include <stdarg.h>
+
+#define T short
+#include "bitint-139.c"
--- gcc/testsuite/gcc.dg/bitint-142.c.jj        2026-07-06 10:10:18.141991203 
+0200
+++ gcc/testsuite/gcc.dg/bitint-142.c   2026-07-06 10:10:32.242804452 +0200
@@ -0,0 +1,7 @@
+/* { dg-do run { target bitint } } */
+/* { dg-options "-O2" } */
+
+#include <stdarg.h>
+
+#define T char
+#include "bitint-138.c"
--- gcc/testsuite/gcc.dg/bitint-143.c.jj        2026-07-06 10:10:20.974953681 
+0200
+++ gcc/testsuite/gcc.dg/bitint-143.c   2026-07-06 10:10:41.418682930 +0200
@@ -0,0 +1,7 @@
+/* { dg-do run { target bitint } } */
+/* { dg-options "-std=c2y -O2" } */
+
+#include <stdarg.h>
+
+#define T char
+#include "bitint-139.c"
--- gcc/testsuite/gcc.dg/bitint-144.c.jj        2026-07-06 10:10:58.889451547 
+0200
+++ gcc/testsuite/gcc.dg/bitint-144.c   2026-07-06 10:11:08.401325574 +0200
@@ -0,0 +1,7 @@
+/* { dg-do run { target bitint } } */
+/* { dg-options "-O2" } */
+
+#include <stdarg.h>
+
+#define T int
+#include "bitint-138.c"
--- gcc/testsuite/gcc.dg/bitint-145.c.jj        2026-07-06 10:11:01.735413856 
+0200
+++ gcc/testsuite/gcc.dg/bitint-145.c   2026-07-06 10:11:14.146249489 +0200
@@ -0,0 +1,7 @@
+/* { dg-do run { target bitint } } */
+/* { dg-options "-std=c2y -O2" } */
+
+#include <stdarg.h>
+
+#define T int
+#include "bitint-139.c"
--- gcc/testsuite/gcc.dg/bitint-146.c.jj        2026-07-06 10:11:26.324088210 
+0200
+++ gcc/testsuite/gcc.dg/bitint-146.c   2026-07-06 10:11:40.595899197 +0200
@@ -0,0 +1,7 @@
+/* { dg-do run { target bitint } } */
+/* { dg-options "-O2" } */
+
+#include <stdarg.h>
+
+#define T long long
+#include "bitint-138.c"
--- gcc/testsuite/gcc.dg/bitint-147.c.jj        2026-07-06 10:11:29.116051233 
+0200
+++ gcc/testsuite/gcc.dg/bitint-147.c   2026-07-06 10:11:51.268757848 +0200
@@ -0,0 +1,7 @@
+/* { dg-do run { target bitint } } */
+/* { dg-options "-std=c2y -O2" } */
+
+#include <stdarg.h>
+
+#define T long long
+#include "bitint-139.c"
--- gcc/testsuite/gcc.dg/bitint-148.c.jj        2026-07-06 10:11:59.170653195 
+0200
+++ gcc/testsuite/gcc.dg/bitint-148.c   2026-07-06 10:12:19.071389631 +0200
@@ -0,0 +1,7 @@
+/* { dg-do run { target { bitint && int128 } } } */
+/* { dg-options "-O2" } */
+
+#include <stdarg.h>
+
+#define T __int128
+#include "bitint-138.c"
--- gcc/testsuite/gcc.dg/bitint-149.c.jj        2026-07-06 10:12:06.143560848 
+0200
+++ gcc/testsuite/gcc.dg/bitint-149.c   2026-07-06 10:18:58.203104785 +0200
@@ -0,0 +1,7 @@
+/* { dg-do run { target { bitint && int128 } } } */
+/* { dg-options "-std=gnu2y -O2" } */
+
+#include <stdarg.h>
+
+#define T __int128
+#include "bitint-139.c"
--- gcc/testsuite/gcc.dg/bitint-150.c.jj        2026-07-06 13:18:24.085344012 
+0200
+++ gcc/testsuite/gcc.dg/bitint-150.c   2026-07-06 13:19:43.870298114 +0200
@@ -0,0 +1,207 @@
+/* { dg-do run { target bitint } } */
+/* { dg-options "-O2" } */
+
+#include <stdarg.h>
+
+#ifndef T
+#define T long
+#endif
+
+#if __BITINT_MAXWIDTH__ >= 837
+#define W (sizeof (T) * __CHAR_BIT__)
+
+[[gnu::noipa]] _BitInt(837)
+bar (int n, ...)
+{
+  va_list ap;
+  unsigned T a[(837 + W - 1) / W + 1]; 
+  va_start (ap);
+  a[(n + W - 1) / W] = 42;
+  __builtin_va_arg_bitint (ap, n, a, false, true);
+  if (a[(n + W - 1) / W] != 42)
+    __builtin_abort ();
+  if (va_arg (ap, int) != 42)
+    __builtin_abort ();
+  va_end (ap);
+  _BitInt(837) r = 0;
+  int i = 0;
+  for (int j = 0; i < n; i += W, ++j)
+    r += ((_BitInt(837)) a[j]) << i;
+  return r;
+}
+
+[[gnu::noipa]] _BitInt(837)
+baz (int n, ...)
+{
+  va_list ap;
+  unsigned T a[(837 + W - 1) / W + 1]; 
+  va_start (ap);
+  a[(n + W - 1) / W] = 42;
+  __builtin_va_arg_bitint (ap, n, a, true, true);
+  if (a[(n + W - 1) / W] != 42)
+    __builtin_abort ();
+  if (va_arg (ap, int) != 42)
+    __builtin_abort ();
+  va_end (ap);
+  _BitInt(837) r = 0;
+  int i = 0;
+  for (int j = 0; i < n; i += W, ++j)
+    r += ((_BitInt(837)) a[(n + W - 1) / W - 1 - j]) << i;
+  return r;
+}
+#endif
+
+#if __BITINT_MAXWIDTH__ >= 837
+[[gnu::noipa]] _BitInt(837)
+corge (int n, void *b)
+{
+  unsigned T a[(837 + W - 1) / W + 1]; 
+  a[(n + W - 1) / W] = 42;
+  __builtin_bitint_unpack (b, n, a, false, true);
+  if (a[(n + W - 1) / W] != 42)
+    __builtin_abort ();
+  _BitInt(837) r = 0;
+  int i = 0;
+  for (int j = 0; i < n; i += W, ++j)
+    r += ((_BitInt(837)) a[j]) << i;
+  return r;
+}
+
+[[gnu::noipa]] _BitInt(837)
+garply (int n, void *b)
+{
+  unsigned T a[(837 + W - 1) / W + 1]; 
+  a[(n + W - 1) / W] = 42;
+  __builtin_bitint_unpack (b, n, a, true, true);
+  if (a[(n + W - 1) / W] != 42)
+    __builtin_abort ();
+  _BitInt(837) r = 0;
+  int i = 0;
+  for (int j = 0; i < n; i += W, ++j)
+    r += ((_BitInt(837)) a[(n + W - 1) / W - 1 - j]) << i;
+  return r;
+}
+#endif
+
+int
+main ()
+{
+#if __BITINT_MAXWIDTH__ >= 837
+  if (bar (1, 0uwb, 42) != 0uwb)
+    __builtin_abort ();
+  if (bar (1, 1uwb, 42) != 1uwb)
+    __builtin_abort ();
+  if (bar (5, 19uwb, 42) != 19uwb)
+    __builtin_abort ();
+  if (bar (8, 206uwb, 42) != 206uwb)
+    __builtin_abort ();
+  if (bar (13, 7570uwb, 42) != 7570uwb)
+    __builtin_abort ();
+  if (bar (16, 38151uwb, 42) != 38151uwb)
+    __builtin_abort ();
+  if (bar (27, 85311871uwb, 42) != 85311871uwb)
+    __builtin_abort ();
+  if (bar (32, 2918365024uwb, 42) != 2918365024uwb)
+    __builtin_abort ();
+  if (bar (52, 2418319599906367uwb, 42) != 2418319599906367uwb)
+    __builtin_abort ();
+  if (bar (64, 10324453899960610638uwb, 42) != 10324453899960610638uwb)
+    __builtin_abort ();
+  if (bar (115, 35493143902794610347964586515544041uwb, 42)
+      != 35493143902794610347964586515544041uwb)
+    __builtin_abort ();
+  if (bar (128, 242619899432347503858857658506928415851uwb, 42)
+      != 242619899432347503858857658506928415851uwb)
+    __builtin_abort ();
+  if (bar (526, 
180194070356886021255857914345126405999398316757939019056773385284724305086631574185580484256183791238681315262210197901922727810824312479861470581236057569742uwb,
 42)
+      != 
180194070356886021255857914345126405999398316757939019056773385284724305086631574185580484256183791238681315262210197901922727810824312479861470581236057569742uwb)
+    __builtin_abort ();
+  if (bar (817, 
873989987746428259412194333913416701987357762822590714399458303903535888835232670878457161432636363996257309241302481691723537010408733419813385804491106555801784494262060916206872597091033287849274902594962928694944169726768114734355431735427071uwb,
 42)
+      != 
873989987746428259412194333913416701987357762822590714399458303903535888835232670878457161432636363996257309241302481691723537010408733419813385804491106555801784494262060916206872597091033287849274902594962928694944169726768114734355431735427071uwb)
+    __builtin_abort ();
+  if (bar (832, 
23594434241796262031251233318841235347130683007441570017128772622267774079572850334920487667606346508713826956600386054750426773544457159868730626269255744559973640839812924189319711235173267236738614098413184882928609457627967564162746003214826547541uwb,
 42)
+      != 
23594434241796262031251233318841235347130683007441570017128772622267774079572850334920487667606346508713826956600386054750426773544457159868730626269255744559973640839812924189319711235173267236738614098413184882928609457627967564162746003214826547541uwb)
+    __builtin_abort ();
+  if (baz (1, 0uwb, 42) != 0uwb)
+    __builtin_abort ();
+  if (baz (1, 1uwb, 42) != 1uwb)
+    __builtin_abort ();
+  if (baz (5, 19uwb, 42) != 19uwb)
+    __builtin_abort ();
+  if (baz (8, 206uwb, 42) != 206uwb)
+    __builtin_abort ();
+  if (baz (13, 7570uwb, 42) != 7570uwb)
+    __builtin_abort ();
+  if (baz (16, 38151uwb, 42) != 38151uwb)
+    __builtin_abort ();
+  if (baz (27, 85311871uwb, 42) != 85311871uwb)
+    __builtin_abort ();
+  if (baz (32, 2918365024uwb, 42) != 2918365024uwb)
+    __builtin_abort ();
+  if (baz (52, 2418319599906367uwb, 42) != 2418319599906367uwb)
+    __builtin_abort ();
+  if (baz (64, 10324453899960610638uwb, 42) != 10324453899960610638uwb)
+    __builtin_abort ();
+  if (baz (115, 35493143902794610347964586515544041uwb, 42)
+      != 35493143902794610347964586515544041uwb)
+    __builtin_abort ();
+  if (baz (128, 242619899432347503858857658506928415851uwb, 42)
+      != 242619899432347503858857658506928415851uwb)
+    __builtin_abort ();
+  if (baz (526, 
180194070356886021255857914345126405999398316757939019056773385284724305086631574185580484256183791238681315262210197901922727810824312479861470581236057569742uwb,
 42)
+      != 
180194070356886021255857914345126405999398316757939019056773385284724305086631574185580484256183791238681315262210197901922727810824312479861470581236057569742uwb)
+    __builtin_abort ();
+  if (baz (817, 
873989987746428259412194333913416701987357762822590714399458303903535888835232670878457161432636363996257309241302481691723537010408733419813385804491106555801784494262060916206872597091033287849274902594962928694944169726768114734355431735427071uwb,
 42)
+      != 
873989987746428259412194333913416701987357762822590714399458303903535888835232670878457161432636363996257309241302481691723537010408733419813385804491106555801784494262060916206872597091033287849274902594962928694944169726768114734355431735427071uwb)
+    __builtin_abort ();
+  if (baz (832, 
23594434241796262031251233318841235347130683007441570017128772622267774079572850334920487667606346508713826956600386054750426773544457159868730626269255744559973640839812924189319711235173267236738614098413184882928609457627967564162746003214826547541uwb,
 42)
+      != 
23594434241796262031251233318841235347130683007441570017128772622267774079572850334920487667606346508713826956600386054750426773544457159868730626269255744559973640839812924189319711235173267236738614098413184882928609457627967564162746003214826547541uwb)
+    __builtin_abort ();
+#define corge(n, v) \
+  do                                   \
+    {                                  \
+      unsigned _BitInt(n) w = v;       \
+      if ((corge) (n, &w) != v)                \
+       __builtin_abort ();             \
+    }                                  \
+  while (0)
+#define garply(n, v) \
+  do                                   \
+    {                                  \
+      unsigned _BitInt(n) w = v;       \
+      if ((garply) (n, &w) != v)       \
+       __builtin_abort ();             \
+    }                                  \
+  while (0)
+  corge (1, 0uwb);
+  corge (1, 1uwb);
+  corge (5, 19uwb);
+  corge (8, 206uwb);
+  corge (13, 7570uwb);
+  corge (16, 38151uwb);
+  corge (27, 85311871uwb);
+  corge (32, 2918365024uwb);
+  corge (52, 2418319599906367uwb);
+  corge (64, 10324453899960610638uwb);
+  corge (115, 35493143902794610347964586515544041uwb);
+  corge (128, 242619899432347503858857658506928415851uwb);
+  corge (526, 
180194070356886021255857914345126405999398316757939019056773385284724305086631574185580484256183791238681315262210197901922727810824312479861470581236057569742uwb);
+  corge (817, 
873989987746428259412194333913416701987357762822590714399458303903535888835232670878457161432636363996257309241302481691723537010408733419813385804491106555801784494262060916206872597091033287849274902594962928694944169726768114734355431735427071uwb);
+  corge (832, 
23594434241796262031251233318841235347130683007441570017128772622267774079572850334920487667606346508713826956600386054750426773544457159868730626269255744559973640839812924189319711235173267236738614098413184882928609457627967564162746003214826547541uwb);
+  garply (1, 0uwb);
+  garply (1, 1uwb);
+  garply (5, 19uwb);
+  garply (8, 206uwb);
+  garply (13, 7570uwb);
+  garply (16, 38151uwb);
+  garply (27, 85311871uwb);
+  garply (32, 2918365024uwb);
+  garply (52, 2418319599906367uwb);
+  garply (64, 10324453899960610638uwb);
+  garply (115, 35493143902794610347964586515544041uwb);
+  garply (128, 242619899432347503858857658506928415851uwb);
+  garply (526, 
180194070356886021255857914345126405999398316757939019056773385284724305086631574185580484256183791238681315262210197901922727810824312479861470581236057569742uwb);
+  garply (817, 
873989987746428259412194333913416701987357762822590714399458303903535888835232670878457161432636363996257309241302481691723537010408733419813385804491106555801784494262060916206872597091033287849274902594962928694944169726768114734355431735427071uwb);
+  garply (832, 
23594434241796262031251233318841235347130683007441570017128772622267774079572850334920487667606346508713826956600386054750426773544457159868730626269255744559973640839812924189319711235173267236738614098413184882928609457627967564162746003214826547541uwb);
+#endif
+}
--- gcc/testsuite/gcc.dg/bitint-151.c.jj        2026-07-06 13:18:27.001305788 
+0200
+++ gcc/testsuite/gcc.dg/bitint-151.c   2026-07-06 13:20:25.573751427 +0200
@@ -0,0 +1,215 @@
+/* { dg-do run { target bitint } } */
+/* { dg-options "-std=c2y -O2" } */
+
+#include <stdarg.h>
+
+#ifndef T
+#define T long
+#endif
+
+#if __BITINT_MAXWIDTH__ >= 837
+#define W (sizeof (T) * __CHAR_BIT__)
+
+[[gnu::noipa]] _BitInt(837)
+bar (int n, ...)
+{
+  va_list ap;
+  unsigned T a[(837 + W - 1) / W + 1]; 
+  va_start (ap);
+  a[(n + W - 1) / W] = 42;
+  __builtin_va_arg_bitint (ap, n, a, false, false);
+  if (a[(n + W - 1) / W] != 42)
+    __builtin_abort ();
+  if (va_arg (ap, int) != 42)
+    __builtin_abort ();
+  va_end (ap);
+  _BitInt(837) r = 0;
+  int i = 0, j;
+  for (j = 0; i < n; i += W, ++j)
+    r += ((_BitInt(837)) a[j]) << i;
+  if ((signed T) a[j - 1] < 0)
+    r += ((_BitInt(837)) -1) << i;
+  return r;
+}
+
+[[gnu::noipa]] _BitInt(837)
+baz (int n, ...)
+{
+  va_list ap;
+  unsigned T a[(837 + W - 1) / W + 1]; 
+  va_start (ap);
+  a[(n + W - 1) / W] = 42;
+  __builtin_va_arg_bitint (ap, n, a, true, false);
+  if (a[(n + W - 1) / W] != 42)
+    __builtin_abort ();
+  if (va_arg (ap, int) != 42)
+    __builtin_abort ();
+  va_end (ap);
+  _BitInt(837) r = 0;
+  int i = 0;
+  for (int j = 0; i < n; i += W, ++j)
+    r += ((_BitInt(837)) a[(n + W - 1) / W - 1 - j]) << i;
+  if ((signed T) a[0] < 0)
+    r += ((_BitInt(837)) -1) << i;
+  return r;
+}
+#endif
+
+#if __BITINT_MAXWIDTH__ >= 837
+[[gnu::noipa]] _BitInt(837)
+corge (int n, void *b)
+{
+  unsigned T a[(837 + W - 1) / W + 1]; 
+  a[(n + W - 1) / W] = 42;
+  __builtin_bitint_unpack (b, n, a, false, false);
+  if (a[(n + W - 1) / W] != 42)
+    __builtin_abort ();
+  _BitInt(837) r = 0;
+  int i = 0, j;
+  for (j = 0; i < n; i += W, ++j)
+    r += ((_BitInt(837)) a[j]) << i;
+  if ((signed T) a[j - 1] < 0)
+    r += ((_BitInt(837)) -1) << i;
+  return r;
+}
+
+[[gnu::noipa]] _BitInt(837)
+garply (int n, void *b)
+{
+  unsigned T a[(837 + W - 1) / W + 1]; 
+  a[(n + W - 1) / W] = 42;
+  __builtin_bitint_unpack (b, n, a, true, false);
+  if (a[(n + W - 1) / W] != 42)
+    __builtin_abort ();
+  _BitInt(837) r = 0;
+  int i = 0;
+  for (int j = 0; i < n; i += W, ++j)
+    r += ((_BitInt(837)) a[(n + W - 1) / W - 1 - j]) << i;
+  if ((signed T) a[0] < 0)
+    r += ((_BitInt(837)) -1) << i;
+  return r;
+}
+#endif
+
+int
+main ()
+{
+#if __BITINT_MAXWIDTH__ >= 837
+  if (bar (1, 0wb, 42) != 0wb)
+    __builtin_abort ();
+  if (bar (1, (_BitInt(1)) -1wb, 42) != -1)
+    __builtin_abort ();
+  if (bar (5, -12wb, 42) != -12wb)
+    __builtin_abort ();
+  if (bar (8, 107wb, 42) != 107wb)
+    __builtin_abort ();
+  if (bar (13, -3412wb, 42) != -3412wb)
+    __builtin_abort ();
+  if (bar (16, 24476wb, 42) != 24476wb)
+    __builtin_abort ();
+  if (bar (27, 62759870wb, 42) != 62759870wb)
+    __builtin_abort ();
+  if (bar (32, -1940906384wb, 42) != -1940906384wb)
+    __builtin_abort ();
+  if (bar (52, 1858183038390462wb, 42) != 1858183038390462wb)
+    __builtin_abort ();
+  if (bar (64, -8256680225559468133wb, 42) != -8256680225559468133wb)
+    __builtin_abort ();
+  if (bar (115, -19567690694941323284865986666034440wb, 42)
+      != -19567690694941323284865986666034440wb)
+    __builtin_abort ();
+  if (bar (128, 161295407943090171995441423582245738873wb, 42)
+      != 161295407943090171995441423582245738873wb)
+    __builtin_abort ();
+  if (bar (526, 
-74271886962589044440447868575290160981240275268510476349065102288448110495100787566581815991681080970045571964341005744164492099577970625349715415120434591551wb,
 42)
+      != 
-74271886962589044440447868575290160981240275268510476349065102288448110495100787566581815991681080970045571964341005744164492099577970625349715415120434591551wb)
+    __builtin_abort ();
+  if (bar (817, 
334564236539647801894756601387982526099412299271253169952919468031421908511714389453640635282951515192153648697545656682447892978128484511111304249912088833406530236950518222889146208703714474459832662825296577861528390922881280570442885198821395wb,
 42)
+      != 
334564236539647801894756601387982526099412299271253169952919468031421908511714389453640635282951515192153648697545656682447892978128484511111304249912088833406530236950518222889146208703714474459832662825296577861528390922881280570442885198821395wb)
+    __builtin_abort ();
+  if (bar (832, 
-10126372172398046441720587244981184637120620339348885338829980023036886270537721600610561760907517491635974396689410675687310513034165727511443880739391604187139125794232654654443819264830956682943559210170711510767483980557257583148651885937914964439wb,
 42)
+      != 
-10126372172398046441720587244981184637120620339348885338829980023036886270537721600610561760907517491635974396689410675687310513034165727511443880739391604187139125794232654654443819264830956682943559210170711510767483980557257583148651885937914964439wb)
+    __builtin_abort ();
+  if (baz (1, 0wb, 42) != 0wb)
+    __builtin_abort ();
+  if (baz (1, (_BitInt(1)) -1wb, 42) != -1)
+    __builtin_abort ();
+  if (baz (5, 12wb, 42) != 12wb)
+    __builtin_abort ();
+  if (baz (8, -107wb, 42) != -107wb)
+    __builtin_abort ();
+  if (baz (13, 3412wb, 42) != 3412wb)
+    __builtin_abort ();
+  if (baz (16, -24476wb, 42) != -24476wb)
+    __builtin_abort ();
+  if (baz (27, -62759870wb, 42) != -62759870wb)
+    __builtin_abort ();
+  if (baz (32, 1940906384wb, 42) != 1940906384wb)
+    __builtin_abort ();
+  if (baz (52, -1858183038390462wb, 42) != -1858183038390462wb)
+    __builtin_abort ();
+  if (baz (64, 8256680225559468133wb, 42) != 8256680225559468133wb)
+    __builtin_abort ();
+  if (baz (115, 19567690694941323284865986666034440wb, 42)
+      != 19567690694941323284865986666034440wb)
+    __builtin_abort ();
+  if (baz (128, -161295407943090171995441423582245738873wb, 42)
+      != -161295407943090171995441423582245738873wb)
+    __builtin_abort ();
+  if (baz (526, 
74271886962589044440447868575290160981240275268510476349065102288448110495100787566581815991681080970045571964341005744164492099577970625349715415120434591551wb,
 42)
+      != 
74271886962589044440447868575290160981240275268510476349065102288448110495100787566581815991681080970045571964341005744164492099577970625349715415120434591551wb)
+    __builtin_abort ();
+  if (baz (817, 
-334564236539647801894756601387982526099412299271253169952919468031421908511714389453640635282951515192153648697545656682447892978128484511111304249912088833406530236950518222889146208703714474459832662825296577861528390922881280570442885198821395wb,
 42)
+      != 
-334564236539647801894756601387982526099412299271253169952919468031421908511714389453640635282951515192153648697545656682447892978128484511111304249912088833406530236950518222889146208703714474459832662825296577861528390922881280570442885198821395wb)
+    __builtin_abort ();
+  if (baz (832, 
10126372172398046441720587244981184637120620339348885338829980023036886270537721600610561760907517491635974396689410675687310513034165727511443880739391604187139125794232654654443819264830956682943559210170711510767483980557257583148651885937914964439wb,
 42)
+      != 
10126372172398046441720587244981184637120620339348885338829980023036886270537721600610561760907517491635974396689410675687310513034165727511443880739391604187139125794232654654443819264830956682943559210170711510767483980557257583148651885937914964439wb)
+    __builtin_abort ();
+#define corge(n, v) \
+  do                                   \
+    {                                  \
+      unsigned _BitInt(n) w = v;       \
+      if ((corge) (n, &w) != v)                \
+       __builtin_abort ();             \
+    }                                  \
+  while (0)
+#define garply(n, v) \
+  do                                   \
+    {                                  \
+      unsigned _BitInt(n) w = v;       \
+      if ((garply) (n, &w) != v)       \
+       __builtin_abort ();             \
+    }                                  \
+  while (0)
+  corge (1, 0wb);
+  corge (1, (_BitInt(1)) -1wb);
+  corge (5, -12wb);
+  corge (8, 107wb);
+  corge (13, -3412wb);
+  corge (16, 24476wb);
+  corge (27, 62759870wb);
+  corge (32, -1940906384wb);
+  corge (52, 1858183038390462wb);
+  corge (64, -8256680225559468133wb);
+  corge (115, -19567690694941323284865986666034440wb);
+  corge (128, 161295407943090171995441423582245738873wb);
+  corge (526, 
-74271886962589044440447868575290160981240275268510476349065102288448110495100787566581815991681080970045571964341005744164492099577970625349715415120434591551wb);
+  corge (817, 
334564236539647801894756601387982526099412299271253169952919468031421908511714389453640635282951515192153648697545656682447892978128484511111304249912088833406530236950518222889146208703714474459832662825296577861528390922881280570442885198821395wb);
+  corge (832, 
-10126372172398046441720587244981184637120620339348885338829980023036886270537721600610561760907517491635974396689410675687310513034165727511443880739391604187139125794232654654443819264830956682943559210170711510767483980557257583148651885937914964439wb);
+  garply (1, 0wb);
+  garply (1, (_BitInt(1)) -1wb);
+  garply (5, 12wb);
+  garply (8, -107wb);
+  garply (13, 3412wb);
+  garply (16, -24476wb);
+  garply (27, -62759870wb);
+  garply (32, 1940906384wb);
+  garply (52, -1858183038390462wb);
+  garply (64, 8256680225559468133wb);
+  garply (115, 19567690694941323284865986666034440wb);
+  garply (128, -161295407943090171995441423582245738873wb);
+  garply (526, 
74271886962589044440447868575290160981240275268510476349065102288448110495100787566581815991681080970045571964341005744164492099577970625349715415120434591551wb);
+  garply (817, 
-334564236539647801894756601387982526099412299271253169952919468031421908511714389453640635282951515192153648697545656682447892978128484511111304249912088833406530236950518222889146208703714474459832662825296577861528390922881280570442885198821395wb);
+  garply (832, 
10126372172398046441720587244981184637120620339348885338829980023036886270537721600610561760907517491635974396689410675687310513034165727511443880739391604187139125794232654654443819264830956682943559210170711510767483980557257583148651885937914964439wb);
+#endif
+}
--- gcc/testsuite/gcc.dg/bitint-152.c.jj        2026-07-06 13:20:53.523385039 
+0200
+++ gcc/testsuite/gcc.dg/bitint-152.c   2026-07-06 13:21:02.968261223 +0200
@@ -0,0 +1,7 @@
+/* { dg-do run { target bitint } } */
+/* { dg-options "-O2" } */
+
+#include <stdarg.h>
+
+#define T short
+#include "bitint-150.c"
--- gcc/testsuite/gcc.dg/bitint-153.c.jj        2026-07-06 13:20:56.616344491 
+0200
+++ gcc/testsuite/gcc.dg/bitint-153.c   2026-07-06 13:21:09.581174533 +0200
@@ -0,0 +1,7 @@
+/* { dg-do run { target bitint } } */
+/* { dg-options "-std=c2y -O2" } */
+
+#include <stdarg.h>
+
+#define T short
+#include "bitint-151.c"
--- gcc/testsuite/gcc.dg/bitint-154.c.jj        2026-07-06 13:21:29.375915045 
+0200
+++ gcc/testsuite/gcc.dg/bitint-154.c   2026-07-06 13:21:51.636623232 +0200
@@ -0,0 +1,11 @@
+/* { dg-do run { target bitint } } */
+/* { dg-options "-O2" } */
+
+#include <stdarg.h>
+
+#ifdef __SIZEOF_INT128__
+#define T __int128
+#else
+#define T long long
+#endif
+#include "bitint-150.c"
--- gcc/testsuite/gcc.dg/bitint-155.c.jj        2026-07-06 13:21:32.455874672 
+0200
+++ gcc/testsuite/gcc.dg/bitint-155.c   2026-07-06 13:22:34.869056503 +0200
@@ -0,0 +1,11 @@
+/* { dg-do run { target bitint } } */
+/* { dg-options "-std=gnu2y -O2" } */
+
+#include <stdarg.h>
+
+#ifdef __SIZEOF_INT128__
+#define T __int128
+#else
+#define T long long
+#endif
+#include "bitint-151.c"

        Jakub

Reply via email to