From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by sourceware.org (Postfix) with ESMTPS id E0BEB3858D20 for ; Sat, 18 Nov 2023 19:37:46 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org E0BEB3858D20 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 E0BEB3858D20 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=170.10.133.124 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1700336269; cv=none; b=WRX3c/4ppcuO7gANdRBqP2nAuVXmYZYsG3X1PHK6vwAm9JeRdyARwGrHhUE2FmgJ5DBZD6+gQGYauk5LKs4HUTFUmYovjEG8xtmoePIw9Ogg0HWXsWVZ+wcTx8UolvwXYRPYF7aaUfm+SUItHSpjp37ICeMKeCNvOXuTyuXRqIE= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1700336269; c=relaxed/simple; bh=eiN8cKaM1NLra393aI6qdF5fQIVjDwq/XKBwjwQFSOc=; h=DKIM-Signature:Date:From:To:Subject:Message-ID:MIME-Version; b=aK3q3xHw4HiHrsBQLPghuPqEbWbizwvsAImB2lQ3+Dx+pPfdebHEuVDuYrJWNM3EsvSrxnAgLMTEzFufURZY0jBXiyKHqIG7firtTC/ZCgu3V7jsYS7iXfGU78bIGe1gnoZ7tZOZBD+7pHIY3F8LhPHEHjW+kVFAxQ1EKuZvWbM= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1700336266; 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=2WF7rGbV47IdMOkO8jJ8uCF/kstMror/2HaE3kOksa4=; b=MVCz3XMUvgi36XADJFSqkb250GUtj939BMWqOtxMz+yo/FMFWC1CpnqfH1Uno8l4by4NGW wRnJYg+Pp9PmW/C2hy8AZM8Ut7IOy5S3IjkoVUWCyaQnIGkZvfNJg+LA9rwyzRunvg5ehW kPEXs0f4HsunW/qPNozA5UwiCkKpg4k= 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-74-7jEcGD5-NPWVdRp-Kh1yUg-1; Sat, 18 Nov 2023 14:37:42 -0500 X-MC-Unique: 7jEcGD5-NPWVdRp-Kh1yUg-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 A9EAA2815E27; Sat, 18 Nov 2023 19:37:42 +0000 (UTC) Received: from tucnak.zalov.cz (unknown [10.39.194.53]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 4BE58C1596F; Sat, 18 Nov 2023 19:37:42 +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 3AIJbd7F3207653 (version=TLSv1.3 cipher=TLS_AES_256_GCM_SHA384 bits=256 verify=NOT); Sat, 18 Nov 2023 20:37:40 +0100 Received: (from jakub@localhost) by tucnak.zalov.cz (8.17.1/8.17.1/Submit) id 3AIJbdTu3207652; Sat, 18 Nov 2023 20:37:39 +0100 Date: Sat, 18 Nov 2023 20:37:38 +0100 From: Jakub Jelinek To: "Joseph S. Myers" Cc: gcc-patches@gcc.gnu.org, Florian Weimer Subject: [PATCH] c: Add __builtin_bit_complement Message-ID: Reply-To: Jakub Jelinek 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-Type: text/plain; charset=us-ascii 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_H3,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 List-Id: Hi! Another obstackle mentioned in the https://sourceware.org/pipermail/libc-alpha/2023-November/152819.html thread is that half of the stdc_{leading,trailing}_{zeros,ones}, stdc_first_{leading,trailing}_{zero,one} and stdc_count_{zeros,ones} type-generic macros actually need to use the __builtin_*g type-generic builtins on inverted values, but need to use (__typeof (value)) ~(value) for that, because if value has unsigned char or unsigned short type, it is promoted to int with the ~ operator, but that suffers from the nested macros problem as well. The following patch adds a C only builtin (if we'd want to make stdbit.h work in C++, I think best would be to use a function template), especially because the builtin needs a type-generic return type, which is functionally equivalent to (__typeof (arg)) ~(arg). Ok for trunk if it passes bootstrap/regtest? 2023-11-18 Jakub Jelinek gcc/ * doc/extend.texi (__builtin_bit_complement): Document. gcc/c-family/ * c-common.h (enum rid): Add RID_BUILTIN_BIT_COMPLEMENT. * c-common.cc (c_common_reswords): Add __builtin_bit_complement. Move __builtin_assoc_barrier alphabetically. gcc/c/ * c-parser.cc (c_parser_postfix_expression): Handle RID_BUILTIN_BIT_COMPLEMENT. * c-decl.cc (names_builtin_p): Likewise. Move RID_BUILTIN_ASSOC_BARRIER alphabetically. gcc/testsuite/ * gcc.dg/builtin-bit-complement-1.c: New test. * gcc.dg/builtin-bit-complement-2.c: New test. --- gcc/doc/extend.texi.jj 2023-11-18 13:17:40.982551766 +0100 +++ gcc/doc/extend.texi 2023-11-18 18:39:24.303561182 +0100 @@ -15066,6 +15066,14 @@ unsigned integer (standard, extended or promotions are performed on the argument. @enddefbuiltin +@defbuiltin{@var{type} __builtin_bit_complement (@var{type} @var{arg})} +The @code{__builtin_bit_complement} function is available only +in C. It is type-generic, the argument can be any integral type, and +is equivalent to @code{(__typeof (@var{arg})) ~(@var{arg})}, except that +there is no need to specify the argument tokens twice. No integral argument +promotions are performed on the argument. +@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-09 09:04:18.422546151 +0100 +++ gcc/c-family/c-common.h 2023-11-18 17:05:00.223049400 +0100 @@ -110,6 +110,7 @@ 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_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 13:20:55.751844490 +0100 +++ gcc/c-family/c-common.cc 2023-11-18 17:03:17.838466559 +0100 @@ -380,7 +380,9 @@ const struct c_common_resword c_common_r { "__attribute__", RID_ATTRIBUTE, 0 }, { "__auto_type", RID_AUTO_TYPE, D_CONLY }, { "__builtin_addressof", RID_ADDRESSOF, D_CXXONLY }, + { "__builtin_assoc_barrier", RID_BUILTIN_ASSOC_BARRIER, 0 }, { "__builtin_bit_cast", RID_BUILTIN_BIT_CAST, D_CXXONLY }, + { "__builtin_bit_complement", RID_BUILTIN_BIT_COMPLEMENT, D_CONLY }, { "__builtin_call_with_static_chain", RID_BUILTIN_CALL_WITH_STATIC_CHAIN, D_CONLY }, { "__builtin_choose_expr", RID_CHOOSE_EXPR, D_CONLY }, @@ -388,7 +390,6 @@ const struct c_common_resword c_common_r { "__builtin_convertvector", RID_BUILTIN_CONVERTVECTOR, 0 }, { "__builtin_has_attribute", RID_BUILTIN_HAS_ATTRIBUTE, 0 }, { "__builtin_launder", RID_BUILTIN_LAUNDER, D_CXXONLY }, - { "__builtin_assoc_barrier", RID_BUILTIN_ASSOC_BARRIER, 0 }, { "__builtin_shuffle", RID_BUILTIN_SHUFFLE, 0 }, { "__builtin_shufflevector", RID_BUILTIN_SHUFFLEVECTOR, 0 }, { "__builtin_tgmath", RID_BUILTIN_TGMATH, D_CONLY }, --- gcc/c/c-parser.cc.jj 2023-11-11 08:51:54.324206082 +0100 +++ gcc/c/c-parser.cc 2023-11-18 17:16:23.228591823 +0100 @@ -11743,6 +11743,46 @@ c_parser_postfix_expression (c_parser *p set_c_expr_source_range (&expr, start_loc, end_loc); } break; + case RID_BUILTIN_BIT_COMPLEMENT: + { + vec *cexpr_list; + c_expr_t *arg_p; + location_t close_paren_loc; + + c_parser_consume_token (parser); + if (!c_parser_get_builtin_args (parser, + "__builtin_bit_complement", + &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 " + "%<__builtin_bit_complement%>"); + expr.set_error (); + break; + } + + arg_p = &(*cexpr_list)[0]; + *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"); + expr.set_error (); + break; + } + expr.value + = build1_loc (loc, BIT_NOT_EXPR, + TYPE_MAIN_VARIANT (TREE_TYPE (arg_p->value)), + arg_p->value); + set_c_expr_source_range (&expr, loc, close_paren_loc); + break; + } case RID_AT_SELECTOR: { gcc_assert (c_dialect_objc ()); --- gcc/c/c-decl.cc.jj 2023-11-09 09:04:18.463545570 +0100 +++ gcc/c/c-decl.cc 2023-11-18 17:31:39.298880201 +0100 @@ -11370,11 +11370,12 @@ names_builtin_p (const char *name) functions. */ switch (C_RID_CODE (id)) { + case RID_BUILTIN_ASSOC_BARRIER: + case RID_BUILTIN_BIT_COMPLEMENT: case RID_BUILTIN_CONVERTVECTOR: case RID_BUILTIN_HAS_ATTRIBUTE: case RID_BUILTIN_SHUFFLE: case RID_BUILTIN_SHUFFLEVECTOR: - case RID_BUILTIN_ASSOC_BARRIER: case RID_CHOOSE_EXPR: case RID_OFFSETOF: case RID_TYPES_COMPATIBLE_P: --- gcc/testsuite/gcc.dg/builtin-bit-complement-1.c.jj 2023-11-18 17:39:47.748104287 +0100 +++ gcc/testsuite/gcc.dg/builtin-bit-complement-1.c 2023-11-18 18:33:08.700744489 +0100 @@ -0,0 +1,87 @@ +/* { dg-do run } */ +/* { dg-options "-std=c11" } */ + +#define expr_has_type(e, t) _Generic (e, default : 0, t : 1) +enum E { E0, E1 }; + +int +main () +{ + if (__builtin_bit_complement ((unsigned char) 0) != (unsigned char) ~(unsigned char) 0 + || __builtin_bit_complement ((unsigned char) 0x33) != (unsigned char) ~(unsigned char) 0x33 + || !expr_has_type (__builtin_bit_complement ((unsigned char) 0), unsigned char) + || __builtin_bit_complement ((unsigned short) 0) != (unsigned short) ~(unsigned short) 0 + || __builtin_bit_complement ((unsigned short) 0x5555) != (unsigned short) ~(unsigned short) 0x5555 + || !expr_has_type (__builtin_bit_complement ((unsigned short) 0), unsigned short) + || __builtin_bit_complement (0U) != ~0U + || __builtin_bit_complement (0xaaaaU) != ~0xaaaaU + || !expr_has_type (__builtin_bit_complement (0U), unsigned int) + || __builtin_bit_complement (0UL) != ~0UL + || __builtin_bit_complement (0xaaaaaaaaUL) != ~0xaaaaaaaaUL + || !expr_has_type (__builtin_bit_complement (0UL), unsigned long) + || __builtin_bit_complement (0ULL) != ~0ULL + || __builtin_bit_complement (0xaaaaaaaa55555555ULL) != ~0xaaaaaaaa55555555ULL + || !expr_has_type (__builtin_bit_complement (0ULL), unsigned long long) + || __builtin_bit_complement ((signed char) 0) != (signed char) ~(signed char) 0 + || __builtin_bit_complement ((signed char) 0x33) != (signed char) ~(signed char) 0x33 + || !expr_has_type (__builtin_bit_complement ((signed char) 0), signed char) + || __builtin_bit_complement ((signed short) 0) != (signed short) ~(signed short) 0 + || __builtin_bit_complement ((signed short) 0x5555) != (signed short) ~(signed short) 0x5555 + || !expr_has_type (__builtin_bit_complement ((signed short) 0), signed short) + || __builtin_bit_complement (0) != ~0 + || __builtin_bit_complement (0x5aaa) != ~0x5aaa + || !expr_has_type (__builtin_bit_complement (0), signed int) + || __builtin_bit_complement (0L) != ~0L + || __builtin_bit_complement (0x5aaaaaaaL) != ~0x5aaaaaaaL + || !expr_has_type (__builtin_bit_complement (0L), signed long) + || __builtin_bit_complement (0LL) != ~0LL + || __builtin_bit_complement (0x5aaaaaaa55555555LL) != ~0x5aaaaaaa55555555LL + || !expr_has_type (__builtin_bit_complement (0LL), signed long long) + || __builtin_bit_complement ((_Bool) 0) != (_Bool) 1 + || __builtin_bit_complement ((_Bool) 1) != (_Bool) 0 + || !expr_has_type (__builtin_bit_complement ((_Bool) 0), _Bool) + || __builtin_bit_complement ((enum E) E0) != (enum E) ~0 + || __builtin_bit_complement ((enum E) E1) != (enum E) ~1 + || !expr_has_type (__builtin_bit_complement ((enum E) E0), enum E)) + __builtin_abort (); +#if __SIZEOF_INT128__ + if (__builtin_bit_complement ((unsigned __int128) 0) != ~(unsigned __int128) 0 + || __builtin_bit_complement ((unsigned __int128) 0xaaaaaaaa55555555ULL) != ~(unsigned __int128) 0xaaaaaaaa55555555ULL + || !expr_has_type (__builtin_bit_complement ((unsigned __int128) 0), unsigned __int128) + || __builtin_bit_complement ((signed __int128) 0) != ~(signed __int128) 0 + || __builtin_bit_complement ((signed __int128) 0x5aaaaaaa55555555LL) != ~(signed __int128) 0x5aaaaaaa55555555LL + || !expr_has_type (__builtin_bit_complement ((signed __int128) 0), signed __int128)) + __builtin_abort (); +#endif +#if __has_builtin (__builtin_bit_complement) != 1 +#error __builtin_bit_complement not implemented +#endif + unsigned char a = 0; + if (__builtin_bit_complement (a++) != (unsigned char) ~(unsigned char) 0 + || a != 1) + __builtin_abort (); + if (!expr_has_type (__builtin_bit_complement (a++), unsigned char) + || a != 1) + __builtin_abort (); + unsigned short b = 0; + if (__builtin_bit_complement (b++) != (unsigned short) ~(unsigned short) 0 + || b != 1) + __builtin_abort (); + if (!expr_has_type (__builtin_bit_complement (b++), unsigned short) + || b != 1) + __builtin_abort (); + int c = 0; + if (__builtin_bit_complement (c++) != ~0 + || c != 1) + __builtin_abort (); + if (!expr_has_type (__builtin_bit_complement (c++), int) + || c != 1) + __builtin_abort (); +#if __BITINT_MAXWIDTH__ >= 256 + if (__builtin_bit_complement (0uwb) != ~0uwb + || !expr_has_type (__builtin_bit_complement (0uwb), unsigned _BitInt(1)) + || __builtin_bit_complement ((signed _BitInt(256)) 0) != ~(signed _BitInt(256)) 0 + || !expr_has_type (__builtin_bit_complement ((signed _BitInt(256)) 0), signed _BitInt(256))) + __builtin_abort (); +#endif +} --- gcc/testsuite/gcc.dg/builtin-bit-complement-2.c.jj 2023-11-18 18:26:01.871634733 +0100 +++ gcc/testsuite/gcc.dg/builtin-bit-complement-2.c 2023-11-18 18:32:55.448927364 +0100 @@ -0,0 +1,16 @@ +/* { dg-do compile } */ +/* { dg-options "" } */ + +void +foo (void) +{ + typedef int V __attribute__ ((vector_size (4 * sizeof (int)))); + struct S { int s; }; + __builtin_bit_complement (0.0f); /* { dg-error "'__builtin_bit_complement' operand not an integral type" } */ + __builtin_bit_complement (0.0); /* { dg-error "'__builtin_bit_complement' operand not an integral type" } */ + __builtin_bit_complement (0.0L); /* { dg-error "'__builtin_bit_complement' operand not an integral type" } */ + __builtin_bit_complement ((V) {}); /* { dg-error "'__builtin_bit_complement' operand not an integral type" } */ + __builtin_bit_complement ((struct S) { 0 }); /* { dg-error "'__builtin_bit_complement' operand not an integral type" } */ + __builtin_bit_complement (); /* { dg-error "wrong number of arguments to '__builtin_bit_complement'" } */ + __builtin_bit_complement (0, 0); /* { dg-error "wrong number of arguments to '__builtin_bit_complement'" } */ +} Jakub