From patchwork Tue Oct 24 10:50:06 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Sandiford X-Patchwork-Id: 1854302 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=gcc.gnu.org (client-ip=2620:52:3:1:0:246e:9693:128c; helo=server2.sourceware.org; envelope-from=gcc-patches-bounces+incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=patchwork.ozlabs.org) Received: from server2.sourceware.org (server2.sourceware.org [IPv6:2620:52:3:1:0:246e:9693:128c]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (secp384r1) server-digest SHA384) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4SF84V4Wmfz23jl for ; Tue, 24 Oct 2023 21:51:22 +1100 (AEDT) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 9F9EE385B513 for ; Tue, 24 Oct 2023 10:51:13 +0000 (GMT) X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by sourceware.org (Postfix) with ESMTP id E90F7385AE41 for ; Tue, 24 Oct 2023 10:50:53 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org E90F7385AE41 Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=arm.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=arm.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org E90F7385AE41 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=217.140.110.172 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1698144659; cv=none; b=HRvllnAkk69/Ac/9jhcnQ0mixsaidn4Etm0DWR6TmwJUyXd4Pcn80hHHitqZkU+6I6/PDmHmPfQBOVkoE0RiTNqcsJbRh6qgRY/9Q4ufZS1Dbhc5EMkPC+9blhk7t6B3y6k1JQoVCiIoJfd1VEia80fPPwgd1IV8m3Xpu7Qw+4A= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1698144659; c=relaxed/simple; bh=5JK4ggY+pnuYNtRnK09JSJK3+IX2mYauz4/EoS90Tpk=; h=From:To:Subject:Date:Message-Id:MIME-Version; b=WJFYxjpkGXwZ5VnKepWY5lif9V/P3voy6kAp/u/b5HCeBx2cBQq40ZBS8hSWTooB/PNCjp43RePeUj5HZhCkp8IamCnzHCKL/j4ZMtkBMHqdEmJRUAr0LR2iWoAvPn5kEOV8QTw776/ORKyj8CghhjDLox7Zq6TqUUuezECIbas= ARC-Authentication-Results: i=1; server2.sourceware.org Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 974781424; Tue, 24 Oct 2023 03:51:34 -0700 (PDT) Received: from e121540-lin.manchester.arm.com (e121540-lin.manchester.arm.com [10.32.110.72]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 09D643F64C; Tue, 24 Oct 2023 03:50:52 -0700 (PDT) From: Richard Sandiford To: jlaw@ventanamicro.com, gcc-patches@gcc.gnu.org Cc: Richard Sandiford Subject: [PATCH 6/6] rtl-ssa: Handle call clobbers in more places Date: Tue, 24 Oct 2023 11:50:06 +0100 Message-Id: <20231024105006.3337671-7-richard.sandiford@arm.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20231024105006.3337671-1-richard.sandiford@arm.com> References: <20231024105006.3337671-1-richard.sandiford@arm.com> MIME-Version: 1.0 X-Spam-Status: No, score=-23.9 required=5.0 tests=BAYES_00, GIT_PATCH_0, KAM_DMARC_NONE, KAM_DMARC_STATUS, KAM_LAZY_DOMAIN_SECURITY, 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: , Errors-To: gcc-patches-bounces+incoming=patchwork.ozlabs.org@gcc.gnu.org In order to save (a lot of) memory, RTL-SSA avoids creating individual clobber records for every call-clobbered register. It instead maintains a list & splay tree of calls in an EBB, grouped by ABI. This patch takes these call clobbers into account in a couple more routines. I don't think this will have any effect on existing users, since it's only necessary for hard registers. gcc/ * rtl-ssa/access-utils.h (next_call_clobbers): New function. (is_single_dominating_def, remains_available_on_exit): Replace with... * rtl-ssa/functions.h (function_info::is_single_dominating_def) (function_info::remains_available_on_exit): ...these new member functions. (function_info::m_clobbered_by_calls): New member variable. * rtl-ssa/functions.cc (function_info::function_info): Explicitly initialize m_clobbered_by_calls. * rtl-ssa/insns.cc (function_info::record_call_clobbers): Update m_clobbered_by_calls for each call-clobber note. * rtl-ssa/member-fns.inl (function_info::is_single_dominating_def): New function. Check for call clobbers. * rtl-ssa/accesses.cc (function_info::remains_available_on_exit): Likewise. --- gcc/rtl-ssa/access-utils.h | 27 +++++++++------------------ gcc/rtl-ssa/accesses.cc | 25 +++++++++++++++++++++++++ gcc/rtl-ssa/functions.cc | 2 +- gcc/rtl-ssa/functions.h | 14 ++++++++++++++ gcc/rtl-ssa/insns.cc | 2 ++ gcc/rtl-ssa/member-fns.inl | 9 +++++++++ 6 files changed, 60 insertions(+), 19 deletions(-) diff --git a/gcc/rtl-ssa/access-utils.h b/gcc/rtl-ssa/access-utils.h index 84d386b7d8b..0d7a57f843c 100644 --- a/gcc/rtl-ssa/access-utils.h +++ b/gcc/rtl-ssa/access-utils.h @@ -127,24 +127,6 @@ set_with_nondebug_insn_uses (access_info *access) return nullptr; } -// Return true if SET is the only set of SET->resource () and if it -// dominates all uses (excluding uses of SET->resource () at points -// where SET->resource () is always undefined). -inline bool -is_single_dominating_def (const set_info *set) -{ - return set->is_first_def () && set->is_last_def (); -} - -// SET is known to be available on entry to BB. Return true if it is -// also available on exit from BB. (The value might or might not be live.) -inline bool -remains_available_on_exit (const set_info *set, bb_info *bb) -{ - return (set->is_last_def () - || *set->next_def ()->insn () > *bb->end_insn ()); -} - // ACCESS is known to be associated with an instruction rather than // a phi node. Return which instruction that is. inline insn_info * @@ -313,6 +295,15 @@ next_call_clobbers_ignoring (insn_call_clobbers_tree &tree, insn_info *insn, return tree->insn (); } +// Search forwards from immediately after INSN for the first instruction +// recorded in TREE. Return null if no such instruction exists. +inline insn_info * +next_call_clobbers (insn_call_clobbers_tree &tree, insn_info *insn) +{ + auto ignore = [](const insn_info *) { return false; }; + return next_call_clobbers_ignoring (tree, insn, ignore); +} + // If ACCESS is a set, return the first use of ACCESS by a nondebug insn I // for which IGNORE (I) is false. Return null if ACCESS is not a set or if // no such use exists. diff --git a/gcc/rtl-ssa/accesses.cc b/gcc/rtl-ssa/accesses.cc index 774ab9d99ee..c35c7efb73d 100644 --- a/gcc/rtl-ssa/accesses.cc +++ b/gcc/rtl-ssa/accesses.cc @@ -1303,6 +1303,31 @@ function_info::insert_temp_clobber (obstack_watermark &watermark, return insert_access (watermark, clobber, old_defs); } +// See the comment above the declaration. +bool +function_info::remains_available_on_exit (const set_info *set, bb_info *bb) +{ + if (HARD_REGISTER_NUM_P (set->regno ()) + && TEST_HARD_REG_BIT (m_clobbered_by_calls, set->regno ())) + { + insn_info *search_insn = (set->bb () == bb + ? set->insn () + : bb->head_insn ()); + for (ebb_call_clobbers_info *call_group : bb->ebb ()->call_clobbers ()) + { + if (!call_group->clobbers (set->resource ())) + continue; + + insn_info *insn = next_call_clobbers (*call_group, search_insn); + if (insn && insn->bb () == bb) + return false; + } + } + + return (set->is_last_def () + || *set->next_def ()->insn () > *bb->end_insn ()); +} + // A subroutine of make_uses_available. Try to make USE's definition // available at the head of BB. WILL_BE_DEBUG_USE is true if the // definition will be used only in debug instructions. diff --git a/gcc/rtl-ssa/functions.cc b/gcc/rtl-ssa/functions.cc index c35d25dbf8f..8a8108baae8 100644 --- a/gcc/rtl-ssa/functions.cc +++ b/gcc/rtl-ssa/functions.cc @@ -32,7 +32,7 @@ using namespace rtl_ssa; function_info::function_info (function *fn) - : m_fn (fn) + : m_fn (fn), m_clobbered_by_calls () { // Force the alignment to be obstack_alignment. Everything else is normal. obstack_specify_allocation (&m_obstack, OBSTACK_CHUNK_SIZE, diff --git a/gcc/rtl-ssa/functions.h b/gcc/rtl-ssa/functions.h index cd90b6aa9df..ab253e750cb 100644 --- a/gcc/rtl-ssa/functions.h +++ b/gcc/rtl-ssa/functions.h @@ -102,6 +102,11 @@ public: // definitions by things like phi nodes. iterator_range reg_defs (unsigned int regno) const; + // Return true if SET is the only set of SET->resource () and if it + // dominates all uses (excluding uses of SET->resource () at points + // where SET->resource () is always undefined). + bool is_single_dominating_def (const set_info *set) const; + // Check if all uses of register REGNO are either unconditionally undefined // or use the same single dominating definition. Return the definition // if so, otherwise return null. @@ -116,6 +121,11 @@ public: // scope until the change has been aborted or successfully completed. obstack_watermark new_change_attempt () { return &m_temp_obstack; } + // SET either occurs in BB or is known to be available on entry to BB. + // Return true if it is also available on exit from BB. (The value + // might or might not be live.) + bool remains_available_on_exit (const set_info *set, bb_info *bb); + // Make a best attempt to check whether the values used by USES are // available on entry to BB, without solving a full dataflow problem. // If all the values are already live on entry to BB or can be made @@ -357,6 +367,10 @@ private: // on it. As with M_QUEUED_INSN_UPDATES, these updates are queued until // a convenient point. auto_bitmap m_need_to_purge_dead_edges; + + // The set of hard registers that are fully or partially clobbered + // by at least one insn_call_clobbers_note. + HARD_REG_SET m_clobbered_by_calls; }; void pp_function (pretty_printer *, const function_info *); diff --git a/gcc/rtl-ssa/insns.cc b/gcc/rtl-ssa/insns.cc index f970375d906..5fde3f2bb4b 100644 --- a/gcc/rtl-ssa/insns.cc +++ b/gcc/rtl-ssa/insns.cc @@ -568,6 +568,8 @@ function_info::record_call_clobbers (build_info &bi, insn_info *insn, insn->add_note (insn_clobbers); ecc->insert_max_node (insn_clobbers); + + m_clobbered_by_calls |= abi.full_and_partial_reg_clobbers (); } else for (unsigned int regno = 0; regno < FIRST_PSEUDO_REGISTER; ++regno) diff --git a/gcc/rtl-ssa/member-fns.inl b/gcc/rtl-ssa/member-fns.inl index 3fdca14e0ef..ce2db045b78 100644 --- a/gcc/rtl-ssa/member-fns.inl +++ b/gcc/rtl-ssa/member-fns.inl @@ -916,6 +916,15 @@ function_info::reg_defs (unsigned int regno) const return { m_defs[regno + 1], nullptr }; } +inline bool +function_info::is_single_dominating_def (const set_info *set) const +{ + return (set->is_first_def () + && set->is_last_def () + && (!HARD_REGISTER_NUM_P (set->regno ()) + || !TEST_HARD_REG_BIT (m_clobbered_by_calls, set->regno ()))); +} + inline set_info * function_info::single_dominating_def (unsigned int regno) const {