OSDN Git Service

* rtl.h (copy_rtx_ptr_loc, print_rtx_ptr_loc, join_c_conditions)
[pf3gnuchains/gcc-fork.git] / gcc / genattrtab.c
index 4a9ad8c..99f66a1 100644 (file)
@@ -21,7 +21,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 02111-1307, USA.  */
 
 /* This program handles insn attributes and the DEFINE_DELAY and
-   DEFINE_FUNCTION_UNIT definitions.
+   DEFINE_INSN_RESERVATION definitions.
 
    It produces a series of functions named `get_attr_...', one for each insn
    attribute.  Each of these is given the rtx for an insn and returns a member
@@ -54,7 +54,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
    used.
 
    Internal attributes are defined to handle DEFINE_DELAY and
-   DEFINE_FUNCTION_UNIT.  Special routines are output for these cases.
+   DEFINE_INSN_RESERVATION.  Special routines are output for these cases.
 
    This program works by keeping a list of possible values for each attribute.
    These include the basic attribute choices, default values for attribute, and
@@ -70,9 +70,8 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
    indicates when the attribute has the specified value for the insn.  This
    avoids recursive calls during compilation.
 
-   The strategy used when processing DEFINE_DELAY and DEFINE_FUNCTION_UNIT
-   definitions is to create arbitrarily complex expressions and have the
-   optimization simplify them.
+   The strategy used when processing DEFINE_DELAY definitions is to create
+   arbitrarily complex expressions and have the optimization simplify them.
 
    Once optimization is complete, any required routines and definitions
    will be written.
@@ -103,9 +102,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #if 0
 #define strcmp_check(S1, S2) ((S1) == (S2)             \
                              ? 0                       \
-                             : (strcmp ((S1), (S2))    \
-                                ? 1                    \
-                                : (abort (), 0)))
+                             : (gcc_assert (strcmp ((S1), (S2))), 1))
 #else
 #define strcmp_check(S1, S2) ((S1) != (S2))
 #endif
@@ -161,9 +158,7 @@ struct insn_def
 struct insn_ent
 {
   struct insn_ent *next;       /* Next in chain.  */
-  int insn_code;               /* Instruction number.  */
-  int insn_index;              /* Index of definition in file */
-  int lineno;                  /* Line number.  */
+  struct insn_def *def;                /* Instruction definition.  */
 };
 
 /* Each value of an attribute (either constant or computed) is assigned a
@@ -193,21 +188,11 @@ struct attr_desc
   unsigned unsigned_p  : 1;    /* Make the output function unsigned int.  */
   unsigned is_const    : 1;    /* Attribute value constant for each run.  */
   unsigned is_special  : 1;    /* Don't call `write_attr_set'.  */
-  unsigned func_units_p        : 1;    /* This is the function_units attribute.  */
-  unsigned blockage_p  : 1;    /* This is the blockage range function.  */
   unsigned static_p    : 1;    /* Make the output function static.  */
 };
 
 #define NULL_ATTR (struct attr_desc *) NULL
 
-/* A range of values.  */
-
-struct range
-{
-  int min;
-  int max;
-};
-
 /* Structure for each DEFINE_DELAY.  */
 
 struct delay_desc
@@ -218,43 +203,6 @@ struct delay_desc
   int lineno;                  /* Line number.  */
 };
 
-/* Record information about each DEFINE_FUNCTION_UNIT.  */
-
-struct function_unit_op
-{
-  rtx condexp;                 /* Expression TRUE for applicable insn.  */
-  struct function_unit_op *next; /* Next operation for this function unit.  */
-  int num;                     /* Ordinal for this operation type in unit.  */
-  int ready;                   /* Cost until data is ready.  */
-  int issue_delay;             /* Cost until unit can accept another insn.  */
-  rtx conflict_exp;            /* Expression TRUE for insns incurring issue delay.  */
-  rtx issue_exp;               /* Expression computing issue delay.  */
-  int lineno;                  /* Line number.  */
-};
-
-/* Record information about each function unit mentioned in a
-   DEFINE_FUNCTION_UNIT.  */
-
-struct function_unit
-{
-  const char *name;            /* Function unit name.  */
-  struct function_unit *next;  /* Next function unit.  */
-  int num;                     /* Ordinal of this unit type.  */
-  int multiplicity;            /* Number of units of this type.  */
-  int simultaneity;            /* Maximum number of simultaneous insns
-                                  on this function unit or 0 if unlimited.  */
-  rtx condexp;                 /* Expression TRUE for insn needing unit.  */
-  int num_opclasses;           /* Number of different operation types.  */
-  struct function_unit_op *ops;        /* Pointer to first operation type.  */
-  int needs_conflict_function; /* Nonzero if a conflict function required.  */
-  int needs_blockage_function; /* Nonzero if a blockage function required.  */
-  int needs_range_function;    /* Nonzero if blockage range function needed.  */
-  rtx default_cost;            /* Conflict cost, if constant.  */
-  struct range issue_delay;    /* Range of issue delay values.  */
-  int max_blockage;            /* Maximum time an insn blocks the unit.  */
-  int first_lineno;            /* First seen line number.  */
-};
-
 /* Listheads of above structures.  */
 
 /* This one is indexed by the first character of the attribute name.  */
@@ -262,50 +210,6 @@ struct function_unit
 static struct attr_desc *attrs[MAX_ATTRS_INDEX];
 static struct insn_def *defs;
 static struct delay_desc *delays;
-static struct function_unit *units;
-
-/* An expression where all the unknown terms are EQ_ATTR tests can be
-   rearranged into a COND provided we can enumerate all possible
-   combinations of the unknown values.  The set of combinations become the
-   tests of the COND; the value of the expression given that combination is
-   computed and becomes the corresponding value.  To do this, we must be
-   able to enumerate all values for each attribute used in the expression
-   (currently, we give up if we find a numeric attribute).
-
-   If the set of EQ_ATTR tests used in an expression tests the value of N
-   different attributes, the list of all possible combinations can be made
-   by walking the N-dimensional attribute space defined by those
-   attributes.  We record each of these as a struct dimension.
-
-   The algorithm relies on sharing EQ_ATTR nodes: if two nodes in an
-   expression are the same, the will also have the same address.  We find
-   all the EQ_ATTR nodes by marking them ATTR_EQ_ATTR_P.  This bit later
-   represents the value of an EQ_ATTR node, so once all nodes are marked,
-   they are also given an initial value of FALSE.
-
-   We then separate the set of EQ_ATTR nodes into dimensions for each
-   attribute and put them on the VALUES list.  Terms are added as needed by
-   `add_values_to_cover' so that all possible values of the attribute are
-   tested.
-
-   Each dimension also has a current value.  This is the node that is
-   currently considered to be TRUE.  If this is one of the nodes added by
-   `add_values_to_cover', all the EQ_ATTR tests in the original expression
-   will be FALSE.  Otherwise, only the CURRENT_VALUE will be true.
-
-   NUM_VALUES is simply the length of the VALUES list and is there for
-   convenience.
-
-   Once the dimensions are created, the algorithm enumerates all possible
-   values and computes the current value of the given expression.  */
-
-struct dimension
-{
-  struct attr_desc *attr;      /* Attribute for this dimension.  */
-  rtx values;                  /* List of attribute values used.  */
-  rtx current_value;           /* Position in the list for the TRUE value.  */
-  int num_values;              /* Length of the values list.  */
-};
 
 /* Other variables.  */
 
@@ -318,15 +222,10 @@ static int address_used;
 static int length_used;
 static int num_delays;
 static int have_annul_true, have_annul_false;
-static int num_units, num_unit_opclasses;
 static int num_insn_ents;
 
 int num_dfa_decls;
 
-/* Used as operand to `operate_exp':  */
-
-enum operator {PLUS_OP, MINUS_OP, POS_MINUS_OP, EQ_OP, OR_OP, ORX_OP, MAX_OP, MIN_OP, RANGE_OP};
-
 /* Stores, for each insn code, the number of constraint alternatives.  */
 
 static int *insn_n_alternatives;
@@ -401,10 +300,6 @@ static struct attr_value *get_attr_value (rtx, struct attr_desc *, int);
 static rtx copy_rtx_unchanging (rtx);
 static rtx copy_boolean                (rtx);
 static void expand_delays      (void);
-static rtx operate_exp         (enum operator, rtx, rtx);
-static void expand_units       (void);
-static rtx simplify_knowing    (rtx, rtx);
-static rtx encode_units_mask   (rtx);
 static void fill_attr          (struct attr_desc *);
 static rtx substitute_address  (rtx, rtx (*) (rtx), rtx (*) (rtx));
 static void make_length_attrs  (void);
@@ -414,14 +309,6 @@ static rtx one_fn          (rtx);
 static rtx max_fn              (rtx);
 static void write_length_unit_log (void);
 static rtx simplify_cond       (rtx, int, int);
-static rtx simplify_by_exploding (rtx);
-static int find_and_mark_used_attributes (rtx, rtx *, int *);
-static void unmark_used_attributes (rtx, struct dimension *, int);
-static int add_values_to_cover (struct dimension *);
-static int increment_current_value (struct dimension *, int);
-static rtx test_for_current_value (struct dimension *, int);
-static rtx simplify_with_current_value (rtx, struct dimension *, int);
-static rtx simplify_with_current_value_aux (rtx);
 static void clear_struct_flag (rtx);
 static void remove_insn_ent  (struct attr_value *, struct insn_ent *);
 static void insert_insn_ent  (struct attr_value *, struct insn_ent *);
@@ -440,7 +327,6 @@ static int compares_alternatives_p (rtx);
 static int contained_in_p      (rtx, rtx);
 static void gen_insn           (rtx, int);
 static void gen_delay          (rtx, int);
-static void gen_unit           (rtx, int);
 static void write_test_expr    (rtx, int);
 static int max_attr_value      (rtx, int*);
 static int or_attr_value       (rtx, int*);
@@ -450,25 +336,19 @@ static rtx eliminate_known_true (rtx, rtx, int, int);
 static void write_attr_set     (struct attr_desc *, int, rtx,
                                 const char *, const char *, rtx,
                                 int, int);
+static void write_insn_cases   (struct insn_ent *, int);
 static void write_attr_case    (struct attr_desc *, struct attr_value *,
                                 int, const char *, const char *, int, rtx);
-static void write_unit_name    (const char *, int, const char *);
 static void write_attr_valueq  (struct attr_desc *, const char *);
 static void write_attr_value   (struct attr_desc *, rtx);
 static void write_upcase       (const char *);
 static void write_indent       (int);
 static void write_eligible_delay (const char *);
-static void write_function_unit_info (void);
-static void write_complex_function (struct function_unit *, const char *,
-                                   const char *);
 static int write_expr_attr_cache (rtx, struct attr_desc *);
-static void write_toplevel_expr        (rtx);
 static void write_const_num_delay_slots (void);
 static char *next_comma_elt    (const char **);
 static struct attr_desc *find_attr (const char **, int);
 static struct attr_value *find_most_used  (struct attr_desc *);
