From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 2709 invoked by alias); 19 May 2014 14:30:41 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Received: (qmail 2694 invoked by uid 89); 19 May 2014 14:30:40 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-1.1 required=5.0 tests=AWL,BAYES_00,KAM_STOCKGEN autolearn=no version=3.3.2 X-HELO: relay1.mentorg.com Received: from relay1.mentorg.com (HELO relay1.mentorg.com) (192.94.38.131) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Mon, 19 May 2014 14:30:38 +0000 Received: from svr-orw-exc-10.mgc.mentorg.com ([147.34.98.58]) by relay1.mentorg.com with esmtp id 1WmOaG-0007MK-JQ from Tom_deVries@mentor.com ; Mon, 19 May 2014 07:30:32 -0700 Received: from SVR-IES-FEM-02.mgc.mentorg.com ([137.202.0.106]) by SVR-ORW-EXC-10.mgc.mentorg.com with Microsoft SMTPSVC(6.0.3790.4675); Mon, 19 May 2014 07:30:32 -0700 Received: from [127.0.0.1] (137.202.0.76) by SVR-IES-FEM-02.mgc.mentorg.com (137.202.0.106) with Microsoft SMTP Server id 14.2.247.3; Mon, 19 May 2014 15:30:30 +0100 Message-ID: <537A1583.7020702@mentor.com> Date: Mon, 19 May 2014 14:30:00 -0000 From: Tom de Vries User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Thunderbird/24.5.0 MIME-Version: 1.0 To: Eric Botcazou CC: , Jan Hubicka , Subject: Re: -fuse-caller-save - Collect register usage information References: <534ED7BC.50300@mentor.com> <878uqwgjoe.fsf@talisman.default> <535BABD1.8050208@mentor.com> <1426417.RtLpSRnsYv@polaris> In-Reply-To: <1426417.RtLpSRnsYv@polaris> Content-Type: multipart/mixed; boundary="------------010909070005010803060702" X-SW-Source: 2014-05/txt/msg01493.txt.bz2 --------------010909070005010803060702 Content-Type: text/plain; charset="ISO-8859-1"; format=flowed Content-Transfer-Encoding: 7bit Content-length: 1739 On 17-05-14 12:51, Eric Botcazou wrote: >> This is the updated version of the previously approved patch >> submitted here (http://gcc.gnu.org/ml/gcc-patches/2013-03/msg01320.html ). >> The changes are: >> - using a new hook call_fusage_contains_non_callee_clobbers, >> - incorporating minor review comments from Richard Sandiford >> ( http://gcc.gnu.org/ml/gcc-patches/2014-04/msg01436.html ). >> >> As part of the fuse-caller-save patch series, bootstrapped and reg-tested on >> x86_64, and build and reg-tested on MIPS. >> >> Eric, non-cgraph part OK for trunk? > Eric, thanks for the review. > I think we should consider creating a new rule: for every target hook added, > another must be first removed... > > So this call_fusage_contains_non_callee_clobbers is essentially only a stop > gap measure for the ports that haven't been changed yet? I think so. > If so, please add a > ??? comment at the beginning of collect_fn_hard_reg_usage: > > /* ??? To be removed when all the ports have been fixed. */ > if (!targetm.call_fusage_contains_non_callee_clobbers) > Done. > and invoke collect_fn_hard_reg_usage from rest_of_handle_final only when > flag_use_caller_save is true. > Done. > Why do you need to retest them in get_call_reg_set_usage and get_call_fndecl? > The test for flag_use_caller-save in get_call_fndecl was unnecessary, I've removed it. The test in get_call_reg_set_usage for flag_use_caller_save and the hook is strictly speaking not necessary. But it's the interface function to retrieve the collected register usage information, so it seems a good location to do an early-out. I've left it in for now. Bootstrapped and reg-tested on x86_64. non-cgraph part OK for trunk? Thanks, - Tom --------------010909070005010803060702 Content-Type: text/x-patch; name="0001-fuse-caller-save-Collect-register-usage-information.patch" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename*0="0001-fuse-caller-save-Collect-register-usage-information.pat"; filename*1="ch" Content-length: 5793 2014-05-19 Radovan Obradovic Tom de Vries * cgraph.h (struct cgraph_node): Add function_used_regs, function_used_regs_initialized and function_used_regs_valid fields. * final.c: Move include of hard-reg-set.h to before rtl.h to declare find_all_hard_reg_sets. (collect_fn_hard_reg_usage, get_call_fndecl, get_call_cgraph_node) (get_call_reg_set_usage): New function. (rest_of_handle_final): Use collect_fn_hard_reg_usage. --- gcc/cgraph.h | 7 ++++ gcc/final.c | 115 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- gcc/regs.h | 4 +++ 3 files changed, 125 insertions(+), 1 deletion(-) diff --git a/gcc/cgraph.h b/gcc/cgraph.h index 84fc1d9..bbbbd1f 100644 --- a/gcc/cgraph.h +++ b/gcc/cgraph.h @@ -408,6 +408,13 @@ public: /* Time profiler: first run of function. */ int tp_first_run; + /* Call unsaved hard registers really used by the corresponding + function (including ones used by functions called by the + function). */ + HARD_REG_SET function_used_regs; + /* Set if function_used_regs is valid. */ + unsigned function_used_regs_valid: 1; + /* Set when decl is an abstract function pointed to by the ABSTRACT_DECL_ORIGIN of a reachable function. */ unsigned used_as_abstract_origin : 1; diff --git a/gcc/final.c b/gcc/final.c index 3271430..e747b80 100644 --- a/gcc/final.c +++ b/gcc/final.c @@ -49,6 +49,7 @@ along with GCC; see the file COPYING3. If not see #include "tree.h" #include "varasm.h" +#include "hard-reg-set.h" #include "rtl.h" #include "tm_p.h" #include "regs.h" @@ -57,7 +58,6 @@ along with GCC; see the file COPYING3. If not see #include "recog.h" #include "conditions.h" #include "flags.h" -#include "hard-reg-set.h" #include "output.h" #include "except.h" #include "function.h" @@ -224,6 +224,7 @@ static int alter_cond (rtx); static int final_addr_vec_align (rtx); #endif static int align_fuzz (rtx, rtx, int, unsigned); +static void collect_fn_hard_reg_usage (void); /* Initialize data in final at the beginning of a compilation. */ @@ -4442,6 +4443,8 @@ rest_of_handle_final (void) assemble_start_function (current_function_decl, fnname); final_start_function (get_insns (), asm_out_file, optimize); final (get_insns (), asm_out_file, optimize); + if (flag_use_caller_save) + collect_fn_hard_reg_usage (); final_end_function (); /* The IA-64 ".handlerdata" directive must be issued before the ".endp" @@ -4740,3 +4743,113 @@ make_pass_clean_state (gcc::context *ctxt) { return new pass_clean_state (ctxt); } + +/* Collect hard register usage for the current function. */ + +static void +collect_fn_hard_reg_usage (void) +{ + rtx insn; + int i; + struct cgraph_node *node; + + /* ??? To be removed when all the ports have been fixed. */ + if (!targetm.call_fusage_contains_non_callee_clobbers) + return; + + node = cgraph_get_node (current_function_decl); + gcc_assert (node != NULL); + + for (insn = get_insns (); insn != NULL_RTX; insn = next_insn (insn)) + { + HARD_REG_SET insn_used_regs; + + if (!NONDEBUG_INSN_P (insn)) + continue; + + find_all_hard_reg_sets (insn, &insn_used_regs, false); + + if (CALL_P (insn) + && !get_call_reg_set_usage (insn, &insn_used_regs, call_used_reg_set)) + { + CLEAR_HARD_REG_SET (node->function_used_regs); + return; + } + + IOR_HARD_REG_SET (node->function_used_regs, insn_used_regs); + } + + /* Be conservative - mark fixed and global registers as used. */ + IOR_HARD_REG_SET (node->function_used_regs, fixed_reg_set); + for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) + if (global_regs[i]) + SET_HARD_REG_BIT (node->function_used_regs, i); + +#ifdef STACK_REGS + /* Handle STACK_REGS conservatively, since the df-framework does not + provide accurate information for them. */ + + for (i = FIRST_STACK_REG; i <= LAST_STACK_REG; i++) + SET_HARD_REG_BIT (node->function_used_regs, i); +#endif + + node->function_used_regs_valid = 1; +} + +/* Get the declaration of the function called by INSN. */ + +static tree +get_call_fndecl (rtx insn) +{ + rtx note, datum; + + note = find_reg_note (insn, REG_CALL_DECL, NULL_RTX); + if (note == NULL_RTX) + return NULL_TREE; + + datum = XEXP (note, 0); + if (datum != NULL_RTX) + return SYMBOL_REF_DECL (datum); + + return NULL_TREE; +} + +static struct cgraph_node * +get_call_cgraph_node (rtx insn) +{ + tree fndecl; + + if (insn == NULL_RTX) + return NULL; + + fndecl = get_call_fndecl (insn); + if (fndecl == NULL_TREE + || !targetm.binds_local_p (fndecl)) + return NULL; + + return cgraph_get_node (fndecl); +} + +/* Find hard registers used by function call instruction INSN, and return them + in REG_SET. Return DEFAULT_SET in REG_SET if not found. */ + +bool +get_call_reg_set_usage (rtx insn, HARD_REG_SET *reg_set, + HARD_REG_SET default_set) +{ + if (flag_use_caller_save + && targetm.call_fusage_contains_non_callee_clobbers) + { + struct cgraph_node *node = get_call_cgraph_node (insn); + if (node != NULL + && node->function_used_regs_valid) + { + COPY_HARD_REG_SET (*reg_set, node->function_used_regs); + AND_HARD_REG_SET (*reg_set, default_set); + return true; + } + } + + COPY_HARD_REG_SET (*reg_set, default_set); + return false; +} diff --git a/gcc/regs.h b/gcc/regs.h index 006caca..44cc005 100644 --- a/gcc/regs.h +++ b/gcc/regs.h @@ -421,4 +421,8 @@ range_in_hard_reg_set_p (const HARD_REG_SET set, unsigned regno, int nregs) return true; } +/* Get registers used by given function call instruction. */ +extern bool get_call_reg_set_usage (rtx insn, HARD_REG_SET *reg_set, + HARD_REG_SET default_set); + #endif /* GCC_REGS_H */ -- 1.9.1 --------------010909070005010803060702--