From patchwork Wed Sep 11 19:18:08 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Sandiford X-Patchwork-Id: 1161266 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=gcc.gnu.org (client-ip=209.132.180.131; helo=sourceware.org; envelope-from=gcc-patches-return-508920-incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=arm.com Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b="kzenp/c1"; dkim-atps=neutral Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 46TBWg4BNmz9s7T for ; Thu, 12 Sep 2019 05:18:21 +1000 (AEST) DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:from :to:subject:references:date:in-reply-to:message-id:mime-version :content-type; q=dns; s=default; b=RxvglAouAyiO1kObiwV6WjAPFSt4f 7PkbcxRLNFVlSb7VKvTO+q36wC0JManH5jqve6FDbzvLozSsQPWniLsZS2pEglEY gH5aZjpPLqyygJoMzdEhLnr/eX9yZyf1yyGCnf3jUGt/MWOTMKUHwn6zAgxV2ts8 iEUHc+pyvsKmVw= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:from :to:subject:references:date:in-reply-to:message-id:mime-version :content-type; s=default; bh=EtP6165vxi60xzkwBL37kpHZSx8=; b=kze np/c1xkgM1crLIzCp7fHsWK9ukGzcXZmAll9G0SwvUhMHjbI+ccCbiUt1hDJpVYo caOltMh/9qjzAggdBH91/IqgzH8uzJzqDqfcJ4q5Ttx8+9Dd/eroZjXLu3iWlPpM hAgbAj6R5Yv7KqOxPPk+2hTELjsOidCm3lqoAj6o= Received: (qmail 101637 invoked by alias); 11 Sep 2019 19:18:14 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Received: (qmail 101478 invoked by uid 89); 11 Sep 2019 19:18:14 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-8.9 required=5.0 tests=AWL, BAYES_00, GIT_PATCH_2, GIT_PATCH_3, KAM_ASCII_DIVIDERS, SPF_PASS autolearn=ham version=3.3.1 spammy=3258, accordance, sk:sched_a, selschedirc X-HELO: foss.arm.com Received: from foss.arm.com (HELO foss.arm.com) (217.140.110.172) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Wed, 11 Sep 2019 19:18:11 +0000 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 36CF11000 for ; Wed, 11 Sep 2019 12:18:10 -0700 (PDT) Received: from localhost (e121540-lin.manchester.arm.com [10.32.99.62]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id D2A503F59C for ; Wed, 11 Sep 2019 12:18:09 -0700 (PDT) From: Richard Sandiford To: gcc-patches@gcc.gnu.org Mail-Followup-To: gcc-patches@gcc.gnu.org, richard.sandiford@arm.com Subject: [30/32] Remove global call sets: sel-sched.c References: Date: Wed, 11 Sep 2019 20:18:08 +0100 In-Reply-To: (Richard Sandiford's message of "Wed, 11 Sep 2019 20:02:26 +0100") Message-ID: User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/26.1 (gnu/linux) MIME-Version: 1.0 X-IsSubscribed: yes The main change here is to replace a crosses_call boolean with a bitmask of the ABIs used by the crossed calls. For space reasons, I didn't also add a HARD_REG_SET that tracks the set of registers that are actually clobbered, which means that this is the one part of the series that doesn't benefit from -fipa-ra. The existing FIXME suggests that the current structures aren't the preferred way of representing this anyhow, and the pass already makes conservative assumptions about call-crossing registers. 2019-09-11 Richard Sandiford gcc/ * sel-sched-ir.h (_def::crosses_call): Replace with... (_def::crossed_call_abis): ..this new field. (def_list_add): Take a mask of ABIs instead of a crosses_call boolean. * sel-sched-ir.c (def_list_add): Likewise. Update initialization of _def accordingly. * sel-sched.c: Include function-abi.h. (hard_regs_data::regs_for_call_clobbered): Delete. (reg_rename::crosses_call): Replace with... (reg_rename::crossed_call_abis): ...this new field. (fur_static_params::crosses_call): Replace with... (fur_static_params::crossed_call_abis): ...this new field. (init_regs_for_mode): Don't initialize sel_hrd.regs_for_call_clobbered. (init_hard_regs_data): Use crtl->abi to test which registers the current function would need to save before it uses them. (mark_unavailable_hard_regs): Update handling of call-clobbered registers, using call_clobbers_in_region to find out which registers might be call-clobbered (but without taking -fipa-ra into account for now). Remove separate handling of partially call-clobbered registers. (verify_target_availability): Use crossed_call_abis instead of crosses_call. (get_spec_check_type_for_insn, find_used_regs): Likewise. (fur_orig_expr_found, fur_on_enter, fur_orig_expr_not_found): Likewise. Index: gcc/sel-sched-ir.h =================================================================== --- gcc/sel-sched-ir.h 2019-07-10 19:41:26.359898316 +0100 +++ gcc/sel-sched-ir.h 2019-09-11 19:49:11.673506894 +0100 @@ -188,12 +188,12 @@ struct _def { insn_t orig_insn; - /* FIXME: Get rid of CROSSES_CALL in each def, since if we're moving up + /* FIXME: Get rid of CROSSED_CALL_ABIS in each def, since if we're moving up rhs from two different places, but only one of the code motion paths crosses a call, we can't use any of the call_used_regs, no matter which - path or whether all paths crosses a call. Thus we should move CROSSES_CALL - to static params. */ - bool crosses_call; + path or whether all paths crosses a call. Thus we should move + CROSSED_CALL_ABIS to static params. */ + unsigned int crossed_call_abis; }; typedef struct _def *def_t; @@ -1510,7 +1510,7 @@ extern void flist_tail_init (flist_tail_ extern fence_t flist_lookup (flist_t, insn_t); extern void flist_clear (flist_t *); -extern void def_list_add (def_list_t *, insn_t, bool); +extern void def_list_add (def_list_t *, insn_t, unsigned int); /* Target context functions. */ extern tc_t create_target_context (bool); Index: gcc/sel-sched-ir.c =================================================================== --- gcc/sel-sched-ir.c 2019-09-09 19:01:40.375078244 +0100 +++ gcc/sel-sched-ir.c 2019-09-11 19:49:11.673506894 +0100 @@ -311,9 +311,10 @@ flist_clear (flist_t *lp) flist_remove (lp); } -/* Add ORIGINAL_INSN the def list DL honoring CROSSES_CALL. */ +/* Add ORIGINAL_INSN the def list DL honoring CROSSED_CALL_ABIS. */ void -def_list_add (def_list_t *dl, insn_t original_insn, bool crosses_call) +def_list_add (def_list_t *dl, insn_t original_insn, + unsigned int crossed_call_abis) { def_t d; @@ -321,7 +322,7 @@ def_list_add (def_list_t *dl, insn_t ori d = DEF_LIST_DEF (*dl); d->orig_insn = original_insn; - d->crosses_call = crosses_call; + d->crossed_call_abis = crossed_call_abis; } Index: gcc/sel-sched.c =================================================================== --- gcc/sel-sched.c 2019-09-11 19:47:32.902202887 +0100 +++ gcc/sel-sched.c 2019-09-11 19:49:11.673506894 +0100 @@ -46,6 +46,7 @@ Software Foundation; either version 3, o #include "sel-sched-dump.h" #include "sel-sched.h" #include "dbgcnt.h" +#include "function-abi.h" /* Implementation of selective scheduling approach. The below implementation follows the original approach with the following @@ -302,10 +303,6 @@ struct hard_regs_data that the whole set is not computed yet. */ HARD_REG_SET regs_for_rename[FIRST_PSEUDO_REGISTER]; - /* For every mode, this stores registers not available due to - call clobbering. */ - HARD_REG_SET regs_for_call_clobbered[NUM_MACHINE_MODES]; - /* All registers that are used or call used. */ HARD_REG_SET regs_ever_used; @@ -325,8 +322,8 @@ struct reg_rename /* These are *available* for renaming. */ HARD_REG_SET available_for_renaming; - /* Whether this code motion path crosses a call. */ - bool crosses_call; + /* The set of ABIs used by calls that the code motion path crosses. */ + unsigned int crossed_call_abis : NUM_ABI_IDS; }; /* A global structure that contains the needed information about harg @@ -390,8 +387,8 @@ struct fur_static_params /* Pointer to the list of original insns definitions. */ def_list_t *original_insns; - /* True if a code motion path contains a CALL insn. */ - bool crosses_call; + /* The set of ABIs used by calls that the code motion path crosses. */ + unsigned int crossed_call_abis : NUM_ABI_IDS; }; typedef struct fur_static_params *fur_static_params_p; @@ -1067,7 +1064,6 @@ init_regs_for_mode (machine_mode mode) int cur_reg; CLEAR_HARD_REG_SET (sel_hrd.regs_for_mode[mode]); - CLEAR_HARD_REG_SET (sel_hrd.regs_for_call_clobbered[mode]); for (cur_reg = 0; cur_reg < FIRST_PSEUDO_REGISTER; cur_reg++) { @@ -1102,10 +1098,6 @@ init_regs_for_mode (machine_mode mode) if (i >= 0) continue; - if (targetm.hard_regno_call_part_clobbered (0, cur_reg, mode)) - SET_HARD_REG_BIT (sel_hrd.regs_for_call_clobbered[mode], - cur_reg); - /* If the CUR_REG passed all the checks above, then it's ok. */ SET_HARD_REG_BIT (sel_hrd.regs_for_mode[mode], cur_reg); @@ -1123,7 +1115,8 @@ init_hard_regs_data (void) CLEAR_HARD_REG_SET (sel_hrd.regs_ever_used); for (cur_reg = 0; cur_reg < FIRST_PSEUDO_REGISTER; cur_reg++) - if (df_regs_ever_live_p (cur_reg) || call_used_or_fixed_reg_p (cur_reg)) + if (df_regs_ever_live_p (cur_reg) + || crtl->abi->clobbers_full_reg_p (cur_reg)) SET_HARD_REG_BIT (sel_hrd.regs_ever_used, cur_reg); /* Initialize registers that are valid based on mode when this is @@ -1193,7 +1186,7 @@ mark_unavailable_hard_regs (def_t def, s SET_HARD_REG_SET (reg_rename_p->unavailable_hard_regs); /* Give a chance for original register, if it isn't in used_regs. */ - if (!def->crosses_call) + if (!def->crossed_call_abis) CLEAR_HARD_REG_BIT (reg_rename_p->unavailable_hard_regs, regno); return; @@ -1224,13 +1217,20 @@ mark_unavailable_hard_regs (def_t def, s reg_rename_p->unavailable_hard_regs |= sel_hrd.stack_regs; #endif - /* If there's a call on this path, make regs from call_used_or_fixed_regs - unavailable. */ - if (def->crosses_call) - reg_rename_p->unavailable_hard_regs |= call_used_or_fixed_regs; + mode = GET_MODE (orig_dest); + + /* If there's a call on this path, make regs from full_reg_clobbers + unavailable. - /* Stop here before reload: we need FRAME_REGS, STACK_REGS, and crosses_call, - but not register classes. */ + ??? It would be better to track the set of clobbered registers + directly, but that would be quite expensive in a def_t. */ + if (def->crossed_call_abis) + reg_rename_p->unavailable_hard_regs + |= call_clobbers_in_region (def->crossed_call_abis, + reg_class_contents[ALL_REGS], mode); + + /* Stop here before reload: we need FRAME_REGS, STACK_REGS, and + crossed_call_abis, but not register classes. */ if (!reload_completed) return; @@ -1238,19 +1238,11 @@ mark_unavailable_hard_regs (def_t def, s register class. */ reg_rename_p->available_for_renaming = reg_class_contents[cl]; - mode = GET_MODE (orig_dest); - /* Leave only registers available for this mode. */ if (!sel_hrd.regs_for_mode_ok[mode]) init_regs_for_mode (mode); reg_rename_p->available_for_renaming &= sel_hrd.regs_for_mode[mode]; - /* Exclude registers that are partially call clobbered. */ - if (def->crosses_call - && !targetm.hard_regno_call_part_clobbered (0, regno, mode)) - reg_rename_p->available_for_renaming - &= ~sel_hrd.regs_for_call_clobbered[mode]; - /* Leave only those that are ok to rename. */ EXECUTE_IF_SET_IN_HARD_REG_SET (reg_rename_p->available_for_renaming, 0, cur_reg, hrsi) @@ -1481,7 +1473,7 @@ choose_best_pseudo_reg (regset used_regs /* Don't let register cross a call if it doesn't already cross one. This condition is written in accordance with that in sched-deps.c sched_analyze_reg(). */ - if (!reg_rename_p->crosses_call + if (!reg_rename_p->crossed_call_abis || REG_N_CALLS_CROSSED (orig_regno) > 0) return gen_rtx_REG (mode, orig_regno); } @@ -1508,7 +1500,8 @@ choose_best_pseudo_reg (regset used_regs max_regno = max_reg_num (); maybe_extend_reg_info_p (); - REG_N_CALLS_CROSSED (REGNO (new_reg)) = reg_rename_p->crosses_call ? 1 : 0; + REG_N_CALLS_CROSSED (REGNO (new_reg)) + = reg_rename_p->crossed_call_abis ? 1 : 0; return new_reg; } @@ -1560,7 +1553,8 @@ verify_target_availability (expr_t expr, as well. */ gcc_assert (scheduled_something_on_previous_fence || !live_available || !hard_available - || (!reload_completed && reg_rename_p->crosses_call + || (!reload_completed + && reg_rename_p->crossed_call_abis && REG_N_CALLS_CROSSED (regno) == 0)); } @@ -3248,7 +3242,7 @@ get_spec_check_type_for_insn (insn_t ins All the original operations found during the traversal are saved in the ORIGINAL_INSNS list. - REG_RENAME_P->CROSSES_CALL is true, if there is a call insn on the path + REG_RENAME_P->CROSSED_CALL_ABIS is true, if there is a call insn on the path from INSN to original insn. In this case CALL_USED_REG_SET will be added to unavailable hard regs at the point original operation is found. */ @@ -3269,7 +3263,7 @@ find_used_regs (insn_t insn, av_set_t or bitmap_clear (code_motion_visited_blocks); /* Init parameters for code_motion_path_driver. */ - sparams.crosses_call = false; + sparams.crossed_call_abis = 0; sparams.original_insns = original_insns; sparams.used_regs = used_regs; @@ -3278,7 +3272,7 @@ find_used_regs (insn_t insn, av_set_t or res = code_motion_path_driver (insn, orig_ops, NULL, &lparams, &sparams); - reg_rename_p->crosses_call |= sparams.crosses_call; + reg_rename_p->crossed_call_abis |= sparams.crossed_call_abis; gcc_assert (res == 1); gcc_assert (original_insns && *original_insns); @@ -6006,7 +6000,7 @@ move_op_orig_expr_found (insn_t insn, ex /* The function is called when original expr is found. INSN - current insn traversed, EXPR - the corresponding expr found, - crosses_call and original_insns in STATIC_PARAMS are updated. */ + crossed_call_abis and original_insns in STATIC_PARAMS are updated. */ static void fur_orig_expr_found (insn_t insn, expr_t expr ATTRIBUTE_UNUSED, cmpd_local_params_p lparams ATTRIBUTE_UNUSED, @@ -6016,9 +6010,9 @@ fur_orig_expr_found (insn_t insn, expr_t regset tmp; if (CALL_P (insn)) - params->crosses_call = true; + params->crossed_call_abis |= 1 << call_insn_abi (insn).id (); - def_list_add (params->original_insns, insn, params->crosses_call); + def_list_add (params->original_insns, insn, params->crossed_call_abis); /* Mark the registers that do not meet the following condition: (2) not among the live registers of the point @@ -6176,10 +6170,10 @@ fur_on_enter (insn_t insn ATTRIBUTE_UNUS least one insn in ORIGINAL_INSNS. */ gcc_assert (*sparams->original_insns); - /* Adjust CROSSES_CALL, since we may have come to this block along + /* Adjust CROSSED_CALL_ABIS, since we may have come to this block along different path. */ - DEF_LIST_DEF (*sparams->original_insns)->crosses_call - |= sparams->crosses_call; + DEF_LIST_DEF (*sparams->original_insns)->crossed_call_abis + |= sparams->crossed_call_abis; } else local_params->old_original_insns = *sparams->original_insns; @@ -6233,7 +6227,7 @@ fur_orig_expr_not_found (insn_t insn, av fur_static_params_p sparams = (fur_static_params_p) static_params; if (CALL_P (insn)) - sparams->crosses_call = true; + sparams->crossed_call_abis |= 1 << call_insn_abi (insn).id (); else if (DEBUG_INSN_P (insn)) return true;