-static rtx find_single_value   (struct attr_desc *);
-static void extend_range       (struct range *, int, int);
 static rtx attr_eq             (const char *, const char *);
 static const char *attr_numeral        (int);
 static int attr_equal_p                (rtx, rtx);
@@ -715,7 +595,7 @@ attr_rtx_1 (enum rtx_code code, va_list p)
              break;
 
            default:
-             abort ();
+             gcc_unreachable ();
            }
        }
       return rt_val;
@@ -752,8 +632,7 @@ attr_printf (unsigned int len, const char *fmt, ...)
 
   va_start (p, fmt);
 
-  if (len > sizeof str - 1) /* Leave room for \0.  */
-    abort ();
+  gcc_assert (len < sizeof str); /* Leave room for \0.  */
 
   vsprintf (str, fmt, p);
   va_end (p);
@@ -838,7 +717,6 @@ attr_copy_rtx (rtx orig)
   switch (code)
     {
     case REG:
-    case QUEUED:
     case CONST_INT:
     case CONST_DOUBLE:
     case CONST_VECTOR:
@@ -897,7 +775,7 @@ attr_copy_rtx (rtx orig)
          break;
 
        default:
-         abort ();
+         gcc_unreachable ();
        }
     }
   return copy;
@@ -1495,7 +1373,7 @@ get_attr_value (rtx value, struct attr_desc *attr, int insn_code)
   for (av = attr->first_value; av; av = av->next)
     if (rtx_equal_p (value, av->value)
        && (num_alt == 0 || av->first_insn == NULL
-           || insn_alternatives[av->first_insn->insn_code]))
+           || insn_alternatives[av->first_insn->def->insn_code]))
       return av;
 
   av = oballoc (sizeof (struct attr_value));
@@ -1607,655 +1485,6 @@ expand_delays (void)
     }
 }
 
