Hi!
Clang has added recently type-generic versions of __builtin_bswap{16,32,64}
and __builtin_bitreverse{8,16,32,64} builtins.
The following patch adds them to GCC as well.
Unlike the other __builtin_*g type-generic builtins, these are different in
that the return type is not fixed (usually int or unsigned int), but is the
same as the argument type, so these can't be handled as normal builtins
and are handled in the C and C++ parsers instead.
For consistency with the other __builtin_*g builtins, these only accept
unsigned INTEGER_TYPE (or for C BITINT_TYPE) - users can use various ways
to request unsigned variant of arbitrary types. For __builtin_bswapg
additionally this requires the type to have precision which is a multiple of
8 (unlike clang, which for some strange reason requires multiple of 16).
Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?
2026-06-02 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-01 09:15:39.025605479 +0200
+++ gcc/doc/extend.texi 2026-06-02 19:20:31.697824450 +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-02 08:14:59.761207073 +0200
+++ gcc/internal-fn.def 2026-06-02 11:20:13.565339257 +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-02 08:14:59.761207073 +0200
+++ gcc/internal-fn.h 2026-06-02 11:20:13.565561425 +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-02 08:14:59.761207073 +0200
+++ gcc/internal-fn.cc 2026-06-02 11:20:13.565878590 +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-02 08:14:59.731207479 +0200
+++ gcc/builtins.h 2026-06-02 11:20:13.567773163 +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-02 08:14:59.722207601 +0200
+++ gcc/builtins.cc 2026-06-02 11:20:13.566725155 +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-02 08:14:59.768206978 +0200
+++ gcc/wide-int.h 2026-06-02 11:20:13.567483302 +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-02 08:14:59.757207127 +0200
+++ gcc/gimple-match-exports.cc 2026-06-02 11:20:13.567951128 +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-02 08:14:59.752207195 +0200
+++ gcc/gencfn-macros.cc 2026-06-02 11:20:13.568130445 +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-02 08:14:59.764207032 +0200
+++ gcc/match.pd 2026-06-02 11:20:13.568685657 +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"
@@ -10317,8 +10313,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-02 08:14:59.768206978 +0200
+++ gcc/tree-ssa-phiopt.cc 2026-06-02 19:34:11.880846430 +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-02 08:14:59.744207303 +0200
+++ gcc/fold-const-call.cc 2026-06-02 11:20:13.569901898 +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-02 08:14:59.747207263 +0200
+++ gcc/fold-const.cc 2026-06-02 11:20:13.570875331 +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-05-30 09:46:04.403303922 +0200
+++ gcc/gimple-lower-bitint.cc 2026-06-02 19:34:11.881570293 +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-02 08:14:59.739207371 +0200
+++ gcc/c-family/c-common.h 2026-06-02 11:20:13.560983540 +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-02 08:15:04.495142958 +0200
+++ gcc/c-family/c-common.cc 2026-06-02 11:20:13.561741435 +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-02 08:14:59.741207344 +0200
+++ gcc/c/c-parser.cc 2026-06-02 19:34:11.878325063 +0200
@@ -13530,6 +13530,83 @@ 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 (type == char_type_node)
+ {
+ error_at (loc, "argument 1 in call to function "
+ "%qs has %<char%> 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-02 08:15:04.592141644 +0200
+++ gcc/cp/parser.cc 2026-06-02 11:35:20.211913589 +0200
@@ -8617,6 +8617,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;
@@ -8736,6 +8738,32 @@ cp_parser_postfix_expression (cp_parser
}
break;
+ case RID_BUILTIN_BSWAPG:
+ if (vec->length () == 1)
+ postfix_expression
+ = build_x_bswapg_bitreverseg (loc, IFN_BSWAP, vec,
+ tf_warning_or_error);
+ else
+ {
+ error_at (loc, "wrong number of arguments to "
+ "%<__builtin_bswapg%>");
+ postfix_expression = error_mark_node;
+ }
+ break;
+
+ case RID_BUILTIN_BITREVERSEG:
+ if (vec->length () == 1)
+ postfix_expression
+ = build_x_bswapg_bitreverseg (loc, IFN_BITREVERSE, vec,
+ tf_warning_or_error);
+ else
+ {
+ error_at (loc, "wrong number of arguments to "
+ "%<__builtin_bitreverseg%>");
+ postfix_expression = error_mark_node;
+ }
+ break;
+
default:
gcc_unreachable ();
}
--- gcc/cp/typeck.cc.jj 2026-05-29 10:08:33.380536476 +0200
+++ gcc/cp/typeck.cc 2026-06-02 12:48:53.944496483 +0200
@@ -7111,6 +7111,72 @@ 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)
+{
+ 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;
+ }
+ const char *name
+ = ifn == IFN_BSWAP ? "__builtin_bswapg" : "__builtin_bitreverseg";
+ 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 (type == char_type_node)
+ {
+ if (complain & tf_error)
+ error_at (loc, "argument 1 in call to function "
+ "%qs has %<char%> 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-05-30 17:45:09.365110027 +0200
+++ gcc/cp/cp-tree.h 2026-06-02 11:41:54.609714752 +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-05-30 17:49:11.819041571 +0200
+++ gcc/cp/pt.cc 2026-06-02 11:43:39.750328823 +0200
@@ -22468,6 +22468,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-05-30 17:45:09.363110052 +0200
+++ gcc/cp/constexpr.cc 2026-06-02 12:54:58.012735377 +0200
@@ -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;
+ 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 +12050,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-05-26 16:32:28.611304806 +0200
+++ gcc/cp/cp-gimplify.cc 2026-06-02 12:47:52.178304231 +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-02
18:55:52.546730877 +0200
+++ gcc/testsuite/c-c++-common/builtin-bswapg-1.c 2026-06-02
18:53:23.591654474 +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-02
19:00:30.252144603 +0200
+++ gcc/testsuite/c-c++-common/builtin-bswapg-2.c 2026-06-02
19:28:21.081815725 +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|argument 1 in call to function
'__builtin_bswapg' has 'char' type)" } */
+}
--- gcc/testsuite/c-c++-common/builtin-bswapg-3.c.jj 2026-06-02
19:28:56.451362952 +0200
+++ gcc/testsuite/c-c++-common/builtin-bswapg-3.c 2026-06-02
19:32:28.058654098 +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-02
18:55:52.546730877 +0200
+++ gcc/testsuite/c-c++-common/builtin-bitreverseg-1.c 2026-06-02
20:31:04.876355418 +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-02
19:00:30.252144603 +0200
+++ gcc/testsuite/c-c++-common/builtin-bitreverseg-2.c 2026-06-02
20:18:23.575187233 +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|argument 1 in call to function
'__builtin_bitreverseg' has 'char' type)" } */
+}
Jakub