From patchwork Thu Oct 24 07:20:47 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jakub Jelinek X-Patchwork-Id: 99474 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 86255385840F for ; Thu, 24 Oct 2024 07:21:38 +0000 (GMT) X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by sourceware.org (Postfix) with ESMTP id 9E7C43858D33 for ; Thu, 24 Oct 2024 07:20:53 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 9E7C43858D33 Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=redhat.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=redhat.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 9E7C43858D33 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=170.10.129.124 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1729754465; cv=none; b=Vel/TiK+vhXIoHDHIJhMEho6FK8ppXWUeRdc4JSsQvAyMMhhCGUdhmlLtUBH8L4tSWk9yGKQR5vJM61XVT5m73wFVnXvniTPEdJ7yQSqRIgLjP87Jd7T2DGZRhfvvBr8CTWfWDFS9vOyWdhOgXx57KumQZhg7Dfauua5QHmnJg0= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1729754465; c=relaxed/simple; bh=L8z7SNjzT+v/rDQ3F31o6cMZJp1IjsZpnGjjhROITBI=; h=DKIM-Signature:Date:From:To:Subject:Message-ID:MIME-Version; b=C2LpnsWPQSbbgagytSKtfXoThVj5W3YOY++eId6RjWtlfQKq0Eof3v8XAoCNEfWgC3Xf8h5hiROnIqMV3BnplNswlRhZfqKry7QLTIMf/ueBbNB+LUd/LdUemkmT6u/wQdVp6/oqGIF9uBKHzYsraCzlmhoP/x8rIqYrqdiiOmE= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1729754453; h=from:from:reply-to:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-type; bh=xbTHo8ktmyzcm6rQnanIYnfsVv9LRlM7eMyHXjKhJM4=; b=MZJkSOH6baQiobD1/IHDZXPIHpo3jWbKkpu8/WHN1S8esDqLNoImRb/s5LIB1fzU9ajNTN uqDXghF7wyPKNQC0qz01W2yDG9DDZK9FIuaIrjLr9lYYFgNnnDB9YDwtPPczcbDMgsgx8o Lu75htT9hTs8y4mDTuRSBK2NCY0qe0Q= Received: from mx-prod-mc-02.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-639-UveWFEWEOf6ou3gYKGmdBQ-1; Thu, 24 Oct 2024 03:20:51 -0400 X-MC-Unique: UveWFEWEOf6ou3gYKGmdBQ-1 Received: from mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.4]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-02.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id D41BE1956096 for ; Thu, 24 Oct 2024 07:20:50 +0000 (UTC) Received: from tucnak.zalov.cz (unknown [10.45.224.16]) by mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 15B2B300018D; Thu, 24 Oct 2024 07:20:49 +0000 (UTC) Received: from tucnak.zalov.cz (localhost [127.0.0.1]) by tucnak.zalov.cz (8.17.1/8.17.1) with ESMTPS id 49O7KlM22282514 (version=TLSv1.3 cipher=TLS_AES_256_GCM_SHA384 bits=256 verify=NOT); Thu, 24 Oct 2024 09:20:47 +0200 Received: (from jakub@localhost) by tucnak.zalov.cz (8.17.1/8.17.1/Submit) id 49O7KllL2282513; Thu, 24 Oct 2024 09:20:47 +0200 Date: Thu, 24 Oct 2024 09:20:47 +0200 From: Jakub Jelinek To: "Joseph S. Myers" Cc: gcc-patches@gcc.gnu.org Subject: [PATCH] c: Add __builtin_stdc_rotate_{left, right} builtins [PR117030] Message-ID: MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.4 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Disposition: inline X-Spam-Status: No, score=-4.5 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H2, SPF_HELO_NONE, SPF_NONE, TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: Jakub Jelinek Errors-To: gcc-patches-bounces~patchwork=sourceware.org@gcc.gnu.org Hi! I believe the new C2Y type-generic functions stdc_rotate_{left,right} have the same problems the other stdc_* type-generic functions had. If we want to support arbitrary unsigned _BitInt(N), don't want to use statement expressions (so that one can actually use them in static variable initializers), don't want to evaluate the arguments multiple times and don't want to expand the arguments multiple times during preprocessing to avoid the old tgmath preprocessing bloat, we need a built-in for those. The following patch adds those. And as we need to support rotations by 0 and tree-ssa-forwprop.cc is only able to pattern recognize with BIT_AND_EXPR for that case (i.e. for power of two widths), the patch just constructs LROTATE_EXPR/RROTATE_EXPR right away. Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk? 2024-10-24 Jakub Jelinek PR c/117030 gcc/ * doc/extend.texi (__builtin_stdc_rotate_left, __builtin_stdc_rotate_right): Document. gcc/c-family/ * c-common.cc (c_common_reswords): Add __builtin_stdc_rotate_left and __builtin_stdc_rotate_right. gcc/c/ * c-parser.cc: Include asan.h and c-family/c-ubsan.h. (c_parser_postfix_expression): Handle __builtin_stdc_rotate_left and __builtin_stdc_rotate_right. * c-fold.cc (c_fully_fold_internal): Handle LROTATE_EXPR and RROTATE_EXPR. gcc/testsuite/ * gcc.dg/builtin-stdc-rotate-1.c: New test. * gcc.dg/builtin-stdc-rotate-2.c: New test. Jakub --- gcc/c-family/c-common.cc.jj 2024-10-16 10:32:27.312945842 +0200 +++ gcc/c-family/c-common.cc 2024-10-23 13:54:00.795038457 +0200 @@ -447,6 +447,8 @@ const struct c_common_resword c_common_r { "__builtin_stdc_has_single_bit", RID_BUILTIN_STDC, D_CONLY }, { "__builtin_stdc_leading_ones", RID_BUILTIN_STDC, D_CONLY }, { "__builtin_stdc_leading_zeros", RID_BUILTIN_STDC, D_CONLY }, + { "__builtin_stdc_rotate_left", RID_BUILTIN_STDC, D_CONLY }, + { "__builtin_stdc_rotate_right", RID_BUILTIN_STDC, D_CONLY }, { "__builtin_stdc_trailing_ones", RID_BUILTIN_STDC, D_CONLY }, { "__builtin_stdc_trailing_zeros", RID_BUILTIN_STDC, D_CONLY }, { "__builtin_tgmath", RID_BUILTIN_TGMATH, D_CONLY }, --- gcc/c/c-parser.cc.jj 2024-10-23 09:53:58.950013285 +0200 +++ gcc/c/c-parser.cc 2024-10-23 15:21:58.955492845 +0200 @@ -74,6 +74,8 @@ along with GCC; see the file COPYING3. #include "bitmap.h" #include "analyzer/analyzer-language.h" #include "toplev.h" +#include "asan.h" +#include "c-family/c-ubsan.h" /* We need to walk over decls with incomplete struct/union/enum types after parsing the whole translation unit. @@ -12262,12 +12264,15 @@ c_parser_postfix_expression (c_parser *p C_BUILTIN_STDC_HAS_SINGLE_BIT, C_BUILTIN_STDC_LEADING_ONES, C_BUILTIN_STDC_LEADING_ZEROS, + C_BUILTIN_STDC_ROTATE_LEFT, + C_BUILTIN_STDC_ROTATE_RIGHT, C_BUILTIN_STDC_TRAILING_ONES, C_BUILTIN_STDC_TRAILING_ZEROS, C_BUILTIN_STDC_MAX } stdc_rid = C_BUILTIN_STDC_MAX; const char *name = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value); + unsigned num_args = 1; switch (name[sizeof ("__builtin_stdc_") - 1]) { case 'b': @@ -12316,6 +12321,13 @@ c_parser_postfix_expression (c_parser *p else stdc_rid = C_BUILTIN_STDC_LEADING_ZEROS; break; + case 'r': + if (name[sizeof ("__builtin_stdc_rotate_") - 1] == 'l') + stdc_rid = C_BUILTIN_STDC_ROTATE_LEFT; + else + stdc_rid = C_BUILTIN_STDC_ROTATE_RIGHT; + num_args = 2; + break; case 't': if (name[sizeof ("__builtin_stdc_trailing_") - 1] == 'o') stdc_rid = C_BUILTIN_STDC_TRAILING_ONES; @@ -12334,7 +12346,7 @@ c_parser_postfix_expression (c_parser *p break; } - if (vec_safe_length (cexpr_list) != 1) + if (vec_safe_length (cexpr_list) != num_args) { error_at (loc, "wrong number of arguments to %qs", name); expr.set_error (); @@ -12406,6 +12418,64 @@ c_parser_postfix_expression (c_parser *p without evaluating arg multiple times, type being __typeof (arg) and prec __builtin_popcountg ((type) ~0)). */ int prec = TYPE_PRECISION (type); + if (num_args == 2) + { + /* Expand: + __builtin_stdc_rotate_left (arg1, arg2) as + arg1 r<< arg2 + __builtin_stdc_rotate_right (arg1, arg2) as + arg1 r>> arg2. */ + arg_p = &(*cexpr_list)[1]; + *arg_p = convert_lvalue_to_rvalue (loc, *arg_p, true, true); + if (!INTEGRAL_TYPE_P (TREE_TYPE (arg_p->value))) + { + error_at (loc, "%qs operand not an integral type", name); + expr.set_error (); + break; + } + if (TREE_CODE (TREE_TYPE (arg_p->value)) == ENUMERAL_TYPE) + { + error_at (loc, "argument %u in call to function " + "%qs has enumerated type", 2, name); + expr.set_error (); + break; + } + if (TREE_CODE (TREE_TYPE (arg_p->value)) == BOOLEAN_TYPE) + { + error_at (loc, "argument %u in call to function " + "%qs has boolean type", 2, name); + expr.set_error (); + break; + } + tree arg1 = save_expr (arg); + tree arg2 = save_expr (arg_p->value); + tree_code code; + if (stdc_rid == C_BUILTIN_STDC_ROTATE_LEFT) + code = LROTATE_EXPR; + else + code = RROTATE_EXPR; + if (TREE_CODE (arg2) == INTEGER_CST) + { + if (tree_int_cst_sgn (arg2) < 0) + warning_at (loc, OPT_Wshift_count_negative, + "rotate count is negative"); + + if (compare_tree_int (arg2, prec) >= 0) + warning_at (loc, OPT_Wshift_count_overflow, + "rotate count >= width of type"); + } + tree instrument_expr = NULL_TREE; + if (sanitize_flags_p (SANITIZE_SHIFT)) + instrument_expr = ubsan_instrument_shift (loc, code, + arg1, arg2); + expr.value = build2_loc (loc, code, TREE_TYPE (arg1), arg1, + arg2); + if (instrument_expr) + expr.value = build2_loc (loc, COMPOUND_EXPR, + TREE_TYPE (expr.value), + instrument_expr, expr.value); + break; + } tree barg1 = arg; switch (stdc_rid) { --- gcc/c/c-fold.cc.jj 2024-10-22 08:59:47.027367060 +0200 +++ gcc/c/c-fold.cc 2024-10-23 15:15:15.634198343 +0200 @@ -327,6 +327,8 @@ c_fully_fold_internal (tree expr, bool i case EXACT_DIV_EXPR: case LSHIFT_EXPR: case RSHIFT_EXPR: + case LROTATE_EXPR: + case RROTATE_EXPR: case BIT_IOR_EXPR: case BIT_XOR_EXPR: case BIT_AND_EXPR: @@ -388,7 +390,10 @@ c_fully_fold_internal (tree expr, bool i && tree_int_cst_sgn (op0) < 0) warning_at (loc, OPT_Wshift_negative_value, "left shift of negative value"); - if ((code == LSHIFT_EXPR || code == RSHIFT_EXPR) + if ((code == LSHIFT_EXPR + || code == RSHIFT_EXPR + || code == LROTATE_EXPR + || code == RROTATE_EXPR) && TREE_CODE (orig_op1) != INTEGER_CST && TREE_CODE (op1) == INTEGER_CST && TREE_CODE (TREE_TYPE (orig_op1)) == INTEGER_TYPE @@ -398,7 +403,9 @@ c_fully_fold_internal (tree expr, bool i warning_at (loc, OPT_Wshift_count_negative, (code == LSHIFT_EXPR ? G_("left shift count is negative") - : G_("right shift count is negative"))); + : code == RSHIFT_EXPR + ? G_("right shift count is negative") + : G_("rotate count is negative"))); else if ((TREE_CODE (TREE_TYPE (orig_op0)) == INTEGER_TYPE || TREE_CODE (TREE_TYPE (orig_op0)) == BITINT_TYPE || TREE_CODE (TREE_TYPE (orig_op0)) == FIXED_POINT_TYPE) @@ -408,7 +415,9 @@ c_fully_fold_internal (tree expr, bool i warning_at (loc, OPT_Wshift_count_overflow, (code == LSHIFT_EXPR ? G_("left shift count >= width of type") - : G_("right shift count >= width of type"))); + : code == RSHIFT_EXPR + ? G_("right shift count >= width of type") + : G_("rotate count >= width of type"))); else if (TREE_CODE (TREE_TYPE (orig_op0)) == VECTOR_TYPE && compare_tree_int (op1, TYPE_PRECISION (TREE_TYPE (TREE_TYPE (orig_op0)))) --- gcc/doc/extend.texi.jj 2024-10-22 08:59:47.538359801 +0200 +++ gcc/doc/extend.texi 2024-10-23 19:27:47.099516139 +0200 @@ -16129,6 +16129,32 @@ performed on the argument. It is equiva @code{(unsigned int) __builtin_ctzg (@var{arg}, @var{prec})} @enddefbuiltin +@defbuiltin{@var{type} __builtin_stdc_rotate_left (@var{type} @var{arg1}, @var{type} @var{arg2})} +The @code{__builtin_stdc_rotate_left} function is available only +in C. It is type-generic, the argument can be any unsigned integer +(standard, extended or bit-precise). No integral argument promotions are +performed on the argument. It is equivalent to +@code{(@var{type}) ((@var{arg1} << @var{arg2}) +| (@var{arg1} >> ((-(unsigned) @var{arg2}) % @var{prec})))} +where @var{prec} is bit width of @var{type}, except that side-effects +in @var{arg1} and @var{arg2} are evaluated just once, and invokes undefined +behavior also if @var{arg2} >= @var{prec} even when @var{type} normally +promotes to @code{int}. +@enddefbuiltin + +@defbuiltin{@var{type} __builtin_stdc_rotate_right (@var{type} @var{arg1}, @var{type} @var{arg2})} +The @code{__builtin_stdc_rotate_left} function is available only +in C. It is type-generic, the argument can be any unsigned integer +(standard, extended or bit-precise). No integral argument promotions are +performed on the argument. It is equivalent to +@code{(@var{type}) ((@var{arg1} >> @var{arg2}) +| (@var{arg1} << ((-(unsigned) @var{arg2}) % @var{prec})))} +where @var{prec} is bit width of @var{type}, except that side-effects +in @var{arg1} and @var{arg2} are evaluated just once, and invokes undefined +behavior also if @var{arg2} >= @var{prec} even when @var{type} normally +promotes to @code{int}. +@enddefbuiltin + @defbuiltin{double __builtin_powi (double, int)} @defbuiltinx{float __builtin_powif (float, int)} @defbuiltinx{{long double} __builtin_powil (long double, int)} --- gcc/testsuite/gcc.dg/builtin-stdc-rotate-1.c.jj 2024-10-23 15:39:22.872733605 +0200 +++ gcc/testsuite/gcc.dg/builtin-stdc-rotate-1.c 2024-10-23 19:16:33.108041928 +0200 @@ -0,0 +1,224 @@ +/* { dg-do run } */ +/* { dg-options "-std=c11" } */ + +unsigned long long +rotate_left (unsigned char a, unsigned short b, unsigned int c, + unsigned long d, unsigned long long e, int n) +{ + return (__builtin_stdc_rotate_left (a, n) + + __builtin_stdc_rotate_left (b, n) + + __builtin_stdc_rotate_left (c, n) + + __builtin_stdc_rotate_left (d, n) + + __builtin_stdc_rotate_left (e, n)); +} + +unsigned long long +rotate_right (unsigned char a, unsigned short b, unsigned int c, + unsigned long d, unsigned long long e, int n) +{ + return (__builtin_stdc_rotate_right (a, n) + + __builtin_stdc_rotate_right (b, n) + + __builtin_stdc_rotate_right (c, n) + + __builtin_stdc_rotate_right (d, n) + + __builtin_stdc_rotate_right (e, n)); +} + +#define expr_has_type(e, t) _Generic (e, default : 0, t : 1) + +int +main () +{ + if (__builtin_stdc_rotate_left ((unsigned char) 0, 0) != 0 + || __builtin_stdc_rotate_left ((unsigned char) 0xdcU, (char) 0) != 0xdcU + || !expr_has_type (__builtin_stdc_rotate_left ((unsigned char) 0, 0), unsigned char) + || __builtin_stdc_rotate_left ((unsigned char) 1, 1) != 2 + || !expr_has_type (__builtin_stdc_rotate_left ((unsigned char) 1, (unsigned char) 1), unsigned char) + || __builtin_stdc_rotate_left ((unsigned char) ~1U, 3) != (unsigned char) ~8U + || __builtin_stdc_rotate_left ((unsigned char) (2U + __SCHAR_MAX__), 1) != 3 + || __builtin_stdc_rotate_left ((unsigned short) 0, 0) != 0 + || __builtin_stdc_rotate_left ((unsigned short) 0xdcabU, 0) != 0xdcabU + || !expr_has_type (__builtin_stdc_rotate_left ((unsigned short) 0, (signed char) 0), unsigned short) + || __builtin_stdc_rotate_left ((unsigned short) 1, 13) != (1U << 13) + || !expr_has_type (__builtin_stdc_rotate_left ((unsigned short) 1, 13), unsigned short) + || __builtin_stdc_rotate_left ((unsigned short) ~1U, 7) != (unsigned short) ~0x80U + || __builtin_stdc_rotate_left ((unsigned short) (2U + __SHRT_MAX__), 1) != 3 + || __builtin_stdc_rotate_left (0U, 0) != 0 + || __builtin_stdc_rotate_left (0xcdbaU, (short int) 0) != 0xcdbaU + || !expr_has_type (__builtin_stdc_rotate_left (0U, 0), unsigned int) + || __builtin_stdc_rotate_left (1U, (char) 15) != (1U << 15) + || !expr_has_type (__builtin_stdc_rotate_left (1U, 15), unsigned int) + || __builtin_stdc_rotate_left (~1U, 9) != ~0x200U + || __builtin_stdc_rotate_left (2U + __INT_MAX__, 1) != 3 + || __builtin_stdc_rotate_left (0UL, 0) != 0 + || __builtin_stdc_rotate_left (0xdc8971baUL, 0) != 0xdc8971baUL + || !expr_has_type (__builtin_stdc_rotate_left (0UL, 0LL), unsigned long) + || __builtin_stdc_rotate_left (1UL, 30) != (1UL << 30) + || !expr_has_type (__builtin_stdc_rotate_left (1UL, 30), unsigned long) + || __builtin_stdc_rotate_left (~1UL, 22) != ~0x400000UL + || __builtin_stdc_rotate_left (2UL + __LONG_MAX__, 1) != 3 + || __builtin_stdc_rotate_left (0ULL, 0) != 0 + || __builtin_stdc_rotate_left (0xdc897143985734baULL, 0) != 0xdc897143985734baULL + || !expr_has_type (__builtin_stdc_rotate_left (0ULL, 0), unsigned long long) + || __builtin_stdc_rotate_left (1ULL, 62) != (1ULL << 62) + || !expr_has_type (__builtin_stdc_rotate_left (1ULL, 62ULL), unsigned long long) + || __builtin_stdc_rotate_left (~1ULL, 53) != ~0x20000000000000ULL + || __builtin_stdc_rotate_left (2ULL + __LONG_LONG_MAX__, 1) != 3) + __builtin_abort (); + if (__builtin_stdc_rotate_right ((unsigned char) 0, 0) != 0 + || __builtin_stdc_rotate_right ((unsigned char) 0xdcU, 0) != 0xdcU + || !expr_has_type (__builtin_stdc_rotate_right ((unsigned char) 0, 0), unsigned char) + || __builtin_stdc_rotate_right ((unsigned char) 1, 1) != (1U + __SCHAR_MAX__) + || !expr_has_type (__builtin_stdc_rotate_right ((unsigned char) 1, 1), unsigned char) + || __builtin_stdc_rotate_right ((unsigned char) ~1U, (char) 3) != (unsigned char) ~((1U + __SCHAR_MAX__) >> 2) + || __builtin_stdc_rotate_right ((unsigned char) 3, 1) != (2U + __SCHAR_MAX__) + || __builtin_stdc_rotate_right ((unsigned short) 0, 0) != 0 + || __builtin_stdc_rotate_right ((unsigned short) 0xdcabU, 0) != 0xdcabU + || !expr_has_type (__builtin_stdc_rotate_right ((unsigned short) 0, 0), unsigned short) + || __builtin_stdc_rotate_right ((unsigned short) (1U << 13), 12) != 2 + || !expr_has_type (__builtin_stdc_rotate_right ((unsigned short) (1U << 13), 2), unsigned short) + || __builtin_stdc_rotate_right ((unsigned short) ~1U, 7) != (unsigned short) ~((1U + __SHRT_MAX__) >> 6) + || __builtin_stdc_rotate_right ((unsigned short) 3, 1) != (2U + __SHRT_MAX__) + || __builtin_stdc_rotate_right (0U, 0) != 0 + || __builtin_stdc_rotate_right (0xcdbaU, 0) != 0xcdbaU + || !expr_has_type (__builtin_stdc_rotate_right (0U, 0), unsigned int) + || __builtin_stdc_rotate_right (1U << 15, 13) != 4U + || !expr_has_type (__builtin_stdc_rotate_right (1U << 15, 13), unsigned int) + || __builtin_stdc_rotate_right (~1U, 9) != ~((1U + __INT_MAX__) >> 8) + || __builtin_stdc_rotate_right (3U, 1) != (2U + __INT_MAX__) + || __builtin_stdc_rotate_right (0UL, 0) != 0 + || __builtin_stdc_rotate_right (0xdc8971baUL, 0) != 0xdc8971baUL + || !expr_has_type (__builtin_stdc_rotate_right (0UL, 0), unsigned long) + || __builtin_stdc_rotate_right (1UL << 30, 27) != 8UL + || !expr_has_type (__builtin_stdc_rotate_right (1UL << 30, 27), unsigned long) + || __builtin_stdc_rotate_right (~1UL, 22) != ~((1UL + __LONG_MAX__) >> 21) + || __builtin_stdc_rotate_right (3UL, 1) != (2UL + __LONG_MAX__) + || __builtin_stdc_rotate_right (0ULL, 0) != 0 + || __builtin_stdc_rotate_right (0xdc897143985734baULL, 0) != 0xdc897143985734baULL + || !expr_has_type (__builtin_stdc_rotate_right (0ULL, 0), unsigned long long) + || __builtin_stdc_rotate_right (1ULL << 62, 60) != 4ULL + || !expr_has_type (__builtin_stdc_rotate_right (1ULL << 62, 60), unsigned long long) + || __builtin_stdc_rotate_right (~1ULL, 53) != ~((1ULL + __LONG_LONG_MAX__) >> 52) + || __builtin_stdc_rotate_right (3ULL, 1) != (2ULL + __LONG_LONG_MAX__)) + __builtin_abort (); +#ifdef __SIZEOF_INT128__ + if (__builtin_stdc_rotate_left ((unsigned __int128) 0U, 0) != 0 + || __builtin_stdc_rotate_left (((unsigned __int128) 0x43256567547ULL) << 64 | 0xdc897143985734baULL, 0) != (((unsigned __int128) 0x43256567547ULL) << 64 | 0xdc897143985734baULL) + || !expr_has_type (__builtin_stdc_rotate_left ((unsigned __int128) 0U, 0), unsigned __int128) + || __builtin_stdc_rotate_left ((unsigned __int128) 1U, 115) != ((unsigned __int128) 1U << 115) + || !expr_has_type (__builtin_stdc_rotate_left ((unsigned __int128) 1U, 115), unsigned __int128) + || __builtin_stdc_rotate_left (~(unsigned __int128) 1ULL, 53) != ~(unsigned __int128) 0x20000000000000ULL + || __builtin_stdc_rotate_left (1ULL + ((unsigned __int128) 1U << 127), 1) != 3) + __builtin_abort (); + if (__builtin_stdc_rotate_right (0ULL, 0) != 0 + || __builtin_stdc_rotate_right (((unsigned __int128) 0x43256567547ULL) << 64 | 0xdc897143985734baULL, 0) != (((unsigned __int128) 0x43256567547ULL) << 64 | 0xdc897143985734baULL) + || !expr_has_type (__builtin_stdc_rotate_right ((unsigned __int128) 0U, 0), unsigned __int128) + || __builtin_stdc_rotate_right ((unsigned __int128) 1ULL << 115, 110) != 32U + || !expr_has_type (__builtin_stdc_rotate_right ((unsigned __int128) 1ULL << 115, 110), unsigned __int128) + || __builtin_stdc_rotate_right (~(unsigned __int128) 1ULL, 53) != ~((unsigned __int128) 1 << 75) + || __builtin_stdc_rotate_right ((unsigned __int128) 3ULL, 1) != 1U + ((unsigned __int128) 1U << 127)) + __builtin_abort (); +#endif +#if __has_builtin (__builtin_stdc_rotate_left) != 1 +#error __builtin_stdc_rotate_left not implemented +#endif +#if __has_builtin (__builtin_stdc_rotate_right) != 1 +#error __builtin_stdc_rotate_right not implemented +#endif + unsigned char a = 1; + unsigned short b = 1; + unsigned int c = 1; + unsigned long d = 1; + unsigned long long e = 1; + int f = 1; + if (__builtin_stdc_rotate_left (a++, f++) != 2 || a != 2 || f != 2) + __builtin_abort (); + if (__builtin_stdc_rotate_left (b++, f++) != 4 || b != 2 || f != 3) + __builtin_abort (); + if (__builtin_stdc_rotate_left (c++, f++) != 8 || c != 2 || f != 4) + __builtin_abort (); + if (__builtin_stdc_rotate_left (d++, f++) != 16 || d != 2 || f != 5) + __builtin_abort (); + if (__builtin_stdc_rotate_left (e++, f++) != 32 || e != 2 || f != 6) + __builtin_abort (); + f = 1; + if (__builtin_stdc_rotate_right (a++, f++) != 1 || a != 3 || f != 2) + __builtin_abort (); + f = 1; + if (__builtin_stdc_rotate_right (b++, f++) != 1 || b != 3 || f != 2) + __builtin_abort (); + f = 1; + if (__builtin_stdc_rotate_right (c++, f++) != 1 || c != 3 || f != 2) + __builtin_abort (); + f = 1; + if (__builtin_stdc_rotate_right (d++, f++) != 1 || d != 3 || f != 2) + __builtin_abort (); + f = 1; + if (__builtin_stdc_rotate_right (e++, f++) != 1 || e != 3 || f != 2) + __builtin_abort (); +#ifdef __SIZEOF_INT128__ + unsigned __int128 g = 1; + if (__builtin_stdc_rotate_left (g++, f++) != 4 || g != 2 || f != 3) + __builtin_abort (); + f = 1; + if (__builtin_stdc_rotate_right (g++, f++) != 1 || g != 3 || f != 2) + __builtin_abort (); +#endif +#if __BITINT_MAXWIDTH__ >= 64 + if (__builtin_stdc_rotate_left (0uwb, 0) != 0 + || __builtin_stdc_rotate_left (1uwb, 0) != 1uwb + || !expr_has_type (__builtin_stdc_rotate_left (0uwb, 0), unsigned _BitInt(1))) + __builtin_abort (); + if (__builtin_stdc_rotate_left ((unsigned _BitInt(2)) 0, 0) != 0 + || __builtin_stdc_rotate_left ((unsigned _BitInt(2)) 1, (_BitInt(27)) 1) != 2uwb + || !expr_has_type (__builtin_stdc_rotate_left ((unsigned _BitInt(2)) 0, 0), unsigned _BitInt(2)) + || __builtin_stdc_rotate_left ((unsigned _BitInt(2)) 1, 1) != 2 + || !expr_has_type (__builtin_stdc_rotate_left ((unsigned _BitInt(2)) 1, (unsigned _BitInt(2)) 1), unsigned _BitInt(2)) + || __builtin_stdc_rotate_left ((unsigned _BitInt(2)) 2, 1) != 1) + __builtin_abort (); + if (__builtin_stdc_rotate_right (0uwb, 0) != 0 + || __builtin_stdc_rotate_right (1uwb, 0) != 1uwb + || !expr_has_type (__builtin_stdc_rotate_right (0uwb, 0), unsigned _BitInt(1))) + __builtin_abort (); + if (__builtin_stdc_rotate_right ((unsigned _BitInt(2)) 0, (_BitInt(3)) 0) != 0 + || __builtin_stdc_rotate_right ((unsigned _BitInt(2)) 1, 1) != 2uwb + || !expr_has_type (__builtin_stdc_rotate_right ((unsigned _BitInt(2)) 0, 0), unsigned _BitInt(2)) + || __builtin_stdc_rotate_right ((unsigned _BitInt(2)) 1, 1) != 2 + || !expr_has_type (__builtin_stdc_rotate_right ((unsigned _BitInt(2)) 1, 1), unsigned _BitInt(2)) + || __builtin_stdc_rotate_right ((unsigned _BitInt(2)) 2, 1) != 1) + __builtin_abort (); + if (__builtin_stdc_rotate_left ((unsigned _BitInt(59)) 0U, 0) != 0 + || __builtin_stdc_rotate_left ((unsigned _BitInt(59)) 0x43256567547ULL, 0) != ((unsigned _BitInt(59)) 0x43256567547ULL) + || !expr_has_type (__builtin_stdc_rotate_left ((unsigned _BitInt(59)) 0U, 0), unsigned _BitInt(59)) + || __builtin_stdc_rotate_left ((unsigned _BitInt(59)) 1U, 57) != ((unsigned _BitInt(59)) 1U << 57) + || !expr_has_type (__builtin_stdc_rotate_left ((unsigned _BitInt(59)) 1U, 57), unsigned _BitInt(59)) + || __builtin_stdc_rotate_left (~(unsigned _BitInt(59)) 1ULL, 53) != ~(unsigned _BitInt(59)) 0x20000000000000ULL + || __builtin_stdc_rotate_left (1uwb + ((unsigned _BitInt(59)) 1U << 58), 1) != 3) + __builtin_abort (); + if (__builtin_stdc_rotate_right (0ULL, 0) != 0 + || __builtin_stdc_rotate_right ((unsigned _BitInt(59)) 0x43256567547ULL, 0) != ((unsigned _BitInt(59)) 0x43256567547ULL) + || !expr_has_type (__builtin_stdc_rotate_right ((unsigned _BitInt(59)) 0U, 0), unsigned _BitInt(59)) + || __builtin_stdc_rotate_right ((unsigned _BitInt(59)) 1ULL << 57, 55) != 4U + || !expr_has_type (__builtin_stdc_rotate_right ((unsigned _BitInt(59)) 1U << 57, 55), unsigned _BitInt(59)) + || __builtin_stdc_rotate_right (~(unsigned _BitInt(59)) 1ULL, 53) != ~((unsigned _BitInt(59)) 1 << 6) + || __builtin_stdc_rotate_right ((unsigned _BitInt(59)) 3ULL, 1) != 1uwb + ((unsigned _BitInt(59)) 1U << 58)) + __builtin_abort (); +#endif +#if __BITINT_MAXWIDTH__ >= 512 + if (__builtin_stdc_rotate_left ((unsigned _BitInt(510)) 0U, (_BitInt(503)) 0) != 0 + || __builtin_stdc_rotate_left (((unsigned _BitInt(510)) 0x43256567547ULL) << 64 | 0xdc897143985734baULL, 0) != (((unsigned _BitInt(510)) 0x43256567547ULL) << 64 | 0xdc897143985734baULL) + || !expr_has_type (__builtin_stdc_rotate_left ((unsigned _BitInt(510)) 0U, 0), unsigned _BitInt(510)) + || __builtin_stdc_rotate_left ((unsigned _BitInt(510)) 1U, 508) != ((unsigned _BitInt(510)) 1U << 508) + || !expr_has_type (__builtin_stdc_rotate_left ((unsigned _BitInt(510)) 1U, (unsigned _BitInt(505)) 508), unsigned _BitInt(510)) + || __builtin_stdc_rotate_left (~(unsigned _BitInt(510)) 1ULL, 53) != ~(unsigned _BitInt(510)) 0x20000000000000ULL + || __builtin_stdc_rotate_left (1uwb + ((unsigned _BitInt(510)) 1U << 509), 1) != 3) + __builtin_abort (); + if (__builtin_stdc_rotate_right (0ULL, 0) != 0 + || __builtin_stdc_rotate_right (((unsigned _BitInt(510)) 0x43256567547ULL) << 64 | 0xdc897143985734baULL, 0) != (((unsigned _BitInt(510)) 0x43256567547ULL) << 64 | 0xdc897143985734baULL) + || !expr_has_type (__builtin_stdc_rotate_right ((unsigned _BitInt(510)) 0U, 0), unsigned _BitInt(510)) + || __builtin_stdc_rotate_right ((unsigned _BitInt(510)) 1ULL << 508, 503) != 32U + || !expr_has_type (__builtin_stdc_rotate_right ((unsigned _BitInt(510)) 1ULL << 508, 503), unsigned _BitInt(510)) + || __builtin_stdc_rotate_right (~(unsigned _BitInt(510)) 1ULL, 499) != ~((unsigned _BitInt(510)) 1 << 11) + || __builtin_stdc_rotate_right ((unsigned _BitInt(510)) 3ULL, 1) != 1uwb + ((unsigned _BitInt(510)) 1U << 509)) + __builtin_abort (); +#endif +} --- gcc/testsuite/gcc.dg/builtin-stdc-rotate-2.c.jj 2024-10-23 18:49:02.101286794 +0200 +++ gcc/testsuite/gcc.dg/builtin-stdc-rotate-2.c 2024-10-23 19:10:49.640893340 +0200 @@ -0,0 +1,92 @@ +/* { dg-do compile } */ +/* { dg-options "" } */ + +void +foo (void) +{ + typedef int V __attribute__ ((vector_size (4 * sizeof (int)))); + struct S { int s; }; + enum E { E0, E1 }; + __builtin_stdc_rotate_left (0.0f, 0); /* { dg-error "'__builtin_stdc_rotate_left' operand not an integral type" } */ + __builtin_stdc_rotate_left (0.0, 0); /* { dg-error "'__builtin_stdc_rotate_left' operand not an integral type" } */ + __builtin_stdc_rotate_left (0.0L, 0); /* { dg-error "'__builtin_stdc_rotate_left' operand not an integral type" } */ + __builtin_stdc_rotate_left ((V) {}, 0); /* { dg-error "'__builtin_stdc_rotate_left' operand not an integral type" } */ + __builtin_stdc_rotate_left ((struct S) { 0 }, 0); /* { dg-error "'__builtin_stdc_rotate_left' operand not an integral type" } */ + __builtin_stdc_rotate_left (); /* { dg-error "wrong number of arguments to '__builtin_stdc_rotate_left'" } */ + __builtin_stdc_rotate_left (0U); /* { dg-error "wrong number of arguments to '__builtin_stdc_rotate_left'" } */ + __builtin_stdc_rotate_left (0U, 0U, 0U); /* { dg-error "wrong number of arguments to '__builtin_stdc_rotate_left'" } */ + __builtin_stdc_rotate_left ((_Bool) 0, 0); /* { dg-error "argument 1 in call to function '__builtin_stdc_rotate_left' has boolean type" } */ + __builtin_stdc_rotate_left ((enum E) E0, 0); /* { dg-error "argument 1 in call to function '__builtin_stdc_rotate_left' has enumerated type" } */ + __builtin_stdc_rotate_left (0, 0); /* { dg-error "argument 1 in call to function '__builtin_stdc_rotate_left' has signed type" } */ + __builtin_stdc_rotate_left (0U, 0.0f); /* { dg-error "'__builtin_stdc_rotate_left' operand not an integral type" } */ + __builtin_stdc_rotate_left (0U, 0.0); /* { dg-error "'__builtin_stdc_rotate_left' operand not an integral type" } */ + __builtin_stdc_rotate_left (0U, 0.0L); /* { dg-error "'__builtin_stdc_rotate_left' operand not an integral type" } */ + __builtin_stdc_rotate_left (0U, (V) {}); /* { dg-error "'__builtin_stdc_rotate_left' operand not an integral type" } */ + __builtin_stdc_rotate_left (0U, (struct S) { 0 }); /* { dg-error "'__builtin_stdc_rotate_left' operand not an integral type" } */ + __builtin_stdc_rotate_left (0U, (_Bool) 0); /* { dg-error "argument 2 in call to function '__builtin_stdc_rotate_left' has boolean type" } */ + __builtin_stdc_rotate_left (0U, (enum E) E0); /* { dg-error "argument 2 in call to function '__builtin_stdc_rotate_left' has enumerated type" } */ + __builtin_stdc_rotate_right (0.0f, 0); /* { dg-error "'__builtin_stdc_rotate_right' operand not an integral type" } */ + __builtin_stdc_rotate_right (0.0, 0); /* { dg-error "'__builtin_stdc_rotate_right' operand not an integral type" } */ + __builtin_stdc_rotate_right (0.0L, 0); /* { dg-error "'__builtin_stdc_rotate_right' operand not an integral type" } */ + __builtin_stdc_rotate_right ((V) {}, 0); /* { dg-error "'__builtin_stdc_rotate_right' operand not an integral type" } */ + __builtin_stdc_rotate_right ((struct S) { 0 }, 0); /* { dg-error "'__builtin_stdc_rotate_right' operand not an integral type" } */ + __builtin_stdc_rotate_right (); /* { dg-error "wrong number of arguments to '__builtin_stdc_rotate_right'" } */ + __builtin_stdc_rotate_right (0U); /* { dg-error "wrong number of arguments to '__builtin_stdc_rotate_right'" } */ + __builtin_stdc_rotate_right (0U, 0U, 0U); /* { dg-error "wrong number of arguments to '__builtin_stdc_rotate_right'" } */ + __builtin_stdc_rotate_right ((_Bool) 0, 0); /* { dg-error "argument 1 in call to function '__builtin_stdc_rotate_right' has boolean type" } */ + __builtin_stdc_rotate_right ((enum E) E0, 0); /* { dg-error "argument 1 in call to function '__builtin_stdc_rotate_right' has enumerated type" } */ + __builtin_stdc_rotate_right (0, 0); /* { dg-error "argument 1 in call to function '__builtin_stdc_rotate_right' has signed type" } */ + __builtin_stdc_rotate_right (0U, 0.0f); /* { dg-error "'__builtin_stdc_rotate_right' operand not an integral type" } */ + __builtin_stdc_rotate_right (0U, 0.0); /* { dg-error "'__builtin_stdc_rotate_right' operand not an integral type" } */ + __builtin_stdc_rotate_right (0U, 0.0L); /* { dg-error "'__builtin_stdc_rotate_right' operand not an integral type" } */ + __builtin_stdc_rotate_right (0U, (V) {}); /* { dg-error "'__builtin_stdc_rotate_right' operand not an integral type" } */ + __builtin_stdc_rotate_right (0U, (struct S) { 0 }); /* { dg-error "'__builtin_stdc_rotate_right' operand not an integral type" } */ + __builtin_stdc_rotate_right (0U, (_Bool) 0); /* { dg-error "argument 2 in call to function '__builtin_stdc_rotate_right' has boolean type" } */ + __builtin_stdc_rotate_right (0U, (enum E) E0); /* { dg-error "argument 2 in call to function '__builtin_stdc_rotate_right' has enumerated type" } */ + __builtin_stdc_rotate_left ((unsigned char) 0, -1); /* { dg-warning "rotate count is negative" } */ + __builtin_stdc_rotate_left ((unsigned char) 0, __CHAR_BIT__); /* { dg-warning "rotate count >= width of type" } */ + __builtin_stdc_rotate_right ((unsigned char) 0, -1); /* { dg-warning "rotate count is negative" } */ + __builtin_stdc_rotate_right ((unsigned char) 0, __CHAR_BIT__); /* { dg-warning "rotate count >= width of type" } */ + __builtin_stdc_rotate_left ((unsigned short) 0, -1); /* { dg-warning "rotate count is negative" } */ + __builtin_stdc_rotate_left ((unsigned short) 0, sizeof (unsigned short) * __CHAR_BIT__); /* { dg-warning "rotate count >= width of type" } */ + __builtin_stdc_rotate_right ((unsigned short) 0, -1); /* { dg-warning "rotate count is negative" } */ + __builtin_stdc_rotate_right ((unsigned short) 0, sizeof (unsigned short) * __CHAR_BIT__); /* { dg-warning "rotate count >= width of type" } */ + __builtin_stdc_rotate_left (0U, -1); /* { dg-warning "rotate count is negative" } */ + __builtin_stdc_rotate_left (0U, sizeof (unsigned int) * __CHAR_BIT__); /* { dg-warning "rotate count >= width of type" } */ + __builtin_stdc_rotate_right (0U, -1); /* { dg-warning "rotate count is negative" } */ + __builtin_stdc_rotate_right (0U, sizeof (unsigned int) * __CHAR_BIT__); /* { dg-warning "rotate count >= width of type" } */ + __builtin_stdc_rotate_left (0UL, -1); /* { dg-warning "rotate count is negative" } */ + __builtin_stdc_rotate_left (0UL, sizeof (unsigned long) * __CHAR_BIT__); /* { dg-warning "rotate count >= width of type" } */ + __builtin_stdc_rotate_right (0UL, -1); /* { dg-warning "rotate count is negative" } */ + __builtin_stdc_rotate_right (0UL, sizeof (unsigned long) * __CHAR_BIT__); /* { dg-warning "rotate count >= width of type" } */ + __builtin_stdc_rotate_left (0ULL, -1); /* { dg-warning "rotate count is negative" } */ + __builtin_stdc_rotate_left (0ULL, sizeof (unsigned long long) * __CHAR_BIT__); /* { dg-warning "rotate count >= width of type" } */ + __builtin_stdc_rotate_right (0ULL, -1); /* { dg-warning "rotate count is negative" } */ + __builtin_stdc_rotate_right (0ULL, sizeof (unsigned long long) * __CHAR_BIT__); /* { dg-warning "rotate count >= width of type" } */ +#ifdef __SIZEOF_INT128__ + __builtin_stdc_rotate_left ((unsigned __int128) 0, -1); /* { dg-warning "rotate count is negative" "" { target int128 } } */ + __builtin_stdc_rotate_left ((unsigned __int128) 0, 128); /* { dg-warning "rotate count >= width of type" "" { target int128 } } */ + __builtin_stdc_rotate_right ((unsigned __int128) 0, -1); /* { dg-warning "rotate count is negative" "" { target int128 } } */ + __builtin_stdc_rotate_right ((unsigned __int128) 0, 128); /* { dg-warning "rotate count >= width of type" "" { target int128 } } */ +#endif +#if __BITINT_MAXWIDTH__ >= 64 + __builtin_stdc_rotate_left (0uwb, -1); /* { dg-warning "rotate count is negative" "" { target bitint } } */ + __builtin_stdc_rotate_left (0uwb, 1); /* { dg-warning "rotate count >= width of type" "" { target bitint } } */ + __builtin_stdc_rotate_right (0uwb, -1); /* { dg-warning "rotate count is negative" "" { target bitint } } */ + __builtin_stdc_rotate_right (0uwb, 1); /* { dg-warning "rotate count >= width of type" "" { target bitint } } */ + __builtin_stdc_rotate_left ((unsigned _BitInt(2)) 0, -1); /* { dg-warning "rotate count is negative" "" { target bitint } } */ + __builtin_stdc_rotate_left ((unsigned _BitInt(2)) 0, 2); /* { dg-warning "rotate count >= width of type" "" { target bitint } } */ + __builtin_stdc_rotate_right ((unsigned _BitInt(2)) 0, -1); /* { dg-warning "rotate count is negative" "" { target bitint } } */ + __builtin_stdc_rotate_right ((unsigned _BitInt(2)) 0, 2); /* { dg-warning "rotate count >= width of type" "" { target bitint } } */ + __builtin_stdc_rotate_left ((unsigned _BitInt(59)) 0, -1); /* { dg-warning "rotate count is negative" "" { target bitint } } */ + __builtin_stdc_rotate_left ((unsigned _BitInt(59)) 0, 59); /* { dg-warning "rotate count >= width of type" "" { target bitint } } */ + __builtin_stdc_rotate_right ((unsigned _BitInt(59)) 0, -1); /* { dg-warning "rotate count is negative" "" { target bitint } } */ + __builtin_stdc_rotate_right ((unsigned _BitInt(59)) 0, 59); /* { dg-warning "rotate count >= width of type" "" { target bitint } } */ +#endif +#if __BITINT_MAXWIDTH__ >= 575 + __builtin_stdc_rotate_left ((unsigned _BitInt(525)) 0, -1); /* { dg-warning "rotate count is negative" "" { target bitint575 } } */ + __builtin_stdc_rotate_left ((unsigned _BitInt(525)) 0, 525); /* { dg-warning "rotate count >= width of type" "" { target bitint575 } } */ + __builtin_stdc_rotate_right ((unsigned _BitInt(525)) 0, -1); /* { dg-warning "rotate count is negative" "" { target bitint575 } } */ + __builtin_stdc_rotate_right ((unsigned _BitInt(525)) 0, 525); /* { dg-warning "rotate count >= width of type" "" { target bitint575 } } */ +#endif +}