From 9840b2fa87cc9657dca2b63dc66d37f94d2c9cb8 Mon Sep 17 00:00:00 2001 From: Richard Sandiford Date: Wed, 22 Oct 2014 12:02:11 +0000 Subject: [PATCH] md.texi: Document "preferred_for_size" and "preferred_for_speed" attributes. gcc/ * doc/md.texi: Document "preferred_for_size" and "preferred_for_speed" attributes. * genattr.c (main): Handle "preferred_for_size" and "preferred_for_speed" in the same way as "enabled". * recog.h (bool_attr): New enum. (target_recog): Replace x_enabled_alternatives with x_bool_attr_masks. (get_preferred_alternatives, check_bool_attrs): Declare. * recog.c (have_bool_attr, get_bool_attr, get_bool_attr_mask_uncached) (get_bool_attr_mask, get_preferred_alternatives, check_bool_attrs): New functions. (get_enabled_alternatives): Use get_bool_attr_mask. * ira-costs.c (record_reg_classes): Use get_preferred_alternatives instead of recog_data.enabled_alternatives. * ira.c (ira_setup_alts): Likewise. * postreload.c (reload_cse_simplify_operands): Likewise. * config/i386/i386.c (ix86_legitimate_combined_insn): Likewise. * ira-lives.c (preferred_alternatives): New variable. (process_bb_node_lives): Set it. (check_and_make_def_conflict, make_early_clobber_and_input_conflicts) (single_reg_class, ira_implicitly_set_insn_hard_regs): Use it instead of recog_data.enabled_alternatives. * lra-int.h (lra_insn_recog_data): Replace enabled_alternatives to preferred_alternatives. * lra-constraints.c (process_alt_operands): Update accordingly. * lra.c (lra_set_insn_recog_data): Likewise. (lra_update_insn_recog_data): Assert check_bool_attrs. From-SVN: r216554 --- gcc/ChangeLog | 29 ++++++++++ gcc/config/i386/i386.c | 4 +- gcc/doc/md.texi | 75 +++++++++++++----------- gcc/genattr.c | 12 +++- gcc/ira-costs.c | 3 +- gcc/ira-lives.c | 27 +++++---- gcc/ira.c | 3 +- gcc/lra-constraints.c | 6 +- gcc/lra-int.h | 4 +- gcc/lra.c | 28 ++------- gcc/postreload.c | 3 +- gcc/recog.c | 128 +++++++++++++++++++++++++++++++++-------- gcc/recog.h | 13 ++++- 13 files changed, 229 insertions(+), 106 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 5de3d9f58b1..c3d8f810741 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,32 @@ +2014-10-22 Richard Sandiford + + * doc/md.texi: Document "preferred_for_size" and "preferred_for_speed" + attributes. + * genattr.c (main): Handle "preferred_for_size" and + "preferred_for_speed" in the same way as "enabled". + * recog.h (bool_attr): New enum. + (target_recog): Replace x_enabled_alternatives with x_bool_attr_masks. + (get_preferred_alternatives, check_bool_attrs): Declare. + * recog.c (have_bool_attr, get_bool_attr, get_bool_attr_mask_uncached) + (get_bool_attr_mask, get_preferred_alternatives, check_bool_attrs): + New functions. + (get_enabled_alternatives): Use get_bool_attr_mask. + * ira-costs.c (record_reg_classes): Use get_preferred_alternatives + instead of recog_data.enabled_alternatives. + * ira.c (ira_setup_alts): Likewise. + * postreload.c (reload_cse_simplify_operands): Likewise. + * config/i386/i386.c (ix86_legitimate_combined_insn): Likewise. + * ira-lives.c (preferred_alternatives): New variable. + (process_bb_node_lives): Set it. + (check_and_make_def_conflict, make_early_clobber_and_input_conflicts) + (single_reg_class, ira_implicitly_set_insn_hard_regs): Use it instead + of recog_data.enabled_alternatives. + * lra-int.h (lra_insn_recog_data): Replace enabled_alternatives + to preferred_alternatives. + * lra-constraints.c (process_alt_operands): Update accordingly. + * lra.c (lra_set_insn_recog_data): Likewise. + (lra_update_insn_recog_data): Assert check_bool_attrs. + 2014-10-22 Richard Sandiford * recog.h (extract_constrain_insn): Declare. diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c index 94b7f798b9e..65b31734d39 100644 --- a/gcc/config/i386/i386.c +++ b/gcc/config/i386/i386.c @@ -5905,10 +5905,10 @@ ix86_legitimate_combined_insn (rtx_insn *insn) /* Operand has no constraints, anything is OK. */ win = !n_alternatives; - alternative_mask enabled = recog_data.enabled_alternatives; + alternative_mask preferred = get_preferred_alternatives (insn); for (j = 0; j < n_alternatives; j++, op_alt += n_operands) { - if (!TEST_BIT (enabled, j)) + if (!TEST_BIT (preferred, j)) continue; if (op_alt[i].anything_ok || (op_alt[i].matches != -1 diff --git a/gcc/doc/md.texi b/gcc/doc/md.texi index 2f2325e907a..1d16e294711 100644 --- a/gcc/doc/md.texi +++ b/gcc/doc/md.texi @@ -1080,7 +1080,7 @@ the addressing register. * Class Preferences:: Constraints guide which hard register to put things in. * Modifiers:: More precise control over effects of constraints. * Machine Constraints:: Existing constraints for some particular machines. -* Disable Insn Alternatives:: Disable insn alternatives using the @code{enabled} attribute. +* Disable Insn Alternatives:: Disable insn alternatives using attributes. * Define Constraints:: How to define machine-specific constraints. * C Constraint Interface:: How to test constraints from C code. @end menu @@ -4006,42 +4006,49 @@ Unsigned constant valid for BccUI instructions @subsection Disable insn alternatives using the @code{enabled} attribute @cindex enabled -The @code{enabled} insn attribute may be used to disable insn -alternatives that are not available for the current subtarget. -This is useful when adding new instructions to an existing pattern -which are only available for certain cpu architecture levels as -specified with the @code{-march=} option. +There are three insn attributes that may be used to selectively disable +instruction alternatives: -If an insn alternative is disabled, then it will never be used. The -compiler treats the constraints for the disabled alternative as -unsatisfiable. +@table @code +@item enabled +Says whether an alternative is available on the current subtarget. -In order to make use of the @code{enabled} attribute a back end has to add -in the machine description files: +@item preferred_for_size +Says whether an enabled alternative should be used in code that is +optimized for size. -@enumerate -@item -A definition of the @code{enabled} insn attribute. The attribute is -defined as usual using the @code{define_attr} command. This -definition should be based on other insn attributes and/or target flags. -The attribute must be a static property of the subtarget; that is, it -must not depend on the current operands or any other dynamic context -(for example, the location of the insn within the body of a loop). - -The @code{enabled} attribute is a numeric attribute and should evaluate to -@code{(const_int 1)} for an enabled alternative and to -@code{(const_int 0)} otherwise. -@item -A definition of another insn attribute used to describe for what -reason an insn alternative might be available or -not. E.g. @code{cpu_facility} as in the example below. -@item -An assignment for the second attribute to each insn definition -combining instructions which are not all available under the same -circumstances. (Note: It obviously only makes sense for definitions -with more than one alternative. Otherwise the insn pattern should be -disabled or enabled using the insn condition.) -@end enumerate +@item preferred_for_speed +Says whether an enabled alternative should be used in code that is +optimized for speed. +@end table + +All these attributes should use @code{(const_int 1)} to allow an alternative +or @code{(const_int 0)} to disallow it. The attributes must be a static +property of the subtarget; they cannot for example depend on the +current operands, on the current optimization level, on the location +of the insn within the body of a loop, on whether register allocation +has finished, or on the current compiler pass. + +The @code{enabled} attribute is a correctness property. It tells GCC to act +as though the disabled alternatives were never defined in the first place. +This is useful when adding new instructions to an existing pattern in +cases where the new instructions are only available for certain cpu +architecture levels (typically mapped to the @code{-march=} command-line +option). + +In contrast, the @code{preferred_for_size} and @code{preferred_for_speed} +attributes are strong optimization hints rather than correctness properties. +@code{preferred_for_size} tells GCC which alternatives to consider when +adding or modifying an instruction that GCC wants to optimize for size. +@code{preferred_for_speed} does the same thing for speed. Note that things +like code motion can lead to cases where code optimized for size uses +alternatives that are not preferred for size, and similarly for speed. + +Although @code{define_insn}s can in principle specify the @code{enabled} +attribute directly, it is often clearer to have subsiduary attributes +for each architectural feature of interest. The @code{define_insn}s +can then use these subsiduary attributes to say which alternatives +require which features. The example below does this for @code{cpu_facility}. E.g. the following two patterns could easily be merged using the @code{enabled} attribute: diff --git a/gcc/genattr.c b/gcc/genattr.c index 699590e9fbe..8c45979bb49 100644 --- a/gcc/genattr.c +++ b/gcc/genattr.c @@ -338,7 +338,9 @@ main (int argc, char **argv) } /* Special-purpose attributes should be tested with if, not #ifdef. */ - const char * const special_attrs[] = { "length", "enabled", 0 }; + const char * const special_attrs[] = { "length", "enabled", + "preferred_for_size", + "preferred_for_speed", 0 }; for (const char * const *p = special_attrs; *p; p++) { printf ("#ifndef HAVE_ATTR_%s\n" @@ -355,9 +357,15 @@ main (int argc, char **argv) "#define insn_current_length hook_int_rtx_insn_unreachable\n" "#include \"insn-addr.h\"\n" "#endif\n" - "#if !HAVE_ATTR_enabled\n" "extern int hook_int_rtx_1 (rtx);\n" + "#if !HAVE_ATTR_enabled\n" "#define get_attr_enabled hook_int_rtx_1\n" + "#endif\n" + "#if !HAVE_ATTR_preferred_for_size\n" + "#define get_attr_preferred_for_size hook_int_rtx_1\n" + "#endif\n" + "#if !HAVE_ATTR_preferred_for_speed\n" + "#define get_attr_preferred_for_speed hook_int_rtx_1\n" "#endif\n"); /* Output flag masks for use by reorg. diff --git a/gcc/ira-costs.c b/gcc/ira-costs.c index 0a930deec95..8b6c9f9047d 100644 --- a/gcc/ira-costs.c +++ b/gcc/ira-costs.c @@ -416,6 +416,7 @@ record_reg_classes (int n_alts, int n_ops, rtx *ops, /* Process each alternative, each time minimizing an operand's cost with the cost for each operand in that alternative. */ + alternative_mask preferred = get_preferred_alternatives (insn); for (alt = 0; alt < n_alts; alt++) { enum reg_class classes[MAX_RECOG_OPERANDS]; @@ -424,7 +425,7 @@ record_reg_classes (int n_alts, int n_ops, rtx *ops, int alt_fail = 0; int alt_cost = 0, op_cost_add; - if (!TEST_BIT (recog_data.enabled_alternatives, alt)) + if (!TEST_BIT (preferred, alt)) { for (i = 0; i < recog_data.n_operands; i++) constraints[i] = skip_alternative (constraints[i]); diff --git a/gcc/ira-lives.c b/gcc/ira-lives.c index 1d410538d16..1c9f8841dfe 100644 --- a/gcc/ira-lives.c +++ b/gcc/ira-lives.c @@ -85,6 +85,10 @@ static int last_call_num; /* The number of last call at which given allocno was saved. */ static int *allocno_saved_at_call; +/* The value of get_preferred_alternatives for the current instruction, + supplemental to recog_data. */ +static alternative_mask preferred_alternatives; + /* Record the birth of hard register REGNO, updating hard_regs_live and hard reg conflict information for living allocnos. */ static void @@ -641,10 +645,9 @@ check_and_make_def_conflict (int alt, int def, enum reg_class def_cl) /* If there's any alternative that allows USE to match DEF, do not record a conflict. If that causes us to create an invalid instruction due to the earlyclobber, reload must fix it up. */ - alternative_mask enabled = recog_data.enabled_alternatives; for (alt1 = 0; alt1 < recog_data.n_alternatives; alt1++) { - if (!TEST_BIT (enabled, alt1)) + if (!TEST_BIT (preferred_alternatives, alt1)) continue; const operand_alternative *op_alt1 = &recog_op_alt[alt1 * n_operands]; @@ -692,10 +695,9 @@ make_early_clobber_and_input_conflicts (void) int n_alternatives = recog_data.n_alternatives; int n_operands = recog_data.n_operands; - alternative_mask enabled = recog_data.enabled_alternatives; const operand_alternative *op_alt = recog_op_alt; for (alt = 0; alt < n_alternatives; alt++, op_alt += n_operands) - if (TEST_BIT (enabled, alt)) + if (TEST_BIT (preferred_alternatives, alt)) for (def = 0; def < n_operands; def++) { def_cl = NO_REGS; @@ -762,13 +764,13 @@ single_reg_class (const char *constraints, rtx op, rtx equiv_const) enum constraint_num cn; cl = NO_REGS; - alternative_mask enabled = recog_data.enabled_alternatives; + alternative_mask preferred = preferred_alternatives; for (; (c = *constraints); constraints += CONSTRAINT_LEN (c, constraints)) if (c == '#') - enabled &= ~ALTERNATIVE_BIT (0); + preferred &= ~ALTERNATIVE_BIT (0); else if (c == ',') - enabled >>= 1; - else if (enabled & 1) + preferred >>= 1; + else if (preferred & 1) switch (c) { case 'g': @@ -851,13 +853,13 @@ ira_implicitly_set_insn_hard_regs (HARD_REG_SET *set) mode = (GET_CODE (op) == SCRATCH ? GET_MODE (op) : PSEUDO_REGNO_MODE (regno)); cl = NO_REGS; - alternative_mask enabled = recog_data.enabled_alternatives; + alternative_mask preferred = preferred_alternatives; for (; (c = *p); p += CONSTRAINT_LEN (c, p)) if (c == '#') - enabled &= ~ALTERNATIVE_BIT (0); + preferred &= ~ALTERNATIVE_BIT (0); else if (c == ',') - enabled >>= 1; - else if (enabled & 1) + preferred >>= 1; + else if (preferred & 1) { cl = reg_class_for_constraint (lookup_constraint (p)); if (cl != NO_REGS) @@ -1174,6 +1176,7 @@ process_bb_node_lives (ira_loop_tree_node_t loop_tree_node) } extract_insn (insn); + preferred_alternatives = get_preferred_alternatives (insn); preprocess_constraints (insn); process_single_reg_class_operands (false, freq); diff --git a/gcc/ira.c b/gcc/ira.c index 3f4405eca08..1bdc44612db 100644 --- a/gcc/ira.c +++ b/gcc/ira.c @@ -1788,6 +1788,7 @@ ira_setup_alts (rtx_insn *insn, HARD_REG_SET &alts) int commutative = -1; extract_insn (insn); + alternative_mask preferred = get_preferred_alternatives (insn); CLEAR_HARD_REG_SET (alts); insn_constraints.release (); insn_constraints.safe_grow_cleared (recog_data.n_operands @@ -1817,7 +1818,7 @@ ira_setup_alts (rtx_insn *insn, HARD_REG_SET &alts) } for (nalt = 0; nalt < recog_data.n_alternatives; nalt++) { - if (!TEST_BIT (recog_data.enabled_alternatives, nalt) + if (!TEST_BIT (preferred, nalt) || TEST_HARD_REG_BIT (alts, nalt)) continue; diff --git a/gcc/lra-constraints.c b/gcc/lra-constraints.c index 6ee99a29312..7f9f3178507 100644 --- a/gcc/lra-constraints.c +++ b/gcc/lra-constraints.c @@ -1685,14 +1685,14 @@ process_alt_operands (int only_alternative) together, the second alternatives go together, etc. First loop over alternatives. */ - alternative_mask enabled = curr_id->enabled_alternatives; + alternative_mask preferred = curr_id->preferred_alternatives; if (only_alternative >= 0) - enabled &= ALTERNATIVE_BIT (only_alternative); + preferred &= ALTERNATIVE_BIT (only_alternative); for (nalt = 0; nalt < n_alternatives; nalt++) { /* Loop over operands for one constraint alternative. */ - if (!TEST_BIT (enabled, nalt)) + if (!TEST_BIT (preferred, nalt)) continue; overall = losers = reject = reload_nregs = reload_sum = 0; diff --git a/gcc/lra-int.h b/gcc/lra-int.h index 1337acad0d0..8bd45b207b5 100644 --- a/gcc/lra-int.h +++ b/gcc/lra-int.h @@ -233,8 +233,8 @@ struct lra_insn_recog_data value can be NULL or points to array of the hard register numbers ending with a negative value. */ int *arg_hard_regs; - /* Alternative enabled for the insn. NULL for debug insns. */ - alternative_mask enabled_alternatives; + /* Cached value of get_preferred_alternatives. */ + alternative_mask preferred_alternatives; /* The following member value is always NULL for a debug insn. */ struct lra_insn_reg *regs; }; diff --git a/gcc/lra.c b/gcc/lra.c index 6326131d8c3..22226361e64 100644 --- a/gcc/lra.c +++ b/gcc/lra.c @@ -921,7 +921,7 @@ lra_set_insn_recog_data (rtx_insn *insn) data->insn_static_data = &debug_insn_static_data; data->dup_loc = NULL; data->arg_hard_regs = NULL; - data->enabled_alternatives = ALL_ALTERNATIVES; + data->preferred_alternatives = ALL_ALTERNATIVES; data->operand_loc = XNEWVEC (rtx *, 1); data->operand_loc[0] = &INSN_VAR_LOCATION_LOC (insn); return data; @@ -981,7 +981,7 @@ lra_set_insn_recog_data (rtx_insn *insn) = (insn_static_data->operand[i].constraint[0] == '=' ? OP_OUT : insn_static_data->operand[i].constraint[0] == '+' ? OP_INOUT : OP_IN); - data->enabled_alternatives = ALL_ALTERNATIVES; + data->preferred_alternatives = ALL_ALTERNATIVES; if (nop > 0) { operand_alternative *op_alt = XCNEWVEC (operand_alternative, @@ -1015,7 +1015,7 @@ lra_set_insn_recog_data (rtx_insn *insn) memcpy (locs, recog_data.dup_loc, n * sizeof (rtx *)); } data->dup_loc = locs; - data->enabled_alternatives = get_enabled_alternatives (insn); + data->preferred_alternatives = get_preferred_alternatives (insn); const operand_alternative *op_alt = preprocess_insn_constraints (icode); if (!insn_static_data->operand_alternative) setup_operand_alternative (data, op_alt); @@ -1206,27 +1206,7 @@ lra_update_insn_recog_data (rtx_insn *insn) n = insn_static_data->n_dups; if (n != 0) memcpy (data->dup_loc, recog_data.dup_loc, n * sizeof (rtx *)); -#if HAVE_ATTR_enabled -#ifdef ENABLE_CHECKING - { - int i; - alternative_mask enabled; - - n = insn_static_data->n_alternatives; - enabled = data->enabled_alternatives; - lra_assert (n >= 0); - /* Cache the insn to prevent extract_insn call from - get_attr_enabled. */ - recog_data.insn = insn; - for (i = 0; i < n; i++) - { - which_alternative = i; - lra_assert (TEST_BIT (enabled, i) - == (bool) get_attr_enabled (insn)); - } - } -#endif -#endif + lra_assert (check_bool_attrs (insn)); } return data; } diff --git a/gcc/postreload.c b/gcc/postreload.c index f460bf3a3a4..dcdfedfd920 100644 --- a/gcc/postreload.c +++ b/gcc/postreload.c @@ -497,6 +497,7 @@ reload_cse_simplify_operands (rtx_insn *insn, rtx testreg) SET_HARD_REG_BIT (equiv_regs[i], REGNO (l->loc)); } + alternative_mask preferred = get_preferred_alternatives (insn); for (i = 0; i < recog_data.n_operands; i++) { enum machine_mode mode; @@ -570,7 +571,7 @@ reload_cse_simplify_operands (rtx_insn *insn, rtx testreg) alternative yet and the operand being replaced is not a cheap CONST_INT. */ if (op_alt_regno[i][j] == -1 - && TEST_BIT (recog_data.enabled_alternatives, j) + && TEST_BIT (preferred, j) && reg_fits_class_p (testreg, rclass, 0, mode) && (!CONST_INT_P (recog_data.operand[i]) || (set_src_cost (recog_data.operand[i], diff --git a/gcc/recog.c b/gcc/recog.c index 199c7debbf8..afcab998124 100644 --- a/gcc/recog.c +++ b/gcc/recog.c @@ -2060,25 +2060,46 @@ mode_dependent_address_p (rtx addr, addr_space_t addrspace) return targetm.mode_dependent_address_p (addr, addrspace); } -/* Return the mask of operand alternatives that are allowed for INSN. - This mask depends only on INSN and on the current target; it does not - depend on things like the values of operands. */ +/* Return true if boolean attribute ATTR is supported. */ -alternative_mask -get_enabled_alternatives (rtx_insn *insn) +static bool +have_bool_attr (bool_attr attr) { - /* Quick exit for asms and for targets that don't use the "enabled" - attribute. */ - int code = INSN_CODE (insn); - if (code < 0 || !HAVE_ATTR_enabled) - return ALL_ALTERNATIVES; + switch (attr) + { + case BA_ENABLED: + return HAVE_ATTR_enabled; + case BA_PREFERRED_FOR_SIZE: + return HAVE_ATTR_enabled || HAVE_ATTR_preferred_for_size; + case BA_PREFERRED_FOR_SPEED: + return HAVE_ATTR_enabled || HAVE_ATTR_preferred_for_speed; + } + gcc_unreachable (); +} - /* Calling get_attr_enabled can be expensive, so cache the mask - for speed. */ - if (this_target_recog->x_enabled_alternatives[code]) - return this_target_recog->x_enabled_alternatives[code]; +/* Return the value of ATTR for instruction INSN. */ - /* Temporarily install enough information for get_attr_enabled to assume +static bool +get_bool_attr (rtx_insn *insn, bool_attr attr) +{ + switch (attr) + { + case BA_ENABLED: + return get_attr_enabled (insn); + case BA_PREFERRED_FOR_SIZE: + return get_attr_enabled (insn) && get_attr_preferred_for_size (insn); + case BA_PREFERRED_FOR_SPEED: + return get_attr_enabled (insn) && get_attr_preferred_for_speed (insn); + } + gcc_unreachable (); +} + +/* Like get_bool_attr_mask, but don't use the cache. */ + +static alternative_mask +get_bool_attr_mask_uncached (rtx_insn *insn, bool_attr attr) +{ + /* Temporarily install enough information for get_attr_ to assume that the insn operands are already cached. As above, the attribute mustn't depend on the values of operands, so we don't provide their real values here. */ @@ -2086,20 +2107,81 @@ get_enabled_alternatives (rtx_insn *insn) int old_alternative = which_alternative; recog_data.insn = insn; - alternative_mask enabled = ALL_ALTERNATIVES; - int n_alternatives = insn_data[code].n_alternatives; + alternative_mask mask = ALL_ALTERNATIVES; + int n_alternatives = insn_data[INSN_CODE (insn)].n_alternatives; for (int i = 0; i < n_alternatives; i++) { which_alternative = i; - if (!get_attr_enabled (insn)) - enabled &= ~ALTERNATIVE_BIT (i); + if (!get_bool_attr (insn, attr)) + mask &= ~ALTERNATIVE_BIT (i); } recog_data.insn = old_insn; which_alternative = old_alternative; + return mask; +} + +/* Return the mask of operand alternatives that are allowed for INSN + by boolean attribute ATTR. This mask depends only on INSN and on + the current target; it does not depend on things like the values of + operands. */ + +static alternative_mask +get_bool_attr_mask (rtx_insn *insn, bool_attr attr) +{ + /* Quick exit for asms and for targets that don't use these attributes. */ + int code = INSN_CODE (insn); + if (code < 0 || !have_bool_attr (attr)) + return ALL_ALTERNATIVES; - this_target_recog->x_enabled_alternatives[code] = enabled; - return enabled; + /* Calling get_attr_ can be expensive, so cache the mask + for speed. */ + if (!this_target_recog->x_bool_attr_masks[code][attr]) + this_target_recog->x_bool_attr_masks[code][attr] + = get_bool_attr_mask_uncached (insn, attr); + return this_target_recog->x_bool_attr_masks[code][attr]; +} + +/* Return the set of alternatives of INSN that are allowed by the current + target. */ + +alternative_mask +get_enabled_alternatives (rtx_insn *insn) +{ + return get_bool_attr_mask (insn, BA_ENABLED); +} + +/* Return the set of alternatives of INSN that are allowed by the current + target and are preferred for the current size/speed optimization + choice. */ + +alternative_mask +get_preferred_alternatives (rtx_insn *insn) +{ + if (optimize_bb_for_speed_p (BLOCK_FOR_INSN (insn))) + return get_bool_attr_mask (insn, BA_PREFERRED_FOR_SPEED); + else + return get_bool_attr_mask (insn, BA_PREFERRED_FOR_SIZE); +} + +/* Assert that the cached boolean attributes for INSN are still accurate. + The backend is required to define these attributes in a way that only + depends on the current target (rather than operands, compiler phase, + etc.). */ + +bool +check_bool_attrs (rtx_insn *insn) +{ + int code = INSN_CODE (insn); + if (code >= 0) + for (int i = 0; i <= BA_LAST; ++i) + { + enum bool_attr attr = (enum bool_attr) i; + if (this_target_recog->x_bool_attr_masks[code][attr]) + gcc_assert (this_target_recog->x_bool_attr_masks[code][attr] + == get_bool_attr_mask_uncached (insn, attr)); + } + return true; } /* Like extract_insn, but save insn extracted and don't extract again, when @@ -4048,8 +4130,8 @@ recog_init () this_target_recog->x_initialized = true; return; } - memset (this_target_recog->x_enabled_alternatives, 0, - sizeof (this_target_recog->x_enabled_alternatives)); + memset (this_target_recog->x_bool_attr_masks, 0, + sizeof (this_target_recog->x_bool_attr_masks)); for (int i = 0; i < LAST_INSN_CODE; ++i) if (this_target_recog->x_op_alt[i]) { diff --git a/gcc/recog.h b/gcc/recog.h index d3619cbbe5a..fe8e0e80e92 100644 --- a/gcc/recog.h +++ b/gcc/recog.h @@ -389,10 +389,19 @@ extern int peep2_current_count; #ifndef GENERATOR_FILE #include "insn-codes.h" +/* An enum of boolean attributes that may only depend on the current + subtarget, not on things like operands or compiler phase. */ +enum bool_attr { + BA_ENABLED, + BA_PREFERRED_FOR_SPEED, + BA_PREFERRED_FOR_SIZE, + BA_LAST = BA_PREFERRED_FOR_SIZE +}; + /* Target-dependent globals. */ struct target_recog { bool x_initialized; - alternative_mask x_enabled_alternatives[LAST_INSN_CODE]; + alternative_mask x_bool_attr_masks[LAST_INSN_CODE][BA_LAST + 1]; operand_alternative *x_op_alt[LAST_INSN_CODE]; }; @@ -404,6 +413,8 @@ extern struct target_recog *this_target_recog; #endif alternative_mask get_enabled_alternatives (rtx_insn *); +alternative_mask get_preferred_alternatives (rtx_insn *); +bool check_bool_attrs (rtx_insn *); void recog_init (); #endif -- 2.30.2