-/* This function is given a left and right side expression and an operator.
-   Each side is a conditional expression, each alternative of which has a
-   numerical value.  The function returns another conditional expression
-   which, for every possible set of condition values, returns a value that is
-   the operator applied to the values of the two sides.
-
-   Since this is called early, it must also support IF_THEN_ELSE.  */
-
-static rtx
-operate_exp (enum operator op, rtx left, rtx right)
-{
-  int left_value, right_value;
-  rtx newexp;
-  int i;
-
-  /* If left is a string, apply operator to it and the right side.  */
-  if (GET_CODE (left) == CONST_STRING)
-    {
-      /* If right is also a string, just perform the operation.  */
-      if (GET_CODE (right) == CONST_STRING)
-       {
-         left_value = atoi (XSTR (left, 0));
-         right_value = atoi (XSTR (right, 0));
-         switch (op)
-           {
-           case PLUS_OP:
-             i = left_value + right_value;
-             break;
-
-           case MINUS_OP:
-             i = left_value - right_value;
-             break;
-
-           case POS_MINUS_OP:  /* The positive part of LEFT - RIGHT.  */
-             if (left_value > right_value)
-               i = left_value - right_value;
-             else
-               i = 0;
-             break;
-
-           case OR_OP:
-           case ORX_OP:
-             i = left_value | right_value;
-             break;
-
-           case EQ_OP:
-             i = left_value == right_value;
-             break;
-
-           case RANGE_OP:
-             i = (left_value << (HOST_BITS_PER_INT / 2)) | right_value;
-             break;
-
-           case MAX_OP:
-             if (left_value > right_value)
-               i = left_value;
-             else
-               i = right_value;
-             break;
-
-           case MIN_OP:
-             if (left_value < right_value)
-               i = left_value;
-             else
-               i = right_value;
-             break;
-
-           default:
-             abort ();
-           }
-
-         if (i == left_value)
-           return left;
-         if (i == right_value)
-           return right;
-         return make_numeric_value (i);
-       }
-      else if (GET_CODE (right) == IF_THEN_ELSE)
-       {
-         /* Apply recursively to all values within.  */
-         rtx newleft = operate_exp (op, left, XEXP (right, 1));
-         rtx newright = operate_exp (op, left, XEXP (right, 2));
-         if (rtx_equal_p (newleft, newright))
-           return newleft;
-         return attr_rtx (IF_THEN_ELSE, XEXP (right, 0), newleft, newright);
-       }
-      else if (GET_CODE (right) == COND)
-       {
-         int allsame = 1;
-         rtx defval;
-
-         newexp = rtx_alloc (COND);
-         XVEC (newexp, 0) = rtvec_alloc (XVECLEN (right, 0));
-         defval = XEXP (newexp, 1) = operate_exp (op, left, XEXP (right, 1));
-
-         for (i = 0; i < XVECLEN (right, 0); i += 2)
-           {
-             XVECEXP (newexp, 0, i) = XVECEXP (right, 0, i);
-             XVECEXP (newexp, 0, i + 1)
-               = operate_exp (op, left, XVECEXP (right, 0, i + 1));
-             if (! rtx_equal_p (XVECEXP (newexp, 0, i + 1),
-                                defval))
-               allsame = 0;
-           }
-
-         /* If the resulting cond is trivial (all alternatives
-            give the same value), optimize it away.  */
-         if (allsame)
-           return operate_exp (op, left, XEXP (right, 1));
-
-         return newexp;
-       }
-      else
-       fatal ("badly formed attribute value");
-    }
-
-  /* A hack to prevent expand_units from completely blowing up: ORX_OP does
-     not associate through IF_THEN_ELSE.  */
-  else if (op == ORX_OP && GET_CODE (right) == IF_THEN_ELSE)
-    {
-      return attr_rtx (IOR, left, right);
-    }
-
-  /* Otherwise, do recursion the other way.  */
-  else if (GET_CODE (left) == IF_THEN_ELSE)
-    {
-      rtx newleft = operate_exp (op, XEXP (left, 1), right);
-      rtx newright = operate_exp (op, XEXP (left, 2), right);
-      if (rtx_equal_p (newleft, newright))
-       return newleft;
-      return attr_rtx (IF_THEN_ELSE, XEXP (left, 0), newleft, newright);
-    }
-  else if (GET_CODE (left) == COND)
-    {
-      int allsame = 1;
-      rtx defval;
-
-      newexp = rtx_alloc (COND);
-      XVEC (newexp, 0) = rtvec_alloc (XVECLEN (left, 0));
-      defval = XEXP (newexp, 1) = operate_exp (op, XEXP (left, 1), right);
-
-      for (i = 0; i < XVECLEN (left, 0); i += 2)
-       {
-         XVECEXP (newexp, 0, i) = XVECEXP (left, 0, i);
-         XVECEXP (newexp, 0, i + 1)
-           = operate_exp (op, XVECEXP (left, 0, i + 1), right);
-         if (! rtx_equal_p (XVECEXP (newexp, 0, i + 1),
-                            defval))
-           allsame = 0;
-       }
-
-      /* If the cond is trivial (all alternatives give the same value),
-        optimize it away.  */
-      if (allsame)
-       return operate_exp (op, XEXP (left, 1), right);
-
-      /* If the result is the same as the LEFT operand,
-        just use that.  */
-      if (rtx_equal_p (newexp, left))
-       return left;
-
-      return newexp;
-    }
-
-  else
-    fatal ("badly formed attribute value");
-  /* NOTREACHED */
-  return NULL;
-}
-
-/* Once all attributes and DEFINE_FUNCTION_UNITs have been read, we
-   construct a number of attributes.
-
-   The first produces a function `function_units_used' which is given an
-   insn and produces an encoding showing which function units are required
-   for the execution of that insn.  If the value is non-negative, the insn
-   uses that unit; otherwise, the value is a one's complement mask of units
-   used.
-
-   The second produces a function `result_ready_cost' which is used to
-   determine the time that the result of an insn will be ready and hence
-   a worst-case schedule.
-
-   Both of these produce quite complex expressions which are then set as the
-   default value of internal attributes.  Normal attribute simplification
-   should produce reasonable expressions.
-
-   For each unit, a `<name>_unit_ready_cost' function will take an
-   insn and give the delay until that unit will be ready with the result
-   and a `<name>_unit_conflict_cost' function is given an insn already
-   executing on the unit and a candidate to execute and will give the
-   cost from the time the executing insn started until the candidate
-   can start (ignore limitations on the number of simultaneous insns).
-
-   For each unit, a `<name>_unit_blockage' function is given an insn
-   already executing on the unit and a candidate to execute and will
-   give the delay incurred due to function unit conflicts.  The range of
-   blockage cost values for a given executing insn is given by the
-   `<name>_unit_blockage_range' function.  These values are encoded in
-   an int where the upper half gives the minimum value and the lower
-   half gives the maximum value.  */
-
-static void
-expand_units (void)
-{
-  struct function_unit *unit, **unit_num;
-  struct function_unit_op *op, **op_array, ***unit_ops;
-  rtx unitsmask;
-  rtx readycost;
-  rtx newexp;
-  const char *str;
-  int i, j, u, num, nvalues;
-
-  /* Rebuild the condition for the unit to share the RTL expressions.
-     Sharing is required by simplify_by_exploding.  Build the issue delay
-     expressions.  Validate the expressions we were given for the conditions
-     and conflict vector.  Then make attributes for use in the conflict
-     function.  */
-
-  for (unit = units; unit; unit = unit->next)
-    {
-      unit->condexp = check_attr_test (unit->condexp, 0, unit->first_lineno);
-
-      for (op = unit->ops; op; op = op->next)
-       {
-         rtx issue_delay = make_numeric_value (op->issue_delay);
-         rtx issue_exp = issue_delay;
-
-         /* Build, validate, and simplify the issue delay expression.  */
-         if (op->conflict_exp != true_rtx)
-           issue_exp = attr_rtx (IF_THEN_ELSE, op->conflict_exp,
-                                 issue_exp, make_numeric_value (0));
-         issue_exp = check_attr_value (make_canonical (NULL_ATTR,
-                                                       issue_exp),
-                                       NULL_ATTR);
-         issue_exp = simplify_knowing (issue_exp, unit->condexp);
-         op->issue_exp = issue_exp;
-
-         /* Make an attribute for use in the conflict function if needed.  */
-         unit->needs_conflict_function = (unit->issue_delay.min
-                                          != unit->issue_delay.max);
-         if (unit->needs_conflict_function)
-           {
-             str = attr_printf ((strlen (unit->name) + sizeof "*_cost_"
-                                 + MAX_DIGITS),
-                                "*%s_cost_%d", unit->name, op->num);
-             make_internal_attr (str, issue_exp, ATTR_SPECIAL);
-           }
-
-         /* Validate the condition.  */
-         op->condexp = check_attr_test (op->condexp, 0, op->lineno);
-       }
-    }
-
-  /* Compute the mask of function units used.  Initially, the unitsmask is
-     zero.   Set up a conditional to compute each unit's contribution.  */
-  unitsmask = make_numeric_value (0);
-  newexp = rtx_alloc (IF_THEN_ELSE);
-  XEXP (newexp, 2) = make_numeric_value (0);
-
-  /* If we have just a few units, we may be all right expanding the whole
-     thing.  But the expansion is 2**N in space on the number of opclasses,
-     so we can't do this for very long -- Alpha and MIPS in particular have
-     problems with this.  So in that situation, we fall back on an alternate
-     implementation method.  */
-#define NUM_UNITOP_CUTOFF 20
-
-  if (num_unit_opclasses < NUM_UNITOP_CUTOFF)
-    {
-      /* Merge each function unit into the unit mask attributes.  */
-      for (unit = units; unit; unit = unit->next)
-       {
-         XEXP (newexp, 0) = unit->condexp;
-         XEXP (newexp, 1) = make_numeric_value (1 << unit->num);
-         unitsmask = operate_exp (OR_OP, unitsmask, newexp);
-       }
-    }
-  else
-    {
-      /* Merge each function unit into the unit mask attributes.  */
-      for (unit = units; unit; unit = unit->next)
-       {
-         XEXP (newexp, 0) = unit->condexp;
-         XEXP (newexp, 1) = make_numeric_value (1 << unit->num);
-         unitsmask = operate_exp (ORX_OP, unitsmask, attr_copy_rtx (newexp));
-       }
-    }
-
-  /* Simplify the unit mask expression, encode it, and make an attribute
-     for the function_units_used function.  */
-  unitsmask = simplify_by_exploding (unitsmask);
-
-  if (num_unit_opclasses < NUM_UNITOP_CUTOFF)
-    unitsmask = encode_units_mask (unitsmask);
-  else
-    {
-      /* We can no longer encode unitsmask at compile time, so emit code to
-         calculate it at runtime.  Rather, put a marker for where we'd do
-        the code, and actually output it in write_attr_get().  */
-      unitsmask = attr_rtx (FFS, unitsmask);
-    }
-
-  make_internal_attr ("*function_units_used", unitsmask,
-                     (ATTR_NEGATIVE_OK | ATTR_FUNC_UNITS));
-
-  /* Create an array of ops for each unit.  Add an extra unit for the
-     result_ready_cost function that has the ops of all other units.  */
-  unit_ops = xmalloc ((num_units + 1) * sizeof (struct function_unit_op **));
-  unit_num = xmalloc ((num_units + 1) * sizeof (struct function_unit *));
-
-  unit_num[num_units] = unit = xmalloc (sizeof (struct function_unit));
-  unit->num = num_units;
-  unit->num_opclasses = 0;
-
-  for (unit = units; unit; unit = unit->next)
-    {
-      unit_num[num_units]->num_opclasses += unit->num_opclasses;
-      unit_num[unit->num] = unit;
-      unit_ops[unit->num] = op_array =
-       xmalloc (unit->num_opclasses * sizeof (struct function_unit_op *));
-
-      for (op = unit->ops; op; op = op->next)
-       op_array[op->num] = op;
-    }
-
-  /* Compose the array of ops for the extra unit.  */
-  unit_ops[num_units] = op_array =
-    xmalloc (unit_num[num_units]->num_opclasses
-           * sizeof (struct function_unit_op *));
-
-  for (unit = units, i = 0; unit; i += unit->num_opclasses, unit = unit->next)
-    memcpy (&op_array[i], unit_ops[unit->num],
-           unit->num_opclasses * sizeof (struct function_unit_op *));
-
-  /* Compute the ready cost function for each unit by computing the
-     condition for each non-default value.  */
-  for (u = 0; u <= num_units; u++)
-    {
-      rtx orexp;
-      int value;
-
-      unit = unit_num[u];
-      op_array = unit_ops[unit->num];
-      num = unit->num_opclasses;
-
-      /* Sort the array of ops into increasing ready cost order.  */
-      for (i = 0; i < num; i++)
-       for (j = num - 1; j > i; j--)
-         if (op_array[j - 1]->ready < op_array[j]->ready)
-           {
-             op = op_array[j];
-             op_array[j] = op_array[j - 1];
-             op_array[j - 1] = op;
-           }
-
-      /* Determine how many distinct non-default ready cost values there
-        are.  We use a default ready cost value of 1.  */
-      nvalues = 0; value = 1;
-      for (i = num - 1; i >= 0; i--)
-       if (op_array[i]->ready > value)
-         {
-           value = op_array[i]->ready;
-           nvalues++;
-         }
-
-      if (nvalues == 0)
-       readycost = make_numeric_value (1);
-      else
-       {
-         /* Construct the ready cost expression as a COND of each value from
-            the largest to the smallest.  */
-         readycost = rtx_alloc (COND);
-         XVEC (readycost, 0) = rtvec_alloc (nvalues * 2);
-         XEXP (readycost, 1) = make_numeric_value (1);
-
-         nvalues = 0;
-         orexp = false_rtx;
-         value = op_array[0]->ready;
-         for (i = 0; i < num; i++)
-           {
-             op = op_array[i];
-             if (op->ready <= 1)
-               break;
-             else if (op->ready == value)
-               orexp = insert_right_side (IOR, orexp, op->condexp, -2, -2);
-             else
-               {
-                 XVECEXP (readycost, 0, nvalues * 2) = orexp;
-                 XVECEXP (readycost, 0, nvalues * 2 + 1)
-                   = make_numeric_value (value);
-                 nvalues++;
-                 value = op->ready;
-                 orexp = op->condexp;
-               }
-           }
-         XVECEXP (readycost, 0, nvalues * 2) = orexp;
-         XVECEXP (readycost, 0, nvalues * 2 + 1) = make_numeric_value (value);
-       }
-
-      if (u < num_units)
-       {
-         rtx max_blockage = 0, min_blockage = 0;
-
-         /* Simplify the readycost expression by only considering insns
-            that use the unit.  */
-         readycost = simplify_knowing (readycost, unit->condexp);
-
-         /* Determine the blockage cost the executing insn (E) given
-            the candidate insn (C).  This is the maximum of the issue
-            delay, the pipeline delay, and the simultaneity constraint.
-            Each function_unit_op represents the characteristics of the
-            candidate insn, so in the expressions below, C is a known
-            term and E is an unknown term.
-
-            We compute the blockage cost for each E for every possible C.
-            Thus OP represents E, and READYCOST is a list of values for
-            every possible C.
-
-            The issue delay function for C is op->issue_exp and is used to
-            write the `<name>_unit_conflict_cost' function.  Symbolically
-            this is "ISSUE-DELAY (E,C)".
-
-            The pipeline delay results form the FIFO constraint on the
-            function unit and is "READY-COST (E) + 1 - READY-COST (C)".
-
-            The simultaneity constraint is based on how long it takes to
-            fill the unit given the minimum issue delay.  FILL-TIME is the
-            constant "MIN (ISSUE-DELAY (*,*)) * (SIMULTANEITY - 1)", and
-            the simultaneity constraint is "READY-COST (E) - FILL-TIME"
-            if SIMULTANEITY is nonzero and zero otherwise.
-
-            Thus, 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)
-
-            The `<name>_unit_blockage' function is computed by determining
-            this value for each candidate insn.  As these values are
-            computed, we also compute the upper and lower bounds for
-            BLOCKAGE (E,*).  These are combined to form the function
-            `<name>_unit_blockage_range'.  Finally, the maximum blockage
-            cost, MAX (BLOCKAGE (*,*)), is computed.  */
-
-         for (op = unit->ops; op; op = op->next)
-           {
-             rtx blockage = op->issue_exp;
-             blockage = simplify_knowing (blockage, unit->condexp);
-
-             /* Add this op's contribution to MAX (BLOCKAGE (E,*)) and
-                MIN (BLOCKAGE (E,*)).  */
-             if (max_blockage == 0)
-               max_blockage = min_blockage = blockage;
-             else
-               {
-                 max_blockage
-                   = simplify_knowing (operate_exp (MAX_OP, max_blockage,
-                                                    blockage),
-                                       unit->condexp);
-                 min_blockage
-                   = simplify_knowing (operate_exp (MIN_OP, min_blockage,
-                                                    blockage),
-                                       unit->condexp);
-               }
-
-             /* Make an attribute for use in the blockage function.  */
-             str = attr_printf ((strlen (unit->name) + sizeof "*_block_"
-                                 + MAX_DIGITS),
-                                "*%s_block_%d", unit->name, op->num);
-             make_internal_attr (str, blockage, ATTR_SPECIAL);
-           }
-
-         /* Record MAX (BLOCKAGE (*,*)).  */
-         {
-           int unknown;
-           unit->max_blockage = max_attr_value (max_blockage, &unknown);
-         }
-
-         /* See if the upper and lower bounds of BLOCKAGE (E,*) are the
-            same.  If so, the blockage function carries no additional
-            information and is not written.  */
-         newexp = operate_exp (EQ_OP, max_blockage, min_blockage);
-         newexp = simplify_knowing (newexp, unit->condexp);
-         unit->needs_blockage_function
-           = (GET_CODE (newexp) != CONST_STRING
-              || atoi (XSTR (newexp, 0)) != 1);
-
-         /* If the all values of BLOCKAGE (E,C) have the same value,
-            neither blockage function is written.  */
-         unit->needs_range_function
-           = (unit->needs_blockage_function
-              || GET_CODE (max_blockage) != CONST_STRING);
-
-         if (unit->needs_range_function)
-           {
-             /* Compute the blockage range function and make an attribute
-                for writing its value.  */
-             newexp = operate_exp (RANGE_OP, min_blockage, max_blockage);
-             newexp = simplify_knowing (newexp, unit->condexp);
-
-             str = attr_printf ((strlen (unit->name)
-                                 + sizeof "*_unit_blockage_range"),
-                                "*%s_unit_blockage_range", unit->name);
-             make_internal_attr (str, newexp, (ATTR_STATIC|ATTR_BLOCKAGE|ATTR_UNSIGNED));
-           }
-
-         str = attr_printf (strlen (unit->name) + sizeof "*_unit_ready_cost",
-                            "*%s_unit_ready_cost", unit->name);
-         make_internal_attr (str, readycost, ATTR_STATIC);
-       }
-      else
-        {
-         /* Make an attribute for the ready_cost function.  Simplifying
-            further with simplify_by_exploding doesn't win.  */
-         str = "*result_ready_cost";
-         make_internal_attr (str, readycost, ATTR_NONE);
-       }
-    }
-
-  /* For each unit that requires a conflict cost function, make an attribute
-     that maps insns to the operation number.  */
-  for (unit = units; unit; unit = unit->next)
-    {
-      rtx caseexp;
-
-      if (! unit->needs_conflict_function
-         && ! unit->needs_blockage_function)
-       continue;
-
-      caseexp = rtx_alloc (COND);
-      XVEC (caseexp, 0) = rtvec_alloc ((unit->num_opclasses - 1) * 2);
-
-      for (op = unit->ops; op; op = op->next)
-       {
-         /* Make our adjustment to the COND being computed.  If we are the
-            last operation class, place our values into the default of the
-            COND.  */
-         if (op->num == unit->num_opclasses - 1)
-           {
-             XEXP (caseexp, 1) = make_numeric_value (op->num);
-           }
-         else
-           {
-             XVECEXP (caseexp, 0, op->num * 2) = op->condexp;
-             XVECEXP (caseexp, 0, op->num * 2 + 1)
-               = make_numeric_value (op->num);
-           }
-       }
-
-      /* Simplifying caseexp with simplify_by_exploding doesn't win.  */
-      str = attr_printf (strlen (unit->name) + sizeof "*_cases",
-                        "*%s_cases", unit->name);
-      make_internal_attr (str, caseexp, ATTR_SPECIAL);
-    }
-}
-
-/* Simplify EXP given KNOWN_TRUE.  */
-
-static rtx
-simplify_knowing (rtx exp, rtx known_true)
-{
-  if (GET_CODE (exp) != CONST_STRING)
-    {
-      int unknown = 0, max;
-      max = max_attr_value (exp, &unknown);
-      if (! unknown)
-       {
-         exp = attr_rtx (IF_THEN_ELSE, known_true, exp,
-                         make_numeric_value (max));
-         exp = simplify_by_exploding (exp);
-       }
-    }
-  return exp;
-}
-
-/* Translate the CONST_STRING expressions in X to change the encoding of
-   value.  On input, the value is a bitmask with a one bit for each unit
-   used; on output, the value is the unit number (zero based) if one
-   and only one unit is used or the one's complement of the bitmask.  */
-
-static rtx
-encode_units_mask (rtx x)
-{
-  int i;
-  int j;
-  enum rtx_code code;
-  const char *fmt;
-
-  code = GET_CODE (x);
-
-  switch (code)
-    {
-    case CONST_STRING:
-      i = atoi (XSTR (x, 0));
-      if (i < 0)
-       /* The sign bit encodes a one's complement mask.  */
-       abort ();
-      else if (i != 0 && i == (i & -i))
-       /* Only one bit is set, so yield that unit number.  */
-       for (j = 0; (i >>= 1) != 0; j++)
-         ;
-      else
-       j = ~i;
-      return attr_rtx (CONST_STRING, attr_printf (MAX_DIGITS, "%d", j));
-
-    case REG:
-    case QUEUED:
-    case CONST_INT:
-    case CONST_DOUBLE:
-    case CONST_VECTOR:
-    case SYMBOL_REF:
-    case CODE_LABEL:
-    case PC:
-    case CC0:
-    case EQ_ATTR:
-    case EQ_ATTR_ALT:
-      return x;
-
-    default:
-      break;
-    }
-
-  /* Compare the elements.  If any pair of corresponding elements
-     fail to match, return 0 for the whole things.  */
-
-  fmt = GET_RTX_FORMAT (code);
-  for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
-    {
-      switch (fmt[i])
-       {
-       case 'V':
-       case 'E':
-         for (j = 0; j < XVECLEN (x, i); j++)
-           XVECEXP (x, i, j) = encode_units_mask (XVECEXP (x, i, j));
-         break;
-
-       case 'e':
-         XEXP (x, i) = encode_units_mask (XEXP (x, i));
-         break;
-       }
-    }
-  return x;
-}
-
 /* Once all attributes and insns have been read and checked, we construct for
    each attribute value a list of all the insns that have that value for
    the attribute.  */
