@@ -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
@@ -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
@@ -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);
@@ -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);
+}
@@ -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 *);
@@ -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. */
@@ -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)
@@ -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]))
@@ -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);
@@ -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))
@@ -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:
@@ -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;
@@ -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;
@@ -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;
@@ -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. */
@@ -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 },
@@ -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 ());
@@ -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 ();
}
@@ -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. */
@@ -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);
@@ -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)
@@ -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;
@@ -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
@@ -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
+}
@@ -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)" } */
+}
@@ -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
+}
@@ -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
+}
@@ -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)" } */
+}