OSDN Git Service

PR middle-end/51994
[pf3gnuchains/gcc-fork.git] / gcc / genattr.c
index cccacba..34e710d 100644 (file)
@@ -1,13 +1,13 @@
 /* Generate attribute information (insn-attr.h) from machine description.
-   Copyright (C) 1991, 1994, 1996, 1998, 1999, 2000, 2003
-   Free Software Foundation, Inc.
+   Copyright (C) 1991, 1994, 1996, 1998, 1999, 2000, 2003, 2004, 2007, 2008,
+   2010, 2011  Free Software Foundation, Inc.
    Contributed by Richard Kenner (kenner@vlsi1.ultra.nyu.edu)
 
 This file is part of GCC.
 
 GCC is free software; you can redistribute it and/or modify it under
 the terms of the GNU General Public License as published by the Free
-Software Foundation; either version 2, or (at your option) any later
+Software Foundation; either version 3, or (at your option) any later
 version.
 
 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
@@ -16,9 +16,8 @@ FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 for more details.
 
 You should have received a copy of the GNU General Public License
-along with GCC; see the file COPYING.  If not, write to the Free
-Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-02111-1307, USA.  */
+along with GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
 
 
 #include "bconfig.h"
@@ -27,89 +26,39 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #include "tm.h"
 #include "rtl.h"
 #include "errors.h"
+#include "read-md.h"
 #include "gensupport.h"
 
 
-/* A range of values.  */
-
-struct range
-{
-  int min;
-  int max;
-};
-
-/* Record information about each function unit mentioned in a
-   DEFINE_FUNCTION_UNIT.  */
-
-struct function_unit
-{
-  char *name;                  /* Function unit name.  */
-  struct function_unit *next;  /* Next function unit.  */
-  int multiplicity;            /* Number of units of this type.  */
-  int simultaneity;            /* Maximum number of simultaneous insns
-                                  on this function unit or 0 if unlimited.  */
-  struct range ready_cost;     /* Range of ready cost values.  */
-  struct range issue_delay;    /* Range of issue delay values.  */
-};
-
-static void extend_range (struct range *, int, int);
-static void init_range (struct range *);
-static void write_upcase (const char *);
 static void gen_attr (rtx);
-static void write_units (int, struct range *, struct range *,
-                        struct range *, struct range *,
-                        struct range *);
-static void
-extend_range (struct range *range, int min, int max)
-{
-  if (range->min > min) range->min = min;
-  if (range->max < max) range->max = max;
-}
 
-static void
-init_range (struct range *range)
-{
-  range->min = 100000;
-  range->max = -1;
-}
+static VEC (rtx, heap) *const_attrs, *reservations;
 
