aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorAndreas Krebbel <krebbel1@de.ibm.com>2008-05-27 11:46:45 +0000
committerAndreas Krebbel <krebbel@gcc.gnu.org>2008-05-27 11:46:45 +0000
commit7ac28727fb6149d6e9301e501a94080cb80be27a (patch)
tree8b144af648d4119d5962a025331d5ae887135564 /gcc
parenta4edaf835918f2dd4a2c36659b3639438a0d1a38 (diff)
downloadgcc-7ac28727fb6149d6e9301e501a94080cb80be27a.zip
gcc-7ac28727fb6149d6e9301e501a94080cb80be27a.tar.gz
gcc-7ac28727fb6149d6e9301e501a94080cb80be27a.tar.bz2
reload.c: (find_reloads): Skip alternatives according to the "enabled" attribute.
2008-05-27 Andreas Krebbel <krebbel1@de.ibm.com> * 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
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog18
-rw-r--r--gcc/doc/md.texi110
-rw-r--r--gcc/recog.c43
-rw-r--r--gcc/recog.h19
-rw-r--r--gcc/regclass.c8
-rw-r--r--gcc/reload.c25
6 files changed, 213 insertions, 10 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index a26bec4..6fe4bdc 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,5 +1,23 @@
2008-05-27 Andreas Krebbel <krebbel1@de.ibm.com>
+ * 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 <krebbel1@de.ibm.com>
+
* defaults.h (TARGET_MEM_CONSTRAINT): New target macro added.
* postreload.c (reload_cse_simplify_operands): Replace 'm'
constraint with TARGET_MEM_CONSTRAINT.
diff --git a/gcc/doc/md.texi b/gcc/doc/md.texi
index ee8021c..05b1754 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.
@@ -3089,6 +3090,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
@cindex defining 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 a8994ea..ee5837d 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 a7e22e6..6a2a2ca 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 1194c5c..8b9e86b 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 b6880ea..7472272 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