On Thu, 4 Jun 2026, Jakub Jelinek wrote:
> On Wed, Jun 03, 2026 at 09:01:31PM -0400, Jason Merrill wrote:
> > Since you pass the vec to the new build_... function, why not give this
> > error there along with all the others?
>
> Done.
>
> > > + if (type == char_type_node)
> > > + {
> > > + if (complain & tf_error)
> > > + error_at (loc, "argument 1 in call to function "
> > > + "%qs has %<char%> type", name);
> >
> > This might suggest using "unsigned char" instead, for clarity.
>
> I've dropped this instead. I've copied this over from the __builtin_stdc_*
> handling because it was right above it in c-parser.cc, but actually
> __builtin_{bswap,bitreverse}g should have consistent behavior with
> __builtin_{clz,ctz,parity,popcount}g, not __builtin_stdc_*. And while
> all the other checks are in both, the is not char is just pedantry
> from the C23 <stdbit.h> requirements on those functions, clz etc. happily
> allow char on -funsigned-char and clrsb/ffs allow char on -fsigned-char
> targets.
>
> > > @@ -3245,6 +3245,30 @@ cxx_eval_internal_function (const conste
> > > case IFN_DEFERRED_INIT:
> > > return build_clobber (TREE_TYPE (t), CLOBBER_OBJECT_BEGIN);
> > > + case IFN_BSWAP:
> > > + case IFN_BITREVERSE:
> > > + {
> > > + tree arg = cxx_eval_constant_expression (ctx, CALL_EXPR_ARG (t, 0),
> > > + vc_prvalue, non_constant_p,
> > > + overflow_p, jump_target);
> > > + if (*jump_target)
> > > + return NULL_TREE;
> >
> > I think we want to check *non_constant_p here rather than fall through to
> > giving a redundant error.
>
> Done.
>
> Here is an updated version of the patch with those changes.
> Tested on x86_64-linux and i686-linux, also with -funsigned-char on the
> relevant tests.
The middle-end changes are OK.
Thanks,
Richard.
> 2026-06-04 Jakub Jelinek <[email protected]>
>
> PR c/122731
> gcc/
> * doc/extend.texi (__builtin_bswapg, __builtin_bitreverseg): Document.
> * internal-fn.def (DEF_INTERNAL_INTSZ_FN): Define.
> (DEF_INTERNAL_INTSZ_EXT_FN): Define.
> (BSWAP): New internal fn.
> (BITREVERSE): Likewise.
> * internal-fn.h (expand_BSWAP, expand_BITREVERSE): Declare.
> * internal-fn.cc (DEF_INTERNAL_INTSZ_EXT_FN): Define.
> (expand_BSWAP, expand_BITREVERSE): New functions.
> * builtins.h (fold_build_builtin_bswapg_bitreverseg): Declare.
> * builtins.cc (fold_build_builtin_bswapg_bitreverseg): New function.
> * wide-int.h (wi::bswap): Fix up docs that only multiple of 8 bits
> is required.
> * gimple-match-exports.cc (build_call_internal): Handle IFN_BSWAP
> and IFN_BITREVERSE.
> * gencfn-macros.cc (internal_fn_intsz_names): New variable.
> (intsz_suffixes): Likewise.
> (suffix_lists): Add intsz_suffixes.
> (main): Handle internal_fn_intsz_names.
> * match.pd (BSWAP, BITREVERSE): Remove.
> (popcount(bswap(x)) is popcount(x)): Use BSWAP BITREVERSE
> op lists.
> * tree-ssa-phiopt.cc (empty_bb_or_one_feeding_into_p): Use
> CASE_CFN_BSWAP and CASE_CFN_BITREVERSE.
> (cond_removal_in_builtin_zero_pattern): Likewise.
> * fold-const-call.cc (fold_const_call_ss): Likewise.
> * fold-const.cc (tree_call_nonnegative_p): Likewise.
> * gimple-lower-bitint.cc (struct bitint_large_huge): Declare
> lower_bswap_bitreverse method.
> (bitint_large_huge::lower_bswap_bitreverse): New method.
> (bitint_large_huge::lower_call): Call it.
> (build_bitint_stmt_ssa_conflicts): Set muldiv_p for IFN_BSWAP
> and IFN_BITREVERSE.
> gcc/c-family/
> * c-common.h (enum rid): Add RID_BUILTIN_BSWAPG and
> RID_BUILTIN_BITREVERSEG.
> * c-common.cc (c_common_reswords): Add __builtin_bswapg
> and __builtin_bitreverseg.
> gcc/c/
> * c-parser.cc (c_parser_postfix_expression): Parse
> __builtin_bswapg and __builtin_bitreverseg.
> gcc/cp/
> * parser.cc (cp_parser_postfix_expression): Parse
> __builtin_bswapg and __builtin_bitreverseg.
> * typeck.cc (build_x_bswapg_bitreverseg): New function.
> * cp-tree.h (build_x_bswapg_bitreverseg): Declare.
> * pt.cc (tsubst_expr): Handle IFN_BSWAP and IFN_BITREVERSE.
> * constexpr.cc (cxx_eval_internal_function): Likewise.
> (potential_constant_expression_1): Likewise.
> * cp-gimplify.cc (cp_gimplify_expr): Likewise.
> gcc/testsuite/
> * c-c++-common/builtin-bswapg-1.c: New test.
> * c-c++-common/builtin-bswapg-2.c: New test.
> * c-c++-common/builtin-bswapg-3.c: New test.
> * c-c++-common/builtin-bitreverseg-1.c: New test.
> * c-c++-common/builtin-bitreverseg-2.c: New test.
>
> --- gcc/doc/extend.texi.jj 2026-06-04 08:24:31.113114961 +0200
> +++ gcc/doc/extend.texi 2026-06-04 08:31:41.561392321 +0200
> @@ -16095,6 +16095,12 @@ Similar to @code{__builtin_bswap64}, exc
> are 128-bit. Only supported on targets when 128-bit types are supported.
> @enddefbuiltin
>
> +@defbuiltin{@var{type} __builtin_bswapg (@var{type} @var{x})}
> +Similar to @code{__builtin_bswap64}, except the argument is type-generic
> +unsigned integer (standard, extended or bit-precise) with width which is
> +multiple of 8. No integral argument promotions are performed on the
> argument.
> +@enddefbuiltin
> +
> @defbuiltin{uint8_t __builtin_bitreverse8 (uint8_t @var{x})}
> Returns @var{x} with all bits reversed.
> @enddefbuiltin
> @@ -16119,6 +16125,12 @@ Similar to @code{__builtin_bitreverse64}
> are 128-bit. Only supported on targets when 128-bit types are supported.
> @enddefbuiltin
>
> +@defbuiltin{@var{type} __builtin_bitreverseg (@var{type} @var{x})}
> +Similar to @code{__builtin_bitreverse64}, except the argument is type-generic
> +unsigned integer (standard, extended or bit-precise).
> +No integral argument promotions are performed on the argument.
> +@enddefbuiltin
> +
> @node CRC Builtins
> @subsection CRC Builtins
> @cindex CRC builtins
> --- gcc/internal-fn.def.jj 2026-06-04 08:24:31.129114748 +0200
> +++ gcc/internal-fn.def 2026-06-04 08:31:41.562941003 +0200
> @@ -36,6 +36,8 @@ along with GCC; see the file COPYING3.
> DEF_INTERNAL_FLT_FLOATN_FN (NAME, FLAGS, OPTAB, TYPE)
> DEF_INTERNAL_INT_FN (NAME, FLAGS, OPTAB, TYPE)
> DEF_INTERNAL_INT_EXT_FN (NAME, FLAGS, OPTAB, TYPE)
> + DEF_INTERNAL_INTSZ_FN (NAME, FLAGS, OPTAB, TYPE)
> + DEF_INTERNAL_INTSZ_EXT_FN (NAME, FLAGS, OPTAB, TYPE)
> DEF_INTERNAL_COND_FN (NAME, FLAGS, OPTAB, TYPE)
> DEF_INTERNAL_SIGNED_COND_FN (NAME, FLAGS, OPTAB, TYPE)
> DEF_INTERNAL_WIDENING_OPTAB_FN (NAME, FLAGS, SELECTOR, SOPTAB, UOPTAB,
> @@ -107,6 +109,14 @@ along with GCC; see the file COPYING3.
> has expand_##NAME defined in internal-fn.cc to override the
> DEF_INTERNAL_INT_FN expansion behavior.
>
> + DEF_INTERNAL_INTSZ_FN is like DEF_INTERNAL_OPTAB_FN, but in addition
> + says that the function extends the C-level BUILT_IN_<NAME>{8,16,32,64,128}
> + group of functions to any integral mode (including vector modes).
> +
> + DEF_INTERNAL_INTSZ_EXT_FN is like DEF_INTERNAL_INTSZ_FN, except that it
> + has expand_##NAME defined in internal-fn.cc to override the
> + DEF_INTERNAL_INTSZ_FN expansion behavior.
> +
> DEF_INTERNAL_WIDENING_OPTAB_FN is a wrapper that defines five internal
> functions with DEF_INTERNAL_SIGNED_OPTAB_FN:
> - one that describes a widening operation with the same number of elements
> @@ -175,6 +185,16 @@ along with GCC; see the file COPYING3.
> DEF_INTERNAL_INT_FN (NAME, FLAGS, OPTAB, TYPE)
> #endif
>
> +#ifndef DEF_INTERNAL_INTSZ_FN
> +#define DEF_INTERNAL_INTSZ_FN(NAME, FLAGS, OPTAB, TYPE) \
> + DEF_INTERNAL_OPTAB_FN (NAME, FLAGS, OPTAB, TYPE)
> +#endif
> +
> +#ifndef DEF_INTERNAL_INTSZ_EXT_FN
> +#define DEF_INTERNAL_INTSZ_EXT_FN(NAME, FLAGS, OPTAB, TYPE) \
> + DEF_INTERNAL_INTSZ_FN (NAME, FLAGS, OPTAB, TYPE)
> +#endif
> +
> #ifndef DEF_INTERNAL_WIDENING_OPTAB_FN
> #define DEF_INTERNAL_WIDENING_OPTAB_FN(NAME, FLAGS, SELECTOR, SOPTAB,
> UOPTAB, TYPE) \
> DEF_INTERNAL_SIGNED_OPTAB_FN (NAME, FLAGS, SELECTOR, SOPTAB, UOPTAB, TYPE)
> \
> @@ -471,6 +491,9 @@ DEF_INTERNAL_INT_EXT_FN (CTZ, ECF_CONST
> DEF_INTERNAL_INT_EXT_FN (FFS, ECF_CONST | ECF_NOTHROW, ffs, unary)
> DEF_INTERNAL_INT_EXT_FN (PARITY, ECF_CONST | ECF_NOTHROW, parity, unary)
> DEF_INTERNAL_INT_EXT_FN (POPCOUNT, ECF_CONST | ECF_NOTHROW, popcount, unary)
> +DEF_INTERNAL_INTSZ_EXT_FN (BSWAP, ECF_CONST | ECF_NOTHROW, bswap, unary)
> +DEF_INTERNAL_INTSZ_EXT_FN (BITREVERSE, ECF_CONST | ECF_NOTHROW, bitreverse,
> + unary)
>
> DEF_INTERNAL_FN (GOMP_TARGET_REV, ECF_NOVOPS | ECF_LEAF | ECF_NOTHROW, NULL)
> DEF_INTERNAL_FN (GOMP_USE_SIMT, ECF_NOVOPS | ECF_LEAF | ECF_NOTHROW, NULL)
> @@ -627,6 +650,8 @@ DEF_INTERNAL_OPTAB_FN (BIT_IORN, ECF_CON
> #undef DEF_INTERNAL_COND_FN
> #undef DEF_INTERNAL_INT_EXT_FN
> #undef DEF_INTERNAL_INT_FN
> +#undef DEF_INTERNAL_INTSZ_EXT_FN
> +#undef DEF_INTERNAL_INTSZ_FN
> #undef DEF_INTERNAL_FLT_FN
> #undef DEF_INTERNAL_FLT_FLOATN_FN
> #undef DEF_INTERNAL_SIGNED_OPTAB_FN
> --- gcc/internal-fn.h.jj 2026-06-04 08:24:31.130114735 +0200
> +++ gcc/internal-fn.h 2026-06-04 08:31:41.563173222 +0200
> @@ -285,6 +285,8 @@ extern void expand_CTZ (internal_fn, gca
> extern void expand_FFS (internal_fn, gcall *);
> extern void expand_PARITY (internal_fn, gcall *);
> extern void expand_POPCOUNT (internal_fn, gcall *);
> +extern void expand_BSWAP (internal_fn, gcall *);
> +extern void expand_BITREVERSE (internal_fn, gcall *);
>
> extern bool vectorized_internal_fn_supported_p (internal_fn, tree);
>
> --- gcc/internal-fn.cc.jj 2026-06-04 08:24:31.129114748 +0200
> +++ gcc/internal-fn.cc 2026-06-04 08:31:41.563540062 +0200
> @@ -4765,6 +4765,7 @@ set_edom_supported_p (void)
> expand_##TYPE##_optab_fn (fn, stmt, OPTAB##_optab); \
> }
> #define DEF_INTERNAL_INT_EXT_FN(CODE, FLAGS, OPTAB, TYPE)
> +#define DEF_INTERNAL_INTSZ_EXT_FN(CODE, FLAGS, OPTAB, TYPE)
> #define DEF_INTERNAL_SIGNED_OPTAB_FN(CODE, FLAGS, SELECTOR, SIGNED_OPTAB, \
> UNSIGNED_OPTAB, TYPE) \
> static void
> \
> @@ -5930,3 +5931,17 @@ expand_POPCOUNT (internal_fn fn, gcall *
> emit_insn (all_insns);
> }
> }
> +
> +void
> +expand_BSWAP (internal_fn fn, gcall *stmt)
> +{
> + if (expand_bitquery (fn, stmt))
> + expand_unary_optab_fn (fn, stmt, bswap_optab);
> +}
> +
> +void
> +expand_BITREVERSE (internal_fn fn, gcall *stmt)
> +{
> + if (expand_bitquery (fn, stmt))
> + expand_unary_optab_fn (fn, stmt, bitreverse_optab);
> +}
> --- gcc/builtins.h.jj 2026-06-04 08:24:31.058115692 +0200
> +++ gcc/builtins.h 2026-06-04 08:31:41.563934858 +0200
> @@ -140,6 +140,8 @@ extern rtx expand_builtin (tree, rtx, rt
> extern enum built_in_function builtin_mathfn_code (const_tree);
> extern tree fold_builtin_expect (location_t, tree, tree, tree, tree);
> extern tree fold_builtin_constant_p (tree);
> +extern tree fold_build_builtin_bswapg_bitreverseg (location_t, internal_fn,
> + tree);
> extern bool avoid_folding_inline_builtin (tree);
> extern tree fold_call_expr (location_t, tree, bool);
> extern tree fold_builtin_call_array (location_t, tree, tree, int, tree *);
> --- gcc/builtins.cc.jj 2026-06-04 08:24:31.047115838 +0200
> +++ gcc/builtins.cc 2026-06-04 08:31:41.564569034 +0200
> @@ -10522,6 +10522,53 @@ fold_builtin_bit_query (location_t loc,
> return call;
> }
>
> +/* Fold or build a __builtin_bswapg (ARG) (if IFN is IFN_BSWAP) or
> + __builtin_bitreverseg (ARG (otherwise) call. The FE should have
> + verified earlier that the argument type is unsigned INTEGER_TYPE
> + or BITINT_TYPE, for __builtin_bswapg with precision divisible by 8. */
> +
> +tree
> +fold_build_builtin_bswapg_bitreverseg (location_t loc, enum internal_fn ifn,
> + tree arg)
> +{
> + tree type = TYPE_MAIN_VARIANT (TREE_TYPE (arg));
> + if (ifn == IFN_BSWAP && TYPE_PRECISION (type) == 8)
> + return fold_convert_loc (loc, type, arg);
> + struct { tree type; built_in_function bswap, bitreverse; } fns[]
> + = { { unsigned_char_type_node, END_BUILTINS, BUILT_IN_BITREVERSE8 },
> + { uint16_type_node, BUILT_IN_BSWAP16, BUILT_IN_BITREVERSE16 },
> + { uint32_type_node, BUILT_IN_BSWAP32, BUILT_IN_BITREVERSE32 },
> + { uint64_type_node, BUILT_IN_BSWAP64, BUILT_IN_BITREVERSE64 },
> + { uint128_type_node, BUILT_IN_BSWAP128, BUILT_IN_BITREVERSE128 } };
> + if (TREE_CODE (arg) == INTEGER_CST)
> + {
> + wide_int res;
> + if (ifn == IFN_BSWAP)
> + res = wi::bswap (wi::to_wide (arg));
> + else
> + res = wi::bitreverse (wi::to_wide (arg));
> + return wide_int_to_tree (type, res);
> + }
> + for (unsigned i = 0; i < ARRAY_SIZE (fns); ++i)
> + if (fns[i].type
> + && TYPE_PRECISION (fns[i].type) >= TYPE_PRECISION (type))
> + {
> + arg = fold_convert_loc (loc, fns[i].type, arg);
> + tree fndecl
> + = builtin_decl_explicit (ifn == IFN_BSWAP
> + ? fns[i].bswap : fns[i].bitreverse);
> + tree ret = build_call_expr_loc (loc, fndecl, 1, arg);
> + if (TYPE_PRECISION (type) != TYPE_PRECISION (fns[i].type))
> + ret = fold_build2_loc (loc, RSHIFT_EXPR, fns[i].type, ret,
> + build_int_cst (unsigned_type_node,
> + TYPE_PRECISION (fns[i].type)
> + - TYPE_PRECISION (type)));
> + return fold_convert_loc (loc, type, ret);
> + }
> + gcc_assert (TREE_CODE (type) == BITINT_TYPE);
> + return build_call_expr_internal_loc (loc, ifn, type, 1, arg);
> +}
> +
> /* Fold __builtin_{add,sub}c{,l,ll} into pair of internal functions
> that return both result of arithmetics and overflowed boolean
> flag in a complex integer result. */
> --- gcc/wide-int.h.jj 2026-06-04 08:24:31.136114655 +0200
> +++ gcc/wide-int.h 2026-06-04 08:31:41.565335815 +0200
> @@ -2655,7 +2655,7 @@ wi::set_bit (const T &x, unsigned int bi
>
> /* Byte swap the integer X.
> ??? This always swaps 8-bit octets, regardless of BITS_PER_UNIT.
> - This function requires X's precision to be a multiple of 16 bits,
> + This function requires X's precision to be a multiple of 8 bits,
> so care needs to be taken for targets where BITS_PER_UNIT != 8. */
> template <typename T>
> inline WI_UNARY_RESULT (T)
> --- gcc/gimple-match-exports.cc.jj 2026-06-04 08:24:31.126114788 +0200
> +++ gcc/gimple-match-exports.cc 2026-06-04 08:31:41.565659698 +0200
> @@ -266,7 +266,9 @@ build_call_internal (internal_fn fn, gim
> case IFN_FFS:
> case IFN_POPCOUNT:
> case IFN_PARITY:
> - /* For these 6 builtins large/huge _BitInt operand is ok
> + case IFN_BSWAP:
> + case IFN_BITREVERSE:
> + /* For these 8 builtins large/huge _BitInt operand is ok
> before bitint lowering pass. */
> if (res_op->num_ops >= 1
> && BITINT_TYPE_P (TREE_TYPE (res_op->ops[0]))
> --- gcc/gencfn-macros.cc.jj 2026-06-04 08:24:31.121114854 +0200
> +++ gcc/gencfn-macros.cc 2026-06-04 08:31:41.565842296 +0200
> @@ -154,6 +154,13 @@ const char *const internal_fn_int_names[
> NULL
> };
>
> +const char *const internal_fn_intsz_names[] = {
> +#define DEF_INTERNAL_INTSZ_FN(NAME, FLAGS, OPTAB, TYPE) \
> + #NAME,
> +#include "internal-fn.def"
> + NULL
> +};
> +
> static const char *const flt_suffixes[] = { "F", "", "L", NULL };
> static const char *const fltfn_suffixes[] = { "F16", "F32", "F64", "F128",
> "F32X", "F64X", "F128X", NULL };
> @@ -161,10 +168,13 @@ static const char *const fltall_suffixes
> "F64", "F128", "F32X", "F64X",
> "F128X", NULL };
> static const char *const int_suffixes[] = { "", "L", "LL", "IMAX", NULL };
> +static const char *const intsz_suffixes[] = { "8", "16", "32", "64", "128",
> + NULL };
>
> static const char *const *const suffix_lists[] = {
> flt_suffixes,
> int_suffixes,
> + intsz_suffixes,
> NULL
> };
>
> @@ -186,6 +196,7 @@ main (int argc, char **argv)
> add_to_set (&builtins, builtin_names);
> add_to_set (&internal_fns, internal_fn_flt_names);
> add_to_set (&internal_fns, internal_fn_int_names);
> + add_to_set (&internal_fns, internal_fn_intsz_names);
>
> /* Check the functions. */
> for (unsigned int i = 0; internal_fn_flt_names[i]; ++i)
> @@ -202,6 +213,15 @@ main (int argc, char **argv)
> error ("DEF_INTERNAL_INT_FN (%s) has no associated built-in"
> " functions", name);
> }
> + for (unsigned int i = 0; internal_fn_intsz_names[i]; ++i)
> + {
> + const char *name = internal_fn_intsz_names[i];
> + if (!is_group (&builtins, name,
> + /* There is no BUILT_IN_BSWAP8. */
> + intsz_suffixes + (startswith (name, "BSWAP") ? 1 : 0)))
> + error ("DEF_INTERNAL_INTSZ_FN (%s) has no associated built-in"
> + " functions", name);
> + }
>
> /* Go through the built-in functions in declaration order, outputting
> definitions as appropriate. */
> @@ -211,10 +231,25 @@ main (int argc, char **argv)
> if (startswith (name, "BUILT_IN_"))
> {
> const char *root = name + 9;
> + char buf[128];
> for (unsigned int j = 0; suffix_lists[j]; ++j)
> {
> - const char *const *const suffix = suffix_lists[j];
> + const char *const *suffix = suffix_lists[j];
>
> + if (suffix == intsz_suffixes)
> + {
> + if (!endswith (root, "32"))
> + continue;
> + size_t len = strlen (root);
> + if (len > sizeof (buf))
> + continue;
> + /* There is no BUILT_IN_BSWAP8. */
> + if (startswith (root, "BSWAP"))
> + suffix++;
> + memcpy (buf, root, len - 2);
> + buf[len - 2] = '\0';
> + root = buf;
> + }
> if (is_group (&builtins, root, suffix))
> {
> bool internal_p = internal_fns.contains (root);
> --- gcc/match.pd.jj 2026-06-04 08:24:37.630028321 +0200
> +++ gcc/match.pd 2026-06-04 08:31:41.566357636 +0200
> @@ -53,10 +53,6 @@ (define_operator_list swapped_tcc_compar
> gt ge eq ne le lt unordered ordered ungt unge unlt unle uneq
> ltgt)
> (define_operator_list simple_comparison lt le eq ne ge gt)
> (define_operator_list swapped_simple_comparison gt ge eq ne le lt)
> -(define_operator_list BSWAP BUILT_IN_BSWAP16 BUILT_IN_BSWAP32
> - BUILT_IN_BSWAP64 BUILT_IN_BSWAP128)
> -(define_operator_list BITREVERSE BUILT_IN_BITREVERSE8 BUILT_IN_BITREVERSE16
> - BUILT_IN_BITREVERSE32 BUILT_IN_BITREVERSE64 BUILT_IN_BITREVERSE128)
>
> #include "cfn-operators.pd"
>
> @@ -10319,8 +10315,7 @@ (define_operator_list SYNC_FETCH_AND_AND
>
> /* popcount(bswap(x)) is popcount(x). */
> (for popcount (POPCOUNT)
> - (for bswap (BUILT_IN_BSWAP16 BUILT_IN_BSWAP32
> - BUILT_IN_BSWAP64 BUILT_IN_BSWAP128)
> + (for bswap (BSWAP BITREVERSE)
> (simplify
> (popcount (convert?@0 (bswap:s@1 @2)))
> (if (INTEGRAL_TYPE_P (TREE_TYPE (@0))
> --- gcc/tree-ssa-phiopt.cc.jj 2026-06-04 08:24:37.641028175 +0200
> +++ gcc/tree-ssa-phiopt.cc 2026-06-04 08:31:41.599391815 +0200
> @@ -813,15 +813,8 @@ empty_bb_or_one_feeding_into_p (basic_bl
> {
> default:
> return false;
> - case CFN_BUILT_IN_BSWAP16:
> - case CFN_BUILT_IN_BSWAP32:
> - case CFN_BUILT_IN_BSWAP64:
> - case CFN_BUILT_IN_BSWAP128:
> - case CFN_BUILT_IN_BITREVERSE8:
> - case CFN_BUILT_IN_BITREVERSE16:
> - case CFN_BUILT_IN_BITREVERSE32:
> - case CFN_BUILT_IN_BITREVERSE64:
> - case CFN_BUILT_IN_BITREVERSE128:
> + CASE_CFN_BSWAP:
> + CASE_CFN_BITREVERSE:
> CASE_CFN_FFS:
> CASE_CFN_PARITY:
> CASE_CFN_POPCOUNT:
> @@ -2577,15 +2570,8 @@ cond_removal_in_builtin_zero_pattern (ba
> bool any_val = false;
> switch (cfn)
> {
> - case CFN_BUILT_IN_BSWAP16:
> - case CFN_BUILT_IN_BSWAP32:
> - case CFN_BUILT_IN_BSWAP64:
> - case CFN_BUILT_IN_BSWAP128:
> - case CFN_BUILT_IN_BITREVERSE8:
> - case CFN_BUILT_IN_BITREVERSE16:
> - case CFN_BUILT_IN_BITREVERSE32:
> - case CFN_BUILT_IN_BITREVERSE64:
> - case CFN_BUILT_IN_BITREVERSE128:
> + CASE_CFN_BSWAP:
> + CASE_CFN_BITREVERSE:
> CASE_CFN_FFS:
> CASE_CFN_PARITY:
> CASE_CFN_POPCOUNT:
> --- gcc/fold-const-call.cc.jj 2026-06-04 08:24:31.114114947 +0200
> +++ gcc/fold-const-call.cc 2026-06-04 08:31:41.600632646 +0200
> @@ -1094,19 +1094,12 @@ fold_const_call_ss (wide_int *result, co
> *result = wi::shwi (wi::parity (arg), precision);
> return true;
>
> - case CFN_BUILT_IN_BSWAP16:
> - case CFN_BUILT_IN_BSWAP32:
> - case CFN_BUILT_IN_BSWAP64:
> - case CFN_BUILT_IN_BSWAP128:
> + CASE_CFN_BSWAP:
> *result = wi::bswap (wide_int::from (arg, precision,
> TYPE_SIGN (arg_type)));
> return true;
>
> - case CFN_BUILT_IN_BITREVERSE8:
> - case CFN_BUILT_IN_BITREVERSE16:
> - case CFN_BUILT_IN_BITREVERSE32:
> - case CFN_BUILT_IN_BITREVERSE64:
> - case CFN_BUILT_IN_BITREVERSE128:
> + CASE_CFN_BITREVERSE:
> *result = wi::bitreverse (wide_int::from (arg, precision,
> TYPE_SIGN (arg_type)));
> return true;
> --- gcc/fold-const.cc.jj 2026-06-04 08:24:31.117114908 +0200
> +++ gcc/fold-const.cc 2026-06-04 08:31:41.601387045 +0200
> @@ -14627,15 +14627,8 @@ tree_call_nonnegative_p (tree type, comb
> CASE_CFN_PARITY:
> CASE_CFN_POPCOUNT:
> CASE_CFN_CLRSB:
> - case CFN_BUILT_IN_BSWAP16:
> - case CFN_BUILT_IN_BSWAP32:
> - case CFN_BUILT_IN_BSWAP64:
> - case CFN_BUILT_IN_BSWAP128:
> - case CFN_BUILT_IN_BITREVERSE8:
> - case CFN_BUILT_IN_BITREVERSE16:
> - case CFN_BUILT_IN_BITREVERSE32:
> - case CFN_BUILT_IN_BITREVERSE64:
> - case CFN_BUILT_IN_BITREVERSE128:
> + CASE_CFN_BSWAP:
> + CASE_CFN_BITREVERSE:
> /* Always true. */
> return true;
>
> --- gcc/gimple-lower-bitint.cc.jj 2026-06-04 08:24:31.122114841 +0200
> +++ gcc/gimple-lower-bitint.cc 2026-06-04 08:31:41.602444764 +0200
> @@ -474,6 +474,7 @@ struct bitint_large_huge
> void lower_cplxpart_stmt (tree, gimple *);
> void lower_complexexpr_stmt (gimple *);
> void lower_bit_query (gimple *);
> + void lower_bswap_bitreverse (gimple *);
> void lower_call (tree, gimple *);
> void lower_asm (gimple *);
> void lower_stmt (gimple *);
> @@ -6106,6 +6107,181 @@ bitint_large_huge::lower_bit_query (gimp
> }
> }
>
> +/* Lower a .{BSWAP,BITREVERSE} call with one large/huge _BitInt argument. */
> +
> +void
> +bitint_large_huge::lower_bswap_bitreverse (gimple *stmt)
> +{
> + tree arg = gimple_call_arg (stmt, 0);
> + tree lhs = gimple_call_lhs (stmt);
> + gimple *g;
> +
> + if (!lhs)
> + {
> + gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
> + gsi_remove (&gsi, true);
> + return;
> + }
> + tree type = TREE_TYPE (arg);
> + gcc_assert (BITINT_TYPE_P (type));
> + bitint_prec_kind kind = bitint_precision_kind (type);
> + gcc_assert (kind >= bitint_prec_large);
> + int part = var_to_partition (m_map, lhs);
> + gcc_assert (m_vars[part] != NULL_TREE);
> + tree obj = m_vars[part];
> + enum internal_fn ifn = gimple_call_internal_fn (stmt);
> + enum built_in_function bcode = END_BUILTINS;
> + switch (limb_prec)
> + {
> + case 16:
> + bcode = ifn == IFN_BSWAP ? BUILT_IN_BSWAP16 : BUILT_IN_BITREVERSE16;
> + break;
> + case 32:
> + bcode = ifn == IFN_BSWAP ? BUILT_IN_BSWAP32 : BUILT_IN_BITREVERSE32;
> + break;
> + case 64:
> + bcode = ifn == IFN_BSWAP ? BUILT_IN_BSWAP64 : BUILT_IN_BITREVERSE64;
> + break;
> + case 128:
> + bcode = ifn == IFN_BSWAP ? BUILT_IN_BSWAP128 : BUILT_IN_BITREVERSE128;
> + break;
> + default:
> + gcc_unreachable ();
> + }
> + tree fndecl = builtin_decl_explicit (bcode);
> + unsigned prec = TYPE_PRECISION (type);
> + tree p = build_int_cst (sizetype,
> + prec / limb_prec - (prec % limb_prec == 0));
> + /* For IFN .BSWAP or .BITREVERSE and
> + FN corresponding __builtin_bswapN or __builtin_bitreverseN where N
> + is limb_prec, lower
> + dst = IFN (src);
> + as
> + size_t p = prec / limb_prec - (prec % limb_prec == 0);
> + if constexpr ((prec % limb_prec) == 0)
> + {
> + for (idx = 0; idx <= p; ++idx)
> + dst[p - idx] = FN (src[idx]);
> + }
> + else
> + {
> + unsigned n1 = prec % limb_prec;
> + unsigned n2 = limb_prec - n1;
> + dst[p] = FN (src[0]) >> n2;
> + for (idx = p - 1; (ssize_t) idx >= 0; --idx)
> + dst[idx] = FN ((src[p - idx] << n2) | (src[p - idx - 1] >> n1));
> + } */
> + if (prec % limb_prec == 0)
> + {
> + tree idx_next;
> + tree idx = create_loop (size_zero_node, &idx_next);
> + tree pmidx = make_ssa_name (sizetype);
> + g = gimple_build_assign (pmidx, MINUS_EXPR, p, idx);
> + insert_before (g);
> + m_data_cnt = 0;
> + tree t = handle_operand (arg, idx);
> + m_first = false;
> + g = gimple_build_call (fndecl, 1, t);
> + t = make_ssa_name (m_limb_type);
> + gimple_call_set_lhs (g, t);
> + insert_before (g);
> + tree l = limb_access (TREE_TYPE (lhs), obj, pmidx, true);
> + g = gimple_build_assign (l, t);
> + insert_before (g);
> + g = gimple_build_assign (idx_next, PLUS_EXPR, idx, size_one_node);
> + insert_before (g);
> + g = gimple_build_cond (LE_EXPR, idx_next, p, NULL_TREE, NULL_TREE);
> + insert_before (g);
> + }
> + else
> + {
> + tree n1 = build_int_cst (unsigned_type_node, prec % limb_prec);
> + tree n2 = build_int_cst (unsigned_type_node,
> + limb_prec - (prec % limb_prec));
> + m_data_cnt = 0;
> + tree t = handle_operand (arg, bitint_big_endian ? p : size_zero_node);
> + m_first = false;
> + /* Nothing is needed to bswap 8 bits or bitreverse 1 bit, so just
> + mask off higher bits in that case. */
> + if ((prec % limb_prec) != (ifn == IFN_BSWAP ? 8 : 1))
> + {
> + g = gimple_build_call (fndecl, 1, t);
> + t = make_ssa_name (m_limb_type);
> + gimple_call_set_lhs (g, t);
> + insert_before (g);
> + g = gimple_build_assign (make_ssa_name (m_limb_type), RSHIFT_EXPR,
> + t, n2);
> + }
> + else
> + g = gimple_build_assign (make_ssa_name (m_limb_type), BIT_AND_EXPR,
> + t, build_int_cst (m_limb_type,
> + ifn == IFN_BSWAP
> + ? 0xff : 1));
> + insert_before (g);
> + t = gimple_assign_lhs (g);
> + tree l = limb_access (TREE_TYPE (lhs), obj,
> + bitint_big_endian ? size_zero_node : p, true);
> + g = gimple_build_assign (l, t);
> + insert_before (g);
> + tree pm1 = build_int_cst (sizetype, prec / limb_prec - 1);
> + tree idx_next;
> + tree idx = create_loop (pm1, &idx_next);
> + tree pmidx = make_ssa_name (sizetype);
> + g = gimple_build_assign (pmidx, MINUS_EXPR, p, idx);
> + insert_before (g);
> + m_data_cnt = 0;
> + t = handle_operand (arg, bitint_big_endian ? idx : pmidx);
> + m_data_cnt = 0;
> + g = gimple_build_assign (make_ssa_name (m_limb_type), LSHIFT_EXPR,
> + t, n2);
> + insert_before (g);
> + t = gimple_assign_lhs (g);
> + tree t2 = make_ssa_name (sizetype);
> + if (bitint_big_endian)
> + g = gimple_build_assign (t2, PLUS_EXPR, idx, size_one_node);
> + else
> + g = gimple_build_assign (t2, PLUS_EXPR, pmidx, size_int (-1));
> + insert_before (g);
> + t2 = handle_operand (arg, t2);
> + g = gimple_build_assign (make_ssa_name (m_limb_type), RSHIFT_EXPR,
> + t2, n1);
> + insert_before (g);
> + t2 = gimple_assign_lhs (g);
> + g = gimple_build_assign (make_ssa_name (m_limb_type), BIT_IOR_EXPR,
> + t, t2);
> + insert_before (g);
> + t = gimple_assign_lhs (g);
> + g = gimple_build_call (fndecl, 1, t);
> + t = make_ssa_name (m_limb_type);
> + gimple_call_set_lhs (g, t);
> + insert_before (g);
> + l = limb_access (TREE_TYPE (lhs), obj,
> + bitint_big_endian ? pmidx : idx, true);
> + g = gimple_build_assign (l, t);
> + insert_before (g);
> + g = gimple_build_assign (idx_next, PLUS_EXPR, idx, size_int (-1));
> + insert_before (g);
> + g = gimple_build_cond (NE_EXPR, idx, size_zero_node, NULL_TREE,
> + NULL_TREE);
> + insert_before (g);
> + }
> + gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
> + if (bitint_extended == bitint_ext_full
> + && abi_limb_prec > limb_prec
> + && (CEIL (prec, abi_limb_prec) * abi_limb_prec
> + > CEIL (prec, limb_prec) * limb_prec))
> + {
> + m_gsi = gsi;
> + tree p2 = build_int_cst (sizetype,
> + CEIL (prec, abi_limb_prec)
> + * abi_limb_prec / limb_prec - 1);
> + tree l = limb_access (TREE_TYPE (lhs), obj, p2, true);
> + g = gimple_build_assign (l, build_zero_cst (m_limb_type));
> + insert_before (g);
> + }
> + gsi_remove (&gsi, true);
> +}
> +
> /* Lower a call statement with one or more large/huge _BitInt
> arguments or large/huge _BitInt return value. */
>
> @@ -6135,6 +6311,10 @@ bitint_large_huge::lower_call (tree obj,
> case IFN_POPCOUNT:
> lower_bit_query (stmt);
> return;
> + case IFN_BSWAP:
> + case IFN_BITREVERSE:
> + lower_bswap_bitreverse (stmt);
> + return;
> default:
> break;
> }
> @@ -6815,8 +6995,7 @@ build_bitint_stmt_ssa_conflicts (gimple
> }
> }
> }
> - else if (bitint_big_endian
> - && is_gimple_call (stmt)
> + else if (is_gimple_call (stmt)
> && gimple_call_internal_p (stmt))
> switch (gimple_call_internal_fn (stmt))
> {
> @@ -6826,6 +7005,15 @@ build_bitint_stmt_ssa_conflicts (gimple
> case IFN_UBSAN_CHECK_SUB:
> case IFN_MUL_OVERFLOW:
> case IFN_UBSAN_CHECK_MUL:
> + if (bitint_big_endian)
> + {
> + lhs = gimple_call_lhs (stmt);
> + if (lhs)
> + muldiv_p = true;
> + }
> + break;
> + case IFN_BSWAP:
> + case IFN_BITREVERSE:
> lhs = gimple_call_lhs (stmt);
> if (lhs)
> muldiv_p = true;
> --- gcc/c-family/c-common.h.jj 2026-06-04 08:24:31.070115532 +0200
> +++ gcc/c-family/c-common.h 2026-06-04 08:31:41.603068847 +0200
> @@ -111,7 +111,8 @@ enum rid
> RID_TYPES_COMPATIBLE_P, RID_BUILTIN_COMPLEX, RID_BUILTIN_SHUFFLE,
> RID_BUILTIN_SHUFFLEVECTOR, RID_BUILTIN_CONVERTVECTOR,
> RID_BUILTIN_TGMATH,
> RID_BUILTIN_HAS_ATTRIBUTE, RID_BUILTIN_ASSOC_BARRIER, RID_BUILTIN_STDC,
> - RID_BUILTIN_COUNTED_BY_REF,
> + RID_BUILTIN_COUNTED_BY_REF, RID_BUILTIN_BSWAPG,
> + RID_BUILTIN_BITREVERSEG,
> RID_DFLOAT32, RID_DFLOAT64, RID_DFLOAT128, RID_DFLOAT64X,
>
> /* TS 18661-3 keywords, in the same sequence as the TI_* values. */
> --- gcc/c-family/c-common.cc.jj 2026-06-04 08:24:31.067115572 +0200
> +++ gcc/c-family/c-common.cc 2026-06-04 08:31:41.603541813 +0200
> @@ -433,7 +433,9 @@ const struct c_common_resword c_common_r
> { "__auto_type", RID_AUTO_TYPE, D_CONLY },
> { "__builtin_addressof", RID_ADDRESSOF, D_CXXONLY },
> { "__builtin_assoc_barrier", RID_BUILTIN_ASSOC_BARRIER, 0 },
> + { "__builtin_bitreverseg", RID_BUILTIN_BITREVERSEG, 0 },
> { "__builtin_bit_cast", RID_BUILTIN_BIT_CAST, D_CXXONLY },
> + { "__builtin_bswapg", RID_BUILTIN_BSWAPG, 0 },
> { "__builtin_call_with_static_chain",
> RID_BUILTIN_CALL_WITH_STATIC_CHAIN, D_CONLY },
> { "__builtin_choose_expr", RID_CHOOSE_EXPR, D_CONLY },
> --- gcc/c/c-parser.cc.jj 2026-06-04 08:24:37.587028893 +0200
> +++ gcc/c/c-parser.cc 2026-06-04 08:53:43.390909824 +0200
> @@ -13534,6 +13534,76 @@ c_parser_postfix_expression (c_parser *p
> expr.value);
> break;
> }
> + case RID_BUILTIN_BSWAPG:
> + case RID_BUILTIN_BITREVERSEG:
> + {
> + vec<c_expr_t, va_gc> *cexpr_list;
> + location_t close_paren_loc;
> + internal_fn ifn
> + = (c_parser_peek_token (parser)->keyword == RID_BUILTIN_BSWAPG
> + ? IFN_BSWAP : IFN_BITREVERSE);
> + const char *name
> + = (ifn == IFN_BSWAP ? "__builtin_bswapg"
> + : "__builtin_bitreverseg");
> +
> + c_parser_consume_token (parser);
> + if (!c_parser_get_builtin_args (parser, name, &cexpr_list, false,
> + &close_paren_loc))
> + {
> + expr.set_error ();
> + break;
> + }
> +
> + if (vec_safe_length (cexpr_list) != 1)
> + {
> + error_at (loc, "wrong number of arguments to %qs", name);
> + expr.set_error ();
> + break;
> + }
> +
> + c_expr_t *arg_p = &(*cexpr_list)[0];
> + *arg_p = convert_lvalue_to_rvalue (loc, *arg_p, true, true);
> + tree arg = arg_p->value;
> + tree type = TYPE_MAIN_VARIANT (TREE_TYPE (arg));
> + if (!INTEGRAL_TYPE_P (type))
> + {
> + error_at (loc, "%qs operand not an integral type", name);
> + expr.set_error ();
> + break;
> + }
> + if (TREE_CODE (type) == ENUMERAL_TYPE)
> + {
> + error_at (loc, "argument %u in call to function "
> + "%qs has enumerated type", 1, name);
> + expr.set_error ();
> + break;
> + }
> + if (TREE_CODE (type) == BOOLEAN_TYPE)
> + {
> + error_at (loc, "argument %u in call to function "
> + "%qs has boolean type", 1, name);
> + expr.set_error ();
> + break;
> + }
> + if (!TYPE_UNSIGNED (type))
> + {
> + error_at (loc, "argument 1 in call to function "
> + "%qs has signed type", name);
> + expr.set_error ();
> + break;
> + }
> + if (ifn == IFN_BSWAP && (TYPE_PRECISION (type) % 8) != 0)
> + {
> + error_at (loc, "precision %d of argument 1 to function "
> + "%qs is not a multiple of 8",
> + TYPE_PRECISION (type), name);
> + expr.set_error ();
> + break;
> + }
> + expr.value = fold_build_builtin_bswapg_bitreverseg (loc, ifn, arg);
> + set_c_expr_source_range (&expr, loc, close_paren_loc);
> + break;
> + }
> case RID_AT_SELECTOR:
> {
> gcc_assert (c_dialect_objc ());
> --- gcc/cp/parser.cc.jj 2026-06-04 08:24:37.610028587 +0200
> +++ gcc/cp/parser.cc 2026-06-04 08:34:05.297481411 +0200
> @@ -8626,6 +8626,8 @@ cp_parser_postfix_expression (cp_parser
> case RID_BUILTIN_ASSOC_BARRIER:
> case RID_BUILTIN_OPERATOR_NEW:
> case RID_BUILTIN_OPERATOR_DELETE:
> + case RID_BUILTIN_BSWAPG:
> + case RID_BUILTIN_BITREVERSEG:
> {
> vec<tree, va_gc> *vec;
>
> @@ -8745,6 +8747,18 @@ cp_parser_postfix_expression (cp_parser
> }
> break;
>
> + case RID_BUILTIN_BSWAPG:
> + postfix_expression
> + = build_x_bswapg_bitreverseg (loc, IFN_BSWAP, vec,
> + tf_warning_or_error);
> + break;
> +
> + case RID_BUILTIN_BITREVERSEG:
> + postfix_expression
> + = build_x_bswapg_bitreverseg (loc, IFN_BITREVERSE, vec,
> + tf_warning_or_error);
> + break;
> +
> default:
> gcc_unreachable ();
> }
> --- gcc/cp/typeck.cc.jj 2026-06-04 08:24:31.102115107 +0200
> +++ gcc/cp/typeck.cc 2026-06-04 08:42:47.069566467 +0200
> @@ -7111,6 +7111,71 @@ build_x_shufflevector (location_t loc, v
> }
> return exp;
> }
> +
> +/* Build __builtin_bswapg (ARG) or __builtin_bitreverseg (ARG). */
> +tree
> +build_x_bswapg_bitreverseg (location_t loc, internal_fn ifn,
> + vec<tree, va_gc> *args, tsubst_flags_t complain)
> +{
> + const char *name
> + = ifn == IFN_BSWAP ? "__builtin_bswapg" : "__builtin_bitreverseg";
> + if (args->length () != 1)
> + {
> + if (complain & tf_error)
> + error_at (loc, "wrong number of arguments to %qs", name);
> + return error_mark_node;
> + }
> + tree arg = (*args)[0];
> + if (type_dependent_expression_p (arg))
> + {
> + tree exp = build_min_nt_call_vec (NULL, args);
> + CALL_EXPR_IFN (exp) = ifn;
> + return exp;
> + }
> + tree type = TYPE_MAIN_VARIANT (TREE_TYPE (arg));
> + if (!INTEGRAL_TYPE_P (type))
> + {
> + if (complain & tf_error)
> + error_at (loc, "%qs operand not an integral type", name);
> + return error_mark_node;
> + }
> + if (TREE_CODE (type) == ENUMERAL_TYPE)
> + {
> + if (complain & tf_error)
> + error_at (loc, "argument %u in call to function "
> + "%qs has enumerated type", 1, name);
> + return error_mark_node;
> + }
> + if (TREE_CODE (type) == BOOLEAN_TYPE)
> + {
> + if (complain & tf_error)
> + error_at (loc, "argument %u in call to function "
> + "%qs has boolean type", 1, name);
> + return error_mark_node;
> + }
> + if (!TYPE_UNSIGNED (type))
> + {
> + if (complain & tf_error)
> + error_at (loc, "argument 1 in call to function "
> + "%qs has signed type", name);
> + return error_mark_node;
> + }
> + if (ifn == IFN_BSWAP && (TYPE_PRECISION (type) % 8) != 0)
> + {
> + if (complain & tf_error)
> + error_at (loc, "precision %d of argument 1 to function "
> + "%qs is not a multiple of 8",
> + TYPE_PRECISION (type), name);
> + return error_mark_node;
> + }
> + tree exp = build_call_expr_internal_loc (loc, ifn, type, 1, arg);
> + if (processing_template_decl)
> + {
> + exp = build_min_non_dep_call_vec (exp, NULL, args);
> + CALL_EXPR_IFN (exp) = ifn;
> + }
> + return exp;
> +}
>
> /* Return a tree for the sum or difference (RESULTCODE says which)
> of pointer PTROP and integer INTOP. */
> --- gcc/cp/cp-tree.h.jj 2026-06-04 08:24:37.606028640 +0200
> +++ gcc/cp/cp-tree.h 2026-06-04 08:31:41.612343919 +0200
> @@ -9050,6 +9050,9 @@ extern tree build_x_vec_perm_expr
> extern tree build_x_shufflevector (location_t,
> vec<tree, va_gc> *,
> tsubst_flags_t);
> +extern tree build_x_bswapg_bitreverseg (location_t,
> internal_fn,
> + vec<tree, va_gc> *,
> + tsubst_flags_t);
> #define cxx_sizeof(T) cxx_sizeof_or_alignof_type (input_location, T,
> SIZEOF_EXPR, false, true)
> extern tree build_simple_component_ref (tree, tree);
> extern tree build_ptrmemfunc_access_expr (tree, tree);
> --- gcc/cp/pt.cc.jj 2026-06-04 08:24:37.613028547 +0200
> +++ gcc/cp/pt.cc 2026-06-04 08:31:41.613787189 +0200
> @@ -22517,6 +22517,17 @@ tsubst_expr (tree t, tree args, tsubst_f
> break;
> }
>
> + case IFN_BSWAP:
> + case IFN_BITREVERSE:
> + {
> + ret = build_x_bswapg_bitreverseg (input_location,
> + CALL_EXPR_IFN (t), call_args,
> + complain);
> + if (ret != error_mark_node)
> + RETURN (ret);
> + break;
> + }
> +
> case IFN_ASSUME:
> gcc_assert (nargs == 1);
> if (vec_safe_length (call_args) != 1)
> --- gcc/cp/constexpr.cc.jj 2026-06-04 08:24:31.073115492 +0200
> +++ gcc/cp/constexpr.cc 2026-06-04 08:34:56.285803540 +0200
> @@ -3245,6 +3245,32 @@ cxx_eval_internal_function (const conste
> case IFN_DEFERRED_INIT:
> return build_clobber (TREE_TYPE (t), CLOBBER_OBJECT_BEGIN);
>
> + case IFN_BSWAP:
> + case IFN_BITREVERSE:
> + {
> + tree arg = cxx_eval_constant_expression (ctx, CALL_EXPR_ARG (t, 0),
> + vc_prvalue, non_constant_p,
> + overflow_p, jump_target);
> + if (*jump_target)
> + return NULL_TREE;
> + if (*non_constant_p)
> + return t;
> + location_t loc = cp_expr_loc_or_input_loc (t);
> + if (TREE_CODE (arg) != INTEGER_CST
> + || !INTEGRAL_TYPE_P (TREE_TYPE (arg))
> + || !TYPE_UNSIGNED (TREE_TYPE (arg))
> + || (CALL_EXPR_IFN (t) == IFN_BSWAP
> + && (TYPE_PRECISION (TREE_TYPE (arg)) % 8) != 0))
> + {
> + if (!ctx->quiet)
> + error_at (loc, "call to internal function %qE", t);
> + *non_constant_p = true;
> + return t;
> + }
> + return fold_build_builtin_bswapg_bitreverseg (loc, CALL_EXPR_IFN (t),
> + arg);
> + }
> +
> case IFN_VEC_CONVERT:
> {
> tree arg = cxx_eval_constant_expression (ctx, CALL_EXPR_ARG (t, 0),
> @@ -12026,6 +12052,8 @@ potential_constant_expression_1 (tree t,
> case IFN_MUL_OVERFLOW:
> case IFN_LAUNDER:
> case IFN_VEC_CONVERT:
> + case IFN_BSWAP:
> + case IFN_BITREVERSE:
> bail = false;
> break;
>
> --- gcc/cp/cp-gimplify.cc.jj 2026-06-04 08:24:31.085115333 +0200
> +++ gcc/cp/cp-gimplify.cc 2026-06-04 08:31:41.616308733 +0200
> @@ -44,6 +44,7 @@ along with GCC; see the file COPYING3.
> #include "opts.h"
> #include "gcc-urlifier.h"
> #include "contracts.h" // build_contract_check ()
> +#include "builtins.h"
>
> /* Keep track of forward references to immediate-escalating functions in
> case they become consteval. This vector contains ADDR_EXPRs and
> @@ -880,7 +881,29 @@ cp_gimplify_expr (tree *expr_p, gimple_s
> = build1 (NOP_EXPR, fnptrtype, CALL_EXPR_FN (*expr_p));
> }
> if (!CALL_EXPR_FN (*expr_p))
> - /* Internal function call. */;
> + /* Internal function call. */
> + switch (CALL_EXPR_IFN (*expr_p))
> + {
> + case IFN_BSWAP:
> + case IFN_BITREVERSE:
> + if (ret == GS_OK)
> + {
> + location_t loc = EXPR_LOCATION (*expr_p);
> + internal_fn ifn = CALL_EXPR_IFN (*expr_p);
> + tree arg = CALL_EXPR_ARG (*expr_p, 0);
> + tree r = fold_build_builtin_bswapg_bitreverseg (loc, ifn,
> + arg);
> + if (TREE_CODE (r) == CALL_EXPR
> + && !CALL_EXPR_FN (r)
> + && CALL_EXPR_IFN (r) == ifn)
> + break;
> + *expr_p = r;
> + return ret;
> + }
> + break;
> + default:
> + break;
> + }
> else if (CALL_EXPR_REVERSE_ARGS (*expr_p))
> {
> /* This is a call to a (compound) assignment operator that used
> --- gcc/testsuite/c-c++-common/builtin-bswapg-1.c.jj 2026-06-04
> 08:31:41.616644255 +0200
> +++ gcc/testsuite/c-c++-common/builtin-bswapg-1.c 2026-06-04
> 08:31:41.616644255 +0200
> @@ -0,0 +1,153 @@
> +/* Test __builtin_bswapg. */
> +/* { dg-do run { target { c || c++11 } } } */
> +/* { dg-options "-O2" } */
> +
> +#if __CHAR_BIT__ == 8
> +#if __SIZEOF_INT__ == 4
> +static_assert (__builtin_bswapg (0x12345678U) == 0x78563412U, "");
> +#endif
> +#if __SIZEOF_LONG_LONG__ == 8
> +static_assert (__builtin_bswapg (0x123456789abcdef0ULL) ==
> 0xf0debc9a78563412ULL, "");
> +#endif
> +static_assert (__builtin_bswapg ((unsigned char) 0x23) == (unsigned char)
> 0x23, "");
> +#if __SIZEOF_SHORT__ == 2
> +static_assert (__builtin_bswapg ((unsigned short) 0x2345) == (unsigned
> short) 0x4523, "");
> +#endif
> +#if __SIZEOF_INT128__ == 16
> +static_assert (__builtin_bswapg ((((unsigned __int128)
> 0x123456789abcdef0ULL) << 64)
> + | 0x23456789abcdef01ULL)
> + == ((((unsigned __int128)
> 0x01efcdab89674523ULL) << 64)
> + | 0xf0debc9a78563412ULL), "");
> +#endif
> +#endif
> +#if __BITINT_MAXWIDTH__ >= 856
> +static_assert (__builtin_bswapg (0xabcdefuwb) == 0xefcdabuwb, "");
> +static_assert (__builtin_bswapg (0xabcdef8081uwb) == 0x8180efcdabuwb, "");
> +static_assert (__builtin_bswapg ((unsigned _BitInt(136))
> 0x66b52574b5fd190b15a1b99858c27d0ac2uwb)
> + == 0xc20a7dc25898b9a1150b19fdb57425b566uwb, "");
> +static_assert (__builtin_bswapg ((unsigned _BitInt(832))
> 0x021256fc7a59ee4dab277edcadfdbfd45c0690f99249cf9e31ad0b16f91a0efb2d64f8a7bde6f4680d7244ba70038ecc091fc59c68943a994146b03a60be368d222e34e0142948229b8ddc0b906bd79a8a9c36f230708b71b63bac17f9e2a41c10d9fc240244469duwb)
> + ==
> 0x9d46440224fcd9101ca4e2f917ac3bb6718b7030f2369c8a9ad76b900bdc8d9b22482914e0342e228d36be603ab04641993a94689cc51f09cc8e0370ba44720d68f4e6bda7f8642dfb0e1af9160bad319ecf4992f990065cd4bffdaddc7e27ab4dee597afc561202uwb,
> "");
> +static_assert (__builtin_bswapg ((unsigned _BitInt(840))
> 0x4c23edce0b5ffd538da2112c333d17f100a0db44f7c9cfb097538e995f3a5bab5d487969a776bc3518cd614b0a783d0b18184f10e11ec078714f11d0896c7be6b5f54f5c6b0c9184d9f3cfe46b0cef84243e94055d547dcea38f9f2cfb1a13b00f620d7b6e9eff4891uwb)
> + ==
> 0x9148ff9e6e7b0d620fb0131afb2c9f8fa3ce7d545d05943e2484ef0c6be4cff3d984910c6b5c4ff5b5e67b6c89d0114f7178c01ee1104f18180b3d780a4b61cd1835bc76a76979485dab5b3a5f998e5397b0cfc9f744dba000f1173d332c11a28d53fd5f0bceed234cuwb,
> "");
> +static_assert (__builtin_bswapg ((unsigned _BitInt(856))
> 0x41c39e2f987be9c81688ecc08a4ded319e4010952ecb6e4ac738a6924d81668f4404bedd7fa7a5952f9156bade43eb7d83fb12b2c780fc8eb9a22006238695678a53440afbe99f2a7af5e45938cfd6bccbe86e92696a20220c41282fc7be965211db5c0cc4fb373ff11b98uwb)
> + ==
> 0x981bf13f37fbc40c5cdb115296bec72f28410c22206a69926ee8cbbcd6cf3859e4f57a2a9fe9fb0a44538a679586230620a2b98efc80c7b212fb837deb43deba56912f95a5a77fddbe04448f66814d92a638c74a6ecb2e9510409e31ed4d8ac0ec8816c8e97b982f9ec341uwb,
> "");
> +#endif
> +
> +#if __CHAR_BIT__ == 8
> +#if __SIZEOF_INT__ == 4
> +[[gnu::noipa]] unsigned
> +bswap32 (unsigned x)
> +{
> + return __builtin_bswapg (x);
> +}
> +#endif
> +#if __SIZEOF_LONG_LONG__ == 8
> +[[gnu::noipa]] unsigned long long
> +bswap64 (unsigned long long x)
> +{
> + return __builtin_bswapg (x);
> +}
> +#endif
> +[[gnu::noipa]] unsigned char
> +bswap8 (unsigned char x)
> +{
> + return __builtin_bswapg (x);
> +}
> +#if __SIZEOF_SHORT__ == 2
> +[[gnu::noipa]] unsigned short
> +bswap16 (unsigned short x)
> +{
> + return __builtin_bswapg (x);
> +}
> +#endif
> +#if __SIZEOF_INT128__ == 16
> +[[gnu::noipa]] unsigned __int128
> +bswap128 (unsigned __int128 x)
> +{
> + return __builtin_bswapg (x);
> +}
> +#endif
> +#endif
> +#if __BITINT_MAXWIDTH__ >= 856
> +[[gnu::noipa]] unsigned _BitInt(24)
> +bswap24 (unsigned _BitInt(24) x)
> +{
> + return __builtin_bswapg (x);
> +}
> +
> +[[gnu::noipa]] unsigned _BitInt(40)
> +bswap40 (unsigned _BitInt(40) x)
> +{
> + return __builtin_bswapg (x);
> +}
> +
> +[[gnu::noipa]] unsigned _BitInt(136)
> +bswap136 (unsigned _BitInt(136) x)
> +{
> + return __builtin_bswapg (x);
> +}
> +
> +[[gnu::noipa]] unsigned _BitInt(832)
> +bswap832 (unsigned _BitInt(832) x)
> +{
> + return __builtin_bswapg (x);
> +}
> +
> +[[gnu::noipa]] unsigned _BitInt(840)
> +bswap840 (unsigned _BitInt(840) x)
> +{
> + return __builtin_bswapg (x);
> +}
> +
> +[[gnu::noipa]] unsigned _BitInt(856)
> +bswap856 (unsigned _BitInt(856) x)
> +{
> + return __builtin_bswapg (x);
> +}
> +#endif
> +
> +int
> +main ()
> +{
> +#if __CHAR_BIT__ == 8
> +#if __SIZEOF_INT__ == 4
> + if (bswap32 (0x12345678U) != 0x78563412U)
> + __builtin_abort ();
> +#endif
> +#if __SIZEOF_LONG_LONG__ == 8
> + if (bswap64 (0x123456789abcdef0ULL) != 0xf0debc9a78563412ULL)
> + __builtin_abort ();
> +#endif
> + if (bswap8 ((unsigned char) 0x23) != (unsigned char) 0x23)
> + __builtin_abort ();
> +#if __SIZEOF_SHORT__ == 2
> + if (bswap16 ((unsigned short) 0x2345) != (unsigned short) 0x4523)
> + __builtin_abort ();
> +#endif
> +#if __SIZEOF_INT128__ == 16
> + if (bswap128 ((((unsigned __int128) 0x123456789abcdef0ULL) << 64)
> + | 0x23456789abcdef01ULL)
> + != ((((unsigned __int128) 0x01efcdab89674523ULL) << 64)
> + | 0xf0debc9a78563412ULL))
> + __builtin_abort ();
> +#endif
> +#endif
> +#if __BITINT_MAXWIDTH__ >= 856
> + if (bswap24 (0xabcdefuwb) != 0xefcdabuwb)
> + __builtin_abort ();
> + if (bswap40 (0xabcdef8081uwb) != 0x8180efcdabuwb)
> + __builtin_abort ();
> + if (bswap136 (0x66b52574b5fd190b15a1b99858c27d0ac2uwb)
> + != 0xc20a7dc25898b9a1150b19fdb57425b566uwb)
> + __builtin_abort ();
> + if (bswap832
> (0x021256fc7a59ee4dab277edcadfdbfd45c0690f99249cf9e31ad0b16f91a0efb2d64f8a7bde6f4680d7244ba70038ecc091fc59c68943a994146b03a60be368d222e34e0142948229b8ddc0b906bd79a8a9c36f230708b71b63bac17f9e2a41c10d9fc240244469duwb)
> + !=
> 0x9d46440224fcd9101ca4e2f917ac3bb6718b7030f2369c8a9ad76b900bdc8d9b22482914e0342e228d36be603ab04641993a94689cc51f09cc8e0370ba44720d68f4e6bda7f8642dfb0e1af9160bad319ecf4992f990065cd4bffdaddc7e27ab4dee597afc561202uwb)
> + __builtin_abort ();
> + if (bswap840
> (0x4c23edce0b5ffd538da2112c333d17f100a0db44f7c9cfb097538e995f3a5bab5d487969a776bc3518cd614b0a783d0b18184f10e11ec078714f11d0896c7be6b5f54f5c6b0c9184d9f3cfe46b0cef84243e94055d547dcea38f9f2cfb1a13b00f620d7b6e9eff4891uwb)
> + !=
> 0x9148ff9e6e7b0d620fb0131afb2c9f8fa3ce7d545d05943e2484ef0c6be4cff3d984910c6b5c4ff5b5e67b6c89d0114f7178c01ee1104f18180b3d780a4b61cd1835bc76a76979485dab5b3a5f998e5397b0cfc9f744dba000f1173d332c11a28d53fd5f0bceed234cuwb)
> + __builtin_abort ();
> + if (bswap856
> (0x41c39e2f987be9c81688ecc08a4ded319e4010952ecb6e4ac738a6924d81668f4404bedd7fa7a5952f9156bade43eb7d83fb12b2c780fc8eb9a22006238695678a53440afbe99f2a7af5e45938cfd6bccbe86e92696a20220c41282fc7be965211db5c0cc4fb373ff11b98uwb)
> + !=
> 0x981bf13f37fbc40c5cdb115296bec72f28410c22206a69926ee8cbbcd6cf3859e4f57a2a9fe9fb0a44538a679586230620a2b98efc80c7b212fb837deb43deba56912f95a5a77fddbe04448f66814d92a638c74a6ecb2e9510409e31ed4d8ac0ec8816c8e97b982f9ec341uwb)
> + __builtin_abort ();
> +#endif
> +}
> --- gcc/testsuite/c-c++-common/builtin-bswapg-2.c.jj 2026-06-04
> 08:31:41.616760455 +0200
> +++ gcc/testsuite/c-c++-common/builtin-bswapg-2.c 2026-06-04
> 08:36:22.357659251 +0200
> @@ -0,0 +1,21 @@
> +/* Test __builtin_bswapg. */
> +/* { dg-do compile } */
> +/* { dg-options "" } */
> +
> +int
> +main ()
> +{
> + __builtin_bswapg (); /* { dg-error "wrong number of
> arguments to '__builtin_bswapg'" } */
> + __builtin_bswapg (1U, 1U); /* { dg-error "wrong number of arguments to
> '__builtin_bswapg'" } */
> + __builtin_bswapg (1.0); /* { dg-error "'__builtin_bswapg' operand not
> an integral type" } */
> + __builtin_bswapg (1.0f); /* { dg-error "'__builtin_bswapg' operand not
> an integral type" } */
> + __builtin_bswapg (1.0L); /* { dg-error "'__builtin_bswapg' operand not
> an integral type" } */
> + struct S { int a; };
> + __builtin_bswapg ((struct S) { 42 }); /* { dg-error
> "'__builtin_bswapg' operand not an integral type" } */
> + enum E { E0, E1 };
> + __builtin_bswapg (E1); /* { dg-error "argument 1 in call to function
> '__builtin_bswapg' has signed type" "" { target c } } */
> + /* { dg-error "argument 1 in call to function
> '__builtin_bswapg' has enumerated type" "" { target c++ } .-1 } */
> + __builtin_bswapg (false); /* { dg-error "argument 1 in call to function
> '__builtin_bswapg' has boolean type" } */
> + __builtin_bswapg (1); /* { dg-error "argument 1 in call to
> function '__builtin_bswapg' has signed type" } */
> + __builtin_bswapg ((char) 1); /* { dg-error "argument 1 in call to
> function '__builtin_bswapg' has signed type" "" { target { ! unsigned_char }
> } } */
> +}
> --- gcc/testsuite/c-c++-common/builtin-bswapg-3.c.jj 2026-06-04
> 08:31:41.616895292 +0200
> +++ gcc/testsuite/c-c++-common/builtin-bswapg-3.c 2026-06-04
> 08:31:41.616895292 +0200
> @@ -0,0 +1,15 @@
> +/* Test __builtin_bswapg. */
> +/* { dg-do compile } */
> +/* { dg-options "" } */
> +
> +int
> +main ()
> +{
> +#if __BITINT_MAXWIDTH__ >= 575
> + __builtin_bswapg (0x0uwb); /* { dg-error "precision 1 of argument 1 to
> function '__builtin_bswapg' is not a multiple of 8" "" { target bitint575 } }
> */
> + __builtin_bswapg (0x3uwb); /* { dg-error "precision 2 of argument 1 to
> function '__builtin_bswapg' is not a multiple of 8" "" { target bitint575 } }
> */
> + __builtin_bswapg (0x34938571398572uwb); /* { dg-error "precision 54 of
> argument 1 to function '__builtin_bswapg' is not a multiple of 8" "" { target
> bitint575 } } */
> + __builtin_bswapg (0x34938571398572abcd9837298dabef9187983uwb); /* {
> dg-error "precision 146 of argument 1 to function '__builtin_bswapg' is not a
> multiple of 8" "" { target bitint575 } } */
> + __builtin_bswapg
> (0x34938571398572abcd9837298dabef918798329387987abef98792837549857983745983475329847uwb);
> /* { dg-error "precision 322 of argument 1 to function '__builtin_bswapg' is
> not a multiple of 8" "" { target bitint575 } } */
> +#endif
> +}
> --- gcc/testsuite/c-c++-common/builtin-bitreverseg-1.c.jj 2026-06-04
> 08:31:41.616984054 +0200
> +++ gcc/testsuite/c-c++-common/builtin-bitreverseg-1.c 2026-06-04
> 08:31:41.616984054 +0200
> @@ -0,0 +1,164 @@
> +/* Test __builtin_bitreverseg. */
> +/* { dg-do run { target { c || c++11 } } } */
> +/* { dg-options "-O2" } */
> +
> +#if __CHAR_BIT__ == 8
> +#if __SIZEOF_INT__ == 4
> +static_assert (__builtin_bitreverseg (0x2fa889a7U) == 0xe59115f4U, "");
> +#endif
> +#if __SIZEOF_LONG_LONG__ == 8
> +static_assert (__builtin_bitreverseg (0xd7632f428bdccb94ULL) ==
> 0x29d33bd142f4c6ebULL, "");
> +#endif
> +static_assert (__builtin_bitreverseg ((unsigned char) 0xac) == (unsigned
> char) 0x35, "");
> +#if __SIZEOF_SHORT__ == 2
> +static_assert (__builtin_bitreverseg ((unsigned short) 0xc4f0) == (unsigned
> short) 0x0f23, "");
> +#endif
> +#if __SIZEOF_INT128__ == 16
> +static_assert (__builtin_bitreverseg ((((unsigned __int128)
> 0x398773ddb9250c54ULL) << 64)
> + | 0x26933639cdf63ea6ULL)
> + == ((((unsigned __int128)
> 0x657c6fb39c6cc964ULL) << 64)
> + | 0x2a30a49dbbcee19cULL), "");
> +#endif
> +#endif
> +#if __BITINT_MAXWIDTH__ >= 856
> +static_assert (__builtin_bitreverseg (0xb75774uwb) == 0x2eeaeduwb, "");
> +static_assert (__builtin_bitreverseg (0xd55668c010uwb) == 0x0803166aabuwb,
> "");
> +static_assert (__builtin_bitreverseg ((unsigned _BitInt(129))
> 0x01cc4426458663d6c35ad6f0c7117fc2b7uwb)
> + == 0x01da87fd11c61ed6b586d78cc344c84467uwb, "");
> +static_assert (__builtin_bitreverseg ((unsigned _BitInt(136))
> 0xc73210faaad84376ebd396f82a166ac5f9uwb)
> + == 0x9fa35668541f69cbd76ec21b555f084ce3uwb, "");
> +static_assert (__builtin_bitreverseg ((unsigned _BitInt(832))
> 0x09d2702b49ac2e9b1010df028451dceaf2cf9938035fa708921fb53a5d509d66220d916bb9bf07c9cfe6cc5437a83e2977d7617a360882c82838038588a0ecaaae7d16673d1d310c03fd603aa59f631c76c497adcc1975f451787ad9196684c7e39a2e20b75f2dbauwb)
> + ==
> 0x5db4faed047459c7e32166989b5e1e8a2fae9833b5e9236e38c6f9a55c06bfc0308cb8bce668be7555370511a1c01c141341106c5e86ebee947c15ec2a3367f393e0fd9dd689b04466b90aba5cadf84910e5fac01c99f34f573b8a2140fb0808d9743592d40e4b90uwb,
> "");
> +static_assert (__builtin_bitreverseg ((unsigned _BitInt(833))
> 0x0054078b08ef56720bb2a2cc52ddac983838de381c548c346e0b4274d51635f36b3c7e732bd4e536868702d864ae709ce74fd403a36037116c79854190bb34fbf7b26e238654590cdb5ce4400a54dcf1a3b1f546112c587da6ddbe3698f23190a49fb32af30c36cf68uwb)
> + ==
> 0x002de6d8619ea99bf24a13189e32d8fb76cb7c346910c55f1b8b1e7654a0044e75b6613454c388ec9bdfbe59ba1305433c6d11d80d8b8057e5ce721cea4c3681c2c2d94e57a99cfc79ad9f58d1565c85a0ec5862547038f63838326b7694668a9ba09cd5ee21a3c054uwb,
> "");
> +static_assert (__builtin_bitreverseg ((unsigned _BitInt(856))
> 0x6aa3d211688a1bc275204e2e83f7ecacfdc42aecdc1ae8093b901c207dc089e8645bf9cce6148e5b34dc89b7d47563d13a8ebd16a8a51fe3353b04b3fc8d9b60e9942ccfa8bb2adc97b4936b29f63c6384f9792c9f9810d4d41487d0a122308ab65c595e17843aaf38cd1auwb)
> + ==
> 0x58b31cf55c21e87a9a3a6d510c44850be1282b2b0819f9349e9f21c63c6f94d6c92de93b54dd15f334299706d9b13fcd20dcacc7f8a51568bd715c8bc6ae2bed913b2cda712867339fda26179103be043809dc9017583b375423bf3537efc1747204ae43d85116884bc556uwb,
> "");
> +#endif
> +
> +#if __CHAR_BIT__ == 8
> +#if __SIZEOF_INT__ == 4
> +[[gnu::noipa]] unsigned
> +bitreverse32 (unsigned x)
> +{
> + return __builtin_bitreverseg (x);
> +}
> +#endif
> +#if __SIZEOF_LONG_LONG__ == 8
> +[[gnu::noipa]] unsigned long long
> +bitreverse64 (unsigned long long x)
> +{
> + return __builtin_bitreverseg (x);
> +}
> +#endif
> +[[gnu::noipa]] unsigned char
> +bitreverse8 (unsigned char x)
> +{
> + return __builtin_bitreverseg (x);
> +}
> +#if __SIZEOF_SHORT__ == 2
> +[[gnu::noipa]] unsigned short
> +bitreverse16 (unsigned short x)
> +{
> + return __builtin_bitreverseg (x);
> +}
> +#endif
> +#if __SIZEOF_INT128__ == 16
> +[[gnu::noipa]] unsigned __int128
> +bitreverse128 (unsigned __int128 x)
> +{
> + return __builtin_bitreverseg (x);
> +}
> +#endif
> +#endif
> +#if __BITINT_MAXWIDTH__ >= 856
> +[[gnu::noipa]] unsigned _BitInt(24)
> +bitreverse24 (unsigned _BitInt(24) x)
> +{
> + return __builtin_bitreverseg (x);
> +}
> +
> +[[gnu::noipa]] unsigned _BitInt(40)
> +bitreverse40 (unsigned _BitInt(40) x)
> +{
> + return __builtin_bitreverseg (x);
> +}
> +
> +[[gnu::noipa]] unsigned _BitInt(129)
> +bitreverse129 (unsigned _BitInt(129) x)
> +{
> + return __builtin_bitreverseg (x);
> +}
> +
> +[[gnu::noipa]] unsigned _BitInt(136)
> +bitreverse136 (unsigned _BitInt(136) x)
> +{
> + return __builtin_bitreverseg (x);
> +}
> +
> +[[gnu::noipa]] unsigned _BitInt(832)
> +bitreverse832 (unsigned _BitInt(832) x)
> +{
> + return __builtin_bitreverseg (x);
> +}
> +
> +[[gnu::noipa]] unsigned _BitInt(833)
> +bitreverse833 (unsigned _BitInt(833) x)
> +{
> + return __builtin_bitreverseg (x);
> +}
> +
> +[[gnu::noipa]] unsigned _BitInt(856)
> +bitreverse856 (unsigned _BitInt(856) x)
> +{
> + return __builtin_bitreverseg (x);
> +}
> +#endif
> +
> +int
> +main ()
> +{
> +#if __CHAR_BIT__ == 8
> +#if __SIZEOF_INT__ == 4
> + if (bitreverse32 (0x2fa889a7U) != 0xe59115f4U)
> + __builtin_abort ();
> +#endif
> +#if __SIZEOF_LONG_LONG__ == 8
> + if (bitreverse64 (0xd7632f428bdccb94ULL) != 0x29d33bd142f4c6ebULL)
> + __builtin_abort ();
> +#endif
> + if (bitreverse8 ((unsigned char) 0xac) != (unsigned char) 0x35)
> + __builtin_abort ();
> +#if __SIZEOF_SHORT__ == 2
> + if (bitreverse16 ((unsigned short) 0xc4f0) != (unsigned short) 0x0f23)
> + __builtin_abort ();
> +#endif
> +#if __SIZEOF_INT128__ == 16
> + if (bitreverse128 ((((unsigned __int128) 0x398773ddb9250c54ULL) << 64)
> + | 0x26933639cdf63ea6ULL)
> + != ((((unsigned __int128) 0x657c6fb39c6cc964ULL) << 64)
> + | 0x2a30a49dbbcee19cULL))
> + __builtin_abort ();
> +#endif
> +#endif
> +#if __BITINT_MAXWIDTH__ >= 856
> + if (bitreverse24 (0xb75774uwb) != 0x2eeaed)
> + __builtin_abort ();
> + if (bitreverse40 (0xd55668c010uwb) != 0x0803166aabuwb)
> + __builtin_abort ();
> + if (bitreverse129 (0x01cc4426458663d6c35ad6f0c7117fc2b7uwb)
> + != 0x01da87fd11c61ed6b586d78cc344c84467uwb)
> + __builtin_abort ();
> + if (bitreverse136 (0xc73210faaad84376ebd396f82a166ac5f9uwb)
> + != 0x9fa35668541f69cbd76ec21b555f084ce3uwb)
> + __builtin_abort ();
> + if (bitreverse832
> (0x09d2702b49ac2e9b1010df028451dceaf2cf9938035fa708921fb53a5d509d66220d916bb9bf07c9cfe6cc5437a83e2977d7617a360882c82838038588a0ecaaae7d16673d1d310c03fd603aa59f631c76c497adcc1975f451787ad9196684c7e39a2e20b75f2dbauwb)
> + !=
> 0x5db4faed047459c7e32166989b5e1e8a2fae9833b5e9236e38c6f9a55c06bfc0308cb8bce668be7555370511a1c01c141341106c5e86ebee947c15ec2a3367f393e0fd9dd689b04466b90aba5cadf84910e5fac01c99f34f573b8a2140fb0808d9743592d40e4b90uwb)
> + __builtin_abort ();
> + if (bitreverse833
> (0x0054078b08ef56720bb2a2cc52ddac983838de381c548c346e0b4274d51635f36b3c7e732bd4e536868702d864ae709ce74fd403a36037116c79854190bb34fbf7b26e238654590cdb5ce4400a54dcf1a3b1f546112c587da6ddbe3698f23190a49fb32af30c36cf68uwb)
> + !=
> 0x002de6d8619ea99bf24a13189e32d8fb76cb7c346910c55f1b8b1e7654a0044e75b6613454c388ec9bdfbe59ba1305433c6d11d80d8b8057e5ce721cea4c3681c2c2d94e57a99cfc79ad9f58d1565c85a0ec5862547038f63838326b7694668a9ba09cd5ee21a3c054uwb)
> + __builtin_abort ();
> + if (bitreverse856
> (0x6aa3d211688a1bc275204e2e83f7ecacfdc42aecdc1ae8093b901c207dc089e8645bf9cce6148e5b34dc89b7d47563d13a8ebd16a8a51fe3353b04b3fc8d9b60e9942ccfa8bb2adc97b4936b29f63c6384f9792c9f9810d4d41487d0a122308ab65c595e17843aaf38cd1auwb)
> + !=
> 0x58b31cf55c21e87a9a3a6d510c44850be1282b2b0819f9349e9f21c63c6f94d6c92de93b54dd15f334299706d9b13fcd20dcacc7f8a51568bd715c8bc6ae2bed913b2cda712867339fda26179103be043809dc9017583b375423bf3537efc1747204ae43d85116884bc556uwb)
> + __builtin_abort ();
> +#endif
> +}
> --- gcc/testsuite/c-c++-common/builtin-bitreverseg-2.c.jj 2026-06-04
> 08:31:41.617122699 +0200
> +++ gcc/testsuite/c-c++-common/builtin-bitreverseg-2.c 2026-06-04
> 08:35:54.425030605 +0200
> @@ -0,0 +1,21 @@
> +/* Test __builtin_bitreverseg. */
> +/* { dg-do compile } */
> +/* { dg-options "" } */
> +
> +int
> +main ()
> +{
> + __builtin_bitreverseg (); /* { dg-error "wrong number of
> arguments to '__builtin_bitreverseg'" } */
> + __builtin_bitreverseg (1U, 1U); /* { dg-error "wrong number of
> arguments to '__builtin_bitreverseg'" } */
> + __builtin_bitreverseg (1.0); /* { dg-error
> "'__builtin_bitreverseg' operand not an integral type" } */
> + __builtin_bitreverseg (1.0f); /* { dg-error
> "'__builtin_bitreverseg' operand not an integral type" } */
> + __builtin_bitreverseg (1.0L); /* { dg-error
> "'__builtin_bitreverseg' operand not an integral type" } */
> + struct S { int a; };
> + __builtin_bitreverseg ((struct S) { 42 }); /* { dg-error
> "'__builtin_bitreverseg' operand not an integral type" } */
> + enum E { E0, E1 };
> + __builtin_bitreverseg (E1); /* { dg-error "argument 1 in
> call to function '__builtin_bitreverseg' has signed type" "" { target c } } */
> + /* { dg-error "argument 1 in call to
> function '__builtin_bitreverseg' has enumerated type" "" { target c++ } .-1 }
> */
> + __builtin_bitreverseg (false); /* { dg-error "argument 1 in call to
> function '__builtin_bitreverseg' has boolean type" } */
> + __builtin_bitreverseg (1); /* { dg-error "argument 1 in call to
> function '__builtin_bitreverseg' has signed type" } */
> + __builtin_bitreverseg ((char) 1); /* { dg-error "argument 1 in call to
> function '__builtin_bitreverseg' has signed type" "" { target { !
> unsigned_char } } } */
> +}
>
>
> Jakub
>
>
--
Richard Biener <[email protected]>
SUSE Software Solutions Germany GmbH,
Frankenstrasse 146, 90461 Nuernberg, Germany;
GF: Jochen Jaser, Andrew McDonald, Werner Knoblich; (HRB 36809, AG Nuernberg)