OSDN Git Service

2008-05-27 Andreas Krebbel <krebbel1@de.ibm.com>
authorkrebbel <krebbel@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 27 May 2008 11:46:45 +0000 (11:46 +0000)
committerkrebbel <krebbel@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 27 May 2008 11:46:45 +0000 (11:46 +0000)
* 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.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@136012 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/doc/md.texi
gcc/recog.c
gcc/recog.h
gcc/regclass.c
gcc/reload.c

index a26bec4..6fe4bdc 100644 (file)
@@ -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.
index ee8021c..05b1754 100644 (file)
@@ -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
index a8994ea..ee5837d 100644 (file)
@@ -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];
index a7e22e6..6a2a2ca 100644 (file)
@@ -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;
 };
index 1194c5c..8b9e86b 100644 (file)
@@ -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.  */
 
index b6880ea..7472272 100644 (file)
@@ -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