From 7ac28727fb6149d6e9301e501a94080cb80be27a Mon Sep 17 00:00:00 2001 From: Andreas Krebbel Date: Tue, 27 May 2008 11:46:45 +0000 Subject: [PATCH] reload.c: (find_reloads): Skip alternatives according to the "enabled" attribute. 2008-05-27 Andreas Krebbel * reload.c: (find_reloads): Skip alternatives according to the "enabled" attribute. Constify the constraint variable. * recog.c (get_attr_enabled): Add default implementation. (extract_insn): Set the alternative_enabled_p array in the recog_data struct. (preprocess_constraints, constrain_operands): Skip alternatives according to the "enabled" attribute * recog.h (struct recog_data): New field alternative_enabled_p. (skip_alternative): New inline function. * regclass.c: (record_operand_costs): Check the "enabled" attribute. (record_reg_classes): Skip alternative according to the "enabled" attribute. * doc/md.texi: Add documention for the "enabled" attribute. From-SVN: r136012 --- gcc/ChangeLog | 18 ++++++++ gcc/doc/md.texi | 110 ++++++++++++++++++++++++++++++++++++++++++++++++ gcc/recog.c | 43 ++++++++++++++++++- gcc/recog.h | 19 +++++++++ gcc/regclass.c | 8 +++- gcc/reload.c | 25 ++++++++--- 6 files changed, 213 insertions(+), 10 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index a26bec4eed4..6fe4bdc684d 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,21 @@ +2008-05-27 Andreas Krebbel + + * reload.c: (find_reloads): Skip alternatives according to the + "enabled" attribute. Constify the constraint variable. + * recog.c (get_attr_enabled): Add default implementation. + (extract_insn): Set the alternative_enabled_p array + in the recog_data struct. + (preprocess_constraints, constrain_operands): Skip + alternatives according to the "enabled" attribute + * recog.h (struct recog_data): New field alternative_enabled_p. + (skip_alternative): New inline function. + * regclass.c: (record_operand_costs): Check the "enabled" + attribute. + (record_reg_classes): Skip alternative according to the + "enabled" attribute. + + * doc/md.texi: Add documention for the "enabled" attribute. + 2008-05-27 Andreas Krebbel * defaults.h (TARGET_MEM_CONSTRAINT): New target macro added. diff --git a/gcc/doc/md.texi b/gcc/doc/md.texi index ee8021c7d59..05b1754b818 100644 --- a/gcc/doc/md.texi +++ b/gcc/doc/md.texi @@ -1050,6 +1050,7 @@ have. Constraints can also require two operands to match. * Multi-Alternative:: When an insn has two alternative constraint-patterns. * Class Preferences:: Constraints guide which hard register to put things in. * Modifiers:: More precise control over effects of constraints. +* Disable Insn Alternatives:: Disable insn alternatives using the @code{enabled} attribute. * Machine Constraints:: Existing constraints for some particular machines. * Define Constraints:: How to define machine-specific constraints. * C Constraint Interface:: How to test constraints from C code. @@ -3088,6 +3089,99 @@ Unsigned constant valid for BccUI instructions @end table +@ifset INTERNALS +@node Disable Insn Alternatives +@subsection Disable insn alternatives using the @code{enabled} attribute +@cindex enabled + +The @code{enabled} insn attribute may be used to disable certain insn +alternatives for machine-specific reasons. 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. + +If an insn alternative is disabled, then it will never be used. The +compiler treats the constraints for the disabled alternative as +unsatisfiable. + +In order to make use of the @code{enabled} attribute a back end has to add +in the machine description files: + +@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 @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 assignement 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 + +E.g. the following two patterns could easily be merged using the @code{enabled} +attribute: + +@smallexample + +(define_insn "*movdi_old" + [(set (match_operand:DI 0 "register_operand" "=d") + (match_operand:DI 1 "register_operand" " d"))] + "!TARGET_NEW" + "lgr %0,%1") + +(define_insn "*movdi_new" + [(set (match_operand:DI 0 "register_operand" "=d,f,d") + (match_operand:DI 1 "register_operand" " d,d,f"))] + "TARGET_NEW" + "@@ + lgr %0,%1 + ldgr %0,%1 + lgdr %0,%1") + +@end smallexample + +to: + +@smallexample + +(define_insn "*movdi_combined" + [(set (match_operand:DI 0 "register_operand" "=d,f,d") + (match_operand:DI 1 "register_operand" " d,d,f"))] + "" + "@@ + lgr %0,%1 + ldgr %0,%1 + lgdr %0,%1" + [(set_attr "cpu_facility" "*,new,new")]) + +@end smallexample + +with the @code{enabled} attribute defined like this: + +@smallexample + +(define_attr "cpu_facility" "standard,new" (const_string "standard")) + +(define_attr "enabled" "" + (cond [(eq_attr "cpu_facility" "standard") (const_int 1) + (and (eq_attr "cpu_facility" "new") + (ne (symbol_ref "TARGET_NEW") (const_int 0))) + (const_int 1)] + (const_int 0))) + +@end smallexample + +@end ifset + @ifset INTERNALS @node Define Constraints @subsection Defining Machine-Specific Constraints @@ -6521,6 +6615,22 @@ If the attribute takes numeric values, no @code{enum} type will be defined and the function to obtain the attribute's value will return @code{int}. +There are attributes which are tied to a specific meaning. These +attributes are not free to use for other purposes: + +@table @code +@item length +The @code{length} attribute is used to calculate the length of emitted +code chunks. This is especially important when verifying branch +distances. @xref{Insn Lengths}. + +@item enabled +The @code{enabled} attribute can be defined to prevent certain +alternatives of an insn definition from being used during code +generation. @xref{Disable Insn Alternatives}. + +@end table + @end ifset @ifset INTERNALS @node Expressions diff --git a/gcc/recog.c b/gcc/recog.c index a8994ea856e..ee5837dc1ec 100644 --- a/gcc/recog.c +++ b/gcc/recog.c @@ -60,6 +60,14 @@ along with GCC; see the file COPYING3. If not see #endif #endif +#ifndef HAVE_ATTR_enabled +static inline bool +get_attr_enabled (rtx insn ATTRIBUTE_UNUSED) +{ + return true; +} +#endif + static void validate_replace_rtx_1 (rtx *, rtx, rtx, rtx); static void validate_replace_src_1 (rtx *, void *); static rtx split_insn (rtx); @@ -1920,11 +1928,9 @@ extract_insn (rtx insn) int noperands; rtx body = PATTERN (insn); - recog_data.insn = NULL; recog_data.n_operands = 0; recog_data.n_alternatives = 0; recog_data.n_dups = 0; - which_alternative = -1; switch (GET_CODE (body)) { @@ -2004,6 +2010,22 @@ extract_insn (rtx insn) : OP_IN); gcc_assert (recog_data.n_alternatives <= MAX_RECOG_ALTERNATIVES); + + if (INSN_CODE (insn) < 0) + for (i = 0; i < recog_data.n_alternatives; i++) + recog_data.alternative_enabled_p[i] = true; + else + { + recog_data.insn = insn; + for (i = 0; i < recog_data.n_alternatives; i++) + { + which_alternative = i; + recog_data.alternative_enabled_p[i] = get_attr_enabled (insn); + } + } + + recog_data.insn = NULL; + which_alternative = -1; } /* After calling extract_insn, you can use this function to extract some @@ -2033,6 +2055,12 @@ preprocess_constraints (void) op_alt[j].matches = -1; op_alt[j].matched = -1; + if (!recog_data.alternative_enabled_p[j]) + { + p = skip_alternative (p); + continue; + } + if (*p == '\0' || *p == ',') { op_alt[j].anything_ok = 1; @@ -2202,6 +2230,17 @@ constrain_operands (int strict) int lose = 0; funny_match_index = 0; + if (!recog_data.alternative_enabled_p[which_alternative]) + { + int i; + + for (i = 0; i < recog_data.n_operands; i++) + constraints[i] = skip_alternative (constraints[i]); + + which_alternative++; + continue; + } + for (opno = 0; opno < recog_data.n_operands; opno++) { rtx op = recog_data.operand[opno]; diff --git a/gcc/recog.h b/gcc/recog.h index a7e22e6e349..6a2a2caf1da 100644 --- a/gcc/recog.h +++ b/gcc/recog.h @@ -143,6 +143,19 @@ recog_memoized (rtx insn) } #endif +/* Skip chars until the next ',' or the end of the string. This is + useful to skip alternatives in a constraint string. */ +static inline const char * +skip_alternative (const char *p) +{ + const char *r = p; + while (*r != '\0' && *r != ',') + r++; + if (*r == ',') + r++; + return r; +} + /* Nonzero means volatile operands are recognized. */ extern int volatile_ok; @@ -202,6 +215,12 @@ struct recog_data /* The number of alternatives in the constraints for the insn. */ char n_alternatives; + /* Specifies whether an insn alternative is enabled using the + `enabled' attribute in the insn pattern definition. For back + ends not using the `enabled' attribute the array fields are + always set to `true' in expand_insn. */ + bool alternative_enabled_p [MAX_RECOG_ALTERNATIVES]; + /* In case we are caching, hold insn data was generated for. */ rtx insn; }; diff --git a/gcc/regclass.c b/gcc/regclass.c index 1194c5ca75d..8b9e86b1411 100644 --- a/gcc/regclass.c +++ b/gcc/regclass.c @@ -1143,8 +1143,9 @@ record_operand_costs (rtx insn, struct costs *op_costs, record_address_regs (GET_MODE (recog_data.operand[i]), XEXP (recog_data.operand[i], 0), 0, MEM, SCRATCH, frequency * 2); - else if (constraints[i][0] == 'p' - || EXTRA_ADDRESS_CONSTRAINT (constraints[i][0], constraints[i])) + else if (recog_data.alternative_enabled_p[0] + && (constraints[i][0] == 'p' + || EXTRA_ADDRESS_CONSTRAINT (constraints[i][0], constraints[i]))) record_address_regs (VOIDmode, recog_data.operand[i], 0, ADDRESS, SCRATCH, frequency * 2); } @@ -1932,6 +1933,9 @@ record_reg_classes (int n_alts, int n_ops, rtx *ops, if (alt_fail) continue; + if (!recog_data.alternative_enabled_p[alt]) + continue; + /* Finally, update the costs with the information we've calculated about this alternative. */ diff --git a/gcc/reload.c b/gcc/reload.c index b6880ea7bc9..7472272d9c4 100644 --- a/gcc/reload.c +++ b/gcc/reload.c @@ -2523,7 +2523,7 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known, int noperands; /* These start out as the constraints for the insn and they are chewed up as we consider alternatives. */ - char *constraints[MAX_RECOG_OPERANDS]; + const char *constraints[MAX_RECOG_OPERANDS]; /* These are the preferred classes for an operand, or NO_REGS if it isn't a register. */ enum reg_class preferred_class[MAX_RECOG_OPERANDS]; @@ -2630,7 +2630,8 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known, memcpy (operand_mode, recog_data.operand_mode, noperands * sizeof (enum machine_mode)); - memcpy (constraints, recog_data.constraints, noperands * sizeof (char *)); + memcpy (constraints, recog_data.constraints, + noperands * sizeof (const char *)); commutative = -1; @@ -2641,8 +2642,9 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known, for (i = 0; i < noperands; i++) { - char *p; + const char *p; int c; + char *end; substed_operand[i] = recog_data.operand[i]; p = constraints[i]; @@ -2686,7 +2688,8 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known, case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': { - c = strtoul (p - 1, &p, 10); + c = strtoul (p - 1, &end, 10); + p = end; operands_match[c][i] = operands_match_p (recog_data.operand[c], @@ -2914,11 +2917,21 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known, a bad register class to only count 1/3 as much. */ int reject = 0; + if (!recog_data.alternative_enabled_p[this_alternative_number]) + { + int i; + + for (i = 0; i < recog_data.n_operands; i++) + constraints[i] = skip_alternative (constraints[i]); + + continue; + } + this_earlyclobber = 0; for (i = 0; i < noperands; i++) { - char *p = constraints[i]; + const char *p = constraints[i]; char *end; int len; int win = 0; @@ -3717,7 +3730,7 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known, address_reloaded[commutative + 1] = t; memcpy (constraints, recog_data.constraints, - noperands * sizeof (char *)); + noperands * sizeof (const char *)); goto try_swapped; } else -- 2.30.2