-static void
-write_upcase (const char *str)
-{
-  for (; *str; str++)
-    putchar (TOUPPER(*str));
-}
 
 static void
 gen_attr (rtx attr)
 {
-  const char *p, *tag;
+  const char *p;
   int is_const = GET_CODE (XEXP (attr, 2)) == CONST;
 
+  if (is_const)
+    VEC_safe_push (rtx, heap, const_attrs, attr);
+
   printf ("#define HAVE_ATTR_%s\n", XSTR (attr, 0));
 
   /* If numeric attribute, don't need to write an enum.  */
-  p = XSTR (attr, 1);
-  if (*p == '\0')
-    printf ("extern int get_attr_%s (%s);\n", XSTR (attr, 0),
-           (is_const ? "void" : "rtx"));
+  if (GET_CODE (attr) == DEFINE_ENUM_ATTR)
+    printf ("extern enum %s get_attr_%s (%s);\n\n",
+           XSTR (attr, 1), XSTR (attr, 0), (is_const ? "void" : "rtx"));
   else
     {
-      printf ("enum attr_%s {", XSTR (attr, 0));
-
-      while ((tag = scan_comma_elt (&p)) != 0)
-       {
-         write_upcase (XSTR (attr, 0));
-         putchar ('_');
-         while (tag != p)
-           putchar (TOUPPER (*tag++));
-         if (*p == ',')
-           fputs (", ", stdout);
-       }
-
-      fputs ("};\n", stdout);
-      printf ("extern enum attr_%s get_attr_%s (%s);\n\n",
-             XSTR (attr, 0), XSTR (attr, 0), (is_const ? "void" : "rtx"));
+      p = XSTR (attr, 1);
+      if (*p == '\0')
+       printf ("extern int get_attr_%s (%s);\n", XSTR (attr, 0),
+               (is_const ? "void" : "rtx"));
+      else
+       printf ("extern enum attr_%s get_attr_%s (%s);\n\n",
+               XSTR (attr, 0), XSTR (attr, 0), (is_const ? "void" : "rtx"));
     }
 
   /* If `length' attribute, write additional function definitions and define
@@ -119,57 +68,73 @@ gen_attr (rtx attr)
       puts ("\
 extern void shorten_branches (rtx);\n\
 extern int insn_default_length (rtx);\n\
+extern int insn_min_length (rtx);\n\
 extern int insn_variable_length_p (rtx);\n\
 extern int insn_current_length (rtx);\n\n\
 #include \"insn-addr.h\"\n");
     }
 }
 
-static void
-write_units (int num_units, struct range *multiplicity, struct range *simultaneity,
-            struct range *ready_cost, struct range *issue_delay,
-            struct range *blockage)
+/* Check that attribute NAME is used in define_insn_reservation condition
+   EXP.  Return true if it is.  */
+static bool
+check_tune_attr (const char *name, rtx exp)
 {
-  int i, q_size;
-
-  printf ("#define INSN_SCHEDULING\n\n");
-  printf ("extern int result_ready_cost (rtx);\n");
-  printf ("extern int function_units_used (rtx);\n\n");
-  printf ("extern const struct function_unit_desc\n");
-  printf ("{\n");
-  printf ("  const char *const name;\n");
-  printf ("  const int bitmask;\n");
-  printf ("  const int multiplicity;\n");
-  printf ("  const int simultaneity;\n");
-  printf ("  const int default_cost;\n");
-  printf ("  const int max_issue_delay;\n");
-  printf ("  int (*const ready_cost_function) (rtx);\n");
-  printf ("  int (*const conflict_cost_function) (rtx, rtx);\n");
-  printf ("  const int max_blockage;\n");
-  printf ("  unsigned int (*const blockage_range_function) (rtx);\n");
-  printf ("  int (*const blockage_function) (rtx, rtx);\n");
-  printf ("} function_units[];\n\n");
-  printf ("#define FUNCTION_UNITS_SIZE %d\n", num_units);
-  printf ("#define MIN_MULTIPLICITY %d\n", multiplicity->min);
-  printf ("#define MAX_MULTIPLICITY %d\n", multiplicity->max);
-  printf ("#define MIN_SIMULTANEITY %d\n", simultaneity->min);
-  printf ("#define MAX_SIMULTANEITY %d\n", simultaneity->max);
-  printf ("#define MIN_READY_COST %d\n", ready_cost->min);
-  printf ("#define MAX_READY_COST %d\n", ready_cost->max);
-  printf ("#define MIN_ISSUE_DELAY %d\n", issue_delay->min);
-  printf ("#define MAX_ISSUE_DELAY %d\n", issue_delay->max);
-  printf ("#define MIN_BLOCKAGE %d\n", blockage->min);
-  printf ("#define MAX_BLOCKAGE %d\n", blockage->max);
-  for (i = 0; (1 << i) < blockage->max; i++)
-    ;
-  printf ("#define BLOCKAGE_BITS %d\n", i + 1);
-
-  /* INSN_QUEUE_SIZE is a power of two larger than MAX_BLOCKAGE and
-     MAX_READY_COST.  This is the longest time an insn may be queued.  */
-  i = MAX (blockage->max, ready_cost->max);
-  for (q_size = 1; q_size <= i; q_size <<= 1)
-    ;
-  printf ("#define INSN_QUEUE_SIZE %d\n", q_size);
+  switch (GET_CODE (exp))
+    {
+    case AND:
+      if (check_tune_attr (name, XEXP (exp, 0)))
+       return true;
+      return check_tune_attr (name, XEXP (exp, 1));
+
+    case IOR:
+      return (check_tune_attr (name, XEXP (exp, 0))
+             && check_tune_attr (name, XEXP (exp, 1)));
+
+    case EQ_ATTR:
+      return strcmp (XSTR (exp, 0), name) == 0;
+
+    default:
+      return false;
+    }
+}
+
+/* Try to find a const attribute (usually cpu or tune) that is used
+   in all define_insn_reservation conditions.  */
+static bool
+find_tune_attr (rtx exp)
+{
+  unsigned int i;
+  rtx attr;
+
+  switch (GET_CODE (exp))
+    {
+    case AND:
+    case IOR:
+      if (find_tune_attr (XEXP (exp, 0)))
+       return true;
+      return find_tune_attr (XEXP (exp, 1));
+
+    case EQ_ATTR:
+      if (strcmp (XSTR (exp, 0), "alternative") == 0)
+       return false;
+
+      FOR_EACH_VEC_ELT (rtx, const_attrs, i, attr)
+       if (strcmp (XSTR (attr, 0), XSTR (exp, 0)) == 0)
+         {
+           unsigned int j;
+           rtx resv;
+
+           FOR_EACH_VEC_ELT (rtx, reservations, j, resv)
+             if (! check_tune_attr (XSTR (attr, 0), XEXP (resv, 2)))
+               return false;
+           return true;
+         }
+      return false;
+
+    default:
+      return false;
+    }
 }
 
 int
@@ -180,24 +145,11 @@ main (int argc, char **argv)
   int have_annul_true = 0;
   int have_annul_false = 0;
   int num_insn_reservations = 0;
-  int num_units = 0;
-  struct range all_simultaneity, all_multiplicity;
-  struct range all_ready_cost, all_issue_delay, all_blockage;
-  struct function_unit *units = 0, *unit;
   int i;
 
-  init_range (&all_multiplicity);
-  init_range (&all_simultaneity);
-  init_range (&all_ready_cost);
-  init_range (&all_issue_delay);
-  init_range (&all_blockage);
-
   progname = "genattr";
 
-  if (argc <= 1)
-    fatal ("no input file name");
-
-  if (init_md_reader_args (argc, argv) != SUCCESS_EXIT_CODE)
+  if (!init_rtx_reader_args (argc, argv))
     return (FATAL_EXIT_CODE);
 
   puts ("/* Generated automatically by the program `genattr'");
@@ -205,6 +157,8 @@ main (int argc, char **argv)
   puts ("#ifndef GCC_INSN_ATTR_H");
   puts ("#define GCC_INSN_ATTR_H\n");
 
+  puts ("#include \"insn-attr-common.h\"\n");
+
   /* For compatibility, define the attribute `alternative', which is just
      a reference to the variable `which_alternative'.  */
 
@@ -221,14 +175,14 @@ main (int argc, char **argv)
       if (desc == NULL)
        break;
 
-      if (GET_CODE (desc) == DEFINE_ATTR)
+      if (GET_CODE (desc) == DEFINE_ATTR
+         || GET_CODE (desc) == DEFINE_ENUM_ATTR)
        gen_attr (desc);
 
       else if (GET_CODE (desc) == DEFINE_DELAY)
         {
          if (! have_delay)
            {
-             printf ("#define DELAY_SLOTS\n");
              printf ("extern int num_delay_slots (rtx);\n");
              printf ("extern int eligible_for_delay (rtx, int, rtx, int);\n\n");
              printf ("extern int const_num_delay_slots (rtx);\n\n");
@@ -253,97 +207,17 @@ main (int argc, char **argv)
            }
         }
 
-      else if (GET_CODE (desc) == DEFINE_FUNCTION_UNIT)
+      else if (GET_CODE (desc) == DEFINE_INSN_RESERVATION)
        {
-         const char *name = XSTR (desc, 0);
-         int multiplicity = XINT (desc, 1);
-         int simultaneity = XINT (desc, 2);
-         int ready_cost = MAX (XINT (desc, 4), 1);
-         int issue_delay = MAX (XINT (desc, 5), 1);
-         int issueexp_p = (XVEC (desc, 6) != 0);
-
-         for (unit = units; unit; unit = unit->next)
-           if (strcmp (unit->name, name) == 0)
-             break;
-
-         if (unit == 0)
-           {
-             unit = (struct function_unit *)
-               xmalloc (sizeof (struct function_unit));
-             unit->name = xstrdup (name);
-             unit->multiplicity = multiplicity;
-             unit->simultaneity = simultaneity;
-             unit->ready_cost.min = unit->ready_cost.max = ready_cost;
-             unit->issue_delay.min = unit->issue_delay.max = issue_delay;
-             unit->next = units;
-             units = unit;
-             num_units++;
-
-             extend_range (&all_multiplicity, multiplicity, multiplicity);
-             extend_range (&all_simultaneity, simultaneity, simultaneity);
-           }
-         else if (unit->multiplicity != multiplicity
-                  || unit->simultaneity != simultaneity)
-           fatal ("Differing specifications given for `%s' function unit",
-                  unit->name);
-
-         extend_range (&unit->ready_cost, ready_cost, ready_cost);
-         extend_range (&unit->issue_delay,
-                       issueexp_p ? 1 : issue_delay, issue_delay);
-         extend_range (&all_ready_cost,
-                       unit->ready_cost.min, unit->ready_cost.max);
-         extend_range (&all_issue_delay,
-                       unit->issue_delay.min, unit->issue_delay.max);
+         num_insn_reservations++;
+         VEC_safe_push (rtx, heap, reservations, desc);
        }
-      else if (GET_CODE (desc) == DEFINE_INSN_RESERVATION)
-       num_insn_reservations++;
     }
 