@@ -2291,8 +1520,7 @@ fill_attr (struct attr_desc *attr)
        av = get_attr_value (value, attr, id->insn_code);
 
       ie = oballoc (sizeof (struct insn_ent));
-      ie->insn_code = id->insn_code;
-      ie->insn_index = id->insn_code;
+      ie->def = id;
       insert_insn_ent (av, ie);
     }
 }
@@ -2418,10 +1646,9 @@ make_length_attrs (void)
            new_av = get_attr_value (substitute_address (av->value,
                                                         no_address_fn[i],
                                                         address_fn[i]),
-                                    new_attr, ie->insn_code);
+                                    new_attr, ie->def->insn_code);
            new_ie = oballoc (sizeof (struct insn_ent));
-           new_ie->insn_code = ie->insn_code;
-           new_ie->insn_index = ie->insn_index;
+           new_ie->def = ie->def;
            insert_insn_ent (new_av, new_ie);
          }
     }
@@ -2621,7 +1848,7 @@ remove_insn_ent (struct attr_value *av, struct insn_ent *ie)
     }
 
   av->num_insns--;
-  if (ie->insn_code == -1)
+  if (ie->def->insn_code == -1)
     av->has_asm_insn = 0;
 
   num_insn_ents--;
@@ -2635,7 +1862,7 @@ insert_insn_ent (struct attr_value *av, struct insn_ent *ie)
   ie->next = av->first_insn;
   av->first_insn = ie;
   av->num_insns++;
-  if (ie->insn_code == -1)
+  if (ie->def->insn_code == -1)
     av->has_asm_insn = 1;
 
   num_insn_ents++;
@@ -2773,45 +2000,46 @@ evaluate_eq_attr (rtx exp, rtx value, int insn_code, int insn_index)
   rtx newexp;
   int i;
 
-  if (GET_CODE (value) == CONST_STRING)
+  switch (GET_CODE (value))
     {
+    case CONST_STRING:
       if (! strcmp_check (XSTR (value, 0), XSTR (exp, 1)))
        newexp = true_rtx;
       else
        newexp = false_rtx;
-    }
-  else if (GET_CODE (value) == SYMBOL_REF)
-    {
-      char *p;
-      char string[256];
-
-      if (GET_CODE (exp) != EQ_ATTR)
-       abort ();
-
-      if (strlen (XSTR (exp, 0)) + strlen (XSTR (exp, 1)) + 2 > 256)
-       abort ();
-
-      strcpy (string, XSTR (exp, 0));
-      strcat (string, "_");
-      strcat (string, XSTR (exp, 1));
-      for (p = string; *p; p++)
-       *p = TOUPPER (*p);
-
-      newexp = attr_rtx (EQ, value,
-                        attr_rtx (SYMBOL_REF,
-                                  DEF_ATTR_STRING (string)));
-    }
-  else if (GET_CODE (value) == COND)
-    {
-      /* We construct an IOR of all the cases for which the requested attribute
-        value is present.  Since we start with FALSE, if it is not present,
-        FALSE will be returned.
+      break;
+      
+    case SYMBOL_REF:
+      {
+       char *p;
+       char string[256];
+       
+       gcc_assert (GET_CODE (exp) == EQ_ATTR);
+       gcc_assert (strlen (XSTR (exp, 0)) + strlen (XSTR (exp, 1)) + 2
+                   <= 256);
+       
+       strcpy (string, XSTR (exp, 0));
+       strcat (string, "_");
+       strcat (string, XSTR (exp, 1));
+       for (p = string; *p; p++)
+         *p = TOUPPER (*p);
+       
+       newexp = attr_rtx (EQ, value,
+                          attr_rtx (SYMBOL_REF,
+                                    DEF_ATTR_STRING (string)));
+       break;
+      }
 
+    case COND:
+      /* We construct an IOR of all the cases for which the
+        requested attribute value is present.  Since we start with
+        FALSE, if it is not present, FALSE will be returned.
+         
         Each case is the AND of the NOT's of the previous conditions with the
         current condition; in the default case the current condition is TRUE.
-
+         
         For each possible COND value, call ourselves recursively.
-
+         
         The extra TRUE and FALSE expressions will be eliminated by another
         call to the simplification routine.  */
 
@@ -2851,9 +2079,11 @@ evaluate_eq_attr (rtx exp, rtx value, int insn_code, int insn_index)
                                                   insn_code, insn_index),
                                 insn_code, insn_index);
       newexp = insert_right_side (IOR, orexp, right, insn_code, insn_index);
+      break;
+
+    default:
+      gcc_unreachable ();
     }
-  else
-    abort ();
 
   /* If uses an address, must return original expression.  But set the
      ATTR_IND_SIMPLIFIED_P bit so we don't try to simplify it again.  */
@@ -3172,13 +2402,14 @@ attr_alt_subset_p (rtx s1, rtx s2)
       return !(XINT (s2, 0) &~ XINT (s1, 0));
 
     default:
-      abort ();
+      gcc_unreachable ();
     }
 }
 
 /* Returns true if S1 is a subset of complement of S2.  */
 
-static bool attr_alt_subset_of_compl_p (rtx s1, rtx s2)
+static bool
+attr_alt_subset_of_compl_p (rtx s1, rtx s2)
 {
   switch ((XINT (s1, 1) << 1) | XINT (s2, 1))
     {
@@ -3195,7 +2426,7 @@ static bool attr_alt_subset_of_compl_p (rtx s1, rtx s2)
       return false;
 
     default:
-      abort ();
+      gcc_unreachable ();
     }
 }
 
@@ -3221,7 +2452,7 @@ attr_alt_intersection (rtx s1, rtx s2)
       XINT (result, 0) = XINT (s1, 0) | XINT (s2, 0);
       break;
     default:
-      abort ();
+      gcc_unreachable ();
     }
   XINT (result, 1) = XINT (s1, 1) & XINT (s2, 1);
 
@@ -3250,7 +2481,7 @@ attr_alt_union (rtx s1, rtx s2)
       XINT (result, 0) = XINT (s1, 0) & XINT (s2, 0);
       break;
     default:
-      abort ();
+      gcc_unreachable ();
     }
 
   XINT (result, 1) = XINT (s1, 1) | XINT (s2, 1);
@@ -3593,7 +2824,7 @@ simplify_test_exp (rtx exp, int insn_code, int insn_index)
          && (attr = find_attr (&XSTR (exp, 0), 0)) != NULL)
        for (av = attr->first_value; av; av = av->next)
          for (ie = av->first_insn; ie; ie = ie->next)
