From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 3874 invoked by alias); 20 May 2014 08:19:13 -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 3865 invoked by uid 89); 20 May 2014 08:19:12 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-2.3 required=5.0 tests=AWL,BAYES_00,FREEMAIL_FROM,RCVD_IN_DNSWL_LOW,SPF_PASS autolearn=ham version=3.3.2 X-HELO: mail-wi0-f176.google.com Received: from mail-wi0-f176.google.com (HELO mail-wi0-f176.google.com) (209.85.212.176) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES128-SHA encrypted) ESMTPS; Tue, 20 May 2014 08:19:11 +0000 Received: by mail-wi0-f176.google.com with SMTP id n15so5446367wiw.15 for ; Tue, 20 May 2014 01:19:08 -0700 (PDT) X-Received: by 10.180.24.68 with SMTP id s4mr2647932wif.12.1400573947966; Tue, 20 May 2014 01:19:07 -0700 (PDT) Received: from localhost ([2.26.169.52]) by mx.google.com with ESMTPSA id cz8sm17399080wjc.11.2014.05.20.01.19.06 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 20 May 2014 01:19:07 -0700 (PDT) From: Richard Sandiford To: gcc-patches@gcc.gnu.org Mail-Followup-To: gcc-patches@gcc.gnu.org, rdsandiford@googlemail.com Subject: RFA: cache recog_op_alt by insn code Date: Tue, 20 May 2014 08:19:00 -0000 Message-ID: <87egzokglh.fsf@talisman.default> User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/24.3 (gnu/linux) MIME-Version: 1.0 Content-Type: text/plain X-SW-Source: 2014-05/txt/msg01588.txt.bz2 Following on from (and depending on) the last patch, process_constraints also shows up high in the profile. This patch caches the recog_op_alt information by insn code too. It also shrinks the size of the structure from 1 pointer + 5 ints to 1 pointer + 2 ints: - no target should have more than 65536 register classes :-) - "reject" is based on a cost of 600 for '!', so 16 bits should be plenty - "matched" and "matches" are operand numbers and so fit in 8 bits Again it seems LRA already did the same thing locally. It has a routine setup_operand_alternative that is mostly a direct cut-&-paste of process_constraints. AFAICT the only difference is that it sets up some parts of the main lra_static_insn_data structure too. Since this code is creating cached data and should only be run once per insn code or asm statement, I don't think the extra in-loop lra_static_insn_data assignments really justify having two copies of such a complicated function. I think it would be better for LRA to use the generic routine and then fill in the lra_static_insn_data fields on the result (basically just an OR of "is_address" and "early_clobber" for each alternative, plus setting up "commutative"). We could then avoid having two caches of the same data. I'll do that as a follow-up if it sounds OK. On the subject of commutativity, we have: static bool commutative_constraint_p (const char *str) { int curr_alt, c; bool ignore_p; for (ignore_p = false, curr_alt = 0;;) { c = *str; if (c == '\0') break; str += CONSTRAINT_LEN (c, str); if (c == '#' || !recog_data.alternative_enabled_p[curr_alt]) ignore_p = true; else if (c == ',') { curr_alt++; ignore_p = false; } else if (! ignore_p) { /* Usually `%' is the first constraint character but the documentation does not require this. */ if (c == '%') return true; } } return false; } Any objections to requiring `%' to be the first constraint character? Seems wasteful to be searching the constraint string just to support an odd case. The patch gives a further ~3.5% improvement in compile time for -O0 fold-const.ii, on top of the other patch. Tested on x86_64-linux-gnu. OK to install? Thanks, Richard gcc/ * recog.h (operand_alternative): Convert reg_class, reject, matched and matches into bitfields. (preprocess_constraints): Take the insn as parameter. (recog_op_alt): Change into an array of pointers. (target_recog): Add x_op_alt. * recog.c (asm_op_alt_1, asm_op_alt): New variables (recog_op_alt): Change into an array of pointers. (preprocess_constraints): Update accordingly. Take the insn as parameter. Use asm_op_alt_1 and asm_op_alt for asms. Cache other instructions in this_target_recog. * ira-lives.c (process_bb_node_lives): Pass the insn to process_constraints. * reg-stack.c (check_asm_stack_operands): Likewise. (subst_asm_stack_regs): Likewise. * regcprop.c (copyprop_hardreg_forward_1): Likewise. * regrename.c (build_def_use): Likewise. * sched-deps.c (sched_analyze_insn): Likewise. * sel-sched.c (get_reg_class, implicit_clobber_conflict_p): Likewise. * config/arm/arm.c (xscale_sched_adjust_cost): Likewise. (note_invalid_constants): Likewise. * config/i386/i386.c (ix86_legitimate_combined_insn): Likewise. Index: gcc/recog.h =================================================================== --- gcc/recog.h 2014-05-19 20:42:50.830279171 +0100 +++ gcc/recog.h 2014-05-19 21:02:22.926604180 +0100 @@ -46,18 +46,18 @@ struct operand_alternative const char *constraint; /* The register class valid for this alternative (possibly NO_REGS). */ - enum reg_class cl; + ENUM_BITFIELD (reg_class) cl : 16; /* "Badness" of this alternative, computed from number of '?' and '!' characters in the constraint string. */ - unsigned int reject; + unsigned int reject : 16; /* -1 if no matching constraint was found, or an operand number. */ - int matches; + int matches : 8; /* The same information, but reversed: -1 if this operand is not matched by any other, or the operand number of the operand that matches this one. */ - int matched; + int matched : 8; /* Nonzero if '&' was found in the constraint string. */ unsigned int earlyclobber:1; @@ -77,8 +77,9 @@ 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 : 8; +}; extern void init_recog (void); extern void init_recog_no_volatile (void); @@ -134,7 +135,7 @@ extern void insn_extract (rtx); extern void extract_insn (rtx); extern void extract_constrain_insn_cached (rtx); extern void extract_insn_cached (rtx); -extern void preprocess_constraints (void); +extern void preprocess_constraints (rtx); extern rtx peep2_next_insn (int); extern int peep2_regno_dead_p (int, int); extern int peep2_reg_dead_p (int, rtx); @@ -258,7 +259,7 @@ struct recog_data_d /* Contains a vector of operand_alternative structures for every operand. Set up by preprocess_constraints. */ -extern struct operand_alternative recog_op_alt[MAX_RECOG_OPERANDS][MAX_RECOG_ALTERNATIVES]; +extern operand_alternative **recog_op_alt; /* A table defined in insn-output.c that give information about each insn-code value. */ @@ -376,6 +377,7 @@ struct insn_data_d /* Target-dependent globals. */ struct target_recog { alternative_mask x_enabled_alternatives[LAST_INSN_CODE]; + operand_alternative **x_op_alt[LAST_INSN_CODE]; }; extern struct target_recog default_target_recog; Index: gcc/recog.c =================================================================== --- gcc/recog.c 2014-05-19 20:43:28.978647678 +0100 +++ gcc/recog.c 2014-05-19 23:26:02.037573014 +0100 @@ -80,7 +80,11 @@ struct recog_data_d recog_data; /* Contains a vector of operand_alternative structures for every operand. Set up by preprocess_constraints. */ -struct operand_alternative recog_op_alt[MAX_RECOG_OPERANDS][MAX_RECOG_ALTERNATIVES]; +operand_alternative **recog_op_alt; + +static operand_alternative asm_op_alt_1[MAX_RECOG_OPERANDS + * MAX_RECOG_ALTERNATIVES]; +static operand_alternative *asm_op_alt[MAX_RECOG_OPERANDS]; /* On return from `constrain_operands', indicate which alternative was satisfied. */ @@ -2326,23 +2330,43 @@ extract_insn (rtx insn) information from the constraint strings into a more usable form. The collected data is stored in recog_op_alt. */ void -preprocess_constraints (void) +preprocess_constraints (rtx insn) { int i; - for (i = 0; i < recog_data.n_operands; i++) - memset (recog_op_alt[i], 0, (recog_data.n_alternatives - * sizeof (struct operand_alternative))); + int code = INSN_CODE (insn); + if (code >= 0 && this_target_recog->x_op_alt[code]) + { + recog_op_alt = this_target_recog->x_op_alt[code]; + return; + } + + int n_alternatives = recog_data.n_alternatives; + int n_operands = recog_data.n_operands; + int n_entries = n_operands * n_alternatives; + + operand_alternative *op_alt; + if (code < 0) + { + memset (asm_op_alt_1, 0, n_entries * sizeof (operand_alternative)); + op_alt = asm_op_alt_1; + recog_op_alt = asm_op_alt; + } + else + { + op_alt = XCNEWVEC (operand_alternative, n_entries); + recog_op_alt = XNEWVEC (operand_alternative *, n_operands); + this_target_recog->x_op_alt[code] = recog_op_alt; + } - for (i = 0; i < recog_data.n_operands; i++) + for (i = 0; i < n_operands; i++, op_alt += n_alternatives) { int j; - struct operand_alternative *op_alt; const char *p = recog_data.constraints[i]; - op_alt = recog_op_alt[i]; + recog_op_alt[i] = op_alt; - for (j = 0; j < recog_data.n_alternatives; j++) + for (j = 0; j < n_alternatives; j++) { op_alt[j].cl = NO_REGS; op_alt[j].constraint = p; Index: gcc/ira-lives.c =================================================================== --- gcc/ira-lives.c 2014-05-19 20:42:50.819279065 +0100 +++ gcc/ira-lives.c 2014-05-19 21:01:12.577922691 +0100 @@ -1238,7 +1238,7 @@ process_bb_node_lives (ira_loop_tree_nod } extract_insn (insn); - preprocess_constraints (); + preprocess_constraints (insn); process_single_reg_class_operands (false, freq); /* See which defined values die here. */ Index: gcc/reg-stack.c =================================================================== --- gcc/reg-stack.c 2014-05-16 09:47:34.336936052 +0100 +++ gcc/reg-stack.c 2014-05-19 21:01:50.349288768 +0100 @@ -473,7 +473,7 @@ check_asm_stack_operands (rtx insn) constrain_operands (1); alt = which_alternative; - preprocess_constraints (); + preprocess_constraints (insn); get_asm_operands_in_out (body, &n_outputs, &n_inputs); @@ -2032,7 +2032,7 @@ subst_asm_stack_regs (rtx insn, stack_pt constrain_operands (1); alt = which_alternative; - preprocess_constraints (); + preprocess_constraints (insn); get_asm_operands_in_out (body, &n_outputs, &n_inputs); Index: gcc/regcprop.c =================================================================== --- gcc/regcprop.c 2014-05-17 07:59:06.436021428 +0100 +++ gcc/regcprop.c 2014-05-19 21:01:29.001081988 +0100 @@ -774,7 +774,7 @@ copyprop_hardreg_forward_1 (basic_block extract_insn (insn); if (! constrain_operands (1)) fatal_insn_not_found (insn); - preprocess_constraints (); + preprocess_constraints (insn); alt = which_alternative; n_ops = recog_data.n_operands; is_asm = asm_noperands (PATTERN (insn)) >= 0; @@ -880,7 +880,7 @@ copyprop_hardreg_forward_1 (basic_block extract_insn (insn); if (! constrain_operands (1)) fatal_insn_not_found (insn); - preprocess_constraints (); + preprocess_constraints (insn); } /* Otherwise, try all valid registers and see if its valid. */ @@ -908,7 +908,7 @@ copyprop_hardreg_forward_1 (basic_block extract_insn (insn); if (! constrain_operands (1)) fatal_insn_not_found (insn); - preprocess_constraints (); + preprocess_constraints (insn); } } } Index: gcc/regrename.c =================================================================== --- gcc/regrename.c 2014-05-06 18:38:47.928200023 +0100 +++ gcc/regrename.c 2014-05-19 21:01:35.724147073 +0100 @@ -1571,7 +1571,7 @@ build_def_use (basic_block bb) extract_insn (insn); if (! constrain_operands (1)) fatal_insn_not_found (insn); - preprocess_constraints (); + preprocess_constraints (insn); alt = which_alternative; n_ops = recog_data.n_operands; untracked_operands = 0; Index: gcc/sched-deps.c =================================================================== --- gcc/sched-deps.c 2014-05-16 09:47:34.347936161 +0100 +++ gcc/sched-deps.c 2014-05-19 21:01:58.526367964 +0100 @@ -2865,7 +2865,7 @@ sched_analyze_insn (struct deps_desc *de HARD_REG_SET temp; extract_insn (insn); - preprocess_constraints (); + preprocess_constraints (insn); ira_implicitly_set_insn_hard_regs (&temp); AND_COMPL_HARD_REG_SET (temp, ira_no_alloc_regs); IOR_HARD_REG_SET (implicit_reg_pending_clobbers, temp); Index: gcc/sel-sched.c =================================================================== --- gcc/sel-sched.c 2014-03-04 21:19:43.120097702 +0000 +++ gcc/sel-sched.c 2014-05-19 21:02:14.471522363 +0100 @@ -1019,7 +1019,7 @@ get_reg_class (rtx insn) extract_insn (insn); if (! constrain_operands (1)) fatal_insn_not_found (insn); - preprocess_constraints (); + preprocess_constraints (insn); alt = which_alternative; n_ops = recog_data.n_operands; @@ -2141,7 +2141,7 @@ implicit_clobber_conflict_p (insn_t thro /* Calculate implicit clobbers. */ extract_insn (insn); - preprocess_constraints (); + preprocess_constraints (insn); ira_implicitly_set_insn_hard_regs (&temp); AND_COMPL_HARD_REG_SET (temp, ira_no_alloc_regs); Index: gcc/config/arm/arm.c =================================================================== --- gcc/config/arm/arm.c 2014-05-19 07:46:29.013179879 +0100 +++ gcc/config/arm/arm.c 2014-05-19 21:05:50.289605508 +0100 @@ -11335,7 +11335,7 @@ xscale_sched_adjust_cost (rtx insn, rtx that overlaps with SHIFTED_OPERAND, then we have increase the cost of this dependency. */ extract_insn (dep); - preprocess_constraints (); + preprocess_constraints (dep); for (opno = 0; opno < recog_data.n_operands; opno++) { /* We can ignore strict inputs. */ @@ -16870,7 +16870,7 @@ note_invalid_constants (rtx insn, HOST_W /* Fill in recog_op_alt with information about the constraints of this insn. */ - preprocess_constraints (); + preprocess_constraints (insn); for (opno = 0; opno < recog_data.n_operands; opno++) { Index: gcc/config/i386/i386.c =================================================================== --- gcc/config/i386/i386.c 2014-05-19 07:46:26.771160339 +0100 +++ gcc/config/i386/i386.c 2014-05-19 21:05:39.461501255 +0100 @@ -5826,7 +5826,7 @@ ix86_legitimate_combined_insn (rtx insn) int i; extract_insn (insn); - preprocess_constraints (); + preprocess_constraints (insn); for (i = 0; i < recog_data.n_operands; i++) {