From patchwork Sat Nov 18 19:42:40 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jakub Jelinek X-Patchwork-Id: 166648 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:9910:0:b0:403:3b70:6f57 with SMTP id i16csp1341702vqn; Sat, 18 Nov 2023 11:43:33 -0800 (PST) X-Google-Smtp-Source: AGHT+IEL2pyMQ8dLkxO+e7mImgXNJQqxXOe4J82O4Yjzz0T2L/MjcjZ1yRFrZ2CCMVB0ys/+9Omo X-Received: by 2002:ad4:5ba4:0:b0:66d:17a2:34cc with SMTP id 4-20020ad45ba4000000b0066d17a234ccmr3564093qvq.64.1700336612975; Sat, 18 Nov 2023 11:43:32 -0800 (PST) ARC-Seal: i=2; a=rsa-sha256; t=1700336612; cv=pass; d=google.com; s=arc-20160816; b=Am1y/s5u9ydJXiWAiCrQ/zMTP7+a69EC3p+h6sWygpLG/Eq0pJ23/TjxTES2LeRfl/ EOtOahHqzoIJNYskiWrL4erCYew2DSdgvIXcqbqxqajiJL+CrHqSBibffKDW+sDpj/eB +KtiLEcuZw5elz7N2gDwXOMOXe13Zmj+xkudlYfead8mC3eY5OGKvT1G+LC6MBveQHXA 18XBgYuo9J6P2lqH7bgYcTTcEjcjVsrYq6BtJNCkjDrVzxrzuGJFXhQ1nX+0GRzNW8JN 19WYrIFf6FgBSwNkxj8m9u0aNckhsZG0c9o9zUbn3fG+xXA9f4/3JXdvG1RMowg/aemC xG3w== ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=errors-to:reply-to:list-subscribe:list-help:list-post:list-archive :list-unsubscribe:list-id:precedence:content-disposition :mime-version:message-id:subject:cc:to:from:date:dkim-signature :arc-filter:dmarc-filter:delivered-to; bh=tie7Oyg0yA4DQqrRR7ZEk8DJS3HHYohoz8lCCnETNmM=; fh=MESqRMDKsXuKgTFMYaJ4HOCHxYeTz1KWj5jMdGLEHJM=; b=Bf91Hxmy6r2Vfedl4YO4NfJGJzZO86beQ1qEqy3OgyNSsmB5pRSnyXclSEoSt/7Ek2 i2RfFkC+evKLXNP7N05hFRq0fuvuiuZbqTv4U8LCafnv5utqsYr+fo9QyoEBpXeKWkcU 1ocJo6A2iMn1szCFDPjcB3lgWoguuKpCUEwYuFpcSSS2jkG51Op4O9Ee87AmHv1+txL2 AVPhKhDM8TQZ0jbM9QDPuHa0J58iGBw2P/ubdcTfDgQhK5GtU0+HUdnRn8vacg7XXWl3 TWMINSippOelR9K+0Fltd5cj1mW7/xpRwjx5CfTXzLwF5fZLb30FynK8EpjbnjZ4V161 pv1g== ARC-Authentication-Results: i=2; mx.google.com; dkim=pass header.i=@redhat.com header.s=mimecast20190719 header.b=bgbRxSUQ; arc=pass (i=1); spf=pass (google.com: domain of gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org designates 8.43.85.97 as permitted sender) smtp.mailfrom="gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=redhat.com Received: from server2.sourceware.org (server2.sourceware.org. [8.43.85.97]) by mx.google.com with ESMTPS id gy11-20020a056214242b00b00677f607682esi4020066qvb.498.2023.11.18.11.43.32 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 18 Nov 2023 11:43:32 -0800 (PST) Received-SPF: pass (google.com: domain of gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org designates 8.43.85.97 as permitted sender) client-ip=8.43.85.97; Authentication-Results: mx.google.com; dkim=pass header.i=@redhat.com header.s=mimecast20190719 header.b=bgbRxSUQ; arc=pass (i=1); spf=pass (google.com: domain of gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org designates 8.43.85.97 as permitted sender) smtp.mailfrom="gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=redhat.com Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id B6D773858C5F for ; Sat, 18 Nov 2023 19:43:32 +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 ESMTPS id 5CDE63858D39 for ; Sat, 18 Nov 2023 19:42:53 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 5CDE63858D39 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 5CDE63858D39 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=1700336576; cv=none; b=FsAokbW2G78GLsbDDSe6fegzMCzct+wf3xYBIhRZZDwmanyihlDn/ZlbV5CYGzYDLMcnKFt26//eIvGNt+dy19R1EV66K+KY/5kxO+D93cgDKGXDDctp7Hpzf7Nt7K4hROPMhtLSwiLcTZvPdtHSkPQ60MwNWTQ0b2q307h8n80= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1700336576; c=relaxed/simple; bh=Ju7D6jgT/m+6Q1Tu2CMmhdOSx/DU2OKD2b3QYUuRej4=; h=DKIM-Signature:Date:From:To:Subject:Message-ID:MIME-Version; b=w4LRj4riYCZhB6k5WZqXETl79wI79/JGtBDUWrG/9IM86siCO7SGuVc4usdNeNlqUU2yAaoFEywJYH79zSeQ62zI8qWR7XDqHfoquCuSZiQWUeeBAEn4lKUhuR0sia8gaqtDWbZnmAPwCj4A1glPeA5LPXZgAotwhXXMRLi6OwA= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1700336573; 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=tie7Oyg0yA4DQqrRR7ZEk8DJS3HHYohoz8lCCnETNmM=; b=bgbRxSUQJp79fcVd1utYSl1fwSVaoLEfk1rX+tl4HoD7zqj0i1Um2AUlBYTCiUH3qXLhd/ OZ7rLTEQieskQ1Y4PA14lZkWCtNKiY+UR5PvfD86ksEcn6BTiJ4+xiLSyB8/cBTiTvodaj cUtPmwDu/m3VbSGFcRdsteFTAYtMpj0= Received: from mimecast-mx02.redhat.com (mx-ext.redhat.com [66.187.233.73]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-423-loJ-im-MOG-ADHkkRWIoRA-1; Sat, 18 Nov 2023 14:42:49 -0500 X-MC-Unique: loJ-im-MOG-ADHkkRWIoRA-1 Received: from smtp.corp.redhat.com (int-mx08.intmail.prod.int.rdu2.redhat.com [10.11.54.8]) (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 mimecast-mx02.redhat.com (Postfix) with ESMTPS id 68C4238117FE; Sat, 18 Nov 2023 19:42:49 +0000 (UTC) Received: from tucnak.zalov.cz (unknown [10.39.194.53]) by smtp.corp.redhat.com (Postfix) with ESMTPS id E4D5BC1596F; Sat, 18 Nov 2023 19:42:48 +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 3AIJgfg23207674 (version=TLSv1.3 cipher=TLS_AES_256_GCM_SHA384 bits=256 verify=NOT); Sat, 18 Nov 2023 20:42:46 +0100 Received: (from jakub@localhost) by tucnak.zalov.cz (8.17.1/8.17.1/Submit) id 3AIJgeMU3207673; Sat, 18 Nov 2023 20:42:40 +0100 Date: Sat, 18 Nov 2023 20:42:40 +0100 From: Jakub Jelinek To: "Joseph S. Myers" Cc: gcc-patches@gcc.gnu.org, Florian Weimer Subject: [PATCH] c: Add __builtin_stdc_bit_{width,floor,ceil} builtins Message-ID: MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.11.54.8 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Disposition: inline X-Spam-Status: No, score=-3.7 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_H4, RCVD_IN_MSPIKE_WL, SPF_HELO_NONE, SPF_NONE, TXREP, T_SCC_BODY_TEXT_LINE 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+ouuuleilei=gmail.com@gcc.gnu.org X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1782932164483937507 X-GMAIL-MSGID: 1782932164483937507 Hi! For these 3 type-generic macros I'm out of ideas how to satisfy all the requirements (no use of ({ ... }), not expanding argument multiple times, not evaluating side-effects multiple times using some small building blocks, so the following patch introduces 3 new C only builtins which can be used to implement those macros. As a bonus, I think with this and previous 2 patches all the type-generic stdbit.h macros can be actually used in constant expressions. While in theory __builtin_stdc_bit_width builtin could be C/C++ in builtins.def, given that it has unsigned return type rather than the type-generic type, because it has very similar implementation to the other two and is not really useful for C++ I chose to implement all 3 in there. Ok for trunk if it passes bootstrap/regtest? 2023-11-18 Jakub Jelinek gcc/ * doc/extend.texi (__builtin_stdc_bit_width, __builtin_stdc_bit_floor, __builtin_stdc_bit_ceil): Document. gcc/c-family/ * c-common.h (enum rid): Add RID_BUILTIN_STDC_BIT_WIDTH, RID_BUILTIN_STDC_BIT_FLOOR and RID_BUILTIN_STDC_BIT_CEIL. * c-common.cc (c_common_reswords): Add __builtin_stdc_bit_width, __builtin_stdc_bit_floor and __builtin_stdc_bit_ceil. gcc/c/ * c-parser.cc (c_parser_postfix_expression): Handle RID_BUILTIN_STDC_BIT_WIDTH, RID_BUILTIN_STDC_BIT_FLOOR and RID_BUILTIN_STDC_BIT_CEIL. * c-decl.cc (names_builtin_p): Likewise. gcc/testsuite/ * gcc.dg/builtin-stdc-bit-1.c: New test. * gcc.dg/builtin-stdc-bit-2.c: New test. Jakub --- gcc/doc/extend.texi.jj 2023-11-18 19:29:08.056176234 +0100 +++ gcc/doc/extend.texi 2023-11-18 19:35:08.454176312 +0100 @@ -15074,6 +15074,37 @@ there is no need to specify the argument promotions are performed on the argument. @enddefbuiltin +@defbuiltin{unsigned int __builtin_stdc_bit_width (@var{type} @var{arg})} +The @code{__builtin_stdc_bit_width} 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{(unsigned int) (@var{prec} - __builtin_clzg (@var{arg}, @var{prec}))} +where @var{prec} is bit width of @var{type}. +@enddefbuiltin + +@defbuiltin{@var{type} __builtin_stdc_bit_floor (@var{type} @var{arg})} +The @code{__builtin_stdc_bit_floor} 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{arg} == 0 ? (@var{type}) 0 +: (@var{type}) 1 << (@var{prec} - 1 - __builtin_clzg (@var{arg}))} +where @var{prec} is bit width of @var{type}, except that side-effects +in @var{arg} are evaluated just once. +@enddefbuiltin + +@defbuiltin{@var{type} __builtin_stdc_bit_ceil (@var{type} @var{arg})} +The @code{__builtin_stdc_bit_ceil} 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{arg} <= 1 ? (@var{type}) 1 +: (@var{type}) 1 << (@var{prec} - __builtin_clzg ((@var{type}) (@var{arg} - 1)))} +where @var{prec} is bit width of @var{type}, except that side-effects +in @var{arg} are evaluated just once. +@enddefbuiltin + @defbuiltin{double __builtin_powi (double, int)} @defbuiltinx{float __builtin_powif (float, int)} @defbuiltinx{{long double} __builtin_powil (long double, int)} --- gcc/c-family/c-common.h.jj 2023-11-18 17:05:00.223049400 +0100 +++ gcc/c-family/c-common.h 2023-11-18 18:46:53.162346148 +0100 @@ -110,7 +110,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_BIT_COMPLEMENT, + RID_BUILTIN_BIT_COMPLEMENT, RID_BUILTIN_STDC_BIT_WIDTH, + RID_BUILTIN_STDC_BIT_CEIL, RID_BUILTIN_STDC_BIT_FLOOR, RID_DFLOAT32, RID_DFLOAT64, RID_DFLOAT128, /* TS 18661-3 keywords, in the same sequence as the TI_* values. */ --- gcc/c-family/c-common.cc.jj 2023-11-18 17:03:17.838466559 +0100 +++ gcc/c-family/c-common.cc 2023-11-18 18:47:47.809588817 +0100 @@ -392,6 +392,9 @@ const struct c_common_resword c_common_r { "__builtin_launder", RID_BUILTIN_LAUNDER, D_CXXONLY }, { "__builtin_shuffle", RID_BUILTIN_SHUFFLE, 0 }, { "__builtin_shufflevector", RID_BUILTIN_SHUFFLEVECTOR, 0 }, + { "__builtin_stdc_bit_ceil", RID_BUILTIN_STDC_BIT_CEIL, D_CONLY }, + { "__builtin_stdc_bit_floor", RID_BUILTIN_STDC_BIT_FLOOR, D_CONLY }, + { "__builtin_stdc_bit_width", RID_BUILTIN_STDC_BIT_WIDTH, D_CONLY }, { "__builtin_tgmath", RID_BUILTIN_TGMATH, D_CONLY }, { "__builtin_offsetof", RID_OFFSETOF, 0 }, { "__builtin_types_compatible_p", RID_TYPES_COMPATIBLE_P, D_CONLY }, --- gcc/c/c-parser.cc.jj 2023-11-18 17:16:23.228591823 +0100 +++ gcc/c/c-parser.cc 2023-11-18 20:15:47.609493782 +0100 @@ -11744,14 +11744,18 @@ c_parser_postfix_expression (c_parser *p } break; case RID_BUILTIN_BIT_COMPLEMENT: + case RID_BUILTIN_STDC_BIT_CEIL: + case RID_BUILTIN_STDC_BIT_FLOOR: + case RID_BUILTIN_STDC_BIT_WIDTH: { vec *cexpr_list; c_expr_t *arg_p; location_t close_paren_loc; + enum rid rid = c_parser_peek_token (parser)->keyword; + const char *name = IDENTIFIER_POINTER (ridpointers[rid]); c_parser_consume_token (parser); - if (!c_parser_get_builtin_args (parser, - "__builtin_bit_complement", + if (!c_parser_get_builtin_args (parser, name, &cexpr_list, false, &close_paren_loc)) { @@ -11761,8 +11765,7 @@ c_parser_postfix_expression (c_parser *p if (vec_safe_length (cexpr_list) != 1) { - error_at (loc, "wrong number of arguments to " - "%<__builtin_bit_complement%>"); + error_at (loc, "wrong number of arguments to %qs", name); expr.set_error (); break; } @@ -11771,16 +11774,92 @@ c_parser_postfix_expression (c_parser *p *arg_p = convert_lvalue_to_rvalue (loc, *arg_p, true, true); if (!INTEGRAL_TYPE_P (TREE_TYPE (arg_p->value))) { - error_at (loc, "%<__builtin_bit_complement%> operand " - "not an integral type"); + error_at (loc, "%qs operand not an integral type", name); expr.set_error (); break; } - expr.value - = build1_loc (loc, BIT_NOT_EXPR, - TYPE_MAIN_VARIANT (TREE_TYPE (arg_p->value)), - arg_p->value); + tree arg = arg_p->value; + tree type = TYPE_MAIN_VARIANT (TREE_TYPE (arg)); + if (rid == RID_BUILTIN_BIT_COMPLEMENT) + { + /* Expand __builtin_bit_complement (arg) as ~arg. */ + expr.value = build1_loc (loc, BIT_NOT_EXPR, type, arg); + set_c_expr_source_range (&expr, loc, close_paren_loc); + break; + } + /* Expand __builtin_stdc_bit_width (arg) as + (unsigned int) (prec - __builtin_clzg (arg, prec)). + Expand __builtin_stdc_bit_floor (arg) as + arg == 0 ? (type) 0 + : (type) 1 << (prec - 1 - __builtin_clzg (arg)) + without evaluating arg multiple times. + Expand __builtin_stdc_bit_ceil (arg) as + arg <= 1 ? (type) 1 + : (type) 1 << (prec - __builtin_clzg (arg - 1)) + without evaluating arg multiple times. */ + int prec = TYPE_PRECISION (type); + if (rid != RID_BUILTIN_STDC_BIT_WIDTH) + arg = save_expr (arg); + /* Construct a call to __builtin_clzg. */ + int nargs = rid == RID_BUILTIN_STDC_BIT_WIDTH ? 2 : 1; + vec *args; + vec_alloc (args, nargs); + vec *origtypes; + vec_alloc (origtypes, nargs); + auto_vec arg_loc (nargs); + if (rid == RID_BUILTIN_STDC_BIT_CEIL) + args->quick_push (build2_loc (loc, PLUS_EXPR, type, + arg, build_int_cst (type, -1))); + else + args->quick_push (arg); + arg_loc.quick_push (arg_p->get_location ()); + origtypes->quick_push (arg_p->original_type); + if (nargs == 2) + { + args->quick_push (build_int_cst (integer_type_node, prec)); + arg_loc.quick_push (loc); + origtypes->quick_push (integer_type_node); + } + tree fndecl = builtin_decl_explicit (BUILT_IN_CLZG); + expr.value = c_build_function_call_vec (loc, arg_loc, fndecl, + args, origtypes); set_c_expr_source_range (&expr, loc, close_paren_loc); + if (expr.value == error_mark_node) + break; + if (rid == RID_BUILTIN_STDC_BIT_FLOOR) + --prec; + expr.value = build2_loc (loc, MINUS_EXPR, integer_type_node, + build_int_cst (integer_type_node, prec), + expr.value); + if (rid == RID_BUILTIN_STDC_BIT_WIDTH) + { + expr.value = fold_convert_loc (loc, unsigned_type_node, + expr.value); + break; + } + /* For __builtin_stdc_bit_ceil (0U) or __builtin_stdc_bit_ceil (1U) + or __builtin_stdc_bit_floor (0U) avoid bogus -Wshift-count-* + warnings. The LSHIFT_EXPR is in dead code in that case. */ + if (integer_zerop (arg) + || (rid == RID_BUILTIN_STDC_BIT_CEIL && integer_onep (arg))) + expr.value = build_int_cst (type, 1); + else + expr.value = build2_loc (loc, LSHIFT_EXPR, type, + build_int_cst (type, 1), expr.value); + if (rid == RID_BUILTIN_STDC_BIT_CEIL) + expr.value = build3_loc (loc, COND_EXPR, type, + build2_loc (loc, LE_EXPR, + boolean_type_node, arg, + build_int_cst (type, 1)), + build_int_cst (type, 1), + expr.value); + else + expr.value = build3_loc (loc, COND_EXPR, type, + build2_loc (loc, EQ_EXPR, + boolean_type_node, arg, + build_int_cst (type, 0)), + build_int_cst (type, 0), + expr.value); break; } case RID_AT_SELECTOR: --- gcc/c/c-decl.cc.jj 2023-11-18 17:31:39.298880201 +0100 +++ gcc/c/c-decl.cc 2023-11-18 18:48:26.796048523 +0100 @@ -11376,6 +11376,9 @@ names_builtin_p (const char *name) case RID_BUILTIN_HAS_ATTRIBUTE: case RID_BUILTIN_SHUFFLE: case RID_BUILTIN_SHUFFLEVECTOR: + case RID_BUILTIN_STDC_BIT_CEIL: + case RID_BUILTIN_STDC_BIT_FLOOR: + case RID_BUILTIN_STDC_BIT_WIDTH: case RID_CHOOSE_EXPR: case RID_OFFSETOF: case RID_TYPES_COMPATIBLE_P: --- gcc/testsuite/gcc.dg/builtin-stdc-bit-1.c.jj 2023-11-18 19:36:34.422984124 +0100 +++ gcc/testsuite/gcc.dg/builtin-stdc-bit-1.c 2023-11-18 20:05:32.678976258 +0100 @@ -0,0 +1,185 @@ +/* { dg-do run } */ +/* { dg-options "-std=c11" } */ + +#define expr_has_type(e, t) _Generic (e, default : 0, t : 1) + +int +main () +{ + if (__builtin_stdc_bit_width ((unsigned char) 0) != 0 + || !expr_has_type (__builtin_stdc_bit_width ((unsigned char) 0), unsigned int) + || __builtin_stdc_bit_width ((unsigned short) 0) != 0 + || !expr_has_type (__builtin_stdc_bit_width ((unsigned short) 0), unsigned int) + || __builtin_stdc_bit_width (0U) != 0 + || !expr_has_type (__builtin_stdc_bit_width (0U), unsigned int) + || __builtin_stdc_bit_width (0UL) != 0 + || !expr_has_type (__builtin_stdc_bit_width (0UL), unsigned int) + || __builtin_stdc_bit_width (0ULL) != 0 + || !expr_has_type (__builtin_stdc_bit_width (0ULL), unsigned int)) + __builtin_abort (); + if (__builtin_stdc_bit_width ((unsigned char) ~0U) != __CHAR_BIT__ + || __builtin_stdc_bit_width ((unsigned short) ~0U) != __SIZEOF_SHORT__ * __CHAR_BIT__ + || __builtin_stdc_bit_width (~0U) != __SIZEOF_INT__ * __CHAR_BIT__ + || __builtin_stdc_bit_width (~0UL) != __SIZEOF_LONG__ * __CHAR_BIT__ + || __builtin_stdc_bit_width (~0ULL) != __SIZEOF_LONG_LONG__ * __CHAR_BIT__) + __builtin_abort (); + if (__builtin_stdc_bit_width ((unsigned char) ((unsigned char) ~0U >> 1)) != __CHAR_BIT__ - 1 + || __builtin_stdc_bit_width ((unsigned char) 6) != 3 + || __builtin_stdc_bit_width ((unsigned short) 12U) != 4 + || __builtin_stdc_bit_width ((unsigned short) ((unsigned short) ~0U >> 5)) != __SIZEOF_SHORT__ * __CHAR_BIT__ - 5 + || __builtin_stdc_bit_width (137U) != 8 + || __builtin_stdc_bit_width (269U) != 9 + || __builtin_stdc_bit_width (39UL) != 6 + || __builtin_stdc_bit_width (~0UL >> 2) != __SIZEOF_LONG__ * __CHAR_BIT__ - 2 + || __builtin_stdc_bit_width (1023ULL) != 10 + || __builtin_stdc_bit_width (1024ULL) != 11) + __builtin_abort (); + if (__builtin_stdc_bit_floor ((unsigned char) 0) != 0 + || !expr_has_type (__builtin_stdc_bit_floor ((unsigned char) 0), unsigned char) + || __builtin_stdc_bit_floor ((unsigned short) 0) != 0 + || !expr_has_type (__builtin_stdc_bit_floor ((unsigned short) 0), unsigned short) + || __builtin_stdc_bit_floor (0U) != 0U + || !expr_has_type (__builtin_stdc_bit_floor (0U), unsigned int) + || __builtin_stdc_bit_floor (0UL) != 0UL + || !expr_has_type (__builtin_stdc_bit_floor (0UL), unsigned long) + || __builtin_stdc_bit_floor (0ULL) != 0ULL + || !expr_has_type (__builtin_stdc_bit_floor (0ULL), unsigned long long)) + __builtin_abort (); + if (__builtin_stdc_bit_floor ((unsigned char) ~0U) != (1U << (__CHAR_BIT__ - 1)) + || __builtin_stdc_bit_floor ((unsigned short) ~0U) != (1U << (__SIZEOF_SHORT__ * __CHAR_BIT__ - 1)) + || __builtin_stdc_bit_floor (~0U) != (1U << (__SIZEOF_INT__ * __CHAR_BIT__ - 1)) + || __builtin_stdc_bit_floor (~0UL) != (1UL << (__SIZEOF_LONG__ * __CHAR_BIT__ - 1)) + || __builtin_stdc_bit_floor (~0ULL) != (1ULL << (__SIZEOF_LONG_LONG__ * __CHAR_BIT__ - 1))) + __builtin_abort (); + if (__builtin_stdc_bit_floor ((unsigned char) 4) != 4 + || __builtin_stdc_bit_floor ((unsigned char) 7) != 4 + || __builtin_stdc_bit_floor ((unsigned short) 8U) != 8 + || __builtin_stdc_bit_floor ((unsigned short) 31U) != 16 + || __builtin_stdc_bit_floor (137U) != 128U + || __builtin_stdc_bit_floor (269U) != 256U + || __builtin_stdc_bit_floor (511UL) != 256UL + || __builtin_stdc_bit_floor (512UL) != 512UL + || __builtin_stdc_bit_floor (513UL) != 512ULL + || __builtin_stdc_bit_floor (1024ULL) != 1024ULL) + __builtin_abort (); + if (__builtin_stdc_bit_ceil ((unsigned char) 0) != 1 + || !expr_has_type (__builtin_stdc_bit_ceil ((unsigned char) 0), unsigned char) + || __builtin_stdc_bit_ceil ((unsigned short) 0) != 1 + || !expr_has_type (__builtin_stdc_bit_ceil ((unsigned short) 0), unsigned short) + || __builtin_stdc_bit_ceil (0U) != 1U + || !expr_has_type (__builtin_stdc_bit_ceil (0U), unsigned int) + || __builtin_stdc_bit_ceil (0UL) != 1UL + || !expr_has_type (__builtin_stdc_bit_ceil (0UL), unsigned long) + || __builtin_stdc_bit_ceil (0ULL) != 1ULL + || !expr_has_type (__builtin_stdc_bit_ceil (0ULL), unsigned long long)) + __builtin_abort (); + if (__builtin_stdc_bit_ceil ((unsigned char) ((unsigned char) ~0U >> 1)) != (1U << (__CHAR_BIT__ - 1)) + || __builtin_stdc_bit_ceil ((unsigned char) ((unsigned char) ~0U >> 1)) != (1U << (__CHAR_BIT__ - 1)) + || __builtin_stdc_bit_ceil ((unsigned short) ((unsigned short) ~0U >> 1)) != (1U << (__SIZEOF_SHORT__ * __CHAR_BIT__ - 1)) + || __builtin_stdc_bit_ceil ((unsigned short) ((unsigned short) ~0U >> 1)) != (1U << (__SIZEOF_SHORT__ * __CHAR_BIT__ - 1)) + || __builtin_stdc_bit_ceil (~0U >> 1) != (1U << (__SIZEOF_INT__ * __CHAR_BIT__ - 1)) + || __builtin_stdc_bit_ceil (1U << (__SIZEOF_INT__ * __CHAR_BIT__ - 1)) != (1U << (__SIZEOF_INT__ * __CHAR_BIT__ - 1)) + || __builtin_stdc_bit_ceil (~0UL >> 1) != (1UL << (__SIZEOF_LONG__ * __CHAR_BIT__ - 1)) + || __builtin_stdc_bit_ceil (~0UL >> 1) != (1UL << (__SIZEOF_LONG__ * __CHAR_BIT__ - 1)) + || __builtin_stdc_bit_ceil (1ULL << (__SIZEOF_LONG_LONG__ * __CHAR_BIT__ - 1)) != (1ULL << (__SIZEOF_LONG_LONG__ * __CHAR_BIT__ - 1)) + || __builtin_stdc_bit_ceil (~0ULL >> 1) != (1ULL << (__SIZEOF_LONG_LONG__ * __CHAR_BIT__ - 1))) + __builtin_abort (); + if (__builtin_stdc_bit_ceil ((unsigned char) 1) != 1 + || __builtin_stdc_bit_ceil ((unsigned char) 2) != 2 + || __builtin_stdc_bit_ceil ((unsigned short) 3U) != 4 + || __builtin_stdc_bit_ceil ((unsigned short) 4U) != 4 + || __builtin_stdc_bit_ceil (5U) != 8U + || __builtin_stdc_bit_ceil (269U) != 512U + || __builtin_stdc_bit_ceil (511UL) != 512UL + || __builtin_stdc_bit_ceil (512UL) != 512UL + || __builtin_stdc_bit_ceil (513ULL) != 1024ULL + || __builtin_stdc_bit_ceil (1025ULL) != 2048ULL) + __builtin_abort (); +#ifdef __SIZEOF_INT128__ + if (__builtin_stdc_bit_width ((unsigned __int128) 0) != 0 + || !expr_has_type (__builtin_stdc_bit_width ((unsigned __int128) 0), unsigned int) + || __builtin_stdc_bit_width (~(unsigned __int128) 0) != __SIZEOF_INT128__ * __CHAR_BIT__) + __builtin_abort (); + if (__builtin_stdc_bit_floor ((unsigned __int128) 0) != 0 + || !expr_has_type (__builtin_stdc_bit_floor ((unsigned __int128) 0), unsigned __int128) + || __builtin_stdc_bit_floor (~(unsigned __int128) 0) != ((unsigned __int128) 1) << (__SIZEOF_INT128__ * __CHAR_BIT__ - 1)) + __builtin_abort (); + if (__builtin_stdc_bit_ceil ((unsigned __int128) 0) != 1 + || !expr_has_type (__builtin_stdc_bit_ceil ((unsigned __int128) 0), unsigned __int128) + || __builtin_stdc_bit_ceil ((unsigned __int128) 1) != 1 + || __builtin_stdc_bit_ceil ((~(unsigned __int128) 0) >> 1) != ((unsigned __int128) 1) << (__SIZEOF_INT128__ * __CHAR_BIT__ - 1)) + __builtin_abort (); +#endif +#if __has_builtin (__builtin_stdc_bit_width) != 1 +#error __builtin_stdc_bit_width not implemented +#endif +#if __has_builtin (__builtin_stdc_bit_floor) != 1 +#error __builtin_stdc_bit_floor not implemented +#endif +#if __has_builtin (__builtin_stdc_bit_ceil) != 1 +#error __builtin_stdc_bit_ceil not implemented +#endif + unsigned char a = 0; + if (__builtin_stdc_bit_width (a++) != 0 || a != 1) + __builtin_abort (); + unsigned long long b = 0; + if (__builtin_stdc_bit_width (b++) != 0 || b != 1) + __builtin_abort (); + if (__builtin_stdc_bit_floor (a++) != 1 || a != 2) + __builtin_abort (); + if (__builtin_stdc_bit_floor (b++) != 1 || b != 2) + __builtin_abort (); + if (__builtin_stdc_bit_ceil (a++) != 2 || a != 3) + __builtin_abort (); + if (__builtin_stdc_bit_ceil (b++) != 2 || b != 3) + __builtin_abort (); +#if BITINT_MAXWIDTH >= 512 + if (__builtin_stdc_bit_width ((unsigned _BitInt(512)) 0) != 0 + || !expr_has_type (__builtin_stdc_bit_width ((unsigned _BitInt(512)) 0), unsigned int) + || __builtin_stdc_bit_width ((unsigned _BitInt(373)) 0) != 0 + || !expr_has_type (__builtin_stdc_bit_width ((unsigned _BitInt(373)) 0), unsigned int)) + __builtin_abort (); + if (__builtin_stdc_bit_width (~(unsigned _BitInt(512)) 0) != 512 + || __builtin_stdc_bit_width (~(unsigned _BitInt(373)) 0) != 373) + __builtin_abort (); + if (__builtin_stdc_bit_width (((unsigned _BitInt(512)) 1023) << 405) != 405 + 10 + || __builtin_stdc_bit_width (((unsigned _BitInt(373)) 1024) << 242) != 242 + 11) + __builtin_abort (); + if (__builtin_stdc_bit_floor ((unsigned _BitInt(512)) 0) != 0 + || !expr_has_type (__builtin_stdc_bit_floor ((unsigned _BitInt(512)) 0), unsigned _BitInt(512)) + || __builtin_stdc_bit_floor ((unsigned _BitInt(373)) 0) != 0 + || !expr_has_type (__builtin_stdc_bit_floor ((unsigned _BitInt(373)) 0), unsigned _BitInt(373))) + __builtin_abort (); + if (__builtin_stdc_bit_floor (~(unsigned _BitInt(512)) 0) != ((unsigned _BitInt(512)) 1) << (512 - 1) + || __builtin_stdc_bit_floor (~(unsigned _BitInt(373)) 0) != ((unsigned _BitInt(373)) 1) << (373 - 1)) + __builtin_abort (); + if (__builtin_stdc_bit_floor (((unsigned _BitInt(512)) 511) << 405) != (((unsigned _BitInt(512)) 256) << 405) + || __builtin_stdc_bit_floor (((unsigned _BitInt(373)) 512) << 242) != (((unsigned _BitInt(512)) 512) << 242)) + __builtin_abort (); + if (__builtin_stdc_bit_ceil ((unsigned _BitInt(512)) 0) != 1 + || !expr_has_type (__builtin_stdc_bit_ceil ((unsigned _BitInt(512)) 0), unsigned _BitInt(512)) + || __builtin_stdc_bit_ceil ((unsigned _BitInt(373)) 0) != 1 + || !expr_has_type (__builtin_stdc_bit_ceil ((unsigned _BitInt(373)) 0), unsigned _BitInt(373))) + __builtin_abort (); + if (__builtin_stdc_bit_ceil (((unsigned _BitInt(512)) 1) << (512 - 1)) != ((unsigned _BitInt(512)) 1) << (512 - 1) + || __builtin_stdc_bit_ceil ((~(unsigned _BitInt(373)) 0) >> 1) != ((unsigned _BitInt(373)) 1) << (373 - 1)) + __builtin_abort (); + if (__builtin_stdc_bit_ceil (((unsigned _BitInt(512)) 512) << 405) != (((unsigned _BitInt(512)) 512) << 405) + || __builtin_stdc_bit_ceil (((unsigned _BitInt(373)) 513) << 242) != (((unsigned _BitInt(512)) 1024) << 242)) + __builtin_abort (); + if (__builtin_stdc_bit_floor ((unsigned _BitInt(BITINT_MAXWIDTH)) 0) != 0) + __builtin_abort (); + if (__builtin_stdc_bit_floor (~(unsigned _BitInt(BITINT_MAXWIDTH)) 0) != ((unsigned _BitInt(BITINT_MAXWIDTH)) 1) << (BITINT_MAXWIDTH - 1)) + __builtin_abort (); + if (__builtin_stdc_bit_floor (((unsigned _BitInt(BITINT_MAXWIDTH)) 511) << 405) != (((unsigned _BitInt(BITINT_MAXWIDTH)) 256) << 405) + || __builtin_stdc_bit_floor (((unsigned _BitInt(BITINT_MAXWIDTH)) 512) << 405) != (((unsigned _BitInt(BITINT_MAXWIDTH)) 512) << 405)) + __builtin_abort (); + if (__builtin_stdc_bit_ceil ((unsigned _BitInt(BITINT_MAXWIDTH)) 0) != 1) + __builtin_abort (); + if (__builtin_stdc_bit_ceil (((unsigned _BitInt(BITINT_MAXWIDTH)) 1) << (BITINT_MAXWIDTH - 1)) != ((unsigned _BitInt(BITINT_MAXWIDTH)) 1) << (BITINT_MAXWIDTH - 1)) + __builtin_abort (); + if (__builtin_stdc_bit_ceil (((unsigned _BitInt(BITINT_MAXWIDTH)) 512) << 405) != (((unsigned _BitInt(BITINT_MAXWIDTH)) 512) << 405) + || __builtin_stdc_bit_ceil (((unsigned _BitInt(BITINT_MAXWIDTH)) 513) << 405) != (((unsigned _BitInt(BITINT_MAXWIDTH)) 1024) << 405)) + __builtin_abort (); +#endif +} --- gcc/testsuite/gcc.dg/builtin-stdc-bit-2.c.jj 2023-11-18 19:55:50.956983185 +0100 +++ gcc/testsuite/gcc.dg/builtin-stdc-bit-2.c 2023-11-18 20:18:06.339579450 +0100 @@ -0,0 +1,40 @@ +/* { 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_bit_width (0.0f); /* { dg-error "'__builtin_stdc_bit_width' operand not an integral type" } */ + __builtin_stdc_bit_width (0.0); /* { dg-error "'__builtin_stdc_bit_width' operand not an integral type" } */ + __builtin_stdc_bit_width (0.0L); /* { dg-error "'__builtin_stdc_bit_width' operand not an integral type" } */ + __builtin_stdc_bit_width ((V) {}); /* { dg-error "'__builtin_stdc_bit_width' operand not an integral type" } */ + __builtin_stdc_bit_width ((struct S) { 0 }); /* { dg-error "'__builtin_stdc_bit_width' operand not an integral type" } */ + __builtin_stdc_bit_width (); /* { dg-error "wrong number of arguments to '__builtin_stdc_bit_width'" } */ + __builtin_stdc_bit_width (0U, 0U); /* { dg-error "wrong number of arguments to '__builtin_stdc_bit_width'" } */ + __builtin_stdc_bit_width ((_Bool) 0); /* { dg-error "argument 1 in call to function '__builtin_clzg' has boolean type" } */ + __builtin_stdc_bit_width ((enum E) E0); /* { dg-error "argument 1 in call to function '__builtin_clzg' has enumerated type" } */ + __builtin_stdc_bit_width (0); /* { dg-error "argument 1 in call to function '__builtin_clzg' has signed type" } */ + __builtin_stdc_bit_floor (0.0f); /* { dg-error "'__builtin_stdc_bit_floor' operand not an integral type" } */ + __builtin_stdc_bit_floor (0.0); /* { dg-error "'__builtin_stdc_bit_floor' operand not an integral type" } */ + __builtin_stdc_bit_floor (0.0L); /* { dg-error "'__builtin_stdc_bit_floor' operand not an integral type" } */ + __builtin_stdc_bit_floor ((V) {}); /* { dg-error "'__builtin_stdc_bit_floor' operand not an integral type" } */ + __builtin_stdc_bit_floor ((struct S) { 0 }); /* { dg-error "'__builtin_stdc_bit_floor' operand not an integral type" } */ + __builtin_stdc_bit_floor (); /* { dg-error "wrong number of arguments to '__builtin_stdc_bit_floor'" } */ + __builtin_stdc_bit_floor (0U, 0U); /* { dg-error "wrong number of arguments to '__builtin_stdc_bit_floor'" } */ + __builtin_stdc_bit_floor ((_Bool) 0); /* { dg-error "argument 1 in call to function '__builtin_clzg' has boolean type" } */ + __builtin_stdc_bit_floor ((enum E) E0); /* { dg-error "argument 1 in call to function '__builtin_clzg' has enumerated type" } */ + __builtin_stdc_bit_floor (0); /* { dg-error "argument 1 in call to function '__builtin_clzg' has signed type" } */ + __builtin_stdc_bit_ceil (0.0f); /* { dg-error "'__builtin_stdc_bit_ceil' operand not an integral type" } */ + __builtin_stdc_bit_ceil (0.0); /* { dg-error "'__builtin_stdc_bit_ceil' operand not an integral type" } */ + __builtin_stdc_bit_ceil (0.0L); /* { dg-error "'__builtin_stdc_bit_ceil' operand not an integral type" } */ + __builtin_stdc_bit_ceil ((V) {}); /* { dg-error "'__builtin_stdc_bit_ceil' operand not an integral type" } */ + __builtin_stdc_bit_ceil ((struct S) { 0 }); /* { dg-error "'__builtin_stdc_bit_ceil' operand not an integral type" } */ + __builtin_stdc_bit_ceil (); /* { dg-error "wrong number of arguments to '__builtin_stdc_bit_ceil'" } */ + __builtin_stdc_bit_ceil (0U, 0U); /* { dg-error "wrong number of arguments to '__builtin_stdc_bit_ceil'" } */ + __builtin_stdc_bit_ceil ((_Bool) 0); /* { dg-error "argument 1 in call to function '__builtin_clzg' has boolean type" } */ + __builtin_stdc_bit_ceil ((enum E) E0); /* { dg-error "argument 1 in call to function '__builtin_clzg' has enumerated type" } */ + __builtin_stdc_bit_ceil (0); /* { dg-error "argument 1 in call to function '__builtin_clzg' has signed type" } */ +}