-           if (ie->insn_code == insn_code)
+           if (ie->def->insn_code == insn_code)
              {
                rtx x;
                x = evaluate_eq_attr (exp, av->value, insn_code, insn_index);
@@ -3650,509 +2881,70 @@ optimize_attrs (void)
   insn_code_values = xcalloc ((insn_code_number + 2),
                              sizeof (struct attr_value_list *));
 
-  /* Offset the table address so we can index by -2 or -1.  */
-  insn_code_values += 2;
-
-  iv = ivbuf = xmalloc (num_insn_ents * sizeof (struct attr_value_list));
-
-  for (i = 0; i < MAX_ATTRS_INDEX; i++)
-    for (attr = attrs[i]; attr; attr = attr->next)
-      for (av = attr->first_value; av; av = av->next)
-       for (ie = av->first_insn; ie; ie = ie->next)
-         {
-           iv->attr = attr;
-           iv->av = av;
-           iv->ie = ie;
-           iv->next = insn_code_values[ie->insn_code];
-           insn_code_values[ie->insn_code] = iv;
-           iv++;
-         }
-
-  /* Sanity check on num_insn_ents.  */
-  if (iv != ivbuf + num_insn_ents)
-    abort ();
-
-  /* Process one insn code at a time.  */
-  for (i = -2; i < insn_code_number; i++)
-    {
-      /* Clear the ATTR_CURR_SIMPLIFIED_P flag everywhere relevant.
-        We use it to mean "already simplified for this insn".  */
-      for (iv = insn_code_values[i]; iv; iv = iv->next)
-       clear_struct_flag (iv->av->value);
-
-      for (iv = insn_code_values[i]; iv; iv = iv->next)
-       {
-         struct obstack *old = rtl_obstack;
-
-         attr = iv->attr;
-         av = iv->av;
-         ie = iv->ie;
-         if (GET_CODE (av->value) != COND)
-           continue;
-
-         rtl_obstack = temp_obstack;
-         newexp = av->value;
-         while (GET_CODE (newexp) == COND)
-           {
-             rtx newexp2 = simplify_cond (newexp, ie->insn_code,
-                                          ie->insn_index);
-             if (newexp2 == newexp)
-               break;
-             newexp = newexp2;
-           }
-
-         rtl_obstack = old;
-         if (newexp != av->value)
-           {
-             newexp = attr_copy_rtx (newexp);
-             remove_insn_ent (av, ie);
-             av = get_attr_value (newexp, attr, ie->insn_code);
-             iv->av = av;
-             insert_insn_ent (av, ie);
-           }
-       }
-    }
-
-  free (ivbuf);
-  free (insn_code_values - 2);
-}
-
-/* If EXP is a suitable expression, reorganize it by constructing an
-   equivalent expression that is a COND with the tests being all combinations
-   of attribute values and the values being simple constants.  */
-
-static rtx
-simplify_by_exploding (rtx exp)
-{
-  rtx list = 0, link, condexp, defval = NULL_RTX;
-  struct dimension *space;
-  rtx *condtest, *condval;
-  int i, j, total, ndim = 0;
-  int most_tests, num_marks, new_marks;
-  rtx ret;
-
-  /* Locate all the EQ_ATTR expressions.  */
-  if (! find_and_mark_used_attributes (exp, &list, &ndim) || ndim == 0)
-    {
-      unmark_used_attributes (list, 0, 0);
-      return exp;
-    }
-
-  /* Create an attribute space from the list of used attributes.  For each
-     dimension in the attribute space, record the attribute, list of values
-     used, and number of values used.  Add members to the list of values to
-     cover the domain of the attribute.  This makes the expanded COND form
-     order independent.  */
-
-  space = xmalloc (ndim * sizeof (struct dimension));
-
-  total = 1;
-  for (ndim = 0; list; ndim++)
-    {
-      /* Pull the first attribute value from the list and record that
-        attribute as another dimension in the attribute space.  */
-      const char *name = XSTR (XEXP (list, 0), 0);
-      rtx *prev;
-
-      space[ndim].attr = find_attr (&name, 0);
-      XSTR (XEXP (list, 0), 0) = name;
-
-      if (space[ndim].attr == 0
-         || space[ndim].attr->is_numeric)
-       {
-         unmark_used_attributes (list, space, ndim);
-         return exp;
-       }
-
-      /* Add all remaining attribute values that refer to this attribute.  */
-      space[ndim].num_values = 0;
-      space[ndim].values = 0;
-      prev = &list;
-      for (link = list; link; link = *prev)
-       if (! strcmp_check (XSTR (XEXP (link, 0), 0), name))
-         {
-           space[ndim].num_values++;
-           *prev = XEXP (link, 1);
-           XEXP (link, 1) = space[ndim].values;
-           space[ndim].values = link;
-         }
-       else
-         prev = &XEXP (link, 1);
-
-      /* Add sufficient members to the list of values to make the list
-        mutually exclusive and record the total size of the attribute
-        space.  */
-      total *= add_values_to_cover (&space[ndim]);
-    }
-
-  /* Sort the attribute space so that the attributes go from non-constant
-     to constant and from most values to least values.  */
-  for (i = 0; i < ndim; i++)
-    for (j = ndim - 1; j > i; j--)
-      if ((space[j-1].attr->is_const && !space[j].attr->is_const)
-         || space[j-1].num_values < space[j].num_values)
-       {
-         struct dimension tmp;
-         tmp = space[j];
-         space[j] = space[j - 1];
-         space[j - 1] = tmp;
-       }
-
-  /* Establish the initial current value.  */
-  for (i = 0; i < ndim; i++)
-    space[i].current_value = space[i].values;
-
-  condtest = xmalloc (total * sizeof (rtx));
-  condval = xmalloc (total * sizeof (rtx));
-
-  /* Expand the tests and values by iterating over all values in the
-     attribute space.  */
-  for (i = 0;; i++)
-    {
-      condtest[i] = test_for_current_value (space, ndim);
-      condval[i] = simplify_with_current_value (exp, space, ndim);
-      if (! increment_current_value (space, ndim))
-       break;
-    }
-  if (i != total - 1)
-    abort ();
-
-  /* We are now finished with the original expression.  */
-  unmark_used_attributes (0, space, ndim);
-  free (space);
-
-  /* Find the most used constant value and make that the default.  */
-  most_tests = -1;
-  for (i = num_marks = 0; i < total; i++)
-    if (GET_CODE (condval[i]) == CONST_STRING
-       && ! ATTR_EQ_ATTR_P (condval[i]))
-      {
-       /* Mark the unmarked constant value and count how many are marked.  */
-       ATTR_EQ_ATTR_P (condval[i]) = 1;
-       for (j = new_marks = 0; j < total; j++)
-         if (GET_CODE (condval[j]) == CONST_STRING
-             && ATTR_EQ_ATTR_P (condval[j]))
-           new_marks++;
-       if (new_marks - num_marks > most_tests)
-         {
-           most_tests = new_marks - num_marks;
-           defval = condval[i];
-         }
-       num_marks = new_marks;
-      }
-  /* Clear all the marks.  */
-  for (i = 0; i < total; i++)
-    ATTR_EQ_ATTR_P (condval[i]) = 0;
-
-  /* Give up if nothing is constant.  */
-  if (num_marks == 0)
-    ret = exp;
-
-  /* If all values are the default, use that.  */
-  else if (total == most_tests)
-    ret = defval;
-
-  /* Make a COND with the most common constant value the default.  (A more
-     complex method where tests with the same value were combined didn't
-     seem to improve things.)  */
-  else
-    {
-      condexp = rtx_alloc (COND);
-      XVEC (condexp, 0) = rtvec_alloc ((total - most_tests) * 2);
-      XEXP (condexp, 1) = defval;
-      for (i = j = 0; i < total; i++)
-       if (condval[i] != defval)
-         {
-           XVECEXP (condexp, 0, 2 * j) = condtest[i];
-           XVECEXP (condexp, 0, 2 * j + 1) = condval[i];
-           j++;
-         }
-      ret = condexp;
-    }
-  free (condtest);
-  free (condval);
-  return ret;
-}
-
-/* Set the ATTR_EQ_ATTR_P flag for all EQ_ATTR expressions in EXP and
-   verify that EXP can be simplified to a constant term if all the EQ_ATTR
-   tests have known value.  */
-
-static int
-find_and_mark_used_attributes (rtx exp, rtx *terms, int *nterms)
-{
-  int i;
-
-  switch (GET_CODE (exp))
-    {
-    case EQ_ATTR:
-      if (! ATTR_EQ_ATTR_P (exp))
-       {
-         rtx link = rtx_alloc (EXPR_LIST);
-         XEXP (link, 0) = exp;
-         XEXP (link, 1) = *terms;
-         *terms = link;
-         *nterms += 1;
-         ATTR_EQ_ATTR_P (exp) = 1;
-       }
-      return 1;
-
-    case CONST_STRING:
-    case CONST_INT:
-      return 1;
-
-    case IF_THEN_ELSE:
-      if (! find_and_mark_used_attributes (XEXP (exp, 2), terms, nterms))
-       return 0;
-    case IOR:
-    case AND:
-      if (! find_and_mark_used_attributes (XEXP (exp, 1), terms, nterms))
-       return 0;
-    case NOT:
-      if (! find_and_mark_used_attributes (XEXP (exp, 0), terms, nterms))
-       return 0;
-      return 1;
-
-    case COND:
-      for (i = 0; i < XVECLEN (exp, 0); i++)
-       if (! find_and_mark_used_attributes (XVECEXP (exp, 0, i), terms, nterms))
-         return 0;
-      if (! find_and_mark_used_attributes (XEXP (exp, 1), terms, nterms))
-       return 0;
-      return 1;
-
-    default:
-      return 0;
-    }
-}
-
-/* Clear the ATTR_EQ_ATTR_P flag in all EQ_ATTR expressions on LIST and
-   in the values of the NDIM-dimensional attribute space SPACE.  */
-
-static void
-unmark_used_attributes (rtx list, struct dimension *space, int ndim)
-{
-  rtx link, exp;
-  int i;
-
-  for (i = 0; i < ndim; i++)
-    unmark_used_attributes (space[i].values, 0, 0);
-
-  for (link = list; link; link = XEXP (link, 1))
-    {
-      exp = XEXP (link, 0);
-      if (GET_CODE (exp) == EQ_ATTR)
-       ATTR_EQ_ATTR_P (exp) = 0;
-    }
-}
-
-/* Update the attribute dimension DIM so that all values of the attribute
-   are tested.  Return the updated number of values.  */
-
-static int
-add_values_to_cover (struct dimension *dim)
-{
-  struct attr_value *av;
-  rtx exp, link, *prev;
-  int nalt = 0;
-
-  for (av = dim->attr->first_value; av; av = av->next)
-    if (GET_CODE (av->value) == CONST_STRING)
-      nalt++;
-
-  if (nalt < dim->num_values)
-    abort ();
-  else if (nalt == dim->num_values)
-    /* OK.  */
-    ;
-  else if (nalt * 2 < dim->num_values * 3)
-    {
-      /* Most all the values of the attribute are used, so add all the unused
-        values.  */
-      prev = &dim->values;
-      for (link = dim->values; link; link = *prev)
-       prev = &XEXP (link, 1);
-
-      for (av = dim->attr->first_value; av; av = av->next)
-       if (GET_CODE (av->value) == CONST_STRING)
-         {
-           exp = attr_eq (dim->attr->name, XSTR (av->value, 0));
-           if (ATTR_EQ_ATTR_P (exp))
-             continue;
-
-           link = rtx_alloc (EXPR_LIST);
-           XEXP (link, 0) = exp;
-           XEXP (link, 1) = 0;
-           *prev = link;
-           prev = &XEXP (link, 1);
-         }
-      dim->num_values = nalt;
-    }
-  else
-    {
-      rtx orexp = false_rtx;
-
-      /* Very few values are used, so compute a mutually exclusive
-        expression.  (We could do this for numeric values if that becomes
-        important.)  */
-      prev = &dim->values;
-      for (link = dim->values; link; link = *prev)
-       {
-         orexp = insert_right_side (IOR, orexp, XEXP (link, 0), -2, -2);
-         prev = &XEXP (link, 1);
-       }
-      link = rtx_alloc (EXPR_LIST);
-      XEXP (link, 0) = attr_rtx (NOT, orexp);
-      XEXP (link, 1) = 0;
-      *prev = link;
-      dim->num_values++;
-    }
-  return dim->num_values;
-}
-
-/* Increment the current value for the NDIM-dimensional attribute space SPACE
-   and return FALSE if the increment overflowed.  */
-
-static int
-increment_current_value (struct dimension *space, int ndim)
-{
-  int i;
-
-  for (i = ndim - 1; i >= 0; i--)
-    {
-      if ((space[i].current_value = XEXP (space[i].current_value, 1)) == 0)
-       space[i].current_value = space[i].values;
-      else
-       return 1;
-    }
-  return 0;
-}
-
-/* Construct an expression corresponding to the current value for the
-   NDIM-dimensional attribute space SPACE.  */
-
-static rtx
-test_for_current_value (struct dimension *space, int ndim)
-{
-  int i;
-  rtx exp = true_rtx;
-
-  for (i = 0; i < ndim; i++)
-    exp = insert_right_side (AND, exp, XEXP (space[i].current_value, 0),
-                            -2, -2);
-
-  return exp;
-}
-
-/* Given the current value of the NDIM-dimensional attribute space SPACE,
-   set the corresponding EQ_ATTR expressions to that value and reduce
-   the expression EXP as much as possible.  On input [and output], all
-   known EQ_ATTR expressions are set to FALSE.  */
-
-static rtx
-simplify_with_current_value (rtx exp, struct dimension *space, int ndim)
-{
-  int i;
-  rtx x;
-
-  /* Mark each current value as TRUE.  */
-  for (i = 0; i < ndim; i++)
-    {
-      x = XEXP (space[i].current_value, 0);
-      if (GET_CODE (x) == EQ_ATTR)
-       ATTR_EQ_ATTR_P (x) = 0;
-    }
-
-  exp = simplify_with_current_value_aux (exp);
-
-  /* Change each current value back to FALSE.  */
-  for (i = 0; i < ndim; i++)
-    {
-      x = XEXP (space[i].current_value, 0);
-      if (GET_CODE (x) == EQ_ATTR)
-       ATTR_EQ_ATTR_P (x) = 1;
-    }
+  /* Offset the table address so we can index by -2 or -1.  */
+  insn_code_values += 2;
 
-  return exp;
-}
+  iv = ivbuf = xmalloc (num_insn_ents * sizeof (struct attr_value_list));
 
