From patchwork Fri Jul 28 10:17:00 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Robin Dapp X-Patchwork-Id: 127508 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:918b:0:b0:3e4:2afc:c1 with SMTP id s11csp330064vqg; Fri, 28 Jul 2023 03:18:05 -0700 (PDT) X-Google-Smtp-Source: APBJJlGQFQ1MYMwIS1tH5O4PnQYcVISmtLK4NytYM6IULJXZl3A2PoGvlYAWd+VvJRDuyMQWm2n3 X-Received: by 2002:a17:906:5349:b0:99b:ef86:60d8 with SMTP id j9-20020a170906534900b0099bef8660d8mr984342ejo.5.1690539485788; Fri, 28 Jul 2023 03:18:05 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1690539485; cv=none; d=google.com; s=arc-20160816; b=SzrCEr+x8iWqVbVABLhZPMKPsYnm5cuadJWjnJ3mbhrIEHWEQ1fvpZpeyG1dsqNzXL Y6gXtybvszZbO37dmzlvn5esldhT1aTdriOiXQmpJqafWyWW5PZncmhm3mmr6h1Y8ltY zgFhufgON6ZIgJlI3mrMJImFABGloe+opOMdV5ZcBaYW1IxW6WmEGZCGI6CBeBgtNoYa 4KLCcV1cLpOYgnGbGBS+ykVGuCArREqW00XdJFXH8HD1AuDVSKEAwvyukfNEoiPyiWhY VDLtkccTqtshkmRc6q1BrS99BSBqb+6SEcilx2zK7jn9BzLVGQ/Zhzv9VuwnBe21+AOk rL0g== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:reply-to:from:list-subscribe:list-help:list-post :list-archive:list-unsubscribe:list-id:precedence :content-transfer-encoding:to:content-language:cc:subject:user-agent :mime-version:date:message-id:dmarc-filter:delivered-to :dkim-signature:dkim-filter; bh=O3mHIfCXhc53okihlbJRDAaBmM6E/kjwWYp0JnesNf0=; fh=RfNrlHQvzmof9NqH9dQWc9AEnQIKqQyorVQkBsH4SEI=; b=r3JmJlltD/wWlVlBi0jGycjXB8RPX7qaVE15OxoyULDJPnriXJPjmhQI5/+TKvmJN2 v3DPaq1AF0QsxpDSc1oum8YyY5H95Ot8sIQ4LmAgUiRcJaSKDpsz+isZH55Dxo12Aymw 8bOAm8LYY5CMTOmBv9Xp8XLfNDFYl0asshWaxtO4B3pZFFnO0py4SdPEVsiYE0kkSaPU nbXUpormlhFXNRLH3QcX1gKk/UrfcXNe/l0hRE0SjrcLsT2wAgpHzC3YgHgxeKmEQgyp tEyo6NE/oFxC+rwWg7ZU+yedyrXeeXFR0ZHVKFyem9W7DLA3mqgzKptGpgKMvczcuT5x oJhw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@gcc.gnu.org header.s=default header.b=J78klJ+L; spf=pass (google.com: domain of gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org designates 2620:52:3:1:0:246e:9693:128c as permitted sender) smtp.mailfrom="gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=gnu.org Received: from server2.sourceware.org (server2.sourceware.org. [2620:52:3:1:0:246e:9693:128c]) by mx.google.com with ESMTPS id q22-20020a17090622d600b0099bd8e4b30esi2640255eja.996.2023.07.28.03.18.05 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 28 Jul 2023 03:18:05 -0700 (PDT) Received-SPF: pass (google.com: domain of gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org designates 2620:52:3:1:0:246e:9693:128c as permitted sender) client-ip=2620:52:3:1:0:246e:9693:128c; Authentication-Results: mx.google.com; dkim=pass header.i=@gcc.gnu.org header.s=default header.b=J78klJ+L; spf=pass (google.com: domain of gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org designates 2620:52:3:1:0:246e:9693:128c as permitted sender) smtp.mailfrom="gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=gnu.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id E265D3854C68 for ; Fri, 28 Jul 2023 10:17:51 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org E265D3854C68 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1690539471; bh=O3mHIfCXhc53okihlbJRDAaBmM6E/kjwWYp0JnesNf0=; h=Date:Subject:Cc:To:List-Id:List-Unsubscribe:List-Archive: List-Post:List-Help:List-Subscribe:From:Reply-To:From; b=J78klJ+Ld0qZ16VLP/CTlbU1qSc32cTde+BR3zLtd0AZKz+wpxJRkvIz6/34nb3PZ CHzMkN3OrPrUDCLuOS3QNBGDsScjbOhnaeP45r3LwkhZ9FDKcz9leon0YLW1H3eKUL HDt2M4Rie7sd/GMkrh5sD23f7bDuZA9fcWs1oDJ0= X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from mail-ej1-x632.google.com (mail-ej1-x632.google.com [IPv6:2a00:1450:4864:20::632]) by sourceware.org (Postfix) with ESMTPS id 8E9FD385AF89 for ; Fri, 28 Jul 2023 10:17:03 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 8E9FD385AF89 Received: by mail-ej1-x632.google.com with SMTP id a640c23a62f3a-992e22c09edso264028866b.2 for ; Fri, 28 Jul 2023 03:17:03 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1690539422; x=1691144222; h=content-transfer-encoding:to:content-language:cc:subject:from :user-agent:mime-version:date:message-id:x-gm-message-state:from:to :cc:subject:date:message-id:reply-to; bh=O3mHIfCXhc53okihlbJRDAaBmM6E/kjwWYp0JnesNf0=; b=MsY5GSOXvSIwAhsQ5HBjclXiALidGIL6a1vEXhz/VeJg+nrzvYwIFUh9uJGDGYPlKv 7JJoKkweqEILs/KZSSKpOF2u8U/S93bPbOcG/3qP9rUpSxANHqme4H7uJKi0yIZYlBWq XJYUDycD7AUWacB9zxOrN21IQasREi1EqPv74f8nwEo9SxQ81m4NvUJl5Qp3lfri1Lcc xe1IHuX+kPnuw/FCty+VzPBSW6fOrxG8wlBxYSMCqMmZ11pSOE/NNUCxXg/M3E5lCY0X G6sq5Sq48KbmHfsaWUZbIKaOLTgqf0i2E4ntFAucyXmPkOhciqDZMHLfmsTegWTi37wy l2pA== X-Gm-Message-State: ABy/qLZ8/LzUA6s79z4EibYhOkyNrl6jfVkJOQkknsjZG37j3DBJHT+L G0tZ8WlPaG3sIzqjnniMlb7XO079fKs5dw== X-Received: by 2002:a17:906:3142:b0:99b:5445:10ca with SMTP id e2-20020a170906314200b0099b544510camr1731925eje.58.1690539421658; Fri, 28 Jul 2023 03:17:01 -0700 (PDT) Received: from [192.168.1.23] (ip-046-005-130-086.um12.pools.vodafone-ip.de. [46.5.130.86]) by smtp.gmail.com with ESMTPSA id s13-20020a1709060c0d00b009930042510csm1857785ejf.222.2023.07.28.03.17.01 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Fri, 28 Jul 2023 03:17:01 -0700 (PDT) Message-ID: <805c3845-09e5-7c92-acee-1c4cf5d81a98@gmail.com> Date: Fri, 28 Jul 2023 12:17:00 +0200 MIME-Version: 1.0 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:102.0) Gecko/20100101 Thunderbird/102.13.0 Subject: [PATCH] gcse: Extract reg pressure handling into separate file. Cc: rdapp.gcc@gmail.com Content-Language: en-US To: gcc-patches X-Spam-Status: No, score=-9.1 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, FREEMAIL_FROM, GIT_PATCH_0, KAM_SHORT, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, 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.29 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Robin Dapp via Gcc-patches From: Robin Dapp Reply-To: Robin Dapp Errors-To: gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org Sender: "Gcc-patches" X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1772659132016031331 X-GMAIL-MSGID: 1772659132016031331 Hi, this patch extracts the hoist-pressure handling from gcse and puts it into a separate file so it can be used by other passes in the future. No functional change and I also abstained from c++ifying the code. The naming with the regpressure_ prefix might be a bit clunky for now and I'm open to a better scheme. Some minor helper functions are added that just encapsulate BB aux data manipulation. All of this is in preparation for fwprop to use register pressure data if needed. Bootstrapped and regtested on x86, aarch64 and power. Regards Robin From 65e69834eeb08ba093786e386ac16797cec4d8a7 Mon Sep 17 00:00:00 2001 From: Robin Dapp Date: Mon, 24 Jul 2023 16:25:38 +0200 Subject: [PATCH] gcse: Extract reg pressure handling into separate file. This patch extracts the hoist-pressure handling from gcse into a separate file so it can be used by other passes in the future. No functional change. gcc/ChangeLog: * Makefile.in: Add regpressure.o. * gcse.cc (struct bb_data): Move to regpressure.cc. (BB_DATA): Ditto. (get_regno_pressure_class): Ditto. (get_pressure_class_and_nregs): Ditto. (record_set_data): Ditto. (update_bb_reg_pressure): Ditto. (should_hoist_expr_to_dom): Ditto. (hoist_code): Ditto. (change_pressure): Ditto. (calculate_bb_reg_pressure): Ditto. (one_code_hoisting_pass): Ditto. * gcse.h (single_set_gcse): Export single_set_gcse. * regpressure.cc: New file. * regpressure.h: New file. --- gcc/Makefile.in | 1 + gcc/gcse.cc | 304 ++---------------------------------- gcc/gcse.h | 2 + gcc/regpressure.cc | 379 +++++++++++++++++++++++++++++++++++++++++++++ gcc/regpressure.h | 46 ++++++ 5 files changed, 445 insertions(+), 287 deletions(-) create mode 100644 gcc/regpressure.cc create mode 100644 gcc/regpressure.h diff --git a/gcc/Makefile.in b/gcc/Makefile.in index 683774ad446..88880a8e23e 100644 --- a/gcc/Makefile.in +++ b/gcc/Makefile.in @@ -1605,6 +1605,7 @@ OBJS = \ reg-stack.o \ regcprop.o \ reginfo.o \ + regpressure.o \ regrename.o \ regstat.o \ reload.o \ diff --git a/gcc/gcse.cc b/gcc/gcse.cc index f689c0c2687..5bafef7970f 100644 --- a/gcc/gcse.cc +++ b/gcc/gcse.cc @@ -160,6 +160,7 @@ along with GCC; see the file COPYING3. If not see #include "gcse.h" #include "gcse-common.h" #include "function-abi.h" +#include "regpressure.h" /* We support GCSE via Partial Redundancy Elimination. PRE optimizations are a superset of those done by classic GCSE. @@ -419,30 +420,6 @@ static bool doing_code_hoisting_p = false; /* For available exprs */ static sbitmap *ae_kill; -/* Data stored for each basic block. */ -struct bb_data -{ - /* Maximal register pressure inside basic block for given register class - (defined only for the pressure classes). */ - int max_reg_pressure[N_REG_CLASSES]; - /* Recorded register pressure of basic block before trying to hoist - an expression. Will be used to restore the register pressure - if the expression should not be hoisted. */ - int old_pressure; - /* Recorded register live_in info of basic block during code hoisting - process. BACKUP is used to record live_in info before trying to - hoist an expression, and will be used to restore LIVE_IN if the - expression should not be hoisted. */ - bitmap live_in, backup; -}; - -#define BB_DATA(bb) ((struct bb_data *) (bb)->aux) - -static basic_block curr_bb; - -/* Current register pressure for each pressure class. */ -static int curr_reg_pressure[N_REG_CLASSES]; - static void compute_can_copy (void); static void *gmalloc (size_t) ATTRIBUTE_MALLOC; @@ -494,8 +471,6 @@ static bool should_hoist_expr_to_dom (basic_block, struct gcse_expr *, enum reg_class, int *, bitmap, rtx_insn *); static bool hoist_code (void); -static enum reg_class get_regno_pressure_class (int regno, int *nregs); -static enum reg_class get_pressure_class_and_nregs (rtx_insn *insn, int *nregs); static bool one_code_hoisting_pass (void); static rtx_insn *process_insert_insn (struct gcse_expr *); static bool pre_edge_insert (struct edge_list *, struct gcse_expr **); @@ -2402,7 +2377,7 @@ record_set_data (rtx dest, const_rtx set, void *data) } } -static const_rtx +const_rtx single_set_gcse (rtx_insn *insn) { struct set_data s; @@ -2804,72 +2779,6 @@ compute_code_hoist_data (void) fprintf (dump_file, "\n"); } -/* Update register pressure for BB when hoisting an expression from - instruction FROM, if live ranges of inputs are shrunk. Also - maintain live_in information if live range of register referred - in FROM is shrunk. - - Return 0 if register pressure doesn't change, otherwise return - the number by which register pressure is decreased. - - NOTE: Register pressure won't be increased in this function. */ - -static int -update_bb_reg_pressure (basic_block bb, rtx_insn *from) -{ - rtx dreg; - rtx_insn *insn; - basic_block succ_bb; - df_ref use, op_ref; - edge succ; - edge_iterator ei; - int decreased_pressure = 0; - int nregs; - enum reg_class pressure_class; - - FOR_EACH_INSN_USE (use, from) - { - dreg = DF_REF_REAL_REG (use); - /* The live range of register is shrunk only if it isn't: - 1. referred on any path from the end of this block to EXIT, or - 2. referred by insns other than FROM in this block. */ - FOR_EACH_EDGE (succ, ei, bb->succs) - { - succ_bb = succ->dest; - if (succ_bb == EXIT_BLOCK_PTR_FOR_FN (cfun)) - continue; - - if (bitmap_bit_p (BB_DATA (succ_bb)->live_in, REGNO (dreg))) - break; - } - if (succ != NULL) - continue; - - op_ref = DF_REG_USE_CHAIN (REGNO (dreg)); - for (; op_ref; op_ref = DF_REF_NEXT_REG (op_ref)) - { - if (!DF_REF_INSN_INFO (op_ref)) - continue; - - insn = DF_REF_INSN (op_ref); - if (BLOCK_FOR_INSN (insn) == bb - && NONDEBUG_INSN_P (insn) && insn != from) - break; - } - - pressure_class = get_regno_pressure_class (REGNO (dreg), &nregs); - /* Decrease register pressure and update live_in information for - this block. */ - if (!op_ref && pressure_class != NO_REGS) - { - decreased_pressure += nregs; - BB_DATA (bb)->max_reg_pressure[pressure_class] -= nregs; - bitmap_clear_bit (BB_DATA (bb)->live_in, REGNO (dreg)); - } - } - return decreased_pressure; -} - /* Determine if the expression EXPR should be hoisted to EXPR_BB up in flow graph, if it can reach BB unimpared. Stop the search if the expression would need to be moved more than DISTANCE instructions. @@ -2917,12 +2826,9 @@ should_hoist_expr_to_dom (basic_block expr_bb, struct gcse_expr *expr, /* Record old information of basic block BB when it is visited at the first time. */ if (!bitmap_bit_p (hoisted_bbs, bb->index)) - { - struct bb_data *data = BB_DATA (bb); - bitmap_copy (data->backup, data->live_in); - data->old_pressure = data->max_reg_pressure[pressure_class]; - } - decreased_pressure = update_bb_reg_pressure (bb, from); + regpressure_init_bb_info (bb, pressure_class); + + decreased_pressure = regpressure_update_bb_reg_pressure (bb, from); } /* Terminate the search if distance, for which EXPR is allowed to move, is exhausted. */ @@ -2945,8 +2851,7 @@ should_hoist_expr_to_dom (basic_block expr_bb, struct gcse_expr *expr, on ARM target, while it has no obvious effect on other targets like x86, x86_64, mips and powerpc. */ else if (CONST_INT_P (expr->expr) - || (BB_DATA (bb)->max_reg_pressure[pressure_class] - >= ira_class_hard_regs_num[pressure_class] + || (!regpressure_viable (bb, pressure_class) && decreased_pressure < *nregs)) distance -= bb_size[bb->index]; } @@ -3073,7 +2978,6 @@ hoist_code (void) int *to_bb_head; int *bb_size; bool changed = false; - struct bb_data *data; /* Basic blocks that have occurrences reachable from BB. */ bitmap from_bbs; /* Basic blocks through which expr is hoisted. */ @@ -3206,8 +3110,9 @@ hoist_code (void) max_distance += (bb_size[dominated->index] - to_bb_head[INSN_UID (occr->insn)]); - pressure_class = get_pressure_class_and_nregs (occr->insn, - &nregs); + pressure_class = + regpressure_get_pressure_class_and_nregs (occr->insn, + &nregs); /* Note if the expression should be hoisted from the dominated block to BB if it can reach DOMINATED unimpared. @@ -3262,13 +3167,11 @@ hoist_code (void) /* Increase register pressure of basic blocks to which expr is hoisted because of extended live range of output. */ - data = BB_DATA (bb); - data->max_reg_pressure[pressure_class] += nregs; + regpressure_increase (bb, pressure_class, nregs); + EXECUTE_IF_SET_IN_BITMAP (hoisted_bbs, 0, k, bi) - { - data = BB_DATA (BASIC_BLOCK_FOR_FN (cfun, k)); - data->max_reg_pressure[pressure_class] += nregs; - } + regpressure_increase (BASIC_BLOCK_FOR_FN (cfun, k), + pressure_class, nregs); } else if (flag_ira_hoist_pressure) { @@ -3276,12 +3179,8 @@ hoist_code (void) blocks recorded in hoisted_bbs when expr will not be hoisted. */ EXECUTE_IF_SET_IN_BITMAP (hoisted_bbs, 0, k, bi) - { - data = BB_DATA (BASIC_BLOCK_FOR_FN (cfun, k)); - bitmap_copy (data->live_in, data->backup); - data->max_reg_pressure[pressure_class] - = data->old_pressure; - } + regpressure_reset (BASIC_BLOCK_FOR_FN (cfun, k), + pressure_class); } if (flag_ira_hoist_pressure) @@ -3343,166 +3242,6 @@ hoist_code (void) return changed; } -/* Return pressure class and number of needed hard registers (through - *NREGS) of register REGNO. */ -static enum reg_class -get_regno_pressure_class (int regno, int *nregs) -{ - if (regno >= FIRST_PSEUDO_REGISTER) - { - enum reg_class pressure_class; - - pressure_class = reg_allocno_class (regno); - pressure_class = ira_pressure_class_translate[pressure_class]; - *nregs - = ira_reg_class_max_nregs[pressure_class][PSEUDO_REGNO_MODE (regno)]; - return pressure_class; - } - else if (! TEST_HARD_REG_BIT (ira_no_alloc_regs, regno) - && ! TEST_HARD_REG_BIT (eliminable_regset, regno)) - { - *nregs = 1; - return ira_pressure_class_translate[REGNO_REG_CLASS (regno)]; - } - else - { - *nregs = 0; - return NO_REGS; - } -} - -/* Return pressure class and number of hard registers (through *NREGS) - for destination of INSN. */ -static enum reg_class -get_pressure_class_and_nregs (rtx_insn *insn, int *nregs) -{ - rtx reg; - enum reg_class pressure_class; - const_rtx set = single_set_gcse (insn); - - reg = SET_DEST (set); - if (GET_CODE (reg) == SUBREG) - reg = SUBREG_REG (reg); - if (MEM_P (reg)) - { - *nregs = 0; - pressure_class = NO_REGS; - } - else - { - gcc_assert (REG_P (reg)); - pressure_class = reg_allocno_class (REGNO (reg)); - pressure_class = ira_pressure_class_translate[pressure_class]; - *nregs - = ira_reg_class_max_nregs[pressure_class][GET_MODE (SET_SRC (set))]; - } - return pressure_class; -} - -/* Increase (if INCR_P) or decrease current register pressure for - register REGNO. */ -static void -change_pressure (int regno, bool incr_p) -{ - int nregs; - enum reg_class pressure_class; - - pressure_class = get_regno_pressure_class (regno, &nregs); - if (! incr_p) - curr_reg_pressure[pressure_class] -= nregs; - else - { - curr_reg_pressure[pressure_class] += nregs; - if (BB_DATA (curr_bb)->max_reg_pressure[pressure_class] - < curr_reg_pressure[pressure_class]) - BB_DATA (curr_bb)->max_reg_pressure[pressure_class] - = curr_reg_pressure[pressure_class]; - } -} - -/* Calculate register pressure for each basic block by walking insns - from last to first. */ -static void -calculate_bb_reg_pressure (void) -{ - int i; - unsigned int j; - rtx_insn *insn; - basic_block bb; - bitmap curr_regs_live; - bitmap_iterator bi; - - - ira_setup_eliminable_regset (); - curr_regs_live = BITMAP_ALLOC (®_obstack); - FOR_EACH_BB_FN (bb, cfun) - { - curr_bb = bb; - BB_DATA (bb)->live_in = BITMAP_ALLOC (NULL); - BB_DATA (bb)->backup = BITMAP_ALLOC (NULL); - bitmap_copy (BB_DATA (bb)->live_in, df_get_live_in (bb)); - bitmap_copy (curr_regs_live, df_get_live_out (bb)); - for (i = 0; i < ira_pressure_classes_num; i++) - curr_reg_pressure[ira_pressure_classes[i]] = 0; - EXECUTE_IF_SET_IN_BITMAP (curr_regs_live, 0, j, bi) - change_pressure (j, true); - - FOR_BB_INSNS_REVERSE (bb, insn) - { - rtx dreg; - int regno; - df_ref def, use; - - if (! NONDEBUG_INSN_P (insn)) - continue; - - FOR_EACH_INSN_DEF (def, insn) - { - dreg = DF_REF_REAL_REG (def); - gcc_assert (REG_P (dreg)); - regno = REGNO (dreg); - if (!(DF_REF_FLAGS (def) - & (DF_REF_PARTIAL | DF_REF_CONDITIONAL))) - { - if (bitmap_clear_bit (curr_regs_live, regno)) - change_pressure (regno, false); - } - } - - FOR_EACH_INSN_USE (use, insn) - { - dreg = DF_REF_REAL_REG (use); - gcc_assert (REG_P (dreg)); - regno = REGNO (dreg); - if (bitmap_set_bit (curr_regs_live, regno)) - change_pressure (regno, true); - } - } - } - BITMAP_FREE (curr_regs_live); - - if (dump_file == NULL) - return; - - fprintf (dump_file, "\nRegister Pressure: \n"); - FOR_EACH_BB_FN (bb, cfun) - { - fprintf (dump_file, " Basic block %d: \n", bb->index); - for (i = 0; (int) i < ira_pressure_classes_num; i++) - { - enum reg_class pressure_class; - - pressure_class = ira_pressure_classes[i]; - if (BB_DATA (bb)->max_reg_pressure[pressure_class] == 0) - continue; - - fprintf (dump_file, " %s=%d\n", reg_class_names[pressure_class], - BB_DATA (bb)->max_reg_pressure[pressure_class]); - } - } - fprintf (dump_file, "\n"); -} - /* Top level routine to perform one code hoisting (aka unification) pass Return true if a change was made. */ @@ -3524,13 +3263,7 @@ one_code_hoisting_pass (void) /* Calculate register pressure for each basic block. */ if (flag_ira_hoist_pressure) - { - regstat_init_n_sets_and_refs (); - ira_set_pseudo_classes (false, dump_file); - alloc_aux_for_blocks (sizeof (struct bb_data)); - calculate_bb_reg_pressure (); - regstat_free_n_sets_and_refs (); - } + regpressure_init (); /* We need alias. */ init_alias_analysis (); @@ -3554,10 +3287,7 @@ one_code_hoisting_pass (void) } if (flag_ira_hoist_pressure) - { - free_aux_for_blocks (); - free_reg_info (); - } + regpressure_cleanup (); free_hash_table (&expr_hash_table); free_gcse_mem (); obstack_free (&gcse_obstack, NULL); diff --git a/gcc/gcse.h b/gcc/gcse.h index e68afdcea21..1162086570d 100644 --- a/gcc/gcse.h +++ b/gcc/gcse.h @@ -43,4 +43,6 @@ void gcse_cc_finalize (void); extern bool gcse_or_cprop_is_too_expensive (const char *); extern rtx_insn *insert_insn_end_basic_block (rtx_insn *, basic_block); +const_rtx single_set_gcse (rtx_insn *insn); + #endif diff --git a/gcc/regpressure.cc b/gcc/regpressure.cc new file mode 100644 index 00000000000..1c967528b04 --- /dev/null +++ b/gcc/regpressure.cc @@ -0,0 +1,379 @@ +/* Register pressure helper functions. + Copyright (C) 2023 Free Software Foundation, Inc. + +This file is part of GCC. + +GCC is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free +Software Foundation; either version 3, or (at your option) any later +version. + +GCC is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with GCC; see the file COPYING3. If not see +. */ + +#include "config.h" +#include "system.h" +#include "coretypes.h" +#include "backend.h" +#include "target.h" +#include "rtl.h" +#include "df.h" +#include "memmodel.h" +#include "tm_p.h" +#include "regs.h" +#include "ira.h" +#include "gcse.h" +#include "gcse-common.h" +#include "regpressure.h" + +struct bb_data +{ + /* Maximal register pressure inside basic block for given register class + (defined only for the pressure classes). */ + int max_reg_pressure[N_REG_CLASSES]; + /* Recorded register pressure of basic block before trying to hoist + an expression. Will be used to restore the register pressure + if the expression should not be hoisted. */ + int old_pressure; + /* Recorded register live_in info of basic block during code hoisting + process. BACKUP is used to record live_in info before trying to + hoist an expression, and will be used to restore LIVE_IN if the + expression should not be hoisted. */ + bitmap live_in, backup; +}; + +#define BB_DATA(bb) ((struct bb_data *) (bb)->aux) + +static basic_block curr_bb; + +/* Current register pressure for each pressure class. */ +static int curr_reg_pressure[N_REG_CLASSES]; + +/* Update register pressure for BB when hoisting an expression from + instruction FROM, if live ranges of inputs are shrunk. Also + maintain live_in information if live range of register referred + in FROM is shrunk. + + Return 0 if register pressure doesn't change, otherwise return + the number by which register pressure is decreased. + + NOTE: Register pressure won't be increased in this function. */ + +int +regpressure_update_bb_reg_pressure (basic_block bb, rtx_insn *from) +{ + rtx dreg; + rtx_insn *insn; + basic_block succ_bb; + df_ref use, op_ref; + edge succ; + edge_iterator ei; + int decreased_pressure = 0; + int nregs; + enum reg_class pressure_class; + + FOR_EACH_INSN_USE (use, from) + { + dreg = DF_REF_REAL_REG (use); + /* The live range of register is shrunk only if it isn't: + 1. referred on any path from the end of this block to EXIT, or + 2. referred by insns other than FROM in this block. */ + FOR_EACH_EDGE (succ, ei, bb->succs) + { + succ_bb = succ->dest; + if (succ_bb == EXIT_BLOCK_PTR_FOR_FN (cfun)) + continue; + + if (regpressure_is_live (succ_bb, REGNO (dreg))) + break; + } + if (succ != NULL) + continue; + + op_ref = DF_REG_USE_CHAIN (REGNO (dreg)); + for (; op_ref; op_ref = DF_REF_NEXT_REG (op_ref)) + { + if (!DF_REF_INSN_INFO (op_ref)) + continue; + + insn = DF_REF_INSN (op_ref); + if (BLOCK_FOR_INSN (insn) == bb && NONDEBUG_INSN_P (insn) + && insn != from) + break; + } + + pressure_class + = regpressure_get_regno_pressure_class (REGNO (dreg), &nregs); + /* Decrease register pressure and update live_in information for + this block. */ + if (!op_ref && pressure_class != NO_REGS) + { + decreased_pressure += nregs; + BB_DATA (bb)->max_reg_pressure[pressure_class] -= nregs; + bitmap_clear_bit (BB_DATA (bb)->live_in, REGNO (dreg)); + } + } + return decreased_pressure; +} + +/* Increase (if INCR_P) or decrease current register pressure for + register REGNO. */ +static void +change_pressure (int regno, bool incr_p) +{ + int nregs; + enum reg_class pressure_class; + + pressure_class = regpressure_get_regno_pressure_class (regno, &nregs); + if (!incr_p) + curr_reg_pressure[pressure_class] -= nregs; + else + { + curr_reg_pressure[pressure_class] += nregs; + if (BB_DATA (curr_bb)->max_reg_pressure[pressure_class] + < curr_reg_pressure[pressure_class]) + BB_DATA (curr_bb)->max_reg_pressure[pressure_class] + = curr_reg_pressure[pressure_class]; + } +} + +/* Calculate register pressure for each basic block by walking insns + from last to first. */ +static void +calculate_bb_reg_pressure (void) +{ + int i; + unsigned int j; + rtx_insn *insn; + basic_block bb; + bitmap curr_regs_live; + bitmap_iterator bi; + + ira_setup_eliminable_regset (); + curr_regs_live = BITMAP_ALLOC (®_obstack); + FOR_EACH_BB_FN (bb, cfun) + { + curr_bb = bb; + BB_DATA (bb)->live_in = BITMAP_ALLOC (NULL); + BB_DATA (bb)->backup = BITMAP_ALLOC (NULL); + bitmap_copy (BB_DATA (bb)->live_in, df_get_live_in (bb)); + bitmap_copy (curr_regs_live, df_get_live_out (bb)); + for (i = 0; i < ira_pressure_classes_num; i++) + curr_reg_pressure[ira_pressure_classes[i]] = 0; + EXECUTE_IF_SET_IN_BITMAP (curr_regs_live, 0, j, bi) + change_pressure (j, true); + + FOR_BB_INSNS_REVERSE (bb, insn) + { + rtx dreg; + int regno; + df_ref def, use; + + if (!NONDEBUG_INSN_P (insn)) + continue; + + FOR_EACH_INSN_DEF (def, insn) + { + dreg = DF_REF_REAL_REG (def); + gcc_assert (REG_P (dreg)); + regno = REGNO (dreg); + if (!(DF_REF_FLAGS (def) & (DF_REF_PARTIAL | DF_REF_CONDITIONAL))) + { + if (bitmap_clear_bit (curr_regs_live, regno)) + change_pressure (regno, false); + } + } + + FOR_EACH_INSN_USE (use, insn) + { + dreg = DF_REF_REAL_REG (use); + gcc_assert (REG_P (dreg)); + regno = REGNO (dreg); + if (bitmap_set_bit (curr_regs_live, regno)) + change_pressure (regno, true); + } + } + } + BITMAP_FREE (curr_regs_live); + + if (dump_file == NULL) + return; + + fprintf (dump_file, "\nRegister Pressure: \n"); + FOR_EACH_BB_FN (bb, cfun) + { + fprintf (dump_file, " Basic block %d: \n", bb->index); + for (i = 0; (int) i < ira_pressure_classes_num; i++) + { + enum reg_class pressure_class; + + pressure_class = ira_pressure_classes[i]; + if (BB_DATA (bb)->max_reg_pressure[pressure_class] == 0) + continue; + + fprintf (dump_file, " %s=%d\n", reg_class_names[pressure_class], + BB_DATA (bb)->max_reg_pressure[pressure_class]); + } + } + fprintf (dump_file, "\n"); +} + +/* Initialized needed resources for register pressure calculation. */ +void +regpressure_init () +{ + if (flag_ira_hoist_pressure) + { + regstat_init_n_sets_and_refs (); + ira_set_pseudo_classes (false, dump_file); + alloc_aux_for_blocks (sizeof (struct bb_data)); + calculate_bb_reg_pressure (); + regstat_free_n_sets_and_refs (); + } +} + +/* Free up all initialized resources. */ +void +regpressure_cleanup () +{ + if (flag_ira_hoist_pressure) + { + free_aux_for_blocks (); + free_reg_info (); + } +} + +/* Initialize aux data for BB regarding PRESSURE_CLASS. */ +void +regpressure_init_bb_info (basic_block bb, enum reg_class pressure_class) +{ + /* Record old information of basic block BB when it is visited + at the first time. */ + struct bb_data *data = BB_DATA (bb); + bitmap_copy (data->backup, data->live_in); + data->old_pressure = data->max_reg_pressure[pressure_class]; +} + +/* Increase PRESSURE_CLASS's register pressure in BB by NREGS. */ +void +regpressure_increase (basic_block bb, enum reg_class pressure_class, int nregs) +{ + struct bb_data *data = BB_DATA (bb); + data->max_reg_pressure[pressure_class] += nregs; +} + +/* Decrease PRESSURE_CLASS's register pressure in BB by NREGS. */ +void +regpressure_decrease (basic_block bb, enum reg_class pressure_class, int nregs) +{ + struct bb_data *data = BB_DATA (bb); + data->max_reg_pressure[pressure_class] -= nregs; +} + +/* Reset PRESSURE_CLASS's register pressure in BB to its initial value. */ +void +regpressure_reset (basic_block bb, enum reg_class pressure_class) +{ + struct bb_data *data = BB_DATA (bb); + bitmap_copy (data->live_in, data->backup); + data->max_reg_pressure[pressure_class] = data->old_pressure; +} + +/* Return TRUE if the current register pressure of PRESSURE_CLASS in BB + is less than the number of hard regs. */ +bool +regpressure_viable (basic_block bb, enum reg_class pressure_class) +{ + return (BB_DATA (bb)->max_reg_pressure[pressure_class] + < ira_class_hard_regs_num[pressure_class]); +} + +/* Return pressure class and number of needed hard registers (through + *NREGS) of register REGNO. */ +enum reg_class +regpressure_get_regno_pressure_class (int regno, int *nregs) +{ + if (regno >= FIRST_PSEUDO_REGISTER) + { + enum reg_class pressure_class; + + pressure_class = reg_allocno_class (regno); + pressure_class = ira_pressure_class_translate[pressure_class]; + *nregs + = ira_reg_class_max_nregs[pressure_class][PSEUDO_REGNO_MODE (regno)]; + return pressure_class; + } + else if (!TEST_HARD_REG_BIT (ira_no_alloc_regs, regno) + && !TEST_HARD_REG_BIT (eliminable_regset, regno)) + { + *nregs = 1; + return ira_pressure_class_translate[REGNO_REG_CLASS (regno)]; + } + else + { + *nregs = 0; + return NO_REGS; + } +} + +/* Return pressure class and number of hard registers (through *NREGS) + for destination of INSN. */ +enum reg_class +regpressure_get_pressure_class_and_nregs (rtx_insn *insn, int *nregs) +{ + rtx reg; + enum reg_class pressure_class; + const_rtx set = single_set_gcse (insn); + + reg = SET_DEST (set); + if (GET_CODE (reg) == SUBREG) + reg = SUBREG_REG (reg); + if (MEM_P (reg)) + { + *nregs = 0; + pressure_class = NO_REGS; + } + else + { + gcc_assert (REG_P (reg)); + pressure_class = reg_allocno_class (REGNO (reg)); + pressure_class = ira_pressure_class_translate[pressure_class]; + *nregs + = ira_reg_class_max_nregs[pressure_class][GET_MODE (SET_SRC (set))]; + } + return pressure_class; +} + +/* Return TRUE if REGNO is live in BB. */ +bool +regpressure_is_live (basic_block bb, int regno) +{ + return bitmap_bit_p (BB_DATA (bb)->live_in, regno); +} + +/* Clear the live bit for REGNO in BB. */ +void +regpressure_clear_live (basic_block bb, int regno) +{ + bitmap_clear_bit (BB_DATA (bb)->live_in, regno); +} + +/* Set the live bit for REGNO in BB. */ +void +regpressure_set_live (basic_block bb, int regno) +{ + bitmap_set_bit (BB_DATA (bb)->live_in, regno); +} + +/* Returns the register pressure for PRESSURE_CLASS in BB. */ +int +regpressure_get (basic_block bb, enum reg_class pressure_class) +{ + return BB_DATA (bb)->max_reg_pressure[pressure_class]; +} diff --git a/gcc/regpressure.h b/gcc/regpressure.h new file mode 100644 index 00000000000..e987d3c7bfe --- /dev/null +++ b/gcc/regpressure.h @@ -0,0 +1,46 @@ +/* Register pressure helper functions. + Copyright (C) 2023 Free Software Foundation, Inc. + +This file is part of GCC. + +GCC is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free +Software Foundation; either version 3, or (at your option) any later +version. + +GCC is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with GCC; see the file COPYING3. If not see +. */ + +#ifndef GCC_REGPRESSURE_H +#define GCC_REGPRESSURE_H + +int regpressure_update_bb_reg_pressure (basic_block bb, rtx_insn *from); + +void regpressure_init (); +void regpressure_cleanup (); + +void regpressure_init_bb_info (basic_block bb, enum reg_class pressure_class); + +void regpressure_increase (basic_block bb, enum reg_class pressure_class, int nregs); +void regpressure_decrease (basic_block bb, enum reg_class pressure_class, int nregs); + +int regpressure_get (basic_block bb, enum reg_class pressure_class); + +bool regpressure_is_live (basic_block bb, int regno); +void regpressure_clear_live (basic_block bb, int regno); +void regpressure_set_live (basic_block bb, int regno); + +void regpressure_reset (basic_block bb, enum reg_class pressure_class); + +bool regpressure_viable (basic_block bb, enum reg_class pressure_class); + +enum reg_class regpressure_get_regno_pressure_class (int regno, int *nregs); +enum reg_class regpressure_get_pressure_class_and_nregs (rtx_insn *insn, int *nregs); + +#endif