From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by sourceware.org (Postfix) with ESMTP id B3E973858426 for ; Sun, 12 Nov 2023 14:52:58 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org B3E973858426 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 B3E973858426 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=1699800780; cv=none; b=mzRRdXGC08i5qADqTZ0kyhIq19+D7lYKSJMwe6talk8mBrCSLjHL/UHMjj9Wi8rNc4FDvme7lkHImhmXjxtVqEqT4ZkSGjs1O+x7DdDn4yKF4jnQBN6uQiBZBlr4sSuM5p0zjoDMJ+RcBRE2EXRl22ZhA6lnxup8L/qoCRs4/Bs= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1699800780; c=relaxed/simple; bh=Xp00aMKO5S31PkxEgyRjWAmBmBhg9EZx3tsF+XijYxU=; h=From:To:Subject:Date:Message-Id:MIME-Version; b=DzdQ0y0I7YAtc8AXfQ/QiaD2dbW7I+8ASZfyf8yI+bSIskFcYQ/5qodpHcWjnEPg6jV+EUbUgFqI/+cbAVeO/QYgF3yAXNVgLLffo3mWFUVF0SdbslFv2uPUu4PMnZ6XkQJJsSL4vzndJ4G+3tIBeT6szCWIz6H2m+6vv+AzRZY= 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 6C017DA7; Sun, 12 Nov 2023 06:53:43 -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 C47173F7B4; Sun, 12 Nov 2023 06:52:57 -0800 (PST) From: Richard Sandiford To: jlaw@ventanamicro.com, vmakarov@redhat.com, gcc-patches@gcc.gnu.org Cc: Richard Sandiford Subject: [PATCH 2/5] recog: Handle register filters Date: Sun, 12 Nov 2023 14:52:26 +0000 Message-Id: <20231112145229.2924713-3-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 Content-Transfer-Encoding: 8bit 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 List-Id: The main (but simplest) part of this patch makes constrain_operands take register filters into account. The rest of the patch adds register filter information to operand_alternative. Generally, if two register constraints have different register filters, it's better if they're in separate alternatives. However, the syntax doesn't enforce that, and we can't assert it due to inline asms. So it's a choice between (a) adding code to enforce consistent filters or (b) dealing with mixes of filters in a conservatively correct way (in the sense of not allowing invalid operands). The latter seems much easier. The patch therefore adds a mask of the filters that apply to at least one constraint in a given operand alternative. A register is OK if it passes all of the filters in the mask. gcc/ * recog.h (operand_alternative): Add a register_filters field. (alternative_register_filters): New function. * recog.cc (preprocess_constraints): Calculate the filters field. (constrain_operands): Check register filters. --- gcc/recog.cc | 14 ++++++++++++-- gcc/recog.h | 24 ++++++++++++++++++++++-- 2 files changed, 34 insertions(+), 4 deletions(-) diff --git a/gcc/recog.cc b/gcc/recog.cc index 3bd2d73c259..eaab79c25d7 100644 --- a/gcc/recog.cc +++ b/gcc/recog.cc @@ -2857,6 +2857,7 @@ preprocess_constraints (int n_operands, int n_alternatives, for (j = 0; j < n_alternatives; j++, op_alt += n_operands) { op_alt[i].cl = NO_REGS; + op_alt[i].register_filters = 0; op_alt[i].constraint = p; op_alt[i].matches = -1; op_alt[i].matched = -1; @@ -2919,7 +2920,12 @@ preprocess_constraints (int n_operands, int n_alternatives, case CT_REGISTER: cl = reg_class_for_constraint (cn); if (cl != NO_REGS) - op_alt[i].cl = reg_class_subunion[op_alt[i].cl][cl]; + { + op_alt[i].cl = reg_class_subunion[op_alt[i].cl][cl]; + auto filter_id = get_register_filter_id (cn); + if (filter_id >= 0) + op_alt[i].register_filters |= 1U << filter_id; + } break; case CT_CONST_INT: @@ -3219,13 +3225,17 @@ constrain_operands (int strict, alternative_mask alternatives) enum reg_class cl = reg_class_for_constraint (cn); if (cl != NO_REGS) { + auto *filter = get_register_filter (cn); if (strict < 0 || (strict == 0 && REG_P (op) && REGNO (op) >= FIRST_PSEUDO_REGISTER) || (strict == 0 && GET_CODE (op) == SCRATCH) || (REG_P (op) - && reg_fits_class_p (op, cl, offset, mode))) + && reg_fits_class_p (op, cl, offset, mode) + && (!filter + || TEST_HARD_REG_BIT (*filter, + REGNO (op) + offset)))) win = true; } diff --git a/gcc/recog.h b/gcc/recog.h index c6ef619c5dd..5c801e7bb81 100644 --- a/gcc/recog.h +++ b/gcc/recog.h @@ -42,6 +42,7 @@ enum op_type { OP_INOUT }; +#ifndef GENERATOR_FILE struct operand_alternative { /* Pointer to the beginning of the constraint string for this alternative, @@ -62,6 +63,11 @@ struct operand_alternative matches this one. */ int matched : 8; + /* Bit ID is set if the constraint string includes a register constraint with + register filter ID. Use test_register_filters (REGISTER_FILTERS, REGNO) + to test whether REGNO is a valid start register for the operand. */ + unsigned int register_filters : MAX (NUM_REGISTER_FILTERS, 1); + /* Nonzero if '&' was found in the constraint string. */ unsigned int earlyclobber : 1; /* Nonzero if TARGET_MEM_CONSTRAINT was found in the constraint @@ -72,8 +78,6 @@ struct operand_alternative /* Nonzero if 'X' was found in the constraint string, or if the constraint string for this alternative was empty. */ unsigned int anything_ok : 1; - - unsigned int unused : 12; }; /* Return the class for operand I of alternative ALT, taking matching @@ -85,6 +89,18 @@ alternative_class (const operand_alternative *alt, int i) return alt[i].matches >= 0 ? alt[alt[i].matches].cl : alt[i].cl; } +/* Return the mask of register filters that should be applied to operand I + of alternative ALT, taking matching constraints into account. */ + +inline unsigned int +alternative_register_filters (const operand_alternative *alt, int i) +{ + return (alt[i].matches >= 0 + ? alt[alt[i].matches].register_filters + : alt[i].register_filters); +} +#endif + /* A class for substituting one rtx for another within an instruction, or for recursively simplifying the instruction as-is. Derived classes can record or filter certain decisions. */ @@ -242,9 +258,11 @@ extern void extract_insn (rtx_insn *); extern void extract_constrain_insn (rtx_insn *insn); extern void extract_constrain_insn_cached (rtx_insn *); extern void extract_insn_cached (rtx_insn *); +#ifndef GENERATOR_FILE extern void preprocess_constraints (int, int, const char **, operand_alternative *, rtx **); extern const operand_alternative *preprocess_insn_constraints (unsigned int); +#endif extern void preprocess_constraints (rtx_insn *); extern rtx_insn *peep2_next_insn (int); extern bool peep2_regno_dead_p (int, int); @@ -380,6 +398,7 @@ struct recog_data_d extern struct recog_data_d recog_data; +#ifndef GENERATOR_FILE extern const operand_alternative *recog_op_alt; /* Return a pointer to an array in which index OP describes the constraints @@ -393,6 +412,7 @@ which_op_alt () recog_data.n_alternatives - 1)); return &recog_op_alt[which_alternative * recog_data.n_operands]; } +#endif /* A table defined in insn-output.cc that give information about each insn-code value. */ -- 2.25.1