From patchwork Sun Nov 12 14:52:28 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Sandiford X-Patchwork-Id: 164254 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:b909:0:b0:403:3b70:6f57 with SMTP id t9csp725661vqg; Sun, 12 Nov 2023 06:53:54 -0800 (PST) X-Google-Smtp-Source: AGHT+IGNIj+DCLGhxvY3eM1NJ3gFUrHsKdANEQT+5lwi7SQCk5los+OxEEimTy6bfYErEUW84nAH X-Received: by 2002:a0c:ebcf:0:b0:66d:a155:9740 with SMTP id k15-20020a0cebcf000000b0066da1559740mr4848512qvq.8.1699800834156; Sun, 12 Nov 2023 06:53:54 -0800 (PST) ARC-Seal: i=2; a=rsa-sha256; t=1699800834; cv=pass; d=google.com; s=arc-20160816; b=QHnG6Llmt3mkNdN1rJuyWgfLtyMMQtcv2nzT+GPqxonek4wGfq45xtQEo2io+i2fiI whZz3Q7v/oez7OaAZrY+Uk29KgwuH4HBW2jqRb0uV/LQa1AzC87EWdjI90eaZ1DNLDKa W/XhyXIzrMM8kseOmL0QJOamHFez+QOLuIy/pAaZFS4yKfYr5SWY74NKhK1mHouBrkR2 Tm8ezWbo/NhLUexHQ33GLsPvG+yJyIMIbd6a43wxpzrouAjpA+gsM5iYm3imhubu19LD NSBapsaFwMppedZd0n90Si5KkKm33rfhHsw8r5apE1InBjb79zDLDH5DRcdBEV5GCwUQ pEDQ== ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=errors-to:list-subscribe:list-help:list-post:list-archive :list-unsubscribe:list-id:precedence:content-transfer-encoding :mime-version:references:in-reply-to:message-id:date:subject:cc:to :from:arc-filter:dmarc-filter:delivered-to; bh=w269r1TZjD9SDzJaRKKybPNh0dPFXBuwLbHR5uDNwPc=; fh=eP38mNCumzc9uAnckmu9HVXCluORSTRDRN4eBnZbl/w=; b=UXbXMZCkPRPEsyOHdmGaebLlEAmoZXiZbgDyEHAlvDuxa7eIgmguOTQabFbSenkjjt 69UPUTF+evhoU6nQtRQVQoBTimxEvqA7dc7RgEqNPdox14aFlVZfmZDi+tot2lOI5idh D6t+xWRxGAVprIC6oNhavkrw+AGDFeN5WkGKpKOFdsxOdx/x03FT28thmOXv52AXKynX bVW9ZWKJu0eaTJjXGXtBRd+GtQvWFsD6/1MzH0YF2gtXuzjrvi+evS91EpuEuiQ/2kaC guHQYsMwb3ViLe/loCEWXRTXoKncqAcgxLCD4qxzXVA2SxaRI117+q8pW1+m0ndcPKkw hPDQ== ARC-Authentication-Results: i=2; mx.google.com; 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=fail (p=NONE sp=NONE dis=NONE) header.from=arm.com Received: from server2.sourceware.org (server2.sourceware.org. [8.43.85.97]) by mx.google.com with ESMTPS id f14-20020a0cf7ce000000b0066d0edaf8fasi2982578qvo.235.2023.11.12.06.53.54 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 12 Nov 2023 06:53:54 -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; 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=fail (p=NONE sp=NONE dis=NONE) header.from=arm.com Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 6F058385841E for ; Sun, 12 Nov 2023 14:53:45 +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 14E2D3858028 for ; Sun, 12 Nov 2023 14:53:21 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 14E2D3858028 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 14E2D3858028 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=1699800803; cv=none; b=mALZHiAFUXuUC7WZGr3acI7HgcC6Rpm5UtCSSuRcB4Z5tXWXUMAsQqKiowljUw4nrl7VqmZxOfMCgkOkk0/r6FNQnvQqydP1mW3dQzJSPWianV7UrMQy7hDRxb0bDcSj4eA6Hue/KHfQHUTBd3PgRsCwkCVVpNaN11lpVWQqFJk= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1699800803; c=relaxed/simple; bh=vHwyfg7WtyVqkpVCvO1zoqr6Yhyd4uYtWtsFWg+DqEY=; h=From:To:Subject:Date:Message-Id:MIME-Version; b=iSLqXVtOQQIhN0iSQOEER8l51GfSj/wwXa+BhAXisQJBvxD+lxAiHpw4jQoIe1sIgcIrgXq6YdK0oHBe0mNaeZne7WLvN3yB+BGpcoznKdcr29a8lEPpT9p/huVTKIqpV6oFFyqJtbfePIOhi38gzWdXCufZeiBqlYhke2OiWBY= 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 93063DA7; Sun, 12 Nov 2023 06:54:05 -0800 (PST) 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 EB4493F7B4; Sun, 12 Nov 2023 06:53:19 -0800 (PST) From: Richard Sandiford To: jlaw@ventanamicro.com, vmakarov@redhat.com, gcc-patches@gcc.gnu.org Cc: Richard Sandiford Subject: [PATCH 4/5] ira: Handle register filters Date: Sun, 12 Nov 2023 14:52:28 +0000 Message-Id: <20231112145229.2924713-5-richard.sandiford@arm.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20231112145229.2924713-1-richard.sandiford@arm.com> References: <20231112145229.2924713-1-richard.sandiford@arm.com> MIME-Version: 1.0 X-Spam-Status: No, score=-23.3 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, 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: , Errors-To: gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1782370359711176094 X-GMAIL-MSGID: 1782370359711176094 This patch makes IRA apply register filters when picking hard registers. All the new code should be optimised away on targets that don't use register filters. On targets that do use them, the new register_filters bitfield is expected to be only a handful of bits. Information about register filters is recorded in process_bb_node_lives. The information isn't really related to liveness, but it's a convenient point because (a) we've already built the allocno structures and (b) we've already extracted the insn and preprocessed the constraints. gcc/ * ira-int.h (ira_allocno): Add a register_filters field. (ALLOCNO_REGISTER_FILTERS): New macro. (ALLOCNO_SET_REGISTER_FILTERS): Likewise. * ira-build.cc (ira_create_allocno): Initialize register_filters. (create_cap_allocno): Propagate register_filters. (propagate_allocno_info): Likewise. (propagate_some_info_from_allocno): Likewise. * ira-lives.cc (process_register_constraint_filters): New function. (process_bb_node_lives): Use it to record register filter information. * ira-color.cc (assign_hard_reg): Check register filters. (improve_allocation, fast_allocation): Likewise. --- gcc/ira-build.cc | 8 +++++++ gcc/ira-color.cc | 10 ++++++++ gcc/ira-int.h | 14 +++++++++++ gcc/ira-lives.cc | 61 ++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 93 insertions(+) diff --git a/gcc/ira-build.cc b/gcc/ira-build.cc index 93e46033170..c715a834f12 100644 --- a/gcc/ira-build.cc +++ b/gcc/ira-build.cc @@ -498,6 +498,7 @@ ira_create_allocno (int regno, bool cap_p, ALLOCNO_NREFS (a) = 0; ALLOCNO_FREQ (a) = 0; ALLOCNO_MIGHT_CONFLICT_WITH_PARENT_P (a) = false; + ALLOCNO_SET_REGISTER_FILTERS (a, 0); ALLOCNO_HARD_REGNO (a) = -1; ALLOCNO_CALL_FREQ (a) = 0; ALLOCNO_CALLS_CROSSED_NUM (a) = 0; @@ -902,6 +903,7 @@ create_cap_allocno (ira_allocno_t a) ALLOCNO_NREFS (cap) = ALLOCNO_NREFS (a); ALLOCNO_FREQ (cap) = ALLOCNO_FREQ (a); ALLOCNO_CALL_FREQ (cap) = ALLOCNO_CALL_FREQ (a); + ALLOCNO_SET_REGISTER_FILTERS (cap, ALLOCNO_REGISTER_FILTERS (a)); merge_hard_reg_conflicts (a, cap, false); @@ -2064,6 +2066,9 @@ propagate_allocno_info (void) ALLOCNO_BAD_SPILL_P (parent_a) = false; ALLOCNO_NREFS (parent_a) += ALLOCNO_NREFS (a); ALLOCNO_FREQ (parent_a) += ALLOCNO_FREQ (a); + ALLOCNO_SET_REGISTER_FILTERS (parent_a, + ALLOCNO_REGISTER_FILTERS (parent_a) + | ALLOCNO_REGISTER_FILTERS (a)); /* If A's allocation can differ from PARENT_A's, we can if necessary spill PARENT_A on entry to A's loop and restore it afterwards. @@ -2465,6 +2470,9 @@ propagate_some_info_from_allocno (ira_allocno_t a, ira_allocno_t from_a) ALLOCNO_CROSSED_CALLS_ABIS (a) |= ALLOCNO_CROSSED_CALLS_ABIS (from_a); ALLOCNO_CROSSED_CALLS_CLOBBERED_REGS (a) |= ALLOCNO_CROSSED_CALLS_CLOBBERED_REGS (from_a); + ALLOCNO_SET_REGISTER_FILTERS (a, + ALLOCNO_REGISTER_FILTERS (from_a) + | ALLOCNO_REGISTER_FILTERS (a)); ALLOCNO_EXCESS_PRESSURE_POINTS_NUM (a) += ALLOCNO_EXCESS_PRESSURE_POINTS_NUM (from_a); diff --git a/gcc/ira-color.cc b/gcc/ira-color.cc index f2e8ea34152..214a4f16d3c 100644 --- a/gcc/ira-color.cc +++ b/gcc/ira-color.cc @@ -2163,6 +2163,9 @@ assign_hard_reg (ira_allocno_t a, bool retry_p) if (! check_hard_reg_p (a, hard_regno, conflicting_regs, profitable_hard_regs)) continue; + if (NUM_REGISTER_FILTERS + && !test_register_filters (ALLOCNO_REGISTER_FILTERS (a), hard_regno)) + continue; cost = costs[i]; full_cost = full_costs[i]; if (!HONOR_REG_ALLOC_ORDER) @@ -3205,6 +3208,9 @@ improve_allocation (void) if (! check_hard_reg_p (a, hregno, conflicting_regs, profitable_hard_regs)) continue; + if (NUM_REGISTER_FILTERS + && !test_register_filters (ALLOCNO_REGISTER_FILTERS (a), hregno)) + continue; ira_assert (ira_class_hard_reg_index[aclass][hregno] == j); k = allocno_costs == NULL ? 0 : j; costs[hregno] = (allocno_costs == NULL @@ -5275,6 +5281,10 @@ fast_allocation (void) || (TEST_HARD_REG_BIT (ira_prohibited_class_mode_regs[aclass][mode], hard_regno))) continue; + if (NUM_REGISTER_FILTERS + && !test_register_filters (ALLOCNO_REGISTER_FILTERS (a), + hard_regno)) + continue; if (costs == NULL) { best_hard_regno = hard_regno; diff --git a/gcc/ira-int.h b/gcc/ira-int.h index 0685e1f4e8d..1c3548df4ea 100644 --- a/gcc/ira-int.h +++ b/gcc/ira-int.h @@ -328,6 +328,13 @@ struct ira_allocno This is only ever true for non-cap allocnos. */ unsigned int might_conflict_with_parent_p : 1; +#ifndef NUM_REGISTER_FILTERS +#error "insn-config.h not included" +#elif NUM_REGISTER_FILTERS + /* The set of register filters applied to the allocno by operand + alternatives that accept class ACLASS. */ + unsigned int register_filters : NUM_REGISTER_FILTERS; +#endif /* Accumulated usage references of the allocno. Here and below, word 'accumulated' means info for given region and all nested subregions. In this case, 'accumulated' means sum of references @@ -432,6 +439,13 @@ struct ira_allocno #define ALLOCNO_FREQ(A) ((A)->freq) #define ALLOCNO_MIGHT_CONFLICT_WITH_PARENT_P(A) \ ((A)->might_conflict_with_parent_p) +#if NUM_REGISTER_FILTERS +#define ALLOCNO_REGISTER_FILTERS(A) (A)->register_filters +#define ALLOCNO_SET_REGISTER_FILTERS(A, X) ((A)->register_filters = (X)) +#else +#define ALLOCNO_REGISTER_FILTERS(A) 0 +#define ALLOCNO_SET_REGISTER_FILTERS(A, X) ((void) (A), gcc_assert ((X) == 0)) +#endif #define ALLOCNO_HARD_REGNO(A) ((A)->hard_regno) #define ALLOCNO_CALL_FREQ(A) ((A)->call_freq) #define ALLOCNO_CALLS_CROSSED_NUM(A) ((A)->calls_crossed_num) diff --git a/gcc/ira-lives.cc b/gcc/ira-lives.cc index 81af5c06460..63f2314409f 100644 --- a/gcc/ira-lives.cc +++ b/gcc/ira-lives.cc @@ -1066,6 +1066,66 @@ process_single_reg_class_operands (bool in_p, int freq) } } +/* Go through the operands of the extracted insn looking for operand + alternatives that apply a register filter. Record any such filters + in the operand's allocno. */ +static void +process_register_constraint_filters () +{ + for (int opno = 0; opno < recog_data.n_operands; ++opno) + { + rtx op = recog_data.operand[opno]; + if (SUBREG_P (op)) + op = SUBREG_REG (op); + if (REG_P (op) && !HARD_REGISTER_P (op)) + { + ira_allocno_t a = ira_curr_regno_allocno_map[REGNO (op)]; + for (int alt = 0; alt < recog_data.n_alternatives; alt++) + { + if (!TEST_BIT (preferred_alternatives, alt)) + continue; + + auto *op_alt = &recog_op_alt[alt * recog_data.n_operands]; + auto cl = alternative_class (op_alt, opno); + /* The two extremes are easy: + + - We should record the filter if CL matches the + allocno class. + + - We should ignore the filter if CL and the allocno class + are disjoint. We'll either pick a different alternative + or reload the operand. + + Things are trickier if the classes overlap. However: + + - If the allocno class includes registers that are not + in CL, some choices of hard register will need a reload + anyway. It isn't obvious that reloads due to filters + are worse than reloads due to regnos being outside CL. + + - Conversely, if the allocno class is a subset of CL, + any allocation will satisfy the class requirement. + We should try to make sure it satisfies the filter + requirement too. This is useful if, for example, + an allocno needs to be in "low" registers to satisfy + some uses, and its allocno class is therefore those + low registers, but the allocno is elsewhere allowed + to be in any even-numbered register. Picking an + even-numbered low register satisfies both types of use. */ + if (!ira_class_subset_p[ALLOCNO_CLASS (a)][cl]) + continue; + + auto filters = alternative_register_filters (op_alt, opno); + if (!filters) + continue; + + filters |= ALLOCNO_REGISTER_FILTERS (a); + ALLOCNO_SET_REGISTER_FILTERS (a, filters); + } + } + } +} + /* Look through the CALL_INSN_FUNCTION_USAGE of a call insn INSN, and see if we find a SET rtx that we can use to deduce that a register can be cheaply caller-saved. Return such a register, or NULL_RTX if none is found. */ @@ -1378,6 +1438,7 @@ process_bb_node_lives (ira_loop_tree_node_t loop_tree_node) } preferred_alternatives = ira_setup_alts (insn); + process_register_constraint_filters (); process_single_reg_class_operands (false, freq); if (call_p)