-  if (num_units > 0 || num_insn_reservations > 0)
+  if (num_insn_reservations > 0)
     {
-      if (num_units > 0)
-       printf ("#define TRADITIONAL_PIPELINE_INTERFACE 1\n");
-
-      if (num_insn_reservations > 0)
-       printf ("#define DFA_PIPELINE_INTERFACE 1\n");
-
-      /* Compute the range of blockage cost values.  See genattrtab.c
-        for the derivation.  BLOCKAGE (E,C) when SIMULTANEITY is zero is
-
-            MAX (ISSUE-DELAY (E,C),
-                 READY-COST (E) - (READY-COST (C) - 1))
-
-        and otherwise
-
-            MAX (ISSUE-DELAY (E,C),
-                 READY-COST (E) - (READY-COST (C) - 1),
-                 READY-COST (E) - FILL-TIME)  */
-
-      for (unit = units; unit; unit = unit->next)
-       {
-         struct range blockage;
-
-         blockage = unit->issue_delay;
-         blockage.max = MAX (unit->ready_cost.max
-                             - (unit->ready_cost.min - 1),
-                             blockage.max);
-         blockage.min = MAX (1, blockage.min);
-
-         if (unit->simultaneity != 0)
-           {
-             int fill_time = ((unit->simultaneity - 1)
-                              * unit->issue_delay.min);
-             blockage.min = MAX (unit->ready_cost.min - fill_time,
-                                 blockage.min);
-             blockage.max = MAX (unit->ready_cost.max - fill_time,
-                                 blockage.max);
-           }
-         extend_range (&all_blockage, blockage.min, blockage.max);
-       }
-
-      write_units (num_units, &all_multiplicity, &all_simultaneity,
-                  &all_ready_cost, &all_issue_delay, &all_blockage);
-
+      bool has_tune_attr
+       = find_tune_attr (XEXP (VEC_index (rtx, reservations, 0), 2));
       /* Output interface for pipeline hazards recognition based on
         DFA (deterministic finite state automata.  */
       printf ("\n/* DFA based pipeline interface.  */");
@@ -357,15 +231,24 @@ main (int argc, char **argv)
       printf ("#define CPU_UNITS_QUERY 0\n");
       printf ("#endif\n\n");
       /* Interface itself: */
-      printf ("extern int max_dfa_issue_rate;\n\n");
-      printf ("/* The following macro value is calculated from the\n");
-      printf ("   automaton based pipeline description and is equal to\n");
-      printf ("   maximal number of all insns described in constructions\n");
-      printf ("   `define_insn_reservation' which can be issued on the\n");
-      printf ("   same processor cycle. */\n");
-      printf ("#define MAX_DFA_ISSUE_RATE max_dfa_issue_rate\n\n");
-      printf ("/* Insn latency time defined in define_insn_reservation. */\n");
-      printf ("extern int insn_default_latency (rtx);\n\n");
+      if (has_tune_attr)
+       {
+         printf ("/* Initialize fn pointers for internal_dfa_insn_code\n");
+         printf ("   and insn_default_latency.  */\n");
+         printf ("extern void init_sched_attrs (void);\n\n");
+         printf ("/* Internal insn code number used by automata.  */\n");
+         printf ("extern int (*internal_dfa_insn_code) (rtx);\n\n");
+         printf ("/* Insn latency time defined in define_insn_reservation. */\n");
+         printf ("extern int (*insn_default_latency) (rtx);\n\n");
+       }
+      else
+       {
+         printf ("#define init_sched_attrs() do { } while (0)\n\n");
+         printf ("/* Internal insn code number used by automata.  */\n");
+         printf ("extern int internal_dfa_insn_code (rtx);\n\n");
+         printf ("/* Insn latency time defined in define_insn_reservation. */\n");
+         printf ("extern int insn_default_latency (rtx);\n\n");
+       }
       printf ("/* Return nonzero if there is a bypass for given insn\n");
       printf ("   which is a data producer.  */\n");
       printf ("extern int bypass_p (rtx);\n\n");
@@ -373,16 +256,19 @@ main (int argc, char **argv)
       printf ("   Use the function if bypass_p returns nonzero for\n");
       printf ("   the 1st insn. */\n");
       printf ("extern int insn_latency (rtx, rtx);\n\n");
+      printf ("/* Maximal insn latency time possible of all bypasses for this insn.\n");
+      printf ("   Use the function if bypass_p returns nonzero for\n");
+      printf ("   the 1st insn. */\n");
+      printf ("extern int maximal_insn_latency (rtx);\n\n");
       printf ("\n#if AUTOMATON_ALTS\n");
       printf ("/* The following function returns number of alternative\n");
       printf ("   reservations of given insn.  It may be used for better\n");
       printf ("   insns scheduling heuristics. */\n");
       printf ("extern int insn_alts (rtx);\n\n");
       printf ("#endif\n\n");
-      printf ("extern int internal_dfa_insn_code (rtx);\n\n");
       printf ("/* Maximal possible number of insns waiting results being\n");
       printf ("   produced by insns whose execution is not finished. */\n");
-      printf ("extern int max_insn_queue_index;\n\n");
+      printf ("extern const int max_insn_queue_index;\n\n");
       printf ("/* Pointer to data describing current state of DFA.  */\n");
       printf ("typedef void *state_t;\n\n");
       printf ("/* Size of the data in bytes.  */\n");
@@ -434,11 +320,15 @@ main (int argc, char **argv)
       printf ("   DFA state.  */\n");
       printf ("extern int cpu_unit_reservation_p (state_t, int);\n");
       printf ("#endif\n\n");
+      printf ("/* The following function returns true if insn\n");
+      printf ("   has a dfa reservation.  */\n");
+      printf ("extern bool insn_has_dfa_reservation_p (rtx);\n\n");
       printf ("/* Clean insn code cache.  It should be called if there\n");
       printf ("   is a chance that condition value in a\n");
       printf ("   define_insn_reservation will be changed after\n");
       printf ("   last call of dfa_start.  */\n");
       printf ("extern void dfa_clean_insn_cache (void);\n\n");
+      printf ("extern void dfa_clear_single_insn_cache (rtx);\n\n");
       printf ("/* Initiate and finish work with DFA.  They should be\n");
       printf ("   called as the first and the last interface\n");
       printf ("   functions.  */\n");
@@ -470,10 +360,3 @@ main (int argc, char **argv)
 
   return SUCCESS_EXIT_CODE;
 }
-
-/* Define this so we can link with print-rtl.o to get debug_rtx function.  */
-const char *
-get_insn_name (int code ATTRIBUTE_UNUSED)
-{
-  return NULL;
-}