From patchwork Tue Jan 3 11:15:23 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Florian Weimer X-Patchwork-Id: 62668 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 B00DC3858C1F for ; Tue, 3 Jan 2023 11:15:58 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org B00DC3858C1F DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1672744558; bh=MZNmt3BiRJ7hVsidmqfU1T9lhK7bvBl34KUH0wiWbmc=; h=To:Cc:Subject:Date:List-Id:List-Unsubscribe:List-Archive: List-Post:List-Help:List-Subscribe:From:Reply-To:From; b=VQ54zjXU+dXiyGdYXrxUp1a5Ql0u8mgb0PxTvPvaGdPQYJlTpE/FSeKK2Bx37vIYT i2Fu99udAkQneDtr493KDZ+fxm+dKwxwwm/p4/Hb8fklcAcVrmv6adlU+gz/fnPOjs 8i3orAowgWAbFkWZPZXSIqRfFr9uyxAHVPSsnA/4= 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 D53E33858D37 for ; Tue, 3 Jan 2023 11:15:30 +0000 (GMT) Received: from mimecast-mx02.redhat.com (mimecast-mx02.redhat.com [66.187.233.88]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-361-a4wcxvK2OjGme3BZMbjefg-1; Tue, 03 Jan 2023 06:15:27 -0500 X-MC-Unique: a4wcxvK2OjGme3BZMbjefg-1 Received: from smtp.corp.redhat.com (int-mx04.intmail.prod.int.rdu2.redhat.com [10.11.54.4]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 05C84811E6E; Tue, 3 Jan 2023 11:15:27 +0000 (UTC) Received: from oldenburg.str.redhat.com (unknown [10.2.16.92]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 586F22026D4B; Tue, 3 Jan 2023 11:15:25 +0000 (UTC) To: gcc-patches@gcc.gnu.org Cc: Andre Vieira , Andrew Pinski , Jakub Jelinek , Jeff Law Subject: [PATCH] Various fixes for DWARF register size computation Date: Tue, 03 Jan 2023 12:15:23 +0100 Message-ID: <87pmbvx41g.fsf@oldenburg.str.redhat.com> User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/28.2 (gnu/linux) MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.1 on 10.11.54.4 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com X-Spam-Status: No, score=-10.6 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, 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.29 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Florian Weimer via Gcc-patches From: Florian Weimer Reply-To: Florian Weimer Errors-To: gcc-patches-bounces+patchwork=sourceware.org@gcc.gnu.org Sender: "Gcc-patches" The previous code had several issues. 1. XALLOCAVEC does not create any objects, so invocating the non-POD poly_uint16 assignment operator is undefined. 2. The default constructor of poly-ints does not create a zero poly-int object (unlike what happens with regular ints). 3. The register size array must have DWARF_FRAME_REGISTERS + 1 elements. The extra element can be DWARF_FRAME_RETURN_COLUMN or DWARF_ALT_FRAME_RETURN_COLUMN. To fix problem 3, merely increasing the array size is sufficient, but it inhibits the x86-64 register size optimization in libgcc because it does not use the extra register, so it has size zero. To re-enable the optimization, expose the maximum used register to libgcc. This is sufficient for the optimizers to figure out that the memcpy call in uw_install_context_1 has a fixed size argument on x86-64. This restores bootstrap on aarch64-linux-gnu and powerpc64-linux-gnu. Not sure about test suite results yet, I need to check the baseline. gcc/ * debug.h (dwarf_reg_sizes_constant): Remove declaration. (dwarf_single_register_size): New struct. * dwarf2cfi.cc (generate_dwarf_reg_sizes): Initialize extra register size. Use in-place new for initialization. Remove unnecessary memset. (dwarf_reg_sizes_constant): Remove. (dwarf_single_register_size::dwarf_single_register_size): New constructor based on removed dwarf_reg_sizes_constant function. Allocate extra size element. (expand_builtin_init_dwarf_reg_sizes): Allocate extra size element. * target.def (init_dwarf_reg_sizes_extra): Mention extra size element. * doc/tm.texi: Update. gcc/c-family/ * c-cppbuiltin.cc (c_cpp_builtins): Switch to dwarf_single_register_size for obtaining DWARF register sizes. Define __LIBGCC_DWARF_REG_MAXIMUM__. libgcc/ * unwind-dw2.c (dwarf_reg_size): Use __LIBGCC_DWARF_REG_MAXIMUM__. --- gcc/c-family/c-cppbuiltin.cc | 12 ++++++++---- gcc/debug.h | 13 ++++++++++++- gcc/doc/tm.texi | 2 +- gcc/dwarf2cfi.cc | 45 +++++++++++++++++++++++++++----------------- gcc/target.def | 2 +- libgcc/unwind-dw2.c | 7 +++++-- 6 files changed, 55 insertions(+), 26 deletions(-) base-commit: 201c21b0e847679645df1af3dd13459274f41047 diff --git a/gcc/c-family/c-cppbuiltin.cc b/gcc/c-family/c-cppbuiltin.cc index ddfd63b8eb9..8098aca41e8 100644 --- a/gcc/c-family/c-cppbuiltin.cc +++ b/gcc/c-family/c-cppbuiltin.cc @@ -1522,10 +1522,14 @@ c_cpp_builtins (cpp_reader *pfile) builtin_define_with_int_value ("__LIBGCC_DWARF_FRAME_REGISTERS__", DWARF_FRAME_REGISTERS); { - int value = dwarf_reg_sizes_constant (); - if (value > 0) - builtin_define_with_int_value ("__LIBGCC_DWARF_REG_SIZES_CONSTANT__", - value); + dwarf_single_register_size srs; + if (srs.common_size > 0) + { + builtin_define_with_int_value ("__LIBGCC_DWARF_REG_SIZES_CONSTANT__", + srs.common_size); + builtin_define_with_int_value ("__LIBGCC_DWARF_REG_MAXIMUM__", + srs.maximum_register); + } } builtin_define_with_int_value ("__LIBGCC_DWARF_CIE_DATA_ALIGNMENT__", DWARF_CIE_DATA_ALIGNMENT); diff --git a/gcc/debug.h b/gcc/debug.h index 4fe9f3570ac..2e843da8b41 100644 --- a/gcc/debug.h +++ b/gcc/debug.h @@ -245,7 +245,18 @@ extern const struct gcc_debug_hooks vmsdbg_debug_hooks; /* Dwarf2 frame information. */ -extern int dwarf_reg_sizes_constant (); +/* Query size information about DWARF registers. */ +struct dwarf_single_register_size +{ + dwarf_single_register_size(); + + /* The common register size, or 0 if the register size varies. */ + unsigned int common_size; + + /* The maximum register number that is actually present. Registers + above the maximum are size zero even if common_size is positive. */ + unsigned int maximum_register; +}; extern void dwarf2out_begin_prologue (unsigned int, unsigned int, const char *); diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi index b6d7900f212..eb29cfb95aa 100644 --- a/gcc/doc/tm.texi +++ b/gcc/doc/tm.texi @@ -9847,7 +9847,7 @@ sizes of those pieces in the table used by the unwinder at runtime. It will be called by @code{generate_dwarf_reg_sizes} after filling in a single size corresponding to each hard register; @var{sizes} is the address of the table. It will contain -@code{DWARF_FRAME_REGISTERS} elements when this hook is called. +@code{DWARF_FRAME_REGISTERS + 1} elements when this hook is called. @end deftypefn @deftypefn {Target Hook} bool TARGET_ASM_TTYPE (rtx @var{sym}) diff --git a/gcc/dwarf2cfi.cc b/gcc/dwarf2cfi.cc index d5a27dc36c5..5bd12e070b3 100644 --- a/gcc/dwarf2cfi.cc +++ b/gcc/dwarf2cfi.cc @@ -291,11 +291,10 @@ init_one_dwarf_reg_size (int regno, machine_mode regmode, static void generate_dwarf_reg_sizes (poly_uint16 *sizes) { - for (unsigned int i = 0; i < DWARF_FRAME_REGISTERS; i++) - sizes[i] = poly_uint16{}; + for (unsigned int i = 0; i <= DWARF_FRAME_REGISTERS; i++) + new (&sizes[i]) poly_uint16(0); init_one_dwarf_reg_state init_state{}; - memset ((char *)&init_state, 0, sizeof (init_state)); for (unsigned int i = 0; i < FIRST_PSEUDO_REGISTER; i++) { @@ -334,27 +333,39 @@ generate_dwarf_reg_sizes (poly_uint16 *sizes) targetm.init_dwarf_reg_sizes_extra (sizes); } -/* Return 0 if the DWARF register sizes are not constant, otherwise - return the size constant. */ - -int -dwarf_reg_sizes_constant () +dwarf_single_register_size::dwarf_single_register_size() { - poly_uint16 *sizes = XALLOCAVEC (poly_uint16, DWARF_FRAME_REGISTERS); + poly_uint16 *sizes = XALLOCAVEC (poly_uint16, DWARF_FRAME_REGISTERS + 1); generate_dwarf_reg_sizes (sizes); - int result; - for (unsigned int i = 0; i < DWARF_FRAME_REGISTERS; i++) + /* Find the last register number actually in use. */ + for (int i = DWARF_FRAME_REGISTERS; i >= 0; --i) + { + unsigned short value; + if (!sizes[i].is_constant (&value) || value != 0) + { + maximum_register = i; + break; + } + } + + /* Check for a common register size among the used registers. */ + for (unsigned int i = 0; i <= maximum_register; ++i) { unsigned short value; if (!sizes[i].is_constant (&value)) - return 0; + { + common_size = 0; + break; + } if (i == 0) - result = value; - else if (result != value) - return 0; + common_size = value; + else if (common_size != value) + { + common_size = 0; + break; + } } - return result; } /* Generate code to initialize the dwarf register size table located @@ -363,7 +374,7 @@ dwarf_reg_sizes_constant () void expand_builtin_init_dwarf_reg_sizes (tree address) { - poly_uint16 *sizes = XALLOCAVEC (poly_uint16, DWARF_FRAME_REGISTERS); + poly_uint16 *sizes = XALLOCAVEC (poly_uint16, DWARF_FRAME_REGISTERS + 1); generate_dwarf_reg_sizes (sizes); scalar_int_mode mode = SCALAR_INT_TYPE_MODE (char_type_node); diff --git a/gcc/target.def b/gcc/target.def index da5dd31d7a4..dfffc534f83 100644 --- a/gcc/target.def +++ b/gcc/target.def @@ -4042,7 +4042,7 @@ sizes of those pieces in the table used by the unwinder at runtime.\n\ It will be called by @code{generate_dwarf_reg_sizes} after\n\ filling in a single size corresponding to each hard register;\n\ @var{sizes} is the address of the table. It will contain\n\ -@code{DWARF_FRAME_REGISTERS} elements when this hook is called.", +@code{DWARF_FRAME_REGISTERS + 1} elements when this hook is called.", void, (poly_uint16 *sizes), nullptr) /* Fetch the fixed register(s) which hold condition codes, for diff --git a/libgcc/unwind-dw2.c b/libgcc/unwind-dw2.c index 792338c1e38..7a173487061 100644 --- a/libgcc/unwind-dw2.c +++ b/libgcc/unwind-dw2.c @@ -150,9 +150,12 @@ struct _Unwind_Context #ifdef __LIBGCC_DWARF_REG_SIZES_CONSTANT__ static inline unsigned char -dwarf_reg_size (int index __attribute__ ((__unused__))) +dwarf_reg_size (unsigned int index) { - return __LIBGCC_DWARF_REG_SIZES_CONSTANT__; + if (index <= __LIBGCC_DWARF_REG_MAXIMUM__) + return __LIBGCC_DWARF_REG_SIZES_CONSTANT__; + else + return 0; } #else /* Byte size of every register managed by these routines. */