-/* Reduce the expression EXP based on the ATTR_EQ_ATTR_P settings of
-   all EQ_ATTR expressions.  */
+  for (i = 0; i < MAX_ATTRS_INDEX; i++)
+    for (attr = attrs[i]; attr; attr = attr->next)
+      for (av = attr->first_value; av; av = av->next)
+       for (ie = av->first_insn; ie; ie = ie->next)
+         {
+           iv->attr = attr;
+           iv->av = av;
+           iv->ie = ie;
+           iv->next = insn_code_values[ie->def->insn_code];
+           insn_code_values[ie->def->insn_code] = iv;
+           iv++;
+         }
 
-static rtx
-simplify_with_current_value_aux (rtx exp)
-{
-  int i;
-  rtx cond;
+  /* Sanity check on num_insn_ents.  */
+  gcc_assert (iv == ivbuf + num_insn_ents);
 
-  switch (GET_CODE (exp))
+  /* Process one insn code at a time.  */
+  for (i = -2; i < insn_code_number; i++)
     {
-    case EQ_ATTR:
-      if (ATTR_EQ_ATTR_P (exp))
-       return false_rtx;
-      else
-       return true_rtx;
-    case CONST_STRING:
-    case CONST_INT:
-      return exp;
-
-    case IF_THEN_ELSE:
-      cond = simplify_with_current_value_aux (XEXP (exp, 0));
-      if (cond == true_rtx)
-       return simplify_with_current_value_aux (XEXP (exp, 1));
-      else if (cond == false_rtx)
-       return simplify_with_current_value_aux (XEXP (exp, 2));
-      else
-       return attr_rtx (IF_THEN_ELSE, cond,
-                        simplify_with_current_value_aux (XEXP (exp, 1)),
-                        simplify_with_current_value_aux (XEXP (exp, 2)));
+      /* Clear the ATTR_CURR_SIMPLIFIED_P flag everywhere relevant.
+        We use it to mean "already simplified for this insn".  */
+      for (iv = insn_code_values[i]; iv; iv = iv->next)
+       clear_struct_flag (iv->av->value);
 
-    case IOR:
-      cond = simplify_with_current_value_aux (XEXP (exp, 1));
-      if (cond == true_rtx)
-       return cond;
-      else if (cond == false_rtx)
-       return simplify_with_current_value_aux (XEXP (exp, 0));
-      else
-       return attr_rtx (IOR, cond,
-                        simplify_with_current_value_aux (XEXP (exp, 0)));
+      for (iv = insn_code_values[i]; iv; iv = iv->next)
+       {
+         struct obstack *old = rtl_obstack;
 
-    case AND:
-      cond = simplify_with_current_value_aux (XEXP (exp, 1));
-      if (cond == true_rtx)
-       return simplify_with_current_value_aux (XEXP (exp, 0));
-      else if (cond == false_rtx)
-       return cond;
-      else
-       return attr_rtx (AND, cond,
-                        simplify_with_current_value_aux (XEXP (exp, 0)));
+         attr = iv->attr;
+         av = iv->av;
+         ie = iv->ie;
+         if (GET_CODE (av->value) != COND)
+           continue;
 
-    case NOT:
-      cond = simplify_with_current_value_aux (XEXP (exp, 0));
-      if (cond == true_rtx)
-       return false_rtx;
-      else if (cond == false_rtx)
-       return true_rtx;
-      else
-       return attr_rtx (NOT, cond);
+         rtl_obstack = temp_obstack;
+         newexp = av->value;
+         while (GET_CODE (newexp) == COND)
+           {
+             rtx newexp2 = simplify_cond (newexp, ie->def->insn_code,
+                                          ie->def->insn_index);
+             if (newexp2 == newexp)
+               break;
+             newexp = newexp2;
+           }
 
-    case COND:
-      for (i = 0; i < XVECLEN (exp, 0); i += 2)
-       {
-         cond = simplify_with_current_value_aux (XVECEXP (exp, 0, i));
-         if (cond == true_rtx)
-           return simplify_with_current_value_aux (XVECEXP (exp, 0, i + 1));
-         else if (cond == false_rtx)
-           continue;
-         else
-           abort (); /* With all EQ_ATTR's of known value, a case should
-                        have been selected.  */
+         rtl_obstack = old;
+         if (newexp != av->value)
+           {
+             newexp = attr_copy_rtx (newexp);
+             remove_insn_ent (av, ie);
+             av = get_attr_value (newexp, attr, ie->def->insn_code);
+             iv->av = av;
+             insert_insn_ent (av, ie);
+           }
        }
-      return simplify_with_current_value_aux (XEXP (exp, 1));
-
-    default:
-      abort ();
     }
+
+  free (ivbuf);
+  free (insn_code_values - 2);
 }
 
 /* Clear the ATTR_CURR_SIMPLIFIED_P flag in EXP and its subexpressions.  */
@@ -4174,7 +2966,6 @@ clear_struct_flag (rtx x)
   switch (code)
     {
     case REG:
-    case QUEUED:
     case CONST_INT:
     case CONST_DOUBLE:
     case CONST_VECTOR:
@@ -4420,7 +3211,7 @@ gen_insn (rtx exp, int lineno)
       break;
 
     default:
-      abort ();
+      gcc_unreachable ();
     }
 }
 
@@ -4457,97 +3248,6 @@ gen_delay (rtx def, int lineno)
   delays = delay;
 }
 
-/* Process a DEFINE_FUNCTION_UNIT.
-
-   This gives information about a function unit contained in the CPU.
-   We fill in a `struct function_unit_op' and a `struct function_unit'
-   with information used later by `expand_unit'.  */
-
-static void
-gen_unit (rtx def, int lineno)
-{
-  struct function_unit *unit;
-  struct function_unit_op *op;
-  const char *name = XSTR (def, 0);
-  int multiplicity = XINT (def, 1);
-  int simultaneity = XINT (def, 2);
-  rtx condexp = XEXP (def, 3);
-  int ready_cost = MAX (XINT (def, 4), 1);
-  int issue_delay = MAX (XINT (def, 5), 1);
-
-  /* See if we have already seen this function unit.  If so, check that
-     the multiplicity and simultaneity values are the same.  If not, make
-     a structure for this function unit.  */
-  for (unit = units; unit; unit = unit->next)
-    if (! strcmp (unit->name, name))
-      {
-       if (unit->multiplicity != multiplicity
-           || unit->simultaneity != simultaneity)
-         {
-           message_with_line (lineno,
-                              "differing specifications given for function unit %s",
-                              unit->name);
-           message_with_line (unit->first_lineno, "previous definition");
-           have_error = 1;
-           return;
-         }
-       break;
-      }
-
-  if (unit == 0)
-    {
-      unit = oballoc (sizeof (struct function_unit));
-      unit->name = name;
-      unit->multiplicity = multiplicity;
-      unit->simultaneity = simultaneity;
-      unit->issue_delay.min = unit->issue_delay.max = issue_delay;
-      unit->num = num_units++;
-      unit->num_opclasses = 0;
-      unit->condexp = false_rtx;
-      unit->ops = 0;
-      unit->next = units;
-      unit->first_lineno = lineno;
-      units = unit;
-    }
-  else
-    XSTR (def, 0) = unit->name;
-
-  /* Make a new operation class structure entry and initialize it.  */
-  op = oballoc (sizeof (struct function_unit_op));
-  op->condexp = condexp;
-  op->num = unit->num_opclasses++;
-  op->ready = ready_cost;
-  op->issue_delay = issue_delay;
-  op->next = unit->ops;
-  op->lineno = lineno;
-  unit->ops = op;
-  num_unit_opclasses++;
-
-  /* Set our issue expression based on whether or not an optional conflict
-     vector was specified.  */
-  if (XVEC (def, 6))
-    {
-      /* Compute the IOR of all the specified expressions.  */
-      rtx orexp = false_rtx;
-      int i;
-
-      for (i = 0; i < XVECLEN (def, 6); i++)
-       orexp = insert_right_side (IOR, orexp, XVECEXP (def, 6, i), -2, -2);
-
-      op->conflict_exp = orexp;
-      extend_range (&unit->issue_delay, 1, issue_delay);
-    }
-  else
-    {
-      op->conflict_exp = true_rtx;
-      extend_range (&unit->issue_delay, issue_delay, issue_delay);
-    }
-
-  /* Merge our conditional into that of the function unit so we can determine
-     which insns are used by the function unit.  */
-  unit->condexp = insert_right_side (IOR, unit->condexp, op->condexp, -2, -2);
-}
-
 /* Given a piece of RTX, print a C expression to test its truth value.
    We use AND and IOR both for logical and bit-wise operations, so
    interpret them as logical unless they are inside a comparison expression.
@@ -4655,7 +3355,7 @@ write_test_expr (rtx exp, int flags)
          printf (" >> ");
          break;
        default:
-         abort ();
+         gcc_unreachable ();
        }
 
       write_test_expr (XEXP (exp, 1), flags | comparison_operator);
@@ -4689,7 +3389,7 @@ write_test_expr (rtx exp, int flags)
          printf ("-");
          break;
        default:
-         abort ();
+         gcc_unreachable ();
        }
 
       write_test_expr (XEXP (exp, 0), flags);
@@ -4755,8 +3455,7 @@ write_test_expr (rtx exp, int flags)
        }
 
       attr = find_attr (&XSTR (exp, 0), 0);
-      if (! attr)
-       abort ();
+      gcc_assert (attr);
 
       /* Now is the time to expand the value of a constant attribute.  */
       if (attr->is_const)
@@ -4807,7 +3506,7 @@ write_test_expr (rtx exp, int flags)
 
     /* A random C expression.  */
     case SYMBOL_REF:
-      printf ("%s", XSTR (exp, 0));
+      print_c_condition (XSTR (exp, 0));
       break;
 
     /* The address of the branch target.  */
@@ -5036,45 +3735,23 @@ write_attr_get (struct attr_desc *attr)
       for (av = attr->first_value; av; av = av->next)
        if (av->num_insns != 0)
          write_attr_set (attr, 2, av->value, "return", ";",
-                         true_rtx, av->first_insn->insn_code,
-                         av->first_insn->insn_index);
+                         true_rtx, av->first_insn->def->insn_code,
+                         av->first_insn->def->insn_index);
 
       printf ("}\n\n");
       return;
     }
 
   printf ("{\n");
+  printf ("  switch (recog_memoized (insn))\n");
+  printf ("    {\n");
 
-  if (GET_CODE (common_av->value) == FFS)
-    {
-      rtx p = XEXP (common_av->value, 0);
-
-      /* No need to emit code to abort if the insn is unrecognized; the
-         other get_attr_foo functions will do that when we call them.  */
-
-      write_toplevel_expr (p);
-
-      printf ("\n  if (accum && accum == (accum & -accum))\n");
-      printf ("    {\n");
-      printf ("      int i;\n");
-      printf ("      for (i = 0; accum >>= 1; ++i) continue;\n");
-      printf ("      accum = i;\n");
-      printf ("    }\n  else\n");
-      printf ("    accum = ~accum;\n");
-      printf ("  return accum;\n}\n\n");
-    }
-  else
-    {
-      printf ("  switch (recog_memoized (insn))\n");
-      printf ("    {\n");
-
-      for (av = attr->first_value; av; av = av->next)
-       if (av != common_av)
-         write_attr_case (attr, av, 1, "return", ";", 4, true_rtx);
+  for (av = attr->first_value; av; av = av->next)
+    if (av != common_av)
+      write_attr_case (attr, av, 1, "return", ";", 4, true_rtx);
 
-      write_attr_case (attr, common_av, 0, "return", ";", 4, true_rtx);
-      printf ("    }\n}\n\n");
-    }
+  write_attr_case (attr, common_av, 0, "return", ";", 4, true_rtx);
+  printf ("    }\n}\n\n");
 }
 
 /* Given an AND tree of known true terms (because we are inside an `if' with
@@ -5197,6 +3874,25 @@ write_attr_set (struct attr_desc *attr, int indent, rtx value,
     }
 }
 
+/* Write a series of case statements for every instruction in list IE.
+   INDENT is the amount of indentation to write before each case.  */
+
+static void
+write_insn_cases (struct insn_ent *ie, int indent)
+{
+  for (; ie != 0; ie = ie->next)
+    if (ie->def->insn_code != -1)
+      {
+       write_indent (indent);
+       if (GET_CODE (ie->def->def) == DEFINE_PEEPHOLE)
+         printf ("case %d:  /* define_peephole, line %d */\n",
+                 ie->def->insn_code, ie->def->lineno);
+       else
+         printf ("case %d:  /* %s */\n",
+                 ie->def->insn_code, XSTR (ie->def->def, 0));
+      }
+}
+
 /* Write out the computation for one attribute value.  */
 
 static void
@@ -5204,8 +3900,6 @@ write_attr_case (struct attr_desc *attr, struct attr_value *av,
                 int write_case_lines, const char *prefix, const char *suffix,
                 int indent, rtx known_true)
 {
-  struct insn_ent *ie;
-
   if (av->num_insns == 0)
     return;
 
@@ -5222,14 +3916,7 @@ write_attr_case (struct attr_desc *attr, struct attr_value *av,
     }
 
   if (write_case_lines)
-    {
-      for (ie = av->first_insn; ie; ie = ie->next)
-       if (ie->insn_code != -1)
-         {
-           write_indent (indent);
-           printf ("case %d:\n", ie->insn_code);
-         }
-    }
+    write_insn_cases (av->first_insn, indent);
   else
     {
       write_indent (indent);
@@ -5252,8 +3939,8 @@ write_attr_case (struct attr_desc *attr, struct attr_value *av,
     }
 
   write_attr_set (attr, indent + 2, av->value, prefix, suffix,
-                 known_true, av->first_insn->insn_code,
-                 av->first_insn->insn_index);
+                 known_true, av->first_insn->def->insn_code,
+                 av->first_insn->def->insn_index);
 
   if (strncmp (prefix, "return", 6))
     {
@@ -5310,56 +3997,7 @@ write_expr_attr_cache (rtx p, struct attr_desc *attr)
   return 0;
 }
 
-/* Evaluate an expression at top level.  A front end to write_test_expr,
-   in which we cache attribute values and break up excessively large
-   expressions to cater to older compilers.  */
-
-static void
-write_toplevel_expr (rtx p)
-{
-  struct attr_desc *attr;
-  int i;
-
-  for (i = 0; i < MAX_ATTRS_INDEX; ++i)
-    for (attr = attrs[i]; attr; attr = attr->next)
-      if (!attr->is_const)
-       write_expr_attr_cache (p, attr);
-
-  printf ("  unsigned long accum = 0;\n\n");
-
-  while (GET_CODE (p) == IOR)
-    {
-      rtx e;
-      if (GET_CODE (XEXP (p, 0)) == IOR)
-       e = XEXP (p, 1), p = XEXP (p, 0);
-      else
-       e = XEXP (p, 0), p = XEXP (p, 1);
-
-      printf ("  accum |= ");
-      write_test_expr (e, 3);
-      printf (";\n");
-    }
-  printf ("  accum |= ");
-  write_test_expr (p, 3);
-  printf (";\n");
-}
-
-/* Utilities to write names in various forms.  */
-
-static void
-write_unit_name (const char *prefix, int num, const char *suffix)
-{
-  struct function_unit *unit;
-
-  for (unit = units; unit; unit = unit->next)
-    if (unit->num == num)
-      {
-       printf ("%s%s%s", prefix, unit->name, suffix);
-       return;
-      }
-
-  printf ("%s<unknown>%s", prefix, suffix);
-}
+/* Utilities to write in various forms.  */
 
 static void
 write_attr_valueq (struct attr_desc *attr, const char *s)
@@ -5370,32 +4008,7 @@ write_attr_valueq (struct attr_desc *attr, const char *s)
 
       printf ("%d", num);
 
-      /* Make the blockage range values and function units used values easier
-         to read.  */
-      if (attr->func_units_p)
-       {
-         if (num == -1)
-           printf (" /* units: none */");
-         else if (num >= 0)
-           write_unit_name (" /* units: ", num, " */");
-         else
-           {
-             int i;
-             const char *sep = " /* units: ";
-             for (i = 0, num = ~num; num; i++, num >>= 1)
-               if (num & 1)
-                 {
-                   write_unit_name (sep, i, (num == 1) ? " */" : "");
-                   sep = ", ";
-                 }
-           }
-       }
-
-      else if (attr->blockage_p)
-       printf (" /* min %d, max %d */", num >> (HOST_BITS_PER_INT / 2),
-               num & ((1 << (HOST_BITS_PER_INT / 2)) - 1));
-
-      else if (num > 9 || num < 0)
+      if (num > 9 || num < 0)
        printf (" /* 0x%x */", num);
     }
   else
@@ -5422,7 +4035,7 @@ write_attr_value (struct attr_desc *attr, rtx value)
       break;
 
     case SYMBOL_REF:
-      fputs (XSTR (value, 0), stdout);
+      print_c_condition (XSTR (value, 0));
       break;
 
     case ATTR:
@@ -5458,7 +4071,7 @@ write_attr_value (struct attr_desc *attr, rtx value)
       break;
 
     default:
-      abort ();
+      gcc_unreachable ();
     }
 }
 
@@ -5522,8 +4135,7 @@ write_eligible_delay (const char *kind)
   printf ("{\n");
   printf ("  rtx insn;\n");
   printf ("\n");
-  printf ("  if (slot >= %d)\n", max_slots);
-  printf ("    abort ();\n");
+  printf ("  gcc_assert (slot < %d);\n", max_slots);
   printf ("\n");
   /* Allow dbr_schedule to pass labels, etc.  This can happen if try_split
      converts a compound instruction into a loop.  */
@@ -5536,8 +4148,7 @@ write_eligible_delay (const char *kind)
   if (num_delays > 1)
     {
       attr = find_attr (&delay_type_str, 0);
-      if (! attr)
-       abort ();
+      gcc_assert (attr);
       common_av = find_most_used (attr);
 
       printf ("  insn = delay_insn;\n");
@@ -5553,8 +4164,7 @@ write_eligible_delay (const char *kind)
       printf ("    }\n\n");
 
       /* Ensure matched.  Otherwise, shouldn't have been called.  */
-      printf ("  if (slot < %d)\n", max_slots);
-      printf ("    abort ();\n\n");
+      printf ("  gcc_assert (slot >= %d);\n\n", max_slots);
     }
 
   /* If just one type of delay slot, write simple switch.  */
@@ -5565,8 +4175,7 @@ write_eligible_delay (const char *kind)
       printf ("    {\n");
 
       attr = find_attr (&delay_1_0_str, 0);
-      if (! attr)
-       abort ();
+      gcc_assert (attr);
       common_av = find_most_used (attr);
 
       for (av = attr->first_value; av; av = av->next)
@@ -5596,8 +4205,7 @@ write_eligible_delay (const char *kind)
            sprintf (str, "*%s_%d_%d", kind, delay->num, i / 3);
            pstr = str;
            attr = find_attr (&pstr, 0);
-           if (! attr)
-             abort ();
+           gcc_assert (attr);
            common_av = find_most_used (attr);
 
            for (av = attr->first_value; av; av = av->next)
@@ -5609,182 +4217,13 @@ write_eligible_delay (const char *kind)
          }
 
       printf ("    default:\n");
-      printf ("      abort ();\n");
+      printf ("      gcc_unreachable ();\n");
       printf ("    }\n");
     }
 
   printf ("}\n\n");
 }
 
-/* Write routines to compute conflict cost for function units.  Then write a
-   table describing the available function units.  */
-
-static void
-write_function_unit_info (void)
-{
-  struct function_unit *unit;
-  int i;
-
-  /* Write out conflict routines for function units.  Don't bother writing
-     one if there is only one issue delay value.  */
-
-  for (unit = units; unit; unit = unit->next)
-    {
-      if (unit->needs_blockage_function)
-       write_complex_function (unit, "blockage", "block");
-
-      /* If the minimum and maximum conflict costs are the same, there
-        is only one value, so we don't need a function.  */
-      if (! unit->needs_conflict_function)
-       {
-         unit->default_cost = make_numeric_value (unit->issue_delay.max);
-         continue;
-       }
-
-      /* The function first computes the case from the candidate insn.  */
-      unit->default_cost = make_numeric_value (0);
-      write_complex_function (unit, "conflict_cost", "cost");
-    }
-
-  /* Now that all functions have been written, write the table describing
-     the function units.   The name is included for documentation purposes
-     only.  */
-
-  printf ("const struct function_unit_desc function_units[] = {\n");
-
-  /* Write out the descriptions in numeric order, but don't force that order
-     on the list.  Doing so increases the runtime of genattrtab.c.  */
-  for (i = 0; i < num_units; i++)
-    {
-      for (unit = units; unit; unit = unit->next)
-       if (unit->num == i)
-         break;
-
-      printf ("  {\"%s\", %d, %d, %d, %s, %d, %s_unit_ready_cost, ",
-             unit->name, 1 << unit->num, unit->multiplicity,
-             unit->simultaneity, XSTR (unit->default_cost, 0),
-             unit->issue_delay.max, unit->name);
-
-      if (unit->needs_conflict_function)
-       printf ("%s_unit_conflict_cost, ", unit->name);
-      else
-       printf ("0, ");
-
-      printf ("%d, ", unit->max_blockage);
-
-      if (unit->needs_range_function)
-       printf ("%s_unit_blockage_range, ", unit->name);
-      else
-       printf ("0, ");
-
-      if (unit->needs_blockage_function)
-       printf ("%s_unit_blockage", unit->name);
-      else
-       printf ("0");
-
-      printf ("}, \n");
-    }
-
-  if (num_units == 0)
-    printf ("{\"dummy\", 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} /* a dummy element */");
-  printf ("};\n\n");
-}
-
-static void
-write_complex_function (struct function_unit *unit,
-                       const char *name,
-                       const char *connection)
-{
-  struct attr_desc *case_attr, *attr;
-  struct attr_value *av, *common_av;
-  rtx value;
-  char str[256];
-  const char *pstr;
-  int using_case;
-  int i;
-
-  printf ("static int\n");
-  printf ("%s_unit_%s (rtx executing_insn, rtx candidate_insn)\n",
-         unit->name, name);
-  printf ("{\n");
-  printf ("  rtx insn;\n");
-  printf ("  int casenum;\n\n");
-  printf ("  insn = executing_insn;\n");
-  printf ("  switch (recog_memoized (insn))\n");
-  printf ("    {\n");
-
-  /* Write the `switch' statement to get the case value.  */
-  if (strlen (unit->name) + sizeof "*_cases" > 256)
-    abort ();
-  sprintf (str, "*%s_cases", unit->name);
-  pstr = str;
-  case_attr = find_attr (&pstr, 0);
-  if (! case_attr)
-    abort ();
-  common_av = find_most_used (case_attr);
-
-  for (av = case_attr->first_value; av; av = av->next)
-    if (av != common_av)
-      write_attr_case (case_attr, av, 1,
-                      "casenum =", ";", 4, unit->condexp);
-
-  write_attr_case (case_attr, common_av, 0,
-                  "casenum =", ";", 4, unit->condexp);
-  printf ("    }\n\n");
-
-  /* Now write an outer switch statement on each case.  Then write
-     the tests on the executing function within each.  */
-  printf ("  insn = candidate_insn;\n");
-  printf ("  switch (casenum)\n");
-  printf ("    {\n");
-
-  for (i = 0; i < unit->num_opclasses; i++)
-    {
-      /* Ensure using this case.  */
-      using_case = 0;
-      for (av = case_attr->first_value; av; av = av->next)
-       if (av->num_insns
-           && contained_in_p (make_numeric_value (i), av->value))
-         using_case = 1;
-
-      if (! using_case)
-       continue;
-
-      printf ("    case %d:\n", i);
-      sprintf (str, "*%s_%s_%d", unit->name, connection, i);
-      pstr = str;
-      attr = find_attr (&pstr, 0);
-      if (! attr)
-       abort ();
-
-      /* If single value, just write it.  */
-      value = find_single_value (attr);
-      if (value)
-       write_attr_set (attr, 6, value, "return", ";\n", true_rtx, -2, -2);
-      else
-       {
-         common_av = find_most_used (attr);
-         printf ("      switch (recog_memoized (insn))\n");
-         printf ("\t{\n");
-
-         for (av = attr->first_value; av; av = av->next)
-           if (av != common_av)
-             write_attr_case (attr, av, 1,
-                              "return", ";", 8, unit->condexp);
-
-         write_attr_case (attr, common_av, 0,
-                          "return", ";", 8, unit->condexp);
-         printf ("      }\n\n");
-       }
-    }
-
-  /* This default case should not be needed, but gcc's analysis is not
-     good enough to realize that the default case is not needed for the
-     second switch statement.  */
-  printf ("    default:\n      abort ();\n");
-  printf ("    }\n}\n\n");
-}
-
 /* This page contains miscellaneous utility routines.  */
 
 /* Given a pointer to a (char *), return a malloc'ed string containing the
@@ -5840,7 +4279,7 @@ find_attr (const char **name_p, int create)
   attr->name = DEF_ATTR_STRING (name);
   attr->first_value = attr->default_val = NULL;
   attr->is_numeric = attr->negative_ok = attr->is_const = attr->is_special = 0;
-  attr->unsigned_p = attr->func_units_p = attr->blockage_p = attr->static_p = 0;
+  attr->unsigned_p = attr->static_p = 0;
   attr->next = attrs[index];
   attrs[index] = attr;
 
@@ -5857,16 +4296,13 @@ make_internal_attr (const char *name, rtx value, int special)
   struct attr_desc *attr;
 
   attr = find_attr (&name, 1);
-  if (attr->default_val)
-    abort ();
+  gcc_assert (!attr->default_val);
 
   attr->is_numeric = 1;
   attr->is_const = 0;
   attr->is_special = (special & ATTR_SPECIAL) != 0;
   attr->negative_ok = (special & ATTR_NEGATIVE_OK) != 0;
   attr->unsigned_p = (special & ATTR_UNSIGNED) != 0;
-  attr->func_units_p = (special & ATTR_FUNC_UNITS) != 0;
-  attr->blockage_p = (special & ATTR_BLOCKAGE) != 0;
   attr->static_p = (special & ATTR_STATIC) != 0;
   attr->default_val = get_attr_value (value, attr, -2);
 }
@@ -5890,28 +4326,6 @@ find_most_used (struct attr_desc *attr)
   return most_used;
 }
 
-/* If an attribute only has a single value used, return it.  Otherwise
-   return NULL.  */
-
-static rtx
-find_single_value (struct attr_desc *attr)
-{
-  struct attr_value *av;
-  rtx unique_value;
-
-  unique_value = NULL;
-  for (av = attr->first_value; av; av = av->next)
-    if (av->num_insns)
-      {
-       if (unique_value)
-         return NULL;
-       else
-         unique_value = av->value;
-      }
-
-  return unique_value;
-}
-
 /* Return (attr_value "n") */
 
 rtx
@@ -5921,8 +4335,7 @@ make_numeric_value (int n)
   rtx exp;
   char *p;
 
-  if (n < 0)
-    abort ();
+  gcc_assert (n >= 0);
 
   if (n < 20 && int_values[n])
     return int_values[n];
@@ -5936,15 +4349,6 @@ make_numeric_value (int n)
   return exp;
 }
 
-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 rtx
 copy_rtx_unchanging (rtx orig)
 {
@@ -5963,7 +4367,6 @@ write_const_num_delay_slots (void)
 {
   struct attr_desc *attr = find_attr (&num_delay_slots_str, 0);
   struct attr_value *av;
-  struct insn_ent *ie;
 
   if (attr)
     {
@@ -5977,12 +4380,7 @@ write_const_num_delay_slots (void)
          length_used = 0;
          walk_attr_value (av->value);
          if (length_used)
-           {
-             for (ie = av->first_insn; ie; ie = ie->next)
-               if (ie->insn_code != -1)
-                 printf ("    case %d:\n", ie->insn_code);
-             printf ("      return 0;\n");
-           }
+           write_insn_cases (av->first_insn, 4);
        }
 
       printf ("    default:\n");
@@ -6002,9 +4400,6 @@ main (int argc, char **argv)
 
   progname = "genattrtab";
 
-  if (argc <= 1)
-    fatal ("no input file name");
-
   if (init_md_reader_args (argc, argv) != SUCCESS_EXIT_CODE)
     return (FATAL_EXIT_CODE);
 
@@ -6055,10 +4450,6 @@ from the machine description file `md'.  */\n\n");
          gen_delay (desc, lineno);
          break;
 
-       case DEFINE_FUNCTION_UNIT:
-         gen_unit (desc, lineno);
-         break;
-
        case DEFINE_CPU_UNIT:
          gen_cpu_unit (desc);
          break;
@@ -6131,14 +4522,10 @@ from the machine description file `md'.  */\n\n");
   if (num_delays)
     expand_delays ();
 
-  if (num_units || num_dfa_decls)
-    {
-      /* Expand DEFINE_FUNCTION_UNIT information into new attributes.  */
-      expand_units ();
-      /* Build DFA, output some functions and expand DFA information
-        into new attributes.  */
-      expand_automata ();
-    }
+  /* Build DFA, output some functions and expand DFA information
+     to new attributes.  */
+  if (num_dfa_decls)
+    expand_automata ();
 
   printf ("#include \"config.h\"\n");
   printf ("#include \"system.h\"\n");
@@ -6194,8 +4581,7 @@ from the machine description file `md'.  */\n\n");
   optimize_attrs ();
 
   /* Now write out all the `gen_attr_...' routines.  Do these before the
-     special routines (specifically before write_function_unit_info), so
-     that they get defined before they are used.  */
+     special routines so that they get defined before they are used.  */
 
   for (i = 0; i < MAX_ATTRS_INDEX; i++)
     for (attr = attrs[i]; attr; attr = attr->next)
@@ -6227,14 +4613,10 @@ from the machine description file `md'.  */\n\n");
        write_eligible_delay ("annul_false");
     }
 
-  if (num_units || num_dfa_decls)
-    {
-      /* Write out information about function units.  */
-      write_function_unit_info ();
-      /* Output code for pipeline hazards recognition based on DFA
-        (deterministic finite state automata.  */
-      write_automata ();
-    }
+  /* Output code for pipeline hazards recognition based on DFA
+     (deterministic finite-state automata).  */
+  if (num_dfa_decls)
+    write_automata ();
 
   /* Write out constant delay slot info.  */
   write_const_num_delay_slots ();