Annotation of GNUtools/cc/genattrtab.c, revision 1.1

1.1     ! root        1: /* Generate code from machine description to compute values of attributes.
        !             2:    Copyright (C) 1991, 1993 Free Software Foundation, Inc.
        !             3:    Contributed by Richard Kenner ([email protected])
        !             4: 
        !             5: This file is part of GNU CC.
        !             6: 
        !             7: GNU CC is free software; you can redistribute it and/or modify
        !             8: it under the terms of the GNU General Public License as published by
        !             9: the Free Software Foundation; either version 2, or (at your option)
        !            10: any later version.
        !            11: 
        !            12: GNU CC is distributed in the hope that it will be useful,
        !            13: but WITHOUT ANY WARRANTY; without even the implied warranty of
        !            14: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
        !            15: GNU General Public License for more details.
        !            16: 
        !            17: You should have received a copy of the GNU General Public License
        !            18: along with GNU CC; see the file COPYING.  If not, write to
        !            19: the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
        !            20: 
        !            21: /* This program handles insn attributes and the DEFINE_DELAY and
        !            22:    DEFINE_FUNCTION_UNIT definitions.
        !            23: 
        !            24:    It produces a series of functions named `get_attr_...', one for each insn
        !            25:    attribute.  Each of these is given the rtx for an insn and returns a member
        !            26:    of the enum for the attribute.
        !            27: 
        !            28:    These subroutines have the form of a `switch' on the INSN_CODE (via
        !            29:    `recog_memoized').  Each case either returns a constant attribute value
        !            30:    or a value that depends on tests on other attributes, the form of
        !            31:    operands, or some random C expression (encoded with a SYMBOL_REF
        !            32:    expression).
        !            33: 
        !            34:    If the attribute `alternative', or a random C expression is present,
        !            35:    `constrain_operands' is called.  If either of these cases of a reference to
        !            36:    an operand is found, `insn_extract' is called.
        !            37: 
        !            38:    The special attribute `length' is also recognized.  For this operand, 
        !            39:    expressions involving the address of an operand or the current insn,
        !            40:    (address (pc)), are valid.  In this case, an initial pass is made to
        !            41:    set all lengths that do not depend on address.  Those that do are set to
        !            42:    the maximum length.  Then each insn that depends on an address is checked
        !            43:    and possibly has its length changed.  The process repeats until no further
        !            44:    changed are made.  The resulting lengths are saved for use by
        !            45:    `get_attr_length'.
        !            46: 
        !            47:    A special form of DEFINE_ATTR, where the expression for default value is a
        !            48:    CONST expression, indicates an attribute that is constant for a given run
        !            49:    of the compiler.  The subroutine generated for these attributes has no
        !            50:    parameters as it does not depend on any particular insn.  Constant
        !            51:    attributes are typically used to specify which variety of processor is
        !            52:    used.
        !            53:    
        !            54:    Internal attributes are defined to handle DEFINE_DELAY and
        !            55:    DEFINE_FUNCTION_UNIT.  Special routines are output for these cases.
        !            56: 
        !            57:    This program works by keeping a list of possible values for each attribute.
        !            58:    These include the basic attribute choices, default values for attribute, and
        !            59:    all derived quantities.
        !            60: 
        !            61:    As the description file is read, the definition for each insn is saved in a
        !            62:    `struct insn_def'.   When the file reading is complete, a `struct insn_ent'
        !            63:    is created for each insn and chained to the corresponding attribute value,
        !            64:    either that specified, or the default.
        !            65: 
        !            66:    An optimization phase is then run.  This simplifies expressions for each
        !            67:    insn.  EQ_ATTR tests are resolved, whenever possible, to a test that
        !            68:    indicates when the attribute has the specified value for the insn.  This
        !            69:    avoids recursive calls during compilation.
        !            70: 
        !            71:    The strategy used when processing DEFINE_DELAY and DEFINE_FUNCTION_UNIT
        !            72:    definitions is to create arbitrarily complex expressions and have the
        !            73:    optimization simplify them.
        !            74: 
        !            75:    Once optimization is complete, any required routines and definitions
        !            76:    will be written.
        !            77: 
        !            78:    An optimization that is not yet implemented is to hoist the constant
        !            79:    expressions entirely out of the routines and definitions that are written.
        !            80:    A way to do this is to iterate over all possible combinations of values
        !            81:    for constant attributes and generate a set of functions for that given
        !            82:    combination.  An initialization function would be written that evaluates
        !            83:    the attributes and installs the corresponding set of routines and
        !            84:    definitions (each would be accessed through a pointer).
        !            85: 
        !            86:    We use the flags in an RTX as follows:
        !            87:    `unchanging' (RTX_UNCHANGING_P): This rtx is fully simplified
        !            88:       independent of the insn code.
        !            89:    `in_struct' (MEM_IN_STRUCT_P): This rtx is fully simplified
        !            90:       for the insn code currently being processed (see optimize_attrs).
        !            91:    `integrated' (RTX_INTEGRATED_P): This rtx is permanent and unique
        !            92:       (see attr_rtx).
        !            93:    `volatil' (MEM_VOLATILE_P): During simplify_by_exploding the value of an
        !            94:       EQ_ATTR rtx is true if !volatil and false if volatil.  */
        !            95: 
        !            96: 
        !            97: #include "hconfig.h"
        !            98: /* gvarargs must always be included after *config.h.  */
        !            99: #include "gvarargs.h"
        !           100: #include "rtl.h"
        !           101: #include "insn-config.h"       /* For REGISTER_CONSTRAINTS */
        !           102: #include <stdio.h>
        !           103: 
        !           104: #ifndef VMS
        !           105: #ifndef USG
        !           106: #include <sys/time.h>
        !           107: #include <sys/resource.h>
        !           108: #endif
        !           109: #endif
        !           110: 
        !           111: /* We must include obstack.h after <sys/time.h>, to avoid lossage with
        !           112:    /usr/include/sys/stdtypes.h on Sun OS 4.x.  */
        !           113: #include "obstack.h"
        !           114: 
        !           115: static struct obstack obstack, obstack1, obstack2;
        !           116: struct obstack *rtl_obstack = &obstack;
        !           117: struct obstack *hash_obstack = &obstack1;
        !           118: struct obstack *temp_obstack = &obstack2;
        !           119: 
        !           120: #define obstack_chunk_alloc xmalloc
        !           121: #define obstack_chunk_free free
        !           122: 
        !           123: /* Define this so we can link with print-rtl.o to get debug_rtx function.  */
        !           124: char **insn_name_ptr = 0;
        !           125: 
        !           126: extern void free ();
        !           127: extern rtx read_rtx ();
        !           128: 
        !           129: static void fatal ();
        !           130: void fancy_abort ();
        !           131: 
        !           132: /* enough space to reserve for printing out ints */
        !           133: #define MAX_DIGITS (HOST_BITS_PER_INT * 3 / 10 + 3)
        !           134: 
        !           135: /* Define structures used to record attributes and values.  */
        !           136: 
        !           137: /* As each DEFINE_INSN, DEFINE_PEEPHOLE, or DEFINE_ASM_ATTRIBUTES is
        !           138:    encountered, we store all the relevant information into a
        !           139:    `struct insn_def'.  This is done to allow attribute definitions to occur
        !           140:    anywhere in the file.  */
        !           141: 
        !           142: struct insn_def
        !           143: {
        !           144:   int insn_code;               /* Instruction number. */
        !           145:   int insn_index;              /* Expression numer in file, for errors. */
        !           146:   struct insn_def *next;       /* Next insn in chain. */
        !           147:   rtx def;                     /* The DEFINE_... */
        !           148:   int num_alternatives;                /* Number of alternatives.  */
        !           149:   int vec_idx;                 /* Index of attribute vector in `def'. */
        !           150: };
        !           151: 
        !           152: /* Once everything has been read in, we store in each attribute value a list
        !           153:    of insn codes that have that value.  Here is the structure used for the
        !           154:    list.  */
        !           155: 
        !           156: struct insn_ent
        !           157: {
        !           158:   int insn_code;               /* Instruction number.  */
        !           159:   int insn_index;              /* Index of definition in file */
        !           160:   struct insn_ent *next;       /* Next in chain.  */
        !           161: };
        !           162: 
        !           163: /* Each value of an attribute (either constant or computed) is assigned a
        !           164:    structure which is used as the listhead of the insns that have that
        !           165:    value.  */
        !           166: 
        !           167: struct attr_value
        !           168: {
        !           169:   rtx value;                   /* Value of attribute.  */
        !           170:   struct attr_value *next;     /* Next attribute value in chain.  */
        !           171:   struct insn_ent *first_insn; /* First insn with this value.  */
        !           172:   int num_insns;               /* Number of insns with this value.  */
        !           173:   int has_asm_insn;            /* True if this value used for `asm' insns */
        !           174: };
        !           175: 
        !           176: /* Structure for each attribute.  */
        !           177: 
        !           178: struct attr_desc
        !           179: {
        !           180:   char *name;                  /* Name of attribute. */
        !           181:   struct attr_desc *next;      /* Next attribute. */
        !           182:   int is_numeric;              /* Values of this attribute are numeric. */
        !           183:   int negative_ok;             /* Allow negative numeric values.  */
        !           184:   int unsigned_p;              /* Make the output function unsigned int.  */
        !           185:   int is_const;                        /* Attribute value constant for each run.  */
        !           186:   int is_special;              /* Don't call `write_attr_set'. */
        !           187:   struct attr_value *first_value; /* First value of this attribute. */
        !           188:   struct attr_value *default_val; /* Default value for this attribute. */
        !           189: };
        !           190: 
        !           191: #define NULL_ATTR (struct attr_desc *) NULL
        !           192: 
        !           193: /* A range of values.  */
        !           194: 
        !           195: struct range
        !           196: {
        !           197:   int min;
        !           198:   int max;
        !           199: };
        !           200: 
        !           201: /* Structure for each DEFINE_DELAY.  */
        !           202: 
        !           203: struct delay_desc
        !           204: {
        !           205:   rtx def;                     /* DEFINE_DELAY expression.  */
        !           206:   struct delay_desc *next;     /* Next DEFINE_DELAY. */
        !           207:   int num;                     /* Number of DEFINE_DELAY, starting at 1.  */
        !           208: };
        !           209: 
        !           210: /* Record information about each DEFINE_FUNCTION_UNIT.  */
        !           211: 
        !           212: struct function_unit_op
        !           213: {
        !           214:   rtx condexp;                 /* Expression TRUE for applicable insn.  */
        !           215:   struct function_unit_op *next; /* Next operation for this function unit.  */
        !           216:   int num;                     /* Ordinal for this operation type in unit.  */
        !           217:   int ready;                   /* Cost until data is ready.  */
        !           218:   int issue_delay;             /* Cost until unit can accept another insn.  */
        !           219:   rtx conflict_exp;            /* Expression TRUE for insns incurring issue delay.  */
        !           220:   rtx issue_exp;               /* Expression computing issue delay.  */
        !           221: };
        !           222: 
        !           223: /* Record information about each function unit mentioned in a
        !           224:    DEFINE_FUNCTION_UNIT.  */
        !           225: 
        !           226: struct function_unit
        !           227: {
        !           228:   char *name;                  /* Function unit name.  */
        !           229:   struct function_unit *next;  /* Next function unit.  */
        !           230:   int num;                     /* Ordinal of this unit type.  */
        !           231:   int multiplicity;            /* Number of units of this type.  */
        !           232:   int simultaneity;            /* Maximum number of simultaneous insns
        !           233:                                   on this function unit or 0 if unlimited.  */
        !           234:   rtx condexp;                 /* Expression TRUE for insn needing unit. */
        !           235:   int num_opclasses;           /* Number of different operation types.  */
        !           236:   struct function_unit_op *ops;        /* Pointer to first operation type.  */
        !           237:   int needs_conflict_function; /* Nonzero if a conflict function required.  */
        !           238:   int needs_blockage_function; /* Nonzero if a blockage function required.  */
        !           239:   int needs_range_function;    /* Nonzero if blockage range function needed.*/
        !           240:   rtx default_cost;            /* Conflict cost, if constant.  */
        !           241:   struct range issue_delay;    /* Range of issue delay values.  */
        !           242:   int max_blockage;            /* Maximum time an insn blocks the unit.  */
        !           243: };
        !           244: 
        !           245: /* Listheads of above structures.  */
        !           246: 
        !           247: /* This one is indexed by the first character of the attribute name.  */
        !           248: #define MAX_ATTRS_INDEX 256
        !           249: static struct attr_desc *attrs[MAX_ATTRS_INDEX];
        !           250: static struct insn_def *defs;
        !           251: static struct delay_desc *delays;
        !           252: static struct function_unit *units;
        !           253: 
        !           254: /* An expression where all the unknown terms are EQ_ATTR tests can be
        !           255:    rearranged into a COND provided we can enumerate all possible
        !           256:    combinations of the unknown values.  The set of combinations become the
        !           257:    tests of the COND; the value of the expression given that combination is
        !           258:    computed and becomes the corresponding value.  To do this, we must be
        !           259:    able to enumerate all values for each attribute used in the expression
        !           260:    (currently, we give up if we find a numeric attribute).
        !           261:    
        !           262:    If the set of EQ_ATTR tests used in an expression tests the value of N
        !           263:    different attributes, the list of all possible combinations can be made
        !           264:    by walking the N-dimensional attribute space defined by those
        !           265:    attributes.  We record each of these as a struct dimension.
        !           266: 
        !           267:    The algorithm relies on sharing EQ_ATTR nodes: if two nodes in an
        !           268:    expression are the same, the will also have the same address.  We find
        !           269:    all the EQ_ATTR nodes by marking them MEM_VOLATILE_P.  This bit later
        !           270:    represents the value of an EQ_ATTR node, so once all nodes are marked,
        !           271:    they are also given an initial value of FALSE.
        !           272: 
        !           273:    We then separate the set of EQ_ATTR nodes into dimensions for each
        !           274:    attribute and put them on the VALUES list.  Terms are added as needed by
        !           275:    `add_values_to_cover' so that all possible values of the attribute are
        !           276:    tested.
        !           277: 
        !           278:    Each dimension also has a current value.  This is the node that is
        !           279:    currently considered to be TRUE.  If this is one of the nodes added by
        !           280:    `add_values_to_cover', all the EQ_ATTR tests in the original expression
        !           281:    will be FALSE.  Otherwise, only the CURRENT_VALUE will be true.
        !           282: 
        !           283:    NUM_VALUES is simply the length of the VALUES list and is there for
        !           284:    convenience.
        !           285: 
        !           286:    Once the dimensions are created, the algorithm enumerates all possible
        !           287:    values and computes the current value of the given expression.  */
        !           288: 
        !           289: struct dimension 
        !           290: {
        !           291:   struct attr_desc *attr;      /* Attribute for this dimension.  */
        !           292:   rtx values;                  /* List of attribute values used.  */
        !           293:   rtx current_value;           /* Position in the list for the TRUE value.  */
        !           294:   int num_values;              /* Length of the values list.  */
        !           295: };
        !           296: 
        !           297: /* Other variables. */
        !           298: 
        !           299: static int insn_code_number;
        !           300: static int insn_index_number;
        !           301: static int got_define_asm_attributes;
        !           302: static int must_extract;
        !           303: static int must_constrain;
        !           304: static int address_used;
        !           305: static int length_used;
        !           306: static int num_delays;
        !           307: static int have_annul_true, have_annul_false;
        !           308: static int num_units;
        !           309: 
        !           310: /* Used as operand to `operate_exp':  */
        !           311: 
        !           312: enum operator {PLUS_OP, MINUS_OP, POS_MINUS_OP, EQ_OP, OR_OP, MAX_OP, MIN_OP, RANGE_OP};
        !           313: 
        !           314: /* Stores, for each insn code, the number of constraint alternatives.  */
        !           315: 
        !           316: static int *insn_n_alternatives;
        !           317: 
        !           318: /* Stores, for each insn code, a bitmap that has bits on for each possible
        !           319:    alternative.  */
        !           320: 
        !           321: static int *insn_alternatives;
        !           322: 
        !           323: /* If nonzero, assume that the `alternative' attr has this value.
        !           324:    This is the hashed, unique string for the numeral
        !           325:    whose value is chosen alternative.  */
        !           326: 
        !           327: static char *current_alternative_string;
        !           328: 
        !           329: /* Used to simplify expressions.  */
        !           330: 
        !           331: static rtx true_rtx, false_rtx;
        !           332: 
        !           333: /* Used to reduce calls to `strcmp' */
        !           334: 
        !           335: static char *alternative_name;
        !           336: 
        !           337: /* Simplify an expression.  Only call the routine if there is something to
        !           338:    simplify.  */
        !           339: #define SIMPLIFY_TEST_EXP(EXP,INSN_CODE,INSN_INDEX)    \
        !           340:   (RTX_UNCHANGING_P (EXP) || MEM_IN_STRUCT_P (EXP) ? (EXP)     \
        !           341:    : simplify_test_exp (EXP, INSN_CODE, INSN_INDEX))
        !           342:   
        !           343: /* Simplify (eq_attr ("alternative") ...)
        !           344:    when we are working with a particular alternative.  */
        !           345: #define SIMPLIFY_ALTERNATIVE(EXP)                              \
        !           346:   if (current_alternative_string                               \
        !           347:       && GET_CODE ((EXP)) == EQ_ATTR                           \
        !           348:       && XSTR ((EXP), 0) == alternative_name)                  \
        !           349:     (EXP) = (XSTR ((EXP), 1) == current_alternative_string     \
        !           350:            ? true_rtx : false_rtx);
        !           351: 
        !           352: /* These are referenced by rtlanal.c and hence need to be defined somewhere.
        !           353:    They won't actually be used.  */
        !           354: 
        !           355: rtx frame_pointer_rtx, hard_frame_pointer_rtx, stack_pointer_rtx;
        !           356: rtx arg_pointer_rtx;
        !           357: 
        !           358: #if 0
        !           359: static rtx attr_rtx            PROTO((enum rtx_code, ...));
        !           360: static char *attr_printf       PROTO((int, char *, ...));
        !           361: #else
        !           362: static rtx attr_rtx ();
        !           363: static char *attr_printf ();
        !           364: #endif
        !           365: 
        !           366: static char *attr_string        PROTO((char *, int));
        !           367: static rtx check_attr_test     PROTO((rtx, int));
        !           368: static rtx check_attr_value    PROTO((rtx, struct attr_desc *));
        !           369: static rtx convert_set_attr_alternative PROTO((rtx, int, int, int));
        !           370: static rtx convert_set_attr    PROTO((rtx, int, int, int));
        !           371: static void check_defs         PROTO((void));
        !           372: static rtx convert_const_symbol_ref PROTO((rtx, struct attr_desc *));
        !           373: static rtx make_canonical      PROTO((struct attr_desc *, rtx));
        !           374: static struct attr_value *get_attr_value PROTO((rtx, struct attr_desc *, int));
        !           375: static rtx copy_rtx_unchanging PROTO((rtx));
        !           376: static rtx copy_boolean                PROTO((rtx));
        !           377: static void expand_delays      PROTO((void));
        !           378: static rtx operate_exp         PROTO((enum operator, rtx, rtx));
        !           379: static void expand_units       PROTO((void));
        !           380: static rtx simplify_knowing    PROTO((rtx, rtx));
        !           381: static rtx encode_units_mask   PROTO((rtx));
        !           382: static void fill_attr          PROTO((struct attr_desc *));
        !           383: /* dpx2 compiler chokes if we specify the arg types of the args.  */
        !           384: static rtx substitute_address  PROTO((rtx, rtx (*) (), rtx (*) ()));
        !           385: static void make_length_attrs  PROTO((void));
        !           386: static rtx identity_fn         PROTO((rtx));
        !           387: static rtx zero_fn             PROTO((rtx));
        !           388: static rtx one_fn              PROTO((rtx));
        !           389: static rtx max_fn              PROTO((rtx));
        !           390: static rtx simplify_cond       PROTO((rtx, int, int));
        !           391: static rtx simplify_by_alternatives PROTO((rtx, int, int));
        !           392: static rtx simplify_by_exploding PROTO((rtx));
        !           393: static int find_and_mark_used_attributes PROTO((rtx, rtx *, int *));
        !           394: static void unmark_used_attributes PROTO((rtx, struct dimension *, int));
        !           395: static int add_values_to_cover PROTO((struct dimension *));
        !           396: static int increment_current_value PROTO((struct dimension *, int));
        !           397: static rtx test_for_current_value PROTO((struct dimension *, int));
        !           398: static rtx simplify_with_current_value PROTO((rtx, struct dimension *, int));
        !           399: static rtx simplify_with_current_value_aux PROTO((rtx));
        !           400: static void clear_struct_flag PROTO((rtx));
        !           401: static int count_sub_rtxs    PROTO((rtx, int));
        !           402: static void remove_insn_ent  PROTO((struct attr_value *, struct insn_ent *));
        !           403: static void insert_insn_ent  PROTO((struct attr_value *, struct insn_ent *));
        !           404: static rtx insert_right_side   PROTO((enum rtx_code, rtx, rtx, int, int));
        !           405: static rtx make_alternative_compare PROTO((int));
        !           406: static int compute_alternative_mask PROTO((rtx, enum rtx_code));
        !           407: static rtx evaluate_eq_attr    PROTO((rtx, rtx, int, int));
        !           408: static rtx simplify_and_tree   PROTO((rtx, rtx *, int, int));
        !           409: static rtx simplify_or_tree    PROTO((rtx, rtx *, int, int));
        !           410: static rtx simplify_test_exp   PROTO((rtx, int, int));
        !           411: static void optimize_attrs     PROTO((void));
        !           412: static void gen_attr           PROTO((rtx));
        !           413: static int count_alternatives  PROTO((rtx));
        !           414: static int compares_alternatives_p PROTO((rtx));
        !           415: static int contained_in_p      PROTO((rtx, rtx));
        !           416: static void gen_insn           PROTO((rtx));
        !           417: static void gen_delay          PROTO((rtx));
        !           418: static void gen_unit           PROTO((rtx));
        !           419: static void write_test_expr    PROTO((rtx, int));
        !           420: static int max_attr_value      PROTO((rtx));
        !           421: static void walk_attr_value    PROTO((rtx));
        !           422: static void write_attr_get     PROTO((struct attr_desc *));
        !           423: static rtx eliminate_known_true PROTO((rtx, rtx, int, int));
        !           424: static void write_attr_set     PROTO((struct attr_desc *, int, rtx, char *,
        !           425:                                       char *, rtx, int, int));
        !           426: static void write_attr_case    PROTO((struct attr_desc *, struct attr_value *,
        !           427:                                       int, char *, char *, int, rtx));
        !           428: static void write_attr_valueq  PROTO((struct attr_desc *, char *));
        !           429: static void write_attr_value   PROTO((struct attr_desc *, rtx));
        !           430: static void write_upcase       PROTO((char *));
        !           431: static void write_indent       PROTO((int));
        !           432: static void write_eligible_delay PROTO((char *));
        !           433: static void write_function_unit_info PROTO((void));
        !           434: static void write_complex_function PROTO((struct function_unit *, char *,
        !           435:                                          char *));
        !           436: static int n_comma_elts                PROTO((char *));
        !           437: static char *next_comma_elt    PROTO((char **));
        !           438: static struct attr_desc *find_attr PROTO((char *, int));
        !           439: static void make_internal_attr PROTO((char *, rtx, int));
        !           440: static struct attr_value *find_most_used  PROTO((struct attr_desc *));
        !           441: static rtx find_single_value   PROTO((struct attr_desc *));
        !           442: static rtx make_numeric_value  PROTO((int));
        !           443: static void extend_range       PROTO((struct range *, int, int));
        !           444: char *xrealloc                 PROTO((char *, unsigned));
        !           445: char *xmalloc                  PROTO((unsigned));
        !           446: 
        !           447: #define oballoc(size) obstack_alloc (hash_obstack, size)
        !           448: 
        !           449: 
        !           450: /* Hash table for sharing RTL and strings.  */
        !           451: 
        !           452: /* Each hash table slot is a bucket containing a chain of these structures.
        !           453:    Strings are given negative hash codes; RTL expressions are given positive
        !           454:    hash codes.  */
        !           455: 
        !           456: struct attr_hash
        !           457: {
        !           458:   struct attr_hash *next;      /* Next structure in the bucket.  */
        !           459:   int hashcode;                        /* Hash code of this rtx or string.  */
        !           460:   union
        !           461:     {
        !           462:       char *str;               /* The string (negative hash codes) */
        !           463:       rtx rtl;                 /* or the RTL recorded here.  */
        !           464:     } u;
        !           465: };
        !           466: 
        !           467: /* Now here is the hash table.  When recording an RTL, it is added to
        !           468:    the slot whose index is the hash code mod the table size.  Note
        !           469:    that the hash table is used for several kinds of RTL (see attr_rtx)
        !           470:    and for strings.  While all these live in the same table, they are
        !           471:    completely independent, and the hash code is computed differently
        !           472:    for each.  */
        !           473: 
        !           474: #define RTL_HASH_SIZE 4093
        !           475: struct attr_hash *attr_hash_table[RTL_HASH_SIZE];
        !           476: 
        !           477: /* Here is how primitive or already-shared RTL's hash
        !           478:    codes are made.  */
        !           479: #define RTL_HASH(RTL) ((HOST_WIDE_INT) (RTL) & 0777777)
        !           480: 
        !           481: /* Add an entry to the hash table for RTL with hash code HASHCODE.  */
        !           482: 
        !           483: static void
        !           484: attr_hash_add_rtx (hashcode, rtl)
        !           485:      int hashcode;
        !           486:      rtx rtl;
        !           487: {
        !           488:   register struct attr_hash *h;
        !           489: 
        !           490:   h = (struct attr_hash *) obstack_alloc (hash_obstack,
        !           491:                                          sizeof (struct attr_hash));
        !           492:   h->hashcode = hashcode;
        !           493:   h->u.rtl = rtl;
        !           494:   h->next = attr_hash_table[hashcode % RTL_HASH_SIZE];
        !           495:   attr_hash_table[hashcode % RTL_HASH_SIZE] = h;
        !           496: }
        !           497: 
        !           498: /* Add an entry to the hash table for STRING with hash code HASHCODE.  */
        !           499: 
        !           500: static void
        !           501: attr_hash_add_string (hashcode, str)
        !           502:      int hashcode;
        !           503:      char *str;
        !           504: {
        !           505:   register struct attr_hash *h;
        !           506: 
        !           507:   h = (struct attr_hash *) obstack_alloc (hash_obstack,
        !           508:                                          sizeof (struct attr_hash));
        !           509:   h->hashcode = -hashcode;
        !           510:   h->u.str = str;
        !           511:   h->next = attr_hash_table[hashcode % RTL_HASH_SIZE];
        !           512:   attr_hash_table[hashcode % RTL_HASH_SIZE] = h;
        !           513: }
        !           514: 
        !           515: /* Generate an RTL expression, but avoid duplicates.
        !           516:    Set the RTX_INTEGRATED_P flag for these permanent objects.
        !           517: 
        !           518:    In some cases we cannot uniquify; then we return an ordinary
        !           519:    impermanent rtx with RTX_INTEGRATED_P clear.
        !           520: 
        !           521:    Args are like gen_rtx, but without the mode:
        !           522: 
        !           523:    rtx attr_rtx (code, [element1, ..., elementn])  */
        !           524: 
        !           525: /*VARARGS1*/
        !           526: static rtx
        !           527: attr_rtx (va_alist)
        !           528:      va_dcl
        !           529: {
        !           530:   va_list p;
        !           531:   enum rtx_code code;
        !           532:   register int i;              /* Array indices...                     */
        !           533:   register char *fmt;          /* Current rtx's format...              */
        !           534:   register rtx rt_val;         /* RTX to return to caller...           */
        !           535:   int hashcode;
        !           536:   register struct attr_hash *h;
        !           537:   struct obstack *old_obstack = rtl_obstack;
        !           538: 
        !           539:   va_start (p);
        !           540:   code = va_arg (p, enum rtx_code);
        !           541: 
        !           542:   /* For each of several cases, search the hash table for an existing entry.
        !           543:      Use that entry if one is found; otherwise create a new RTL and add it
        !           544:      to the table.  */
        !           545: 
        !           546:   if (GET_RTX_CLASS (code) == '1')
        !           547:     {
        !           548:       rtx arg0 = va_arg (p, rtx);
        !           549: 
        !           550:       /* A permanent object cannot point to impermanent ones.  */
        !           551:       if (! RTX_INTEGRATED_P (arg0))
        !           552:        {
        !           553:          rt_val = rtx_alloc (code);
        !           554:          XEXP (rt_val, 0) = arg0;
        !           555:          va_end (p);
        !           556:          return rt_val;
        !           557:        }
        !           558: 
        !           559:       hashcode = ((HOST_WIDE_INT) code + RTL_HASH (arg0));
        !           560:       for (h = attr_hash_table[hashcode % RTL_HASH_SIZE]; h; h = h->next)
        !           561:        if (h->hashcode == hashcode
        !           562:            && GET_CODE (h->u.rtl) == code
        !           563:            && XEXP (h->u.rtl, 0) == arg0)
        !           564:          goto found;
        !           565: 
        !           566:       if (h == 0)
        !           567:        {
        !           568:          rtl_obstack = hash_obstack;
        !           569:          rt_val = rtx_alloc (code);
        !           570:          XEXP (rt_val, 0) = arg0;
        !           571:        }
        !           572:     }
        !           573:   else if (GET_RTX_CLASS (code) == 'c'
        !           574:           || GET_RTX_CLASS (code) == '2'
        !           575:           || GET_RTX_CLASS (code) == '<')
        !           576:     {
        !           577:       rtx arg0 = va_arg (p, rtx);
        !           578:       rtx arg1 = va_arg (p, rtx);
        !           579: 
        !           580:       /* A permanent object cannot point to impermanent ones.  */
        !           581:       if (! RTX_INTEGRATED_P (arg0) || ! RTX_INTEGRATED_P (arg1))
        !           582:        {
        !           583:          rt_val = rtx_alloc (code);
        !           584:          XEXP (rt_val, 0) = arg0;
        !           585:          XEXP (rt_val, 1) = arg1;
        !           586:          va_end (p);
        !           587:          return rt_val;
        !           588:        }
        !           589: 
        !           590:       hashcode = ((HOST_WIDE_INT) code + RTL_HASH (arg0) + RTL_HASH (arg1));
        !           591:       for (h = attr_hash_table[hashcode % RTL_HASH_SIZE]; h; h = h->next)
        !           592:        if (h->hashcode == hashcode
        !           593:            && GET_CODE (h->u.rtl) == code
        !           594:            && XEXP (h->u.rtl, 0) == arg0
        !           595:            && XEXP (h->u.rtl, 1) == arg1)
        !           596:          goto found;
        !           597: 
        !           598:       if (h == 0)
        !           599:        {
        !           600:          rtl_obstack = hash_obstack;
        !           601:          rt_val = rtx_alloc (code);
        !           602:          XEXP (rt_val, 0) = arg0;
        !           603:          XEXP (rt_val, 1) = arg1;
        !           604:        }
        !           605:     }
        !           606:   else if (GET_RTX_LENGTH (code) == 1
        !           607:           && GET_RTX_FORMAT (code)[0] == 's')
        !           608:     {
        !           609:       char * arg0 = va_arg (p, char *);
        !           610: 
        !           611:       if (code == SYMBOL_REF)
        !           612:        arg0 = attr_string (arg0, strlen (arg0));
        !           613: 
        !           614:       hashcode = ((HOST_WIDE_INT) code + RTL_HASH (arg0));
        !           615:       for (h = attr_hash_table[hashcode % RTL_HASH_SIZE]; h; h = h->next)
        !           616:        if (h->hashcode == hashcode
        !           617:            && GET_CODE (h->u.rtl) == code
        !           618:            && XSTR (h->u.rtl, 0) == arg0)
        !           619:          goto found;
        !           620: 
        !           621:       if (h == 0)
        !           622:        {
        !           623:          rtl_obstack = hash_obstack;
        !           624:          rt_val = rtx_alloc (code);
        !           625:          XSTR (rt_val, 0) = arg0;
        !           626:        }
        !           627:     }
        !           628:   else if (GET_RTX_LENGTH (code) == 2
        !           629:           && GET_RTX_FORMAT (code)[0] == 's'
        !           630:           && GET_RTX_FORMAT (code)[1] == 's')
        !           631:     {
        !           632:       char *arg0 = va_arg (p, char *);
        !           633:       char *arg1 = va_arg (p, char *);
        !           634: 
        !           635:       hashcode = ((HOST_WIDE_INT) code + RTL_HASH (arg0) + RTL_HASH (arg1));
        !           636:       for (h = attr_hash_table[hashcode % RTL_HASH_SIZE]; h; h = h->next)
        !           637:        if (h->hashcode == hashcode
        !           638:            && GET_CODE (h->u.rtl) == code
        !           639:            && XSTR (h->u.rtl, 0) == arg0
        !           640:            && XSTR (h->u.rtl, 1) == arg1)
        !           641:          goto found;
        !           642: 
        !           643:       if (h == 0)
        !           644:        {
        !           645:          rtl_obstack = hash_obstack;
        !           646:          rt_val = rtx_alloc (code);
        !           647:          XSTR (rt_val, 0) = arg0;
        !           648:          XSTR (rt_val, 1) = arg1;
        !           649:        }
        !           650:     }
        !           651:   else if (code == CONST_INT)
        !           652:     {
        !           653:       HOST_WIDE_INT arg0 = va_arg (p, HOST_WIDE_INT);
        !           654:       if (arg0 == 0)
        !           655:        return false_rtx;
        !           656:       if (arg0 == 1)
        !           657:        return true_rtx;
        !           658:       goto nohash;
        !           659:     }
        !           660:   else
        !           661:     {
        !           662:     nohash:
        !           663:       rt_val = rtx_alloc (code);       /* Allocate the storage space.  */
        !           664:       
        !           665:       fmt = GET_RTX_FORMAT (code);     /* Find the right format...  */
        !           666:       for (i = 0; i < GET_RTX_LENGTH (code); i++)
        !           667:        {
        !           668:          switch (*fmt++)
        !           669:            {
        !           670:            case '0':           /* Unused field.  */
        !           671:              break;
        !           672: 
        !           673:            case 'i':           /* An integer?  */
        !           674:              XINT (rt_val, i) = va_arg (p, int);
        !           675:              break;
        !           676: 
        !           677:            case 'w':           /* A wide integer? */
        !           678:              XWINT (rt_val, i) = va_arg (p, HOST_WIDE_INT);
        !           679:              break;
        !           680: 
        !           681:            case 's':           /* A string?  */
        !           682:              XSTR (rt_val, i) = va_arg (p, char *);
        !           683:              break;
        !           684: 
        !           685:            case 'e':           /* An expression?  */
        !           686:            case 'u':           /* An insn?  Same except when printing.  */
        !           687:              XEXP (rt_val, i) = va_arg (p, rtx);
        !           688:              break;
        !           689: 
        !           690:            case 'E':           /* An RTX vector?  */
        !           691:              XVEC (rt_val, i) = va_arg (p, rtvec);
        !           692:              break;
        !           693: 
        !           694:            default:
        !           695:              abort();
        !           696:            }
        !           697:        }
        !           698:       va_end (p);
        !           699:       return rt_val;
        !           700:     }
        !           701: 
        !           702:   rtl_obstack = old_obstack;
        !           703:   va_end (p);
        !           704:   attr_hash_add_rtx (hashcode, rt_val);
        !           705:   RTX_INTEGRATED_P (rt_val) = 1;
        !           706:   return rt_val;
        !           707: 
        !           708:  found:
        !           709:   va_end (p);
        !           710:   return h->u.rtl;
        !           711: }
        !           712: 
        !           713: /* Create a new string printed with the printf line arguments into a space
        !           714:    of at most LEN bytes:
        !           715: 
        !           716:    rtx attr_printf (len, format, [arg1, ..., argn])  */
        !           717: 
        !           718: #ifdef HAVE_VPRINTF
        !           719: 
        !           720: /*VARARGS2*/
        !           721: static char *
        !           722: attr_printf (va_alist)
        !           723:      va_dcl
        !           724: {
        !           725:   va_list p;
        !           726:   register int len;
        !           727:   register char *fmt;
        !           728:   register char *str;
        !           729: 
        !           730:   /* Print the string into a temporary location.  */
        !           731:   va_start (p);
        !           732:   len = va_arg (p, int);
        !           733:   str = (char *) alloca (len);
        !           734:   fmt = va_arg (p, char *);
        !           735:   vsprintf (str, fmt, p);
        !           736:   va_end (p);
        !           737: 
        !           738:   return attr_string (str, strlen (str));
        !           739: }
        !           740: 
        !           741: #else /* not HAVE_VPRINTF */
        !           742: 
        !           743: static char *
        !           744: attr_printf (len, fmt, arg1, arg2, arg3)
        !           745:      int len;
        !           746:      char *fmt;
        !           747:      char *arg1, *arg2, *arg3; /* also int */
        !           748: {
        !           749:   register char *str;
        !           750: 
        !           751:   /* Print the string into a temporary location.  */
        !           752:   str = (char *) alloca (len);
        !           753:   sprintf (str, fmt, arg1, arg2, arg3);
        !           754: 
        !           755:   return attr_string (str, strlen (str));
        !           756: }
        !           757: #endif /* not HAVE_VPRINTF */
        !           758: 
        !           759: rtx
        !           760: attr_eq (name, value)
        !           761:      char *name, *value;
        !           762: {
        !           763:   return attr_rtx (EQ_ATTR, attr_string (name, strlen (name)),
        !           764:                   attr_string (value, strlen (value)));
        !           765: }
        !           766: 
        !           767: char *
        !           768: attr_numeral (n)
        !           769:      int n;
        !           770: {
        !           771:   return XSTR (make_numeric_value (n), 0);
        !           772: }
        !           773: 
        !           774: /* Return a permanent (possibly shared) copy of a string STR (not assumed
        !           775:    to be null terminated) with LEN bytes.  */
        !           776: 
        !           777: static char *
        !           778: attr_string (str, len)
        !           779:      char *str;
        !           780:      int len;
        !           781: {
        !           782:   register struct attr_hash *h;
        !           783:   int hashcode;
        !           784:   int i;
        !           785:   register char *new_str;
        !           786: 
        !           787:   /* Compute the hash code.  */
        !           788:   hashcode = (len + 1) * 613 + (unsigned)str[0];
        !           789:   for (i = 1; i <= len; i += 2)
        !           790:     hashcode = ((hashcode * 613) + (unsigned)str[i]);
        !           791:   if (hashcode < 0)
        !           792:     hashcode = -hashcode;
        !           793: 
        !           794:   /* Search the table for the string.  */
        !           795:   for (h = attr_hash_table[hashcode % RTL_HASH_SIZE]; h; h = h->next)
        !           796:     if (h->hashcode == -hashcode && h->u.str[0] == str[0]
        !           797:        && !strncmp (h->u.str, str, len))
        !           798:       return h->u.str;                 /* <-- return if found.  */
        !           799: 
        !           800:   /* Not found; create a permanent copy and add it to the hash table.  */
        !           801:   new_str = (char *) obstack_alloc (hash_obstack, len + 1);
        !           802:   bcopy (str, new_str, len);
        !           803:   new_str[len] = '\0';
        !           804:   attr_hash_add_string (hashcode, new_str);
        !           805: 
        !           806:   return new_str;                      /* Return the new string.  */
        !           807: }
        !           808: 
        !           809: /* Check two rtx's for equality of contents,
        !           810:    taking advantage of the fact that if both are hashed
        !           811:    then they can't be equal unless they are the same object.  */
        !           812: 
        !           813: int
        !           814: attr_equal_p (x, y)
        !           815:      rtx x, y;
        !           816: {
        !           817:   return (x == y || (! (RTX_INTEGRATED_P (x) && RTX_INTEGRATED_P (y))
        !           818:                     && rtx_equal_p (x, y)));
        !           819: }
        !           820: 
        !           821: /* Copy an attribute value expression,
        !           822:    descending to all depths, but not copying any
        !           823:    permanent hashed subexpressions.  */
        !           824: 
        !           825: rtx
        !           826: attr_copy_rtx (orig)
        !           827:      register rtx orig;
        !           828: {
        !           829:   register rtx copy;
        !           830:   register int i, j;
        !           831:   register RTX_CODE code;
        !           832:   register char *format_ptr;
        !           833: 
        !           834:   /* No need to copy a permanent object.  */
        !           835:   if (RTX_INTEGRATED_P (orig))
        !           836:     return orig;
        !           837: 
        !           838:   code = GET_CODE (orig);
        !           839: 
        !           840:   switch (code)
        !           841:     {
        !           842:     case REG:
        !           843:     case QUEUED:
        !           844:     case CONST_INT:
        !           845:     case CONST_DOUBLE:
        !           846:     case SYMBOL_REF:
        !           847:     case CODE_LABEL:
        !           848:     case PC:
        !           849:     case CC0:
        !           850:       return orig;
        !           851:     }
        !           852: 
        !           853:   copy = rtx_alloc (code);
        !           854:   PUT_MODE (copy, GET_MODE (orig));
        !           855:   copy->in_struct = orig->in_struct;
        !           856:   copy->volatil = orig->volatil;
        !           857:   copy->unchanging = orig->unchanging;
        !           858:   copy->integrated = orig->integrated;
        !           859:   
        !           860:   format_ptr = GET_RTX_FORMAT (GET_CODE (copy));
        !           861: 
        !           862:   for (i = 0; i < GET_RTX_LENGTH (GET_CODE (copy)); i++)
        !           863:     {
        !           864:       switch (*format_ptr++)
        !           865:        {
        !           866:        case 'e':
        !           867:          XEXP (copy, i) = XEXP (orig, i);
        !           868:          if (XEXP (orig, i) != NULL)
        !           869:            XEXP (copy, i) = attr_copy_rtx (XEXP (orig, i));
        !           870:          break;
        !           871: 
        !           872:        case 'E':
        !           873:        case 'V':
        !           874:          XVEC (copy, i) = XVEC (orig, i);
        !           875:          if (XVEC (orig, i) != NULL)
        !           876:            {
        !           877:              XVEC (copy, i) = rtvec_alloc (XVECLEN (orig, i));
        !           878:              for (j = 0; j < XVECLEN (copy, i); j++)
        !           879:                XVECEXP (copy, i, j) = attr_copy_rtx (XVECEXP (orig, i, j));
        !           880:            }
        !           881:          break;
        !           882: 
        !           883:        case 'n':
        !           884:        case 'i':
        !           885:          XINT (copy, i) = XINT (orig, i);
        !           886:          break;
        !           887: 
        !           888:        case 'w':
        !           889:          XWINT (copy, i) = XWINT (orig, i);
        !           890:          break;
        !           891: 
        !           892:        case 's':
        !           893:        case 'S':
        !           894:          XSTR (copy, i) = XSTR (orig, i);
        !           895:          break;
        !           896: 
        !           897:        default:
        !           898:          abort ();
        !           899:        }
        !           900:     }
        !           901:   return copy;
        !           902: }
        !           903: 
        !           904: /* Given a test expression for an attribute, ensure it is validly formed.
        !           905:    IS_CONST indicates whether the expression is constant for each compiler
        !           906:    run (a constant expression may not test any particular insn).
        !           907: 
        !           908:    Convert (eq_attr "att" "a1,a2") to (ior (eq_attr ... ) (eq_attrq ..))
        !           909:    and (eq_attr "att" "!a1") to (not (eq_attr "att" "a1")).  Do the latter
        !           910:    test first so that (eq_attr "att" "!a1,a2,a3") works as expected.
        !           911: 
        !           912:    Update the string address in EQ_ATTR expression to be the same used
        !           913:    in the attribute (or `alternative_name') to speed up subsequent
        !           914:    `find_attr' calls and eliminate most `strcmp' calls.
        !           915: 
        !           916:    Return the new expression, if any.   */
        !           917: 
        !           918: static rtx
        !           919: check_attr_test (exp, is_const)
        !           920:      rtx exp;
        !           921:      int is_const;
        !           922: {
        !           923:   struct attr_desc *attr;
        !           924:   struct attr_value *av;
        !           925:   char *name_ptr, *p;
        !           926:   rtx orexp, newexp;
        !           927: 
        !           928:   switch (GET_CODE (exp))
        !           929:     {
        !           930:     case EQ_ATTR:
        !           931:       /* Handle negation test.  */
        !           932:       if (XSTR (exp, 1)[0] == '!')
        !           933:        return check_attr_test (attr_rtx (NOT,
        !           934:                                          attr_eq (XSTR (exp, 0),
        !           935:                                                   &XSTR (exp, 1)[1])),
        !           936:                                is_const);
        !           937: 
        !           938:       else if (n_comma_elts (XSTR (exp, 1)) == 1)
        !           939:        {
        !           940:          attr = find_attr (XSTR (exp, 0), 0);
        !           941:          if (attr == NULL)
        !           942:            {
        !           943:              if (! strcmp (XSTR (exp, 0), "alternative"))
        !           944:                {
        !           945:                  XSTR (exp, 0) = alternative_name;
        !           946:                  /* This can't be simplified any further.  */
        !           947:                  RTX_UNCHANGING_P (exp) = 1;
        !           948:                  return exp;
        !           949:                }
        !           950:              else
        !           951:                fatal ("Unknown attribute `%s' in EQ_ATTR", XEXP (exp, 0));
        !           952:            }
        !           953: 
        !           954:          if (is_const && ! attr->is_const)
        !           955:            fatal ("Constant expression uses insn attribute `%s' in EQ_ATTR",
        !           956:                   XEXP (exp, 0));
        !           957: 
        !           958:          /* Copy this just to make it permanent,
        !           959:             so expressions using it can be permanent too.  */
        !           960:          exp = attr_eq (XSTR (exp, 0), XSTR (exp, 1));
        !           961: 
        !           962:          /* It shouldn't be possible to simplify the value given to a
        !           963:             constant attribute, so don't expand this until it's time to
        !           964:             write the test expression.  */            
        !           965:          if (attr->is_const)
        !           966:            RTX_UNCHANGING_P (exp) = 1;
        !           967: 
        !           968:          if (attr->is_numeric)
        !           969:            {
        !           970:              for (p = XSTR (exp, 1); *p; p++)
        !           971:                if (*p < '0' || *p > '9')
        !           972:                   fatal ("Attribute `%s' takes only numeric values", 
        !           973:                          XEXP (exp, 0));
        !           974:            }
        !           975:          else
        !           976:            {
        !           977:              for (av = attr->first_value; av; av = av->next)
        !           978:                if (GET_CODE (av->value) == CONST_STRING
        !           979:                    && ! strcmp (XSTR (exp, 1), XSTR (av->value, 0)))
        !           980:                  break;
        !           981: 
        !           982:              if (av == NULL)
        !           983:                fatal ("Unknown value `%s' for `%s' attribute",
        !           984:                       XEXP (exp, 1), XEXP (exp, 0));
        !           985:            }
        !           986:        }
        !           987:       else
        !           988:        {
        !           989:          /* Make an IOR tree of the possible values.  */
        !           990:          orexp = false_rtx;
        !           991:          name_ptr = XSTR (exp, 1);
        !           992:          while ((p = next_comma_elt (&name_ptr)) != NULL)
        !           993:            {
        !           994:              newexp = attr_eq (XSTR (exp, 0), p);
        !           995:              orexp = insert_right_side (IOR, orexp, newexp, -2, -2);
        !           996:            }
        !           997: 
        !           998:          return check_attr_test (orexp, is_const);
        !           999:        }
        !          1000:       break;
        !          1001: 
        !          1002:     case ATTR_FLAG:
        !          1003:       break;
        !          1004: 
        !          1005:     case CONST_INT:
        !          1006:       /* Either TRUE or FALSE.  */
        !          1007:       if (XWINT (exp, 0))
        !          1008:        return true_rtx;
        !          1009:       else
        !          1010:        return false_rtx;
        !          1011: 
        !          1012:     case IOR:
        !          1013:     case AND:
        !          1014:       XEXP (exp, 0) = check_attr_test (XEXP (exp, 0), is_const);
        !          1015:       XEXP (exp, 1) = check_attr_test (XEXP (exp, 1), is_const);
        !          1016:       break;
        !          1017: 
        !          1018:     case NOT:
        !          1019:       XEXP (exp, 0) = check_attr_test (XEXP (exp, 0), is_const);
        !          1020:       break;
        !          1021: 
        !          1022:     case MATCH_OPERAND:
        !          1023:       if (is_const)
        !          1024:        fatal ("RTL operator \"%s\" not valid in constant attribute test",
        !          1025:               GET_RTX_NAME (MATCH_OPERAND));
        !          1026:       /* These cases can't be simplified.  */
        !          1027:       RTX_UNCHANGING_P (exp) = 1;
        !          1028:       break;
        !          1029: 
        !          1030:     case LE:  case LT:  case GT:  case GE:
        !          1031:     case LEU: case LTU: case GTU: case GEU:
        !          1032:     case NE:  case EQ:
        !          1033:       if (GET_CODE (XEXP (exp, 0)) == SYMBOL_REF
        !          1034:          && GET_CODE (XEXP (exp, 1)) == SYMBOL_REF)
        !          1035:        exp = attr_rtx (GET_CODE (exp),
        !          1036:                        attr_rtx (SYMBOL_REF, XSTR (XEXP (exp, 0), 0)),
        !          1037:                        attr_rtx (SYMBOL_REF, XSTR (XEXP (exp, 1), 0)));
        !          1038:       /* These cases can't be simplified.  */
        !          1039:       RTX_UNCHANGING_P (exp) = 1;
        !          1040:       break;
        !          1041: 
        !          1042:     case SYMBOL_REF:
        !          1043:       if (is_const)
        !          1044:        {
        !          1045:          /* These cases are valid for constant attributes, but can't be
        !          1046:             simplified.  */
        !          1047:          exp = attr_rtx (SYMBOL_REF, XSTR (exp, 0));
        !          1048:          RTX_UNCHANGING_P (exp) = 1;
        !          1049:          break;
        !          1050:        }
        !          1051:     default:
        !          1052:       fatal ("RTL operator \"%s\" not valid in attribute test",
        !          1053:             GET_RTX_NAME (GET_CODE (exp)));
        !          1054:     }
        !          1055: 
        !          1056:   return exp;
        !          1057: }
        !          1058: 
        !          1059: /* Given an expression, ensure that it is validly formed and that all named
        !          1060:    attribute values are valid for the given attribute.  Issue a fatal error
        !          1061:    if not.  If no attribute is specified, assume a numeric attribute.
        !          1062: 
        !          1063:    Return a perhaps modified replacement expression for the value.  */
        !          1064: 
        !          1065: static rtx
        !          1066: check_attr_value (exp, attr)
        !          1067:      rtx exp;
        !          1068:      struct attr_desc *attr;
        !          1069: {
        !          1070:   struct attr_value *av;
        !          1071:   char *p;
        !          1072:   int i;
        !          1073: 
        !          1074:   switch (GET_CODE (exp))
        !          1075:     {
        !          1076:     case CONST_INT:
        !          1077:       if (attr && ! attr->is_numeric)
        !          1078:        fatal ("CONST_INT not valid for non-numeric `%s' attribute",
        !          1079:               attr->name);
        !          1080: 
        !          1081:       if (INTVAL (exp) < 0)
        !          1082:        fatal ("Negative numeric value specified for `%s' attribute",
        !          1083:               attr->name);
        !          1084: 
        !          1085:       break;
        !          1086: 
        !          1087:     case CONST_STRING:
        !          1088:       if (! strcmp (XSTR (exp, 0), "*"))
        !          1089:        break;
        !          1090: 
        !          1091:       if (attr == 0 || attr->is_numeric)
        !          1092:        {
        !          1093:          p = XSTR (exp, 0);
        !          1094:          if (attr && attr->negative_ok && *p == '-')
        !          1095:            p++;
        !          1096:          for (; *p; p++)
        !          1097:            if (*p > '9' || *p < '0')
        !          1098:              fatal ("Non-numeric value for numeric `%s' attribute",
        !          1099:                     attr ? attr->name : "internal");
        !          1100:          break;
        !          1101:        }
        !          1102: 
        !          1103:       for (av = attr->first_value; av; av = av->next)
        !          1104:        if (GET_CODE (av->value) == CONST_STRING
        !          1105:            && ! strcmp (XSTR (av->value, 0), XSTR (exp, 0)))
        !          1106:          break;
        !          1107: 
        !          1108:       if (av == NULL)
        !          1109:        fatal ("Unknown value `%s' for `%s' attribute",
        !          1110:               XSTR (exp, 0), attr ? attr->name : "internal");
        !          1111: 
        !          1112:       break;
        !          1113: 
        !          1114:     case IF_THEN_ELSE:
        !          1115:       XEXP (exp, 0) = check_attr_test (XEXP (exp, 0),
        !          1116:                                       attr ? attr->is_const : 0);
        !          1117:       XEXP (exp, 1) = check_attr_value (XEXP (exp, 1), attr);
        !          1118:       XEXP (exp, 2) = check_attr_value (XEXP (exp, 2), attr);
        !          1119:       break;
        !          1120: 
        !          1121:     case COND:
        !          1122:       if (XVECLEN (exp, 0) % 2 != 0)
        !          1123:        fatal ("First operand of COND must have even length");
        !          1124: 
        !          1125:       for (i = 0; i < XVECLEN (exp, 0); i += 2)
        !          1126:        {
        !          1127:          XVECEXP (exp, 0, i) = check_attr_test (XVECEXP (exp, 0, i),
        !          1128:                                                 attr ? attr->is_const : 0);
        !          1129:          XVECEXP (exp, 0, i + 1)
        !          1130:            = check_attr_value (XVECEXP (exp, 0, i + 1), attr);
        !          1131:        }
        !          1132: 
        !          1133:       XEXP (exp, 1) = check_attr_value (XEXP (exp, 1), attr);
        !          1134:       break;
        !          1135: 
        !          1136:     case SYMBOL_REF:
        !          1137:       if (attr && attr->is_const)
        !          1138:        /* A constant SYMBOL_REF is valid as a constant attribute test and
        !          1139:           is expanded later by make_canonical into a COND.  */
        !          1140:        return attr_rtx (SYMBOL_REF, XSTR (exp, 0));
        !          1141:       /* Otherwise, fall through... */
        !          1142: 
        !          1143:     default:
        !          1144:       fatal ("Illegal operation `%s' for attribute value",
        !          1145:             GET_RTX_NAME (GET_CODE (exp)));
        !          1146:     }
        !          1147: 
        !          1148:   return exp;
        !          1149: }
        !          1150: 
        !          1151: /* Given an SET_ATTR_ALTERNATIVE expression, convert to the canonical SET.
        !          1152:    It becomes a COND with each test being (eq_attr "alternative "n") */
        !          1153: 
        !          1154: static rtx
        !          1155: convert_set_attr_alternative (exp, num_alt, insn_code, insn_index)
        !          1156:      rtx exp;
        !          1157:      int num_alt;
        !          1158:      int insn_code, insn_index;
        !          1159: {
        !          1160:   rtx condexp;
        !          1161:   int i;
        !          1162: 
        !          1163:   if (XVECLEN (exp, 1) != num_alt)
        !          1164:     fatal ("Bad number of entries in SET_ATTR_ALTERNATIVE for insn %d",
        !          1165:           insn_index);
        !          1166: 
        !          1167:   /* Make a COND with all tests but the last.  Select the last value via the
        !          1168:      default.  */
        !          1169:   condexp = rtx_alloc (COND);
        !          1170:   XVEC (condexp, 0) = rtvec_alloc ((num_alt - 1) * 2);
        !          1171: 
        !          1172:   for (i = 0; i < num_alt - 1; i++)
        !          1173:     {
        !          1174:       char *p;
        !          1175:       p = attr_numeral (i);
        !          1176: 
        !          1177:       XVECEXP (condexp, 0, 2 * i) = attr_eq (alternative_name, p);
        !          1178: #if 0
        !          1179:       /* Sharing this EQ_ATTR rtl causes trouble.  */   
        !          1180:       XVECEXP (condexp, 0, 2 * i) = rtx_alloc (EQ_ATTR);
        !          1181:       XSTR (XVECEXP (condexp, 0, 2 * i), 0) = alternative_name;
        !          1182:       XSTR (XVECEXP (condexp, 0, 2 * i), 1) = p;
        !          1183: #endif
        !          1184:       XVECEXP (condexp, 0, 2 * i + 1) = XVECEXP (exp, 1, i);
        !          1185:     }
        !          1186: 
        !          1187:   XEXP (condexp, 1) = XVECEXP (exp, 1, i);
        !          1188: 
        !          1189:   return attr_rtx (SET, attr_rtx (ATTR, XSTR (exp, 0)), condexp);
        !          1190: }
        !          1191: 
        !          1192: /* Given a SET_ATTR, convert to the appropriate SET.  If a comma-separated
        !          1193:    list of values is given, convert to SET_ATTR_ALTERNATIVE first.  */
        !          1194: 
        !          1195: static rtx
        !          1196: convert_set_attr (exp, num_alt, insn_code, insn_index)
        !          1197:      rtx exp;
        !          1198:      int num_alt;
        !          1199:      int insn_code, insn_index;
        !          1200: {
        !          1201:   rtx newexp;
        !          1202:   char *name_ptr;
        !          1203:   char *p;
        !          1204:   int n;
        !          1205: 
        !          1206:   /* See how many alternative specified.  */
        !          1207:   n = n_comma_elts (XSTR (exp, 1));
        !          1208:   if (n == 1)
        !          1209:     return attr_rtx (SET,
        !          1210:                     attr_rtx (ATTR, XSTR (exp, 0)),
        !          1211:                     attr_rtx (CONST_STRING, XSTR (exp, 1)));
        !          1212: 
        !          1213:   newexp = rtx_alloc (SET_ATTR_ALTERNATIVE);
        !          1214:   XSTR (newexp, 0) = XSTR (exp, 0);
        !          1215:   XVEC (newexp, 1) = rtvec_alloc (n);
        !          1216: 
        !          1217:   /* Process each comma-separated name.  */
        !          1218:   name_ptr = XSTR (exp, 1);
        !          1219:   n = 0;
        !          1220:   while ((p = next_comma_elt (&name_ptr)) != NULL)
        !          1221:     XVECEXP (newexp, 1, n++) = attr_rtx (CONST_STRING, p);
        !          1222: 
        !          1223:   return convert_set_attr_alternative (newexp, num_alt, insn_code, insn_index);
        !          1224: }
        !          1225: 
        !          1226: /* Scan all definitions, checking for validity.  Also, convert any SET_ATTR
        !          1227:    and SET_ATTR_ALTERNATIVE expressions to the corresponding SET
        !          1228:    expressions. */
        !          1229: 
        !          1230: static void
        !          1231: check_defs ()
        !          1232: {
        !          1233:   struct insn_def *id;
        !          1234:   struct attr_desc *attr;
        !          1235:   int i;
        !          1236:   rtx value;
        !          1237: 
        !          1238:   for (id = defs; id; id = id->next)
        !          1239:     {
        !          1240:       if (XVEC (id->def, id->vec_idx) == NULL)
        !          1241:        continue;
        !          1242: 
        !          1243:       for (i = 0; i < XVECLEN (id->def, id->vec_idx); i++)
        !          1244:        {
        !          1245:          value = XVECEXP (id->def, id->vec_idx, i);
        !          1246:          switch (GET_CODE (value))
        !          1247:            {
        !          1248:            case SET:
        !          1249:              if (GET_CODE (XEXP (value, 0)) != ATTR)
        !          1250:                fatal ("Bad attribute set in pattern %d", id->insn_index);
        !          1251:              break;
        !          1252: 
        !          1253:            case SET_ATTR_ALTERNATIVE:
        !          1254:              value = convert_set_attr_alternative (value,
        !          1255:                                                    id->num_alternatives,
        !          1256:                                                    id->insn_code,
        !          1257:                                                    id->insn_index);
        !          1258:              break;
        !          1259: 
        !          1260:            case SET_ATTR:
        !          1261:              value = convert_set_attr (value, id->num_alternatives,
        !          1262:                                        id->insn_code, id->insn_index);
        !          1263:              break;
        !          1264: 
        !          1265:            default:
        !          1266:              fatal ("Invalid attribute code `%s' for pattern %d",
        !          1267:                     GET_RTX_NAME (GET_CODE (value)), id->insn_index);
        !          1268:            }
        !          1269: 
        !          1270:          if ((attr = find_attr (XSTR (XEXP (value, 0), 0), 0)) == NULL)
        !          1271:            fatal ("Unknown attribute `%s' for pattern number %d",
        !          1272:                   XSTR (XEXP (value, 0), 0), id->insn_index);
        !          1273: 
        !          1274:          XVECEXP (id->def, id->vec_idx, i) = value;
        !          1275:          XEXP (value, 1) = check_attr_value (XEXP (value, 1), attr);
        !          1276:        }
        !          1277:     }
        !          1278: }
        !          1279: 
        !          1280: /* Given a constant SYMBOL_REF expression, convert to a COND that
        !          1281:    explicitly tests each enumerated value.  */
        !          1282: 
        !          1283: static rtx
        !          1284: convert_const_symbol_ref (exp, attr)
        !          1285:      rtx exp;
        !          1286:      struct attr_desc *attr;
        !          1287: {
        !          1288:   rtx condexp;
        !          1289:   struct attr_value *av;
        !          1290:   int i;
        !          1291:   int num_alt = 0;
        !          1292: 
        !          1293:   for (av = attr->first_value; av; av = av->next)
        !          1294:     num_alt++;
        !          1295: 
        !          1296:   /* Make a COND with all tests but the last, and in the original order.
        !          1297:      Select the last value via the default.  Note that the attr values
        !          1298:      are constructed in reverse order.  */
        !          1299: 
        !          1300:   condexp = rtx_alloc (COND);
        !          1301:   XVEC (condexp, 0) = rtvec_alloc ((num_alt - 1) * 2);
        !          1302:   av = attr->first_value;
        !          1303:   XEXP (condexp, 1) = av->value;
        !          1304: 
        !          1305:   for (i = num_alt - 2; av = av->next, i >= 0; i--)
        !          1306:     {
        !          1307:       char *p, *string;
        !          1308:       rtx value;
        !          1309: 
        !          1310:       string = p = (char *) oballoc (2
        !          1311:                                     + strlen (attr->name)
        !          1312:                                     + strlen (XSTR (av->value, 0)));
        !          1313:       strcpy (p, attr->name);
        !          1314:       strcat (p, "_");
        !          1315:       strcat (p, XSTR (av->value, 0));
        !          1316:       for (; *p != '\0'; p++)
        !          1317:        if (*p >= 'a' && *p <= 'z')
        !          1318:          *p -= 'a' - 'A';
        !          1319: 
        !          1320:       value = attr_rtx (SYMBOL_REF, string);
        !          1321:       RTX_UNCHANGING_P (value) = 1;
        !          1322:       
        !          1323:       XVECEXP (condexp, 0, 2 * i) = attr_rtx (EQ, exp, value);
        !          1324: 
        !          1325:       XVECEXP (condexp, 0, 2 * i + 1) = av->value;
        !          1326:     }
        !          1327: 
        !          1328:   return condexp;
        !          1329: }
        !          1330: 
        !          1331: /* Given a valid expression for an attribute value, remove any IF_THEN_ELSE
        !          1332:    expressions by converting them into a COND.  This removes cases from this
        !          1333:    program.  Also, replace an attribute value of "*" with the default attribute
        !          1334:    value.  */
        !          1335: 
        !          1336: static rtx
        !          1337: make_canonical (attr, exp)
        !          1338:      struct attr_desc *attr;
        !          1339:      rtx exp;
        !          1340: {
        !          1341:   int i;
        !          1342:   rtx newexp;
        !          1343: 
        !          1344:   switch (GET_CODE (exp))
        !          1345:     {
        !          1346:     case CONST_INT:
        !          1347:       exp = make_numeric_value (INTVAL (exp));
        !          1348:       break;
        !          1349: 
        !          1350:     case CONST_STRING:
        !          1351:       if (! strcmp (XSTR (exp, 0), "*"))
        !          1352:        {
        !          1353:          if (attr == 0 || attr->default_val == 0)
        !          1354:            fatal ("(attr_value \"*\") used in invalid context.");
        !          1355:          exp = attr->default_val->value;
        !          1356:        }
        !          1357: 
        !          1358:       break;
        !          1359: 
        !          1360:     case SYMBOL_REF:
        !          1361:       if (!attr->is_const || RTX_UNCHANGING_P (exp))
        !          1362:        break;
        !          1363:       /* The SYMBOL_REF is constant for a given run, so mark it as unchanging.
        !          1364:         This makes the COND something that won't be considered an arbitrary
        !          1365:         expression by walk_attr_value.  */
        !          1366:       RTX_UNCHANGING_P (exp) = 1;
        !          1367:       exp = convert_const_symbol_ref (exp, attr);
        !          1368:       RTX_UNCHANGING_P (exp) = 1;
        !          1369:       exp = check_attr_value (exp, attr);
        !          1370:       /* Goto COND case since this is now a COND.  Note that while the
        !          1371:          new expression is rescanned, all symbol_ref notes are mared as
        !          1372:         unchanging.  */
        !          1373:       goto cond;
        !          1374: 
        !          1375:     case IF_THEN_ELSE:
        !          1376:       newexp = rtx_alloc (COND);
        !          1377:       XVEC (newexp, 0) = rtvec_alloc (2);
        !          1378:       XVECEXP (newexp, 0, 0) = XEXP (exp, 0);
        !          1379:       XVECEXP (newexp, 0, 1) = XEXP (exp, 1);
        !          1380: 
        !          1381:       XEXP (newexp, 1) = XEXP (exp, 2);
        !          1382: 
        !          1383:       exp = newexp;
        !          1384:       /* Fall through to COND case since this is now a COND.  */
        !          1385: 
        !          1386:     case COND:
        !          1387:     cond:
        !          1388:       {
        !          1389:        int allsame = 1;
        !          1390:        rtx defval;
        !          1391: 
        !          1392:        /* First, check for degenerate COND. */
        !          1393:        if (XVECLEN (exp, 0) == 0)
        !          1394:          return make_canonical (attr, XEXP (exp, 1));
        !          1395:        defval = XEXP (exp, 1) = make_canonical (attr, XEXP (exp, 1));
        !          1396: 
        !          1397:        for (i = 0; i < XVECLEN (exp, 0); i += 2)
        !          1398:          {
        !          1399:            XVECEXP (exp, 0, i) = copy_boolean (XVECEXP (exp, 0, i));
        !          1400:            XVECEXP (exp, 0, i + 1)
        !          1401:              = make_canonical (attr, XVECEXP (exp, 0, i + 1));
        !          1402:            if (! rtx_equal_p (XVECEXP (exp, 0, i + 1), defval))
        !          1403:              allsame = 0;
        !          1404:          }
        !          1405:        if (allsame)
        !          1406:          return defval;
        !          1407:        break;
        !          1408:       }
        !          1409:     }
        !          1410: 
        !          1411:   return exp;
        !          1412: }
        !          1413: 
        !          1414: static rtx
        !          1415: copy_boolean (exp)
        !          1416:      rtx exp;
        !          1417: {
        !          1418:   if (GET_CODE (exp) == AND || GET_CODE (exp) == IOR)
        !          1419:     return attr_rtx (GET_CODE (exp), copy_boolean (XEXP (exp, 0)),
        !          1420:                     copy_boolean (XEXP (exp, 1)));
        !          1421:   return exp;
        !          1422: }
        !          1423: 
        !          1424: /* Given a value and an attribute description, return a `struct attr_value *'
        !          1425:    that represents that value.  This is either an existing structure, if the
        !          1426:    value has been previously encountered, or a newly-created structure.
        !          1427: 
        !          1428:    `insn_code' is the code of an insn whose attribute has the specified
        !          1429:    value (-2 if not processing an insn).  We ensure that all insns for
        !          1430:    a given value have the same number of alternatives if the value checks
        !          1431:    alternatives.  */
        !          1432: 
        !          1433: static struct attr_value *
        !          1434: get_attr_value (value, attr, insn_code)
        !          1435:      rtx value;
        !          1436:      struct attr_desc *attr;
        !          1437:      int insn_code;
        !          1438: {
        !          1439:   struct attr_value *av;
        !          1440:   int num_alt = 0;
        !          1441: 
        !          1442:   value = make_canonical (attr, value);
        !          1443:   if (compares_alternatives_p (value))
        !          1444:     {
        !          1445:       if (insn_code < 0 || insn_alternatives == NULL)
        !          1446:        fatal ("(eq_attr \"alternatives\" ...) used in non-insn context");
        !          1447:       else
        !          1448:        num_alt = insn_alternatives[insn_code];
        !          1449:     }
        !          1450: 
        !          1451:   for (av = attr->first_value; av; av = av->next)
        !          1452:     if (rtx_equal_p (value, av->value)
        !          1453:        && (num_alt == 0 || av->first_insn == NULL
        !          1454:            || insn_alternatives[av->first_insn->insn_code]))
        !          1455:       return av;
        !          1456: 
        !          1457:   av = (struct attr_value *) oballoc (sizeof (struct attr_value));
        !          1458:   av->value = value;
        !          1459:   av->next = attr->first_value;
        !          1460:   attr->first_value = av;
        !          1461:   av->first_insn = NULL;
        !          1462:   av->num_insns = 0;
        !          1463:   av->has_asm_insn = 0;
        !          1464: 
        !          1465:   return av;
        !          1466: }
        !          1467: 
        !          1468: /* After all DEFINE_DELAYs have been read in, create internal attributes
        !          1469:    to generate the required routines.
        !          1470: 
        !          1471:    First, we compute the number of delay slots for each insn (as a COND of
        !          1472:    each of the test expressions in DEFINE_DELAYs).  Then, if more than one
        !          1473:    delay type is specified, we compute a similar function giving the
        !          1474:    DEFINE_DELAY ordinal for each insn.
        !          1475: 
        !          1476:    Finally, for each [DEFINE_DELAY, slot #] pair, we compute an attribute that
        !          1477:    tells whether a given insn can be in that delay slot.
        !          1478: 
        !          1479:    Normal attribute filling and optimization expands these to contain the
        !          1480:    information needed to handle delay slots.  */
        !          1481: 
        !          1482: static void
        !          1483: expand_delays ()
        !          1484: {
        !          1485:   struct delay_desc *delay;
        !          1486:   rtx condexp;
        !          1487:   rtx newexp;
        !          1488:   int i;
        !          1489:   char *p;
        !          1490: 
        !          1491:   /* First, generate data for `num_delay_slots' function.  */
        !          1492: 
        !          1493:   condexp = rtx_alloc (COND);
        !          1494:   XVEC (condexp, 0) = rtvec_alloc (num_delays * 2);
        !          1495:   XEXP (condexp, 1) = make_numeric_value (0);
        !          1496: 
        !          1497:   for (i = 0, delay = delays; delay; i += 2, delay = delay->next)
        !          1498:     {
        !          1499:       XVECEXP (condexp, 0, i) = XEXP (delay->def, 0);
        !          1500:       XVECEXP (condexp, 0, i + 1)
        !          1501:        = make_numeric_value (XVECLEN (delay->def, 1) / 3);
        !          1502:     }
        !          1503: 
        !          1504:   make_internal_attr ("*num_delay_slots", condexp, 0);
        !          1505: 
        !          1506:   /* If more than one delay type, do the same for computing the delay type.  */
        !          1507:   if (num_delays > 1)
        !          1508:     {
        !          1509:       condexp = rtx_alloc (COND);
        !          1510:       XVEC (condexp, 0) = rtvec_alloc (num_delays * 2);
        !          1511:       XEXP (condexp, 1) = make_numeric_value (0);
        !          1512: 
        !          1513:       for (i = 0, delay = delays; delay; i += 2, delay = delay->next)
        !          1514:        {
        !          1515:          XVECEXP (condexp, 0, i) = XEXP (delay->def, 0);
        !          1516:          XVECEXP (condexp, 0, i + 1) = make_numeric_value (delay->num);
        !          1517:        }
        !          1518: 
        !          1519:       make_internal_attr ("*delay_type", condexp, 1);
        !          1520:     }
        !          1521: 
        !          1522:   /* For each delay possibility and delay slot, compute an eligibility
        !          1523:      attribute for non-annulled insns and for each type of annulled (annul
        !          1524:      if true and annul if false).  */
        !          1525:  for (delay = delays; delay; delay = delay->next)
        !          1526:    {
        !          1527:      for (i = 0; i < XVECLEN (delay->def, 1); i += 3)
        !          1528:        {
        !          1529:         condexp = XVECEXP (delay->def, 1, i);
        !          1530:         if (condexp == 0) condexp = false_rtx;
        !          1531:         newexp = attr_rtx (IF_THEN_ELSE, condexp,
        !          1532:                            make_numeric_value (1), make_numeric_value (0));
        !          1533: 
        !          1534:         p = attr_printf (sizeof ("*delay__") + MAX_DIGITS*2, "*delay_%d_%d",
        !          1535:                          delay->num, i / 3);
        !          1536:         make_internal_attr (p, newexp, 1);
        !          1537: 
        !          1538:         if (have_annul_true)
        !          1539:           {
        !          1540:             condexp = XVECEXP (delay->def, 1, i + 1);
        !          1541:             if (condexp == 0) condexp = false_rtx;
        !          1542:             newexp = attr_rtx (IF_THEN_ELSE, condexp,
        !          1543:                                make_numeric_value (1),
        !          1544:                                make_numeric_value (0));
        !          1545:             p = attr_printf (sizeof ("*annul_true__") + MAX_DIGITS*2,
        !          1546:                              "*annul_true_%d_%d", delay->num, i / 3);
        !          1547:             make_internal_attr (p, newexp, 1);
        !          1548:           }
        !          1549: 
        !          1550:         if (have_annul_false)
        !          1551:           {
        !          1552:             condexp = XVECEXP (delay->def, 1, i + 2);
        !          1553:             if (condexp == 0) condexp = false_rtx;
        !          1554:             newexp = attr_rtx (IF_THEN_ELSE, condexp,
        !          1555:                                make_numeric_value (1),
        !          1556:                                make_numeric_value (0));
        !          1557:             p = attr_printf (sizeof ("*annul_false__") + MAX_DIGITS*2,
        !          1558:                              "*annul_false_%d_%d", delay->num, i / 3);
        !          1559:             make_internal_attr (p, newexp, 1);
        !          1560:           }
        !          1561:        }
        !          1562:    }
        !          1563: }
        !          1564: 
        !          1565: /* This function is given a left and right side expression and an operator.
        !          1566:    Each side is a conditional expression, each alternative of which has a
        !          1567:    numerical value.  The function returns another conditional expression
        !          1568:    which, for every possible set of condition values, returns a value that is
        !          1569:    the operator applied to the values of the two sides.
        !          1570: 
        !          1571:    Since this is called early, it must also support IF_THEN_ELSE.  */
        !          1572: 
        !          1573: static rtx
        !          1574: operate_exp (op, left, right)
        !          1575:      enum operator op;
        !          1576:      rtx left, right;
        !          1577: {
        !          1578:   int left_value, right_value;
        !          1579:   rtx newexp;
        !          1580:   int i;
        !          1581: 
        !          1582:   /* If left is a string, apply operator to it and the right side.  */
        !          1583:   if (GET_CODE (left) == CONST_STRING)
        !          1584:     {
        !          1585:       /* If right is also a string, just perform the operation.  */
        !          1586:       if (GET_CODE (right) == CONST_STRING)
        !          1587:        {
        !          1588:          left_value = atoi (XSTR (left, 0));
        !          1589:          right_value = atoi (XSTR (right, 0));
        !          1590:          switch (op)
        !          1591:            {
        !          1592:            case PLUS_OP:
        !          1593:              i = left_value + right_value;
        !          1594:              break;
        !          1595: 
        !          1596:            case MINUS_OP:
        !          1597:              i = left_value - right_value;
        !          1598:              break;
        !          1599: 
        !          1600:            case POS_MINUS_OP:  /* The positive part of LEFT - RIGHT.  */
        !          1601:              if (left_value > right_value)
        !          1602:                i = left_value - right_value;
        !          1603:              else
        !          1604:                i = 0;
        !          1605:              break;
        !          1606: 
        !          1607:            case OR_OP:
        !          1608:              i = left_value | right_value;
        !          1609:              break;
        !          1610: 
        !          1611:            case EQ_OP:
        !          1612:              i = left_value == right_value;
        !          1613:              break;
        !          1614: 
        !          1615:            case RANGE_OP:
        !          1616:              i = (left_value << (HOST_BITS_PER_INT / 2)) | right_value;
        !          1617:              break;
        !          1618: 
        !          1619:            case MAX_OP:
        !          1620:              if (left_value > right_value)
        !          1621:                i = left_value;
        !          1622:              else
        !          1623:                i = right_value;
        !          1624:              break;
        !          1625: 
        !          1626:            case MIN_OP:
        !          1627:              if (left_value < right_value)
        !          1628:                i = left_value;
        !          1629:              else
        !          1630:                i = right_value;
        !          1631:              break;
        !          1632: 
        !          1633:            default:
        !          1634:              abort ();
        !          1635:            }
        !          1636: 
        !          1637:          return make_numeric_value (i);
        !          1638:        }
        !          1639:       else if (GET_CODE (right) == IF_THEN_ELSE)
        !          1640:        {
        !          1641:          /* Apply recursively to all values within.  */
        !          1642:          rtx newleft = operate_exp (op, left, XEXP (right, 1));
        !          1643:          rtx newright = operate_exp (op, left, XEXP (right, 2));
        !          1644:          if (rtx_equal_p (newleft, newright))
        !          1645:            return newleft;
        !          1646:          return attr_rtx (IF_THEN_ELSE, XEXP (right, 0), newleft, newright);
        !          1647:        }
        !          1648:       else if (GET_CODE (right) == COND)
        !          1649:        {
        !          1650:          int allsame = 1;
        !          1651:          rtx defval;
        !          1652: 
        !          1653:          newexp = rtx_alloc (COND);
        !          1654:          XVEC (newexp, 0) = rtvec_alloc (XVECLEN (right, 0));
        !          1655:          defval = XEXP (newexp, 1) = operate_exp (op, left, XEXP (right, 1));
        !          1656: 
        !          1657:          for (i = 0; i < XVECLEN (right, 0); i += 2)
        !          1658:            {
        !          1659:              XVECEXP (newexp, 0, i) = XVECEXP (right, 0, i);
        !          1660:              XVECEXP (newexp, 0, i + 1)
        !          1661:                = operate_exp (op, left, XVECEXP (right, 0, i + 1));
        !          1662:              if (! rtx_equal_p (XVECEXP (newexp, 0, i + 1),
        !          1663:                                 defval))     
        !          1664:                allsame = 0;
        !          1665:            }
        !          1666: 
        !          1667:          /* If the resulting cond is trivial (all alternatives
        !          1668:             give the same value), optimize it away.  */
        !          1669:          if (allsame)
        !          1670:            {
        !          1671:              obstack_free (rtl_obstack, newexp);
        !          1672:              return operate_exp (op, left, XEXP (right, 1));
        !          1673:            }
        !          1674: 
        !          1675:          /* If the result is the same as the RIGHT operand,
        !          1676:             just use that.  */
        !          1677:          if (rtx_equal_p (newexp, right))
        !          1678:            {
        !          1679:              obstack_free (rtl_obstack, newexp);
        !          1680:              return right;
        !          1681:            }
        !          1682: 
        !          1683:          return newexp;
        !          1684:        }
        !          1685:       else
        !          1686:        fatal ("Badly formed attribute value");
        !          1687:     }
        !          1688: 
        !          1689:   /* Otherwise, do recursion the other way.  */
        !          1690:   else if (GET_CODE (left) == IF_THEN_ELSE)
        !          1691:     {
        !          1692:       rtx newleft = operate_exp (op, XEXP (left, 1), right);
        !          1693:       rtx newright = operate_exp (op, XEXP (left, 2), right);
        !          1694:       if (rtx_equal_p (newleft, newright))
        !          1695:        return newleft;
        !          1696:       return attr_rtx (IF_THEN_ELSE, XEXP (left, 0), newleft, newright);
        !          1697:     }
        !          1698:   else if (GET_CODE (left) == COND)
        !          1699:     {
        !          1700:       int allsame = 1;
        !          1701:       rtx defval;
        !          1702: 
        !          1703:       newexp = rtx_alloc (COND);
        !          1704:       XVEC (newexp, 0) = rtvec_alloc (XVECLEN (left, 0));
        !          1705:       defval = XEXP (newexp, 1) = operate_exp (op, XEXP (left, 1), right);
        !          1706: 
        !          1707:       for (i = 0; i < XVECLEN (left, 0); i += 2)
        !          1708:        {
        !          1709:          XVECEXP (newexp, 0, i) = XVECEXP (left, 0, i);
        !          1710:          XVECEXP (newexp, 0, i + 1)
        !          1711:            = operate_exp (op, XVECEXP (left, 0, i + 1), right);
        !          1712:          if (! rtx_equal_p (XVECEXP (newexp, 0, i + 1),
        !          1713:                             defval))     
        !          1714:            allsame = 0;
        !          1715:        }
        !          1716: 
        !          1717:       /* If the cond is trivial (all alternatives give the same value),
        !          1718:         optimize it away.  */
        !          1719:       if (allsame)
        !          1720:        {
        !          1721:          obstack_free (rtl_obstack, newexp);
        !          1722:          return operate_exp (op, XEXP (left, 1), right);
        !          1723:        }
        !          1724: 
        !          1725:       /* If the result is the same as the LEFT operand,
        !          1726:         just use that.  */
        !          1727:       if (rtx_equal_p (newexp, left))
        !          1728:        {
        !          1729:          obstack_free (rtl_obstack, newexp);
        !          1730:          return left;
        !          1731:        }
        !          1732: 
        !          1733:       return newexp;
        !          1734:     }
        !          1735: 
        !          1736:   else
        !          1737:     fatal ("Badly formed attribute value.");
        !          1738:   /* NOTREACHED */
        !          1739:   return NULL;
        !          1740: }
        !          1741: 
        !          1742: /* Once all attributes and DEFINE_FUNCTION_UNITs have been read, we
        !          1743:    construct a number of attributes.
        !          1744: 
        !          1745:    The first produces a function `function_units_used' which is given an
        !          1746:    insn and produces an encoding showing which function units are required
        !          1747:    for the execution of that insn.  If the value is non-negative, the insn
        !          1748:    uses that unit; otherwise, the value is a one's compliment mask of units
        !          1749:    used.
        !          1750: 
        !          1751:    The second produces a function `result_ready_cost' which is used to
        !          1752:    determine the time that the result of an insn will be ready and hence
        !          1753:    a worst-case schedule.
        !          1754: 
        !          1755:    Both of these produce quite complex expressions which are then set as the
        !          1756:    default value of internal attributes.  Normal attribute simplification
        !          1757:    should produce reasonable expressions.
        !          1758: 
        !          1759:    For each unit, a `<name>_unit_ready_cost' function will take an
        !          1760:    insn and give the delay until that unit will be ready with the result
        !          1761:    and a `<name>_unit_conflict_cost' function is given an insn already
        !          1762:    executing on the unit and a candidate to execute and will give the
        !          1763:    cost from the time the executing insn started until the candidate
        !          1764:    can start (ignore limitations on the number of simultaneous insns).
        !          1765: 
        !          1766:    For each unit, a `<name>_unit_blockage' function is given an insn
        !          1767:    already executing on the unit and a candidate to execute and will
        !          1768:    give the delay incurred due to function unit conflicts.  The range of
        !          1769:    blockage cost values for a given executing insn is given by the
        !          1770:    `<name>_unit_blockage_range' function.  These values are encoded in
        !          1771:    an int where the upper half gives the minimum value and the lower
        !          1772:    half gives the maximum value.  */
        !          1773: 
        !          1774: static void
        !          1775: expand_units ()
        !          1776: {
        !          1777:   struct function_unit *unit, **unit_num;
        !          1778:   struct function_unit_op *op, **op_array, ***unit_ops;
        !          1779:   rtx unitsmask;
        !          1780:   rtx readycost;
        !          1781:   rtx newexp;
        !          1782:   char *str;
        !          1783:   int i, j, u, num, nvalues;
        !          1784: 
        !          1785:   /* Rebuild the condition for the unit to share the RTL expressions.
        !          1786:      Sharing is required by simplify_by_exploding.  Build the issue delay
        !          1787:      expressions.  Validate the expressions we were given for the conditions
        !          1788:      and conflict vector.  Then make attributes for use in the conflict
        !          1789:      function.  */
        !          1790: 
        !          1791:   for (unit = units; unit; unit = unit->next)
        !          1792:     {
        !          1793:       rtx min_issue = make_numeric_value (unit->issue_delay.min);
        !          1794: 
        !          1795:       unit->condexp = check_attr_test (unit->condexp, 0);
        !          1796: 
        !          1797:       for (op = unit->ops; op; op = op->next)
        !          1798:        {
        !          1799:          rtx issue_delay = make_numeric_value (op->issue_delay);
        !          1800:          rtx issue_exp = issue_delay;
        !          1801: 
        !          1802:          /* Build, validate, and simplify the issue delay expression.  */
        !          1803:          if (op->conflict_exp != true_rtx)
        !          1804:            issue_exp = attr_rtx (IF_THEN_ELSE, op->conflict_exp,
        !          1805:                                  issue_exp, make_numeric_value (0));
        !          1806:          issue_exp = check_attr_value (make_canonical (NULL_ATTR,
        !          1807:                                                        issue_exp),
        !          1808:                                        NULL_ATTR);
        !          1809:          issue_exp = simplify_knowing (issue_exp, unit->condexp);
        !          1810:          op->issue_exp = issue_exp;
        !          1811: 
        !          1812:          /* Make an attribute for use in the conflict function if needed.  */
        !          1813:          unit->needs_conflict_function = (unit->issue_delay.min
        !          1814:                                           != unit->issue_delay.max);
        !          1815:          if (unit->needs_conflict_function)
        !          1816:            {
        !          1817:              str = attr_printf (strlen (unit->name) + sizeof ("*_cost_") + MAX_DIGITS,
        !          1818:                                 "*%s_cost_%d", unit->name, op->num);
        !          1819:              make_internal_attr (str, issue_exp, 1);
        !          1820:            }
        !          1821: 
        !          1822:          /* Validate the condition.  */
        !          1823:          op->condexp = check_attr_test (op->condexp, 0);
        !          1824:        }
        !          1825:     }
        !          1826: 
        !          1827:   /* Compute the mask of function units used.  Initially, the unitsmask is
        !          1828:      zero.   Set up a conditional to compute each unit's contribution.  */
        !          1829:   unitsmask = make_numeric_value (0);
        !          1830:   newexp = rtx_alloc (IF_THEN_ELSE);
        !          1831:   XEXP (newexp, 2) = make_numeric_value (0);
        !          1832: 
        !          1833:   /* Merge each function unit into the unit mask attributes.  */
        !          1834:   for (unit = units; unit; unit = unit->next)
        !          1835:     {
        !          1836:       XEXP (newexp, 0) = unit->condexp;
        !          1837:       XEXP (newexp, 1) = make_numeric_value (1 << unit->num);
        !          1838:       unitsmask = operate_exp (OR_OP, unitsmask, newexp);
        !          1839:     }
        !          1840: 
        !          1841:   /* Simplify the unit mask expression, encode it, and make an attribute
        !          1842:      for the function_units_used function.  */
        !          1843:   unitsmask = simplify_by_exploding (unitsmask);
        !          1844:   unitsmask = encode_units_mask (unitsmask);
        !          1845:   make_internal_attr ("*function_units_used", unitsmask, 2);
        !          1846: 
        !          1847:   /* Create an array of ops for each unit.  Add an extra unit for the
        !          1848:      result_ready_cost function that has the ops of all other units.  */
        !          1849:   unit_ops = (struct function_unit_op ***)
        !          1850:     alloca ((num_units + 1) * sizeof (struct function_unit_op **));
        !          1851:   unit_num = (struct function_unit **)
        !          1852:     alloca ((num_units + 1) * sizeof (struct function_unit *));
        !          1853: 
        !          1854:   unit_num[num_units] = unit = (struct function_unit *)
        !          1855:     alloca (sizeof (struct function_unit));
        !          1856:   unit->num = num_units;
        !          1857:   unit->num_opclasses = 0;
        !          1858: 
        !          1859:   for (unit = units; unit; unit = unit->next)
        !          1860:     {
        !          1861:       unit_num[num_units]->num_opclasses += unit->num_opclasses;
        !          1862:       unit_num[unit->num] = unit;
        !          1863:       unit_ops[unit->num] = op_array = (struct function_unit_op **)
        !          1864:        alloca (unit->num_opclasses * sizeof (struct function_unit_op *));
        !          1865: 
        !          1866:       for (op = unit->ops; op; op = op->next)
        !          1867:        op_array[op->num] = op;
        !          1868:     }
        !          1869: 
        !          1870:   /* Compose the array of ops for the extra unit.  */
        !          1871:   unit_ops[num_units] = op_array = (struct function_unit_op **)
        !          1872:     alloca (unit_num[num_units]->num_opclasses
        !          1873:            * sizeof (struct function_unit_op *));
        !          1874: 
        !          1875:   for (unit = units, i = 0; unit; i += unit->num_opclasses, unit = unit->next)
        !          1876:     bcopy (unit_ops[unit->num], &op_array[i],
        !          1877:           unit->num_opclasses * sizeof (struct function_unit_op *));
        !          1878: 
        !          1879:   /* Compute the ready cost function for each unit by computing the
        !          1880:      condition for each non-default value.  */
        !          1881:   for (u = 0; u <= num_units; u++)
        !          1882:     {
        !          1883:       rtx orexp;
        !          1884:       int value;
        !          1885: 
        !          1886:       unit = unit_num[u];
        !          1887:       op_array = unit_ops[unit->num];
        !          1888:       num = unit->num_opclasses;
        !          1889: 
        !          1890:       /* Sort the array of ops into increasing ready cost order.  */
        !          1891:       for (i = 0; i < num; i++)
        !          1892:        for (j = num - 1; j > i; j--)
        !          1893:          if (op_array[j-1]->ready < op_array[j]->ready)
        !          1894:            {
        !          1895:              op = op_array[j];
        !          1896:              op_array[j] = op_array[j-1];
        !          1897:              op_array[j-1] = op;
        !          1898:            }
        !          1899: 
        !          1900:       /* Determine how many distinct non-default ready cost values there
        !          1901:         are.  We use a default ready cost value of 1.  */
        !          1902:       nvalues = 0; value = 1;
        !          1903:       for (i = num - 1; i >= 0; i--)
        !          1904:        if (op_array[i]->ready > value)
        !          1905:          {
        !          1906:            value = op_array[i]->ready;
        !          1907:            nvalues++;
        !          1908:          }
        !          1909: 
        !          1910:       if (nvalues == 0)
        !          1911:        readycost = make_numeric_value (1);
        !          1912:       else
        !          1913:        {
        !          1914:          /* Construct the ready cost expression as a COND of each value from
        !          1915:             the largest to the smallest.  */
        !          1916:          readycost = rtx_alloc (COND);
        !          1917:          XVEC (readycost, 0) = rtvec_alloc (nvalues * 2);
        !          1918:          XEXP (readycost, 1) = make_numeric_value (1);
        !          1919: 
        !          1920:          nvalues = 0; orexp = false_rtx; value = op_array[0]->ready;
        !          1921:          for (i = 0; i < num; i++)
        !          1922:            {
        !          1923:              op = op_array[i];
        !          1924:              if (op->ready <= 1)
        !          1925:                break;
        !          1926:              else if (op->ready == value)
        !          1927:                orexp = insert_right_side (IOR, orexp, op->condexp, -2, -2);
        !          1928:              else
        !          1929:                {
        !          1930:                  XVECEXP (readycost, 0, nvalues * 2) = orexp;
        !          1931:                  XVECEXP (readycost, 0, nvalues * 2 + 1)
        !          1932:                    = make_numeric_value (value);
        !          1933:                  nvalues++;
        !          1934:                  value = op->ready;
        !          1935:                  orexp = op->condexp;
        !          1936:                }
        !          1937:            }
        !          1938:          XVECEXP (readycost, 0, nvalues * 2) = orexp;
        !          1939:          XVECEXP (readycost, 0, nvalues * 2 + 1) = make_numeric_value (value);
        !          1940:        }
        !          1941: 
        !          1942:       if (u < num_units)
        !          1943:        {
        !          1944:          rtx max_blockage = 0, min_blockage = 0;
        !          1945: 
        !          1946:          /* Simplify the readycost expression by only considering insns
        !          1947:             that use the unit.  */
        !          1948:          readycost = simplify_knowing (readycost, unit->condexp);
        !          1949: 
        !          1950:          /* Determine the blockage cost the executing insn (E) given
        !          1951:             the candidate insn (C).  This is the maximum of the issue
        !          1952:             delay, the pipeline delay, and the simultaneity constraint.
        !          1953:             Each function_unit_op represents the characteristics of the
        !          1954:             candidate insn, so in the expressions below, C is a known
        !          1955:             term and E is an unknown term.
        !          1956: 
        !          1957:             The issue delay function for C is op->issue_exp and is used to
        !          1958:             write the `<name>_unit_conflict_cost' function.  Symbolicly
        !          1959:             this is "ISSUE-DELAY (E,C)".
        !          1960: 
        !          1961:             The pipeline delay results form the FIFO constraint on the
        !          1962:             function unit and is "READY-COST (E) + 1 - READY-COST (C)".
        !          1963: 
        !          1964:             The simultaneity constraint is based on how long it takes to
        !          1965:             fill the unit given the minimum issue delay.  FILL-TIME is the
        !          1966:             constant "MIN (ISSUE-DELAY (*,*)) * (SIMULTANEITY - 1)", and
        !          1967:             the simultaneity constraint is "READY-COST (E) - FILL-TIME"
        !          1968:             if SIMULTANEITY is non-zero and zero otherwise.
        !          1969: 
        !          1970:             Thus, BLOCKAGE (E,C) when SIMULTANEITY is zero is
        !          1971: 
        !          1972:                 MAX (ISSUE-DELAY (E,C),
        !          1973:                      READY-COST (E) - (READY-COST (C) - 1))
        !          1974: 
        !          1975:             and otherwise
        !          1976: 
        !          1977:                 MAX (ISSUE-DELAY (E,C),
        !          1978:                      READY-COST (E) - (READY-COST (C) - 1),
        !          1979:                      READY-COST (E) - FILL-TIME)
        !          1980: 
        !          1981:             The `<name>_unit_blockage' function is computed by determining
        !          1982:             this value for each candidate insn.  As these values are
        !          1983:             computed, we also compute the upper and lower bounds for
        !          1984:             BLOCKAGE (E,*).  These are combined to form the function
        !          1985:             `<name>_unit_blockage_range'.  Finally, the maximum blockage
        !          1986:             cost, MAX (BLOCKAGE (*,*)), is computed.  */
        !          1987: 
        !          1988:          for (op = unit->ops; op; op = op->next)
        !          1989:            {
        !          1990:              rtx blockage = readycost;
        !          1991:              int delay = op->ready - 1;
        !          1992: 
        !          1993:              if (unit->simultaneity != 0)
        !          1994:                delay = MIN (delay, ((unit->simultaneity - 1)
        !          1995:                                     * unit->issue_delay.min));
        !          1996: 
        !          1997:              if (delay > 0)
        !          1998:                blockage = operate_exp (POS_MINUS_OP, blockage,
        !          1999:                                        make_numeric_value (delay));
        !          2000: 
        !          2001:              blockage = operate_exp (MAX_OP, blockage, op->issue_exp);
        !          2002:              blockage = simplify_knowing (blockage, unit->condexp);
        !          2003: 
        !          2004:              /* Add this op's contribution to MAX (BLOCKAGE (E,*)) and
        !          2005:                 MIN (BLOCKAGE (E,*)).  */
        !          2006:              if (max_blockage == 0)
        !          2007:                max_blockage = min_blockage = blockage;
        !          2008:              else
        !          2009:                {
        !          2010:                  max_blockage
        !          2011:                    = simplify_knowing (operate_exp (MAX_OP, max_blockage,
        !          2012:                                                     blockage),
        !          2013:                                        unit->condexp);
        !          2014:                  min_blockage
        !          2015:                    = simplify_knowing (operate_exp (MIN_OP, min_blockage,
        !          2016:                                                     blockage),
        !          2017:                                        unit->condexp);
        !          2018:                }
        !          2019: 
        !          2020:              /* Make an attribute for use in the blockage function.  */
        !          2021:              str = attr_printf (strlen (unit->name) + sizeof ("*_block_") + MAX_DIGITS,
        !          2022:                                 "*%s_block_%d", unit->name, op->num);
        !          2023:              make_internal_attr (str, blockage, 1);
        !          2024:            }
        !          2025: 
        !          2026:          /* Record MAX (BLOCKAGE (*,*)).  */
        !          2027:          unit->max_blockage = max_attr_value (max_blockage);
        !          2028: 
        !          2029:          /* See if the upper and lower bounds of BLOCKAGE (E,*) are the
        !          2030:             same.  If so, the blockage function carries no additional
        !          2031:             information and is not written.  */
        !          2032:          newexp = operate_exp (EQ_OP, max_blockage, min_blockage);
        !          2033:          newexp = simplify_knowing (newexp, unit->condexp);
        !          2034:          unit->needs_blockage_function
        !          2035:            = (GET_CODE (newexp) != CONST_STRING
        !          2036:               || atoi (XSTR (newexp, 0)) != 1);
        !          2037: 
        !          2038:          /* If the all values of BLOCKAGE (E,C) have the same value,
        !          2039:             neither blockage function is written.  */    
        !          2040:          unit->needs_range_function
        !          2041:            = (unit->needs_blockage_function
        !          2042:               || GET_CODE (max_blockage) != CONST_STRING);
        !          2043: 
        !          2044:          if (unit->needs_range_function)
        !          2045:            {
        !          2046:              /* Compute the blockage range function and make an attribute
        !          2047:                 for writing it's value.  */
        !          2048:              newexp = operate_exp (RANGE_OP, min_blockage, max_blockage);
        !          2049:              newexp = simplify_knowing (newexp, unit->condexp);
        !          2050: 
        !          2051:              str = attr_printf (strlen (unit->name) + sizeof ("*_unit_blockage_range"),
        !          2052:                                 "*%s_unit_blockage_range", unit->name);
        !          2053:              make_internal_attr (str, newexp, 4);
        !          2054:            }
        !          2055: 
        !          2056:          str = attr_printf (strlen (unit->name) + sizeof ("*_unit_ready_cost"),
        !          2057:                             "*%s_unit_ready_cost", unit->name);
        !          2058:        }
        !          2059:       else
        !          2060:        str = "*result_ready_cost";
        !          2061: 
        !          2062:       /* Make an attribute for the ready_cost function.  Simplifying
        !          2063:         further with simplify_by_exploding doesn't win.  */
        !          2064:       make_internal_attr (str, readycost, 0);
        !          2065:     }
        !          2066: 
        !          2067:   /* For each unit that requires a conflict cost function, make an attribute
        !          2068:      that maps insns to the operation number.  */
        !          2069:   for (unit = units; unit; unit = unit->next)
        !          2070:     {
        !          2071:       rtx caseexp;
        !          2072: 
        !          2073:       if (! unit->needs_conflict_function
        !          2074:          && ! unit->needs_blockage_function)
        !          2075:        continue;
        !          2076: 
        !          2077:       caseexp = rtx_alloc (COND);
        !          2078:       XVEC (caseexp, 0) = rtvec_alloc ((unit->num_opclasses - 1) * 2);
        !          2079: 
        !          2080:       for (op = unit->ops; op; op = op->next)
        !          2081:        {
        !          2082:          /* Make our adjustment to the COND being computed.  If we are the
        !          2083:             last operation class, place our values into the default of the
        !          2084:             COND.  */
        !          2085:          if (op->num == unit->num_opclasses - 1)
        !          2086:            {
        !          2087:              XEXP (caseexp, 1) = make_numeric_value (op->num);
        !          2088:            }
        !          2089:          else
        !          2090:            {
        !          2091:              XVECEXP (caseexp, 0, op->num * 2) = op->condexp;
        !          2092:              XVECEXP (caseexp, 0, op->num * 2 + 1)
        !          2093:                = make_numeric_value (op->num);
        !          2094:            }
        !          2095:        }
        !          2096: 
        !          2097:       /* Simplifying caseexp with simplify_by_exploding doesn't win.  */
        !          2098:       str = attr_printf (strlen (unit->name) + sizeof ("*_cases"),
        !          2099:                         "*%s_cases", unit->name);
        !          2100:       make_internal_attr (str, caseexp, 1);
        !          2101:     }
        !          2102: }
        !          2103: 
        !          2104: /* Simplify EXP given KNOWN_TRUE.  */
        !          2105: 
        !          2106: static rtx
        !          2107: simplify_knowing (exp, known_true)
        !          2108:      rtx exp, known_true;
        !          2109: {
        !          2110:   if (GET_CODE (exp) != CONST_STRING)
        !          2111:     {
        !          2112:       exp = attr_rtx (IF_THEN_ELSE, known_true, exp,
        !          2113:                      make_numeric_value (max_attr_value (exp)));
        !          2114:       exp = simplify_by_exploding (exp);
        !          2115:     }
        !          2116:   return exp;
        !          2117: }
        !          2118: 
        !          2119: /* Translate the CONST_STRING expressions in X to change the encoding of
        !          2120:    value.  On input, the value is a bitmask with a one bit for each unit
        !          2121:    used; on output, the value is the unit number (zero based) if one
        !          2122:    and only one unit is used or the one's compliment of the bitmask.  */
        !          2123: 
        !          2124: static rtx
        !          2125: encode_units_mask (x)
        !          2126:      rtx x;
        !          2127: {
        !          2128:   register int i;
        !          2129:   register int j;
        !          2130:   register enum rtx_code code;
        !          2131:   register char *fmt;
        !          2132: 
        !          2133:   code = GET_CODE (x);
        !          2134: 
        !          2135:   switch (code)
        !          2136:     {
        !          2137:     case CONST_STRING:
        !          2138:       i = atoi (XSTR (x, 0));
        !          2139:       if (i < 0)
        !          2140:        abort (); /* The sign bit encodes a one's compliment mask.  */
        !          2141:       else if (i != 0 && i == (i & -i))
        !          2142:        /* Only one bit is set, so yield that unit number.  */
        !          2143:        for (j = 0; (i >>= 1) != 0; j++)
        !          2144:          ;
        !          2145:       else
        !          2146:        j = ~i;
        !          2147:       return attr_rtx (CONST_STRING, attr_printf (MAX_DIGITS, "%d", j));
        !          2148: 
        !          2149:     case REG:
        !          2150:     case QUEUED:
        !          2151:     case CONST_INT:
        !          2152:     case CONST_DOUBLE:
        !          2153:     case SYMBOL_REF:
        !          2154:     case CODE_LABEL:
        !          2155:     case PC:
        !          2156:     case CC0:
        !          2157:     case EQ_ATTR:
        !          2158:       return x;
        !          2159:     }
        !          2160: 
        !          2161:   /* Compare the elements.  If any pair of corresponding elements
        !          2162:      fail to match, return 0 for the whole things.  */
        !          2163: 
        !          2164:   fmt = GET_RTX_FORMAT (code);
        !          2165:   for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
        !          2166:     {
        !          2167:       switch (fmt[i])
        !          2168:        {
        !          2169:        case 'V':
        !          2170:        case 'E':
        !          2171:          for (j = 0; j < XVECLEN (x, i); j++)
        !          2172:            XVECEXP (x, i, j) = encode_units_mask (XVECEXP (x, i, j));
        !          2173:          break;
        !          2174: 
        !          2175:        case 'e':
        !          2176:          XEXP (x, i) = encode_units_mask (XEXP (x, i));
        !          2177:          break;
        !          2178:        }
        !          2179:     }
        !          2180:   return x;
        !          2181: }
        !          2182: 
        !          2183: /* Once all attributes and insns have been read and checked, we construct for
        !          2184:    each attribute value a list of all the insns that have that value for
        !          2185:    the attribute.  */
        !          2186: 
        !          2187: static void
        !          2188: fill_attr (attr)
        !          2189:      struct attr_desc *attr;
        !          2190: {
        !          2191:   struct attr_value *av;
        !          2192:   struct insn_ent *ie;
        !          2193:   struct insn_def *id;
        !          2194:   int i;
        !          2195:   rtx value;
        !          2196: 
        !          2197:   /* Don't fill constant attributes.  The value is independent of
        !          2198:      any particular insn.  */
        !          2199:   if (attr->is_const)
        !          2200:     return;
        !          2201: 
        !          2202:   for (id = defs; id; id = id->next)
        !          2203:     {
        !          2204:       /* If no value is specified for this insn for this attribute, use the
        !          2205:         default.  */
        !          2206:       value = NULL;
        !          2207:       if (XVEC (id->def, id->vec_idx))
        !          2208:        for (i = 0; i < XVECLEN (id->def, id->vec_idx); i++)
        !          2209:          if (! strcmp (XSTR (XEXP (XVECEXP (id->def, id->vec_idx, i), 0), 0), 
        !          2210:                        attr->name))
        !          2211:            value = XEXP (XVECEXP (id->def, id->vec_idx, i), 1);
        !          2212: 
        !          2213:       if (value == NULL)
        !          2214:        av = attr->default_val;
        !          2215:       else
        !          2216:        av = get_attr_value (value, attr, id->insn_code);
        !          2217: 
        !          2218:       ie = (struct insn_ent *) oballoc (sizeof (struct insn_ent));
        !          2219:       ie->insn_code = id->insn_code;
        !          2220:       ie->insn_index = id->insn_code;
        !          2221:       insert_insn_ent (av, ie);
        !          2222:     }
        !          2223: }
        !          2224: 
        !          2225: /* Given an expression EXP, see if it is a COND or IF_THEN_ELSE that has a
        !          2226:    test that checks relative positions of insns (uses MATCH_DUP or PC).
        !          2227:    If so, replace it with what is obtained by passing the expression to
        !          2228:    ADDRESS_FN.  If not but it is a COND or IF_THEN_ELSE, call this routine
        !          2229:    recursively on each value (including the default value).  Otherwise,
        !          2230:    return the value returned by NO_ADDRESS_FN applied to EXP.  */
        !          2231: 
        !          2232: static rtx
        !          2233: substitute_address (exp, no_address_fn, address_fn)
        !          2234:      rtx exp;
        !          2235:      rtx (*no_address_fn) ();
        !          2236:      rtx (*address_fn) ();
        !          2237: {
        !          2238:   int i;
        !          2239:   rtx newexp;
        !          2240: 
        !          2241:   if (GET_CODE (exp) == COND)
        !          2242:     {
        !          2243:       /* See if any tests use addresses.  */
        !          2244:       address_used = 0;
        !          2245:       for (i = 0; i < XVECLEN (exp, 0); i += 2)
        !          2246:        walk_attr_value (XVECEXP (exp, 0, i));
        !          2247: 
        !          2248:       if (address_used)
        !          2249:        return (*address_fn) (exp);
        !          2250: 
        !          2251:       /* Make a new copy of this COND, replacing each element.  */
        !          2252:       newexp = rtx_alloc (COND);
        !          2253:       XVEC (newexp, 0) = rtvec_alloc (XVECLEN (exp, 0));
        !          2254:       for (i = 0; i < XVECLEN (exp, 0); i += 2)
        !          2255:        {
        !          2256:          XVECEXP (newexp, 0, i) = XVECEXP (exp, 0, i);
        !          2257:          XVECEXP (newexp, 0, i + 1)
        !          2258:            = substitute_address (XVECEXP (exp, 0, i + 1),
        !          2259:                                  no_address_fn, address_fn);
        !          2260:        }
        !          2261: 
        !          2262:       XEXP (newexp, 1) = substitute_address (XEXP (exp, 1),
        !          2263:                                             no_address_fn, address_fn);
        !          2264: 
        !          2265:       return newexp;
        !          2266:     }
        !          2267: 
        !          2268:   else if (GET_CODE (exp) == IF_THEN_ELSE)
        !          2269:     {
        !          2270:       address_used = 0;
        !          2271:       walk_attr_value (XEXP (exp, 0));
        !          2272:       if (address_used)
        !          2273:        return (*address_fn) (exp);
        !          2274: 
        !          2275:       return attr_rtx (IF_THEN_ELSE,
        !          2276:                       substitute_address (XEXP (exp, 0),
        !          2277:                                           no_address_fn, address_fn),
        !          2278:                       substitute_address (XEXP (exp, 1),
        !          2279:                                           no_address_fn, address_fn),
        !          2280:                       substitute_address (XEXP (exp, 2),
        !          2281:                                           no_address_fn, address_fn));
        !          2282:     }
        !          2283: 
        !          2284:   return (*no_address_fn) (exp);
        !          2285: }
        !          2286: 
        !          2287: /* Make new attributes from the `length' attribute.  The following are made,
        !          2288:    each corresponding to a function called from `shorten_branches' or
        !          2289:    `get_attr_length':
        !          2290: 
        !          2291:    *insn_default_length                This is the length of the insn to be returned
        !          2292:                                by `get_attr_length' before `shorten_branches'
        !          2293:                                has been called.  In each case where the length
        !          2294:                                depends on relative addresses, the largest
        !          2295:                                possible is used.  This routine is also used
        !          2296:                                to compute the initial size of the insn.
        !          2297: 
        !          2298:    *insn_variable_length_p     This returns 1 if the insn's length depends
        !          2299:                                on relative addresses, zero otherwise.
        !          2300: 
        !          2301:    *insn_current_length                This is only called when it is known that the
        !          2302:                                insn has a variable length and returns the
        !          2303:                                current length, based on relative addresses.
        !          2304:   */
        !          2305: 
        !          2306: static void
        !          2307: make_length_attrs ()
        !          2308: {
        !          2309:   static char *new_names[] = {"*insn_default_length",
        !          2310:                              "*insn_variable_length_p",
        !          2311:                              "*insn_current_length"};
        !          2312:   static rtx (*no_address_fn[]) PROTO((rtx)) = {identity_fn, zero_fn, zero_fn};
        !          2313:   static rtx (*address_fn[]) PROTO((rtx)) = {max_fn, one_fn, identity_fn};
        !          2314:   int i;
        !          2315:   struct attr_desc *length_attr, *new_attr;
        !          2316:   struct attr_value *av, *new_av;
        !          2317:   struct insn_ent *ie, *new_ie;
        !          2318: 
        !          2319:   /* See if length attribute is defined.  If so, it must be numeric.  Make
        !          2320:      it special so we don't output anything for it.  */
        !          2321:   length_attr = find_attr ("length", 0);
        !          2322:   if (length_attr == 0)
        !          2323:     return;
        !          2324: 
        !          2325:   if (! length_attr->is_numeric)
        !          2326:     fatal ("length attribute must be numeric.");
        !          2327: 
        !          2328:   length_attr->is_const = 0;
        !          2329:   length_attr->is_special = 1;
        !          2330: 
        !          2331:   /* Make each new attribute, in turn.  */
        !          2332:   for (i = 0; i < sizeof new_names / sizeof new_names[0]; i++)
        !          2333:     {
        !          2334:       make_internal_attr (new_names[i],
        !          2335:                          substitute_address (length_attr->default_val->value,
        !          2336:                                              no_address_fn[i], address_fn[i]),
        !          2337:                          0);
        !          2338:       new_attr = find_attr (new_names[i], 0);
        !          2339:       for (av = length_attr->first_value; av; av = av->next)
        !          2340:        for (ie = av->first_insn; ie; ie = ie->next)
        !          2341:          {
        !          2342:            new_av = get_attr_value (substitute_address (av->value,
        !          2343:                                                         no_address_fn[i],
        !          2344:                                                         address_fn[i]),
        !          2345:                                     new_attr, ie->insn_code);
        !          2346:            new_ie = (struct insn_ent *) oballoc (sizeof (struct insn_ent));
        !          2347:            new_ie->insn_code = ie->insn_code;
        !          2348:            new_ie->insn_index = ie->insn_index;
        !          2349:            insert_insn_ent (new_av, new_ie);
        !          2350:          }
        !          2351:     }
        !          2352: }
        !          2353: 
        !          2354: /* Utility functions called from above routine.  */
        !          2355: 
        !          2356: static rtx
        !          2357: identity_fn (exp)
        !          2358:      rtx exp;
        !          2359: {
        !          2360:   return exp;
        !          2361: }
        !          2362: 
        !          2363: static rtx
        !          2364: zero_fn (exp)
        !          2365:      rtx exp;
        !          2366: {
        !          2367:   return make_numeric_value (0);
        !          2368: }
        !          2369: 
        !          2370: static rtx
        !          2371: one_fn (exp)
        !          2372:      rtx exp;
        !          2373: {
        !          2374:   return make_numeric_value (1);
        !          2375: }
        !          2376: 
        !          2377: static rtx
        !          2378: max_fn (exp)
        !          2379:      rtx exp;
        !          2380: {
        !          2381:   return make_numeric_value (max_attr_value (exp));
        !          2382: }
        !          2383: 
        !          2384: /* Take a COND expression and see if any of the conditions in it can be
        !          2385:    simplified.  If any are known true or known false for the particular insn
        !          2386:    code, the COND can be further simplified.
        !          2387: 
        !          2388:    Also call ourselves on any COND operations that are values of this COND.
        !          2389: 
        !          2390:    We do not modify EXP; rather, we make and return a new rtx.  */
        !          2391: 
        !          2392: static rtx
        !          2393: simplify_cond (exp, insn_code, insn_index)
        !          2394:      rtx exp;
        !          2395:      int insn_code, insn_index;
        !          2396: {
        !          2397:   int i, j;
        !          2398:   /* We store the desired contents here,
        !          2399:      then build a new expression if they don't match EXP.  */
        !          2400:   rtx defval = XEXP (exp, 1);
        !          2401:   rtx new_defval = XEXP (exp, 1);
        !          2402: 
        !          2403:   int len = XVECLEN (exp, 0);
        !          2404:   rtx *tests = (rtx *) alloca (len * sizeof (rtx));
        !          2405:   int allsame = 1;
        !          2406:   char *first_spacer;
        !          2407: 
        !          2408:   /* This lets us free all storage allocated below, if appropriate.  */
        !          2409:   first_spacer = (char *) obstack_finish (rtl_obstack);
        !          2410: 
        !          2411:   bcopy (&XVECEXP (exp, 0, 0), tests, len * sizeof (rtx));
        !          2412: 
        !          2413:   /* See if default value needs simplification.  */
        !          2414:   if (GET_CODE (defval) == COND)
        !          2415:     new_defval = simplify_cond (defval, insn_code, insn_index);
        !          2416: 
        !          2417:   /* Simplify the subexpressions, and see what tests we can get rid of.  */
        !          2418: 
        !          2419:   for (i = 0; i < len; i += 2)
        !          2420:     {
        !          2421:       rtx newtest, newval;
        !          2422: 
        !          2423:       /* Simplify this test.  */
        !          2424:       newtest = SIMPLIFY_TEST_EXP (tests[i], insn_code, insn_index);
        !          2425:       tests[i] = newtest;
        !          2426: 
        !          2427:       newval = tests[i + 1];
        !          2428:       /* See if this value may need simplification.  */
        !          2429:       if (GET_CODE (newval) == COND)
        !          2430:        newval = simplify_cond (newval, insn_code, insn_index);
        !          2431: 
        !          2432:       /* Look for ways to delete or combine this test.  */
        !          2433:       if (newtest == true_rtx)
        !          2434:        {
        !          2435:          /* If test is true, make this value the default
        !          2436:             and discard this + any following tests.  */
        !          2437:          len = i;
        !          2438:          defval = tests[i + 1];
        !          2439:          new_defval = newval;
        !          2440:        }
        !          2441: 
        !          2442:       else if (newtest == false_rtx)
        !          2443:        {
        !          2444:          /* If test is false, discard it and its value.  */
        !          2445:          for (j = i; j < len - 2; j++)
        !          2446:            tests[j] = tests[j + 2];
        !          2447:          len -= 2;
        !          2448:        }
        !          2449: 
        !          2450:       else if (i > 0 && attr_equal_p (newval, tests[i - 1]))
        !          2451:        {
        !          2452:          /* If this value and the value for the prev test are the same,
        !          2453:             merge the tests.  */
        !          2454: 
        !          2455:          tests[i - 2]
        !          2456:            = insert_right_side (IOR, tests[i - 2], newtest,
        !          2457:                                 insn_code, insn_index);
        !          2458: 
        !          2459:          /* Delete this test/value.  */
        !          2460:          for (j = i; j < len - 2; j++)
        !          2461:            tests[j] = tests[j + 2];
        !          2462:          len -= 2;
        !          2463:        }
        !          2464: 
        !          2465:       else
        !          2466:        tests[i + 1] = newval;
        !          2467:     }
        !          2468: 
        !          2469:   /* If the last test in a COND has the same value
        !          2470:      as the default value, that test isn't needed.  */
        !          2471: 
        !          2472:   while (len > 0 && attr_equal_p (tests[len - 1], new_defval))
        !          2473:     len -= 2;
        !          2474: 
        !          2475:   /* See if we changed anything.  */
        !          2476:   if (len != XVECLEN (exp, 0) || new_defval != XEXP (exp, 1))
        !          2477:     allsame = 0;
        !          2478:   else
        !          2479:     for (i = 0; i < len; i++)
        !          2480:       if (! attr_equal_p (tests[i], XVECEXP (exp, 0, i)))
        !          2481:        {
        !          2482:          allsame = 0;
        !          2483:          break;
        !          2484:        }
        !          2485: 
        !          2486:   if (len == 0)
        !          2487:     {
        !          2488:       obstack_free (rtl_obstack, first_spacer);
        !          2489:       if (GET_CODE (defval) == COND)
        !          2490:        return simplify_cond (defval, insn_code, insn_index);
        !          2491:       return defval;
        !          2492:     }
        !          2493:   else if (allsame)
        !          2494:     {
        !          2495:       obstack_free (rtl_obstack, first_spacer);
        !          2496:       return exp;
        !          2497:     }
        !          2498:   else
        !          2499:     {
        !          2500:       rtx newexp = rtx_alloc (COND);
        !          2501: 
        !          2502:       XVEC (newexp, 0) = rtvec_alloc (len);
        !          2503:       bcopy (tests, &XVECEXP (newexp, 0, 0), len * sizeof (rtx));
        !          2504:       XEXP (newexp, 1) = new_defval;
        !          2505:       return newexp;
        !          2506:     }
        !          2507: }
        !          2508: 
        !          2509: /* Remove an insn entry from an attribute value.  */
        !          2510: 
        !          2511: static void
        !          2512: remove_insn_ent (av, ie)
        !          2513:      struct attr_value *av;
        !          2514:      struct insn_ent *ie;
        !          2515: {
        !          2516:   struct insn_ent *previe;
        !          2517: 
        !          2518:   if (av->first_insn == ie)
        !          2519:     av->first_insn = ie->next;
        !          2520:   else
        !          2521:     {
        !          2522:       for (previe = av->first_insn; previe->next != ie; previe = previe->next)
        !          2523:        ;
        !          2524:       previe->next = ie->next;
        !          2525:     }
        !          2526: 
        !          2527:   av->num_insns--;
        !          2528:   if (ie->insn_code == -1)
        !          2529:     av->has_asm_insn = 0;
        !          2530: }
        !          2531: 
        !          2532: /* Insert an insn entry in an attribute value list.  */
        !          2533: 
        !          2534: static void
        !          2535: insert_insn_ent (av, ie)
        !          2536:      struct attr_value *av;
        !          2537:      struct insn_ent *ie;
        !          2538: {
        !          2539:   ie->next = av->first_insn;
        !          2540:   av->first_insn = ie;
        !          2541:   av->num_insns++;
        !          2542:   if (ie->insn_code == -1)
        !          2543:     av->has_asm_insn = 1;
        !          2544: }
        !          2545: 
        !          2546: /* This is a utility routine to take an expression that is a tree of either
        !          2547:    AND or IOR expressions and insert a new term.  The new term will be
        !          2548:    inserted at the right side of the first node whose code does not match
        !          2549:    the root.  A new node will be created with the root's code.  Its left
        !          2550:    side will be the old right side and its right side will be the new
        !          2551:    term.
        !          2552: 
        !          2553:    If the `term' is itself a tree, all its leaves will be inserted.  */
        !          2554: 
        !          2555: static rtx
        !          2556: insert_right_side (code, exp, term, insn_code, insn_index)
        !          2557:      enum rtx_code code;
        !          2558:      rtx exp;
        !          2559:      rtx term;
        !          2560:      int insn_code, insn_index;
        !          2561: {
        !          2562:   rtx newexp;
        !          2563: 
        !          2564:   /* Avoid consing in some special cases.  */
        !          2565:   if (code == AND && term == true_rtx)
        !          2566:     return exp;
        !          2567:   if (code == AND && term == false_rtx)
        !          2568:     return false_rtx;
        !          2569:   if (code == AND && exp == true_rtx)
        !          2570:     return term;
        !          2571:   if (code == AND && exp == false_rtx)
        !          2572:     return false_rtx;
        !          2573:   if (code == IOR && term == true_rtx)
        !          2574:     return true_rtx;
        !          2575:   if (code == IOR && term == false_rtx)
        !          2576:     return exp;
        !          2577:   if (code == IOR && exp == true_rtx)
        !          2578:     return true_rtx;
        !          2579:   if (code == IOR && exp == false_rtx)
        !          2580:     return term;
        !          2581:   if (attr_equal_p (exp, term))
        !          2582:     return exp;
        !          2583: 
        !          2584:   if (GET_CODE (term) == code)
        !          2585:     {
        !          2586:       exp = insert_right_side (code, exp, XEXP (term, 0),
        !          2587:                               insn_code, insn_index);
        !          2588:       exp = insert_right_side (code, exp, XEXP (term, 1),
        !          2589:                               insn_code, insn_index);
        !          2590: 
        !          2591:       return exp;
        !          2592:     }
        !          2593: 
        !          2594:   if (GET_CODE (exp) == code)
        !          2595:     {
        !          2596:       rtx new = insert_right_side (code, XEXP (exp, 1),
        !          2597:                                   term, insn_code, insn_index);
        !          2598:       if (new != XEXP (exp, 1))
        !          2599:        /* Make a copy of this expression and call recursively.  */
        !          2600:        newexp = attr_rtx (code, XEXP (exp, 0), new);
        !          2601:       else
        !          2602:        newexp = exp;
        !          2603:     }
        !          2604:   else
        !          2605:     {
        !          2606:       /* Insert the new term.  */
        !          2607:       newexp = attr_rtx (code, exp, term);
        !          2608:     }
        !          2609: 
        !          2610:   return SIMPLIFY_TEST_EXP (newexp, insn_code, insn_index);
        !          2611: }
        !          2612: 
        !          2613: /* If we have an expression which AND's a bunch of
        !          2614:        (not (eq_attrq "alternative" "n"))
        !          2615:    terms, we may have covered all or all but one of the possible alternatives.
        !          2616:    If so, we can optimize.  Similarly for IOR's of EQ_ATTR.
        !          2617: 
        !          2618:    This routine is passed an expression and either AND or IOR.  It returns a
        !          2619:    bitmask indicating which alternatives are mentioned within EXP.  */
        !          2620: 
        !          2621: static int
        !          2622: compute_alternative_mask (exp, code)
        !          2623:      rtx exp;
        !          2624:      enum rtx_code code;
        !          2625: {
        !          2626:   char *string;
        !          2627:   if (GET_CODE (exp) == code)
        !          2628:     return compute_alternative_mask (XEXP (exp, 0), code)
        !          2629:           | compute_alternative_mask (XEXP (exp, 1), code);
        !          2630: 
        !          2631:   else if (code == AND && GET_CODE (exp) == NOT
        !          2632:           && GET_CODE (XEXP (exp, 0)) == EQ_ATTR
        !          2633:           && XSTR (XEXP (exp, 0), 0) == alternative_name)
        !          2634:     string = XSTR (XEXP (exp, 0), 1);
        !          2635: 
        !          2636:   else if (code == IOR && GET_CODE (exp) == EQ_ATTR
        !          2637:           && XSTR (exp, 0) == alternative_name)
        !          2638:     string = XSTR (exp, 1);
        !          2639: 
        !          2640:   else
        !          2641:     return 0;
        !          2642: 
        !          2643:   if (string[1] == 0)
        !          2644:     return 1 << (string[0] - '0');
        !          2645:   return 1 << atoi (string);
        !          2646: }
        !          2647: 
        !          2648: /* Given I, a single-bit mask, return RTX to compare the `alternative'
        !          2649:    attribute with the value represented by that bit.  */
        !          2650: 
        !          2651: static rtx
        !          2652: make_alternative_compare (mask)
        !          2653:      int mask;
        !          2654: {
        !          2655:   rtx newexp;
        !          2656:   int i;
        !          2657: 
        !          2658:   /* Find the bit.  */
        !          2659:   for (i = 0; (mask & (1 << i)) == 0; i++)
        !          2660:     ;
        !          2661: 
        !          2662:   newexp = attr_rtx (EQ_ATTR, alternative_name, attr_numeral (i));
        !          2663:   RTX_UNCHANGING_P (newexp) = 1;
        !          2664: 
        !          2665:   return newexp;
        !          2666: }
        !          2667: 
        !          2668: /* If we are processing an (eq_attr "attr" "value") test, we find the value
        !          2669:    of "attr" for this insn code.  From that value, we can compute a test
        !          2670:    showing when the EQ_ATTR will be true.  This routine performs that
        !          2671:    computation.  If a test condition involves an address, we leave the EQ_ATTR
        !          2672:    intact because addresses are only valid for the `length' attribute. 
        !          2673: 
        !          2674:    EXP is the EQ_ATTR expression and VALUE is the value of that attribute
        !          2675:    for the insn corresponding to INSN_CODE and INSN_INDEX.  */
        !          2676: 
        !          2677: static rtx
        !          2678: evaluate_eq_attr (exp, value, insn_code, insn_index)
        !          2679:      rtx exp;
        !          2680:      rtx value;
        !          2681:      int insn_code, insn_index;
        !          2682: {
        !          2683:   rtx orexp, andexp;
        !          2684:   rtx right;
        !          2685:   rtx newexp;
        !          2686:   int i;
        !          2687: 
        !          2688:   if (GET_CODE (value) == CONST_STRING)
        !          2689:     {
        !          2690:       if (! strcmp (XSTR (value, 0), XSTR (exp, 1)))
        !          2691:        newexp = true_rtx;
        !          2692:       else
        !          2693:        newexp = false_rtx;
        !          2694:     }
        !          2695:   else if (GET_CODE (value) == COND)
        !          2696:     {
        !          2697:       /* We construct an IOR of all the cases for which the requested attribute
        !          2698:         value is present.  Since we start with FALSE, if it is not present,
        !          2699:         FALSE will be returned.
        !          2700: 
        !          2701:         Each case is the AND of the NOT's of the previous conditions with the
        !          2702:         current condition; in the default case the current condition is TRUE. 
        !          2703: 
        !          2704:         For each possible COND value, call ourselves recursively.
        !          2705: 
        !          2706:         The extra TRUE and FALSE expressions will be eliminated by another
        !          2707:         call to the simplification routine. */
        !          2708: 
        !          2709:       orexp = false_rtx;
        !          2710:       andexp = true_rtx;
        !          2711: 
        !          2712:       if (current_alternative_string)
        !          2713:        clear_struct_flag (value);
        !          2714: 
        !          2715:       for (i = 0; i < XVECLEN (value, 0); i += 2)
        !          2716:        {
        !          2717:          rtx this = SIMPLIFY_TEST_EXP (XVECEXP (value, 0, i),
        !          2718:                                        insn_code, insn_index);
        !          2719: 
        !          2720:          SIMPLIFY_ALTERNATIVE (this);
        !          2721: 
        !          2722:          right = insert_right_side (AND, andexp, this,
        !          2723:                                     insn_code, insn_index);
        !          2724:          right = insert_right_side (AND, right,
        !          2725:                                     evaluate_eq_attr (exp,
        !          2726:                                                       XVECEXP (value, 0,
        !          2727:                                                                i + 1),
        !          2728:                                                       insn_code, insn_index),
        !          2729:                                     insn_code, insn_index);
        !          2730:          orexp = insert_right_side (IOR, orexp, right,
        !          2731:                                     insn_code, insn_index);
        !          2732: 
        !          2733:          /* Add this condition into the AND expression.  */
        !          2734:          newexp = attr_rtx (NOT, this);
        !          2735:          andexp = insert_right_side (AND, andexp, newexp,
        !          2736:                                      insn_code, insn_index);
        !          2737:        }
        !          2738: 
        !          2739:       /* Handle the default case.  */
        !          2740:       right = insert_right_side (AND, andexp,
        !          2741:                                 evaluate_eq_attr (exp, XEXP (value, 1),
        !          2742:                                                   insn_code, insn_index),
        !          2743:                                 insn_code, insn_index);
        !          2744:       newexp = insert_right_side (IOR, orexp, right, insn_code, insn_index);
        !          2745:     }
        !          2746:   else
        !          2747:     abort ();
        !          2748: 
        !          2749:   /* If uses an address, must return original expression.  But set the
        !          2750:      RTX_UNCHANGING_P bit so we don't try to simplify it again.  */
        !          2751: 
        !          2752:   address_used = 0;
        !          2753:   walk_attr_value (newexp);
        !          2754: 
        !          2755:   if (address_used)
        !          2756:     {
        !          2757:       /* This had `&& current_alternative_string', which seems to be wrong.  */
        !          2758:       if (! RTX_UNCHANGING_P (exp))
        !          2759:        return copy_rtx_unchanging (exp);
        !          2760:       return exp;
        !          2761:     }
        !          2762:   else
        !          2763:     return newexp;
        !          2764: }
        !          2765: 
        !          2766: /* This routine is called when an AND of a term with a tree of AND's is
        !          2767:    encountered.  If the term or its complement is present in the tree, it
        !          2768:    can be replaced with TRUE or FALSE, respectively.
        !          2769: 
        !          2770:    Note that (eq_attr "att" "v1") and (eq_attr "att" "v2") cannot both
        !          2771:    be true and hence are complementary.  
        !          2772: 
        !          2773:    There is one special case:  If we see
        !          2774:        (and (not (eq_attr "att" "v1"))
        !          2775:             (eq_attr "att" "v2"))
        !          2776:    this can be replaced by (eq_attr "att" "v2").  To do this we need to
        !          2777:    replace the term, not anything in the AND tree.  So we pass a pointer to
        !          2778:    the term.  */
        !          2779: 
        !          2780: static rtx
        !          2781: simplify_and_tree (exp, pterm, insn_code, insn_index)
        !          2782:      rtx exp;
        !          2783:      rtx *pterm;
        !          2784:      int insn_code, insn_index;
        !          2785: {
        !          2786:   rtx left, right;
        !          2787:   rtx newexp;
        !          2788:   rtx temp;
        !          2789:   int left_eliminates_term, right_eliminates_term;
        !          2790: 
        !          2791:   if (GET_CODE (exp) == AND)
        !          2792:     {
        !          2793:       left = simplify_and_tree (XEXP (exp, 0), pterm,  insn_code, insn_index);
        !          2794:       right = simplify_and_tree (XEXP (exp, 1), pterm, insn_code, insn_index);
        !          2795:       if (left != XEXP (exp, 0) || right != XEXP (exp, 1))
        !          2796:        {
        !          2797:          newexp = attr_rtx (GET_CODE (exp), left, right);
        !          2798: 
        !          2799:          exp = SIMPLIFY_TEST_EXP (newexp, insn_code, insn_index);
        !          2800:        }
        !          2801:     }
        !          2802: 
        !          2803:   else if (GET_CODE (exp) == IOR)
        !          2804:     {
        !          2805:       /* For the IOR case, we do the same as above, except that we can
        !          2806:          only eliminate `term' if both sides of the IOR would do so.  */
        !          2807:       temp = *pterm;
        !          2808:       left = simplify_and_tree (XEXP (exp, 0), &temp,  insn_code, insn_index);
        !          2809:       left_eliminates_term = (temp == true_rtx);
        !          2810: 
        !          2811:       temp = *pterm;
        !          2812:       right = simplify_and_tree (XEXP (exp, 1), &temp, insn_code, insn_index);
        !          2813:       right_eliminates_term = (temp == true_rtx);
        !          2814: 
        !          2815:       if (left_eliminates_term && right_eliminates_term)
        !          2816:        *pterm = true_rtx;
        !          2817: 
        !          2818:       if (left != XEXP (exp, 0) || right != XEXP (exp, 1))
        !          2819:        {
        !          2820:          newexp = attr_rtx (GET_CODE (exp), left, right);
        !          2821: 
        !          2822:          exp = SIMPLIFY_TEST_EXP (newexp, insn_code, insn_index);
        !          2823:        }
        !          2824:     }
        !          2825: 
        !          2826:   /* Check for simplifications.  Do some extra checking here since this
        !          2827:      routine is called so many times.  */
        !          2828: 
        !          2829:   if (exp == *pterm)
        !          2830:     return true_rtx;
        !          2831: 
        !          2832:   else if (GET_CODE (exp) == NOT && XEXP (exp, 0) == *pterm)
        !          2833:     return false_rtx;
        !          2834: 
        !          2835:   else if (GET_CODE (*pterm) == NOT && exp == XEXP (*pterm, 0))
        !          2836:     return false_rtx;
        !          2837: 
        !          2838:   else if (GET_CODE (exp) == EQ_ATTR && GET_CODE (*pterm) == EQ_ATTR)
        !          2839:     {
        !          2840:       if (XSTR (exp, 0) != XSTR (*pterm, 0))
        !          2841:        return exp;
        !          2842: 
        !          2843:       if (! strcmp (XSTR (exp, 1), XSTR (*pterm, 1)))
        !          2844:        return true_rtx;
        !          2845:       else
        !          2846:        return false_rtx;
        !          2847:     }
        !          2848: 
        !          2849:   else if (GET_CODE (*pterm) == EQ_ATTR && GET_CODE (exp) == NOT
        !          2850:           && GET_CODE (XEXP (exp, 0)) == EQ_ATTR)
        !          2851:     {
        !          2852:       if (XSTR (*pterm, 0) != XSTR (XEXP (exp, 0), 0))
        !          2853:        return exp;
        !          2854: 
        !          2855:       if (! strcmp (XSTR (*pterm, 1), XSTR (XEXP (exp, 0), 1)))
        !          2856:        return false_rtx;
        !          2857:       else
        !          2858:        return true_rtx;
        !          2859:     }
        !          2860: 
        !          2861:   else if (GET_CODE (exp) == EQ_ATTR && GET_CODE (*pterm) == NOT
        !          2862:           && GET_CODE (XEXP (*pterm, 0)) == EQ_ATTR)
        !          2863:     {
        !          2864:       if (XSTR (exp, 0) != XSTR (XEXP (*pterm, 0), 0))
        !          2865:        return exp;
        !          2866: 
        !          2867:       if (! strcmp (XSTR (exp, 1), XSTR (XEXP (*pterm, 0), 1)))
        !          2868:        return false_rtx;
        !          2869:       else
        !          2870:        *pterm = true_rtx;
        !          2871:     }
        !          2872: 
        !          2873:   else if (GET_CODE (exp) == NOT && GET_CODE (*pterm) == NOT)
        !          2874:     {
        !          2875:       if (attr_equal_p (XEXP (exp, 0), XEXP (*pterm, 0)))
        !          2876:        return true_rtx;
        !          2877:     }
        !          2878: 
        !          2879:   else if (GET_CODE (exp) == NOT)
        !          2880:     {
        !          2881:       if (attr_equal_p (XEXP (exp, 0), *pterm))
        !          2882:        return false_rtx;
        !          2883:     }
        !          2884: 
        !          2885:   else if (GET_CODE (*pterm) == NOT)
        !          2886:     {
        !          2887:       if (attr_equal_p (XEXP (*pterm, 0), exp))
        !          2888:        return false_rtx;
        !          2889:     }
        !          2890: 
        !          2891:   else if (attr_equal_p (exp, *pterm))
        !          2892:     return true_rtx;
        !          2893: 
        !          2894:   return exp;
        !          2895: }
        !          2896: 
        !          2897: /* Similar to `simplify_and_tree', but for IOR trees.  */
        !          2898: 
        !          2899: static rtx
        !          2900: simplify_or_tree (exp, pterm, insn_code, insn_index)
        !          2901:      rtx exp;
        !          2902:      rtx *pterm;
        !          2903:      int insn_code, insn_index;
        !          2904: {
        !          2905:   rtx left, right;
        !          2906:   rtx newexp;
        !          2907:   rtx temp;
        !          2908:   int left_eliminates_term, right_eliminates_term;
        !          2909: 
        !          2910:   if (GET_CODE (exp) == IOR)
        !          2911:     {
        !          2912:       left = simplify_or_tree (XEXP (exp, 0), pterm,  insn_code, insn_index);
        !          2913:       right = simplify_or_tree (XEXP (exp, 1), pterm, insn_code, insn_index);
        !          2914:       if (left != XEXP (exp, 0) || right != XEXP (exp, 1))
        !          2915:        {
        !          2916:          newexp = attr_rtx (GET_CODE (exp), left, right);
        !          2917: 
        !          2918:          exp = SIMPLIFY_TEST_EXP (newexp, insn_code, insn_index);
        !          2919:        }
        !          2920:     }
        !          2921: 
        !          2922:   else if (GET_CODE (exp) == AND)
        !          2923:     {
        !          2924:       /* For the AND case, we do the same as above, except that we can
        !          2925:          only eliminate `term' if both sides of the AND would do so.  */
        !          2926:       temp = *pterm;
        !          2927:       left = simplify_or_tree (XEXP (exp, 0), &temp,  insn_code, insn_index);
        !          2928:       left_eliminates_term = (temp == false_rtx);
        !          2929: 
        !          2930:       temp = *pterm;
        !          2931:       right = simplify_or_tree (XEXP (exp, 1), &temp, insn_code, insn_index);
        !          2932:       right_eliminates_term = (temp == false_rtx);
        !          2933: 
        !          2934:       if (left_eliminates_term && right_eliminates_term)
        !          2935:        *pterm = false_rtx;
        !          2936: 
        !          2937:       if (left != XEXP (exp, 0) || right != XEXP (exp, 1))
        !          2938:        {
        !          2939:          newexp = attr_rtx (GET_CODE (exp), left, right);
        !          2940: 
        !          2941:          exp = SIMPLIFY_TEST_EXP (newexp, insn_code, insn_index);
        !          2942:        }
        !          2943:     }
        !          2944: 
        !          2945:   if (attr_equal_p (exp, *pterm))
        !          2946:     return false_rtx;
        !          2947: 
        !          2948:   else if (GET_CODE (exp) == NOT && attr_equal_p (XEXP (exp, 0), *pterm))
        !          2949:     return true_rtx;
        !          2950: 
        !          2951:   else if (GET_CODE (*pterm) == NOT && attr_equal_p (XEXP (*pterm, 0), exp))
        !          2952:     return true_rtx;
        !          2953: 
        !          2954:   else if (GET_CODE (*pterm) == EQ_ATTR && GET_CODE (exp) == NOT
        !          2955:           && GET_CODE (XEXP (exp, 0)) == EQ_ATTR
        !          2956:           && XSTR (*pterm, 0) == XSTR (XEXP (exp, 0), 0))
        !          2957:     *pterm = false_rtx;
        !          2958: 
        !          2959:   else if (GET_CODE (exp) == EQ_ATTR && GET_CODE (*pterm) == NOT
        !          2960:           && GET_CODE (XEXP (*pterm, 0)) == EQ_ATTR
        !          2961:           && XSTR (exp, 0) == XSTR (XEXP (*pterm, 0), 0))
        !          2962:     return false_rtx;
        !          2963: 
        !          2964:   return exp;
        !          2965: }
        !          2966: 
        !          2967: /* Given an expression, see if it can be simplified for a particular insn
        !          2968:    code based on the values of other attributes being tested.  This can
        !          2969:    eliminate nested get_attr_... calls.
        !          2970: 
        !          2971:    Note that if an endless recursion is specified in the patterns, the 
        !          2972:    optimization will loop.  However, it will do so in precisely the cases where
        !          2973:    an infinite recursion loop could occur during compilation.  It's better that
        !          2974:    it occurs here!  */
        !          2975: 
        !          2976: static rtx
        !          2977: simplify_test_exp (exp, insn_code, insn_index)
        !          2978:      rtx exp;
        !          2979:      int insn_code, insn_index;
        !          2980: {
        !          2981:   rtx left, right;
        !          2982:   struct attr_desc *attr;
        !          2983:   struct attr_value *av;
        !          2984:   struct insn_ent *ie;
        !          2985:   int i;
        !          2986:   rtx newexp = exp;
        !          2987:   char *spacer = (char *) obstack_finish (rtl_obstack);
        !          2988: 
        !          2989:   /* Don't re-simplify something we already simplified.  */
        !          2990:   if (RTX_UNCHANGING_P (exp) || MEM_IN_STRUCT_P (exp))
        !          2991:     return exp;
        !          2992: 
        !          2993:   switch (GET_CODE (exp))
        !          2994:     {
        !          2995:     case AND:
        !          2996:       left = SIMPLIFY_TEST_EXP (XEXP (exp, 0), insn_code, insn_index);
        !          2997:       SIMPLIFY_ALTERNATIVE (left);
        !          2998:       if (left == false_rtx)
        !          2999:        {
        !          3000:          obstack_free (rtl_obstack, spacer);
        !          3001:          return false_rtx;
        !          3002:        }
        !          3003:       right = SIMPLIFY_TEST_EXP (XEXP (exp, 1), insn_code, insn_index);
        !          3004:       SIMPLIFY_ALTERNATIVE (right);
        !          3005:       if (left == false_rtx)
        !          3006:        {
        !          3007:          obstack_free (rtl_obstack, spacer);
        !          3008:          return false_rtx;
        !          3009:        }
        !          3010: 
        !          3011:       /* If either side is an IOR and we have (eq_attr "alternative" ..")
        !          3012:         present on both sides, apply the distributive law since this will
        !          3013:         yield simplifications.  */
        !          3014:       if ((GET_CODE (left) == IOR || GET_CODE (right) == IOR)
        !          3015:          && compute_alternative_mask (left, IOR)
        !          3016:          && compute_alternative_mask (right, IOR))
        !          3017:        {
        !          3018:          if (GET_CODE (left) == IOR)
        !          3019:            {
        !          3020:              rtx tem = left;
        !          3021:              left = right;
        !          3022:              right = tem;
        !          3023:            }
        !          3024: 
        !          3025:          newexp = attr_rtx (IOR,
        !          3026:                             attr_rtx (AND, left, XEXP (right, 0)),
        !          3027:                             attr_rtx (AND, left, XEXP (right, 1)));
        !          3028: 
        !          3029:          return SIMPLIFY_TEST_EXP (newexp, insn_code, insn_index);
        !          3030:        }
        !          3031: 
        !          3032:       /* Try with the term on both sides.  */
        !          3033:       right = simplify_and_tree (right, &left, insn_code, insn_index);
        !          3034:       if (left == XEXP (exp, 0) && right == XEXP (exp, 1))
        !          3035:        left = simplify_and_tree (left, &right, insn_code, insn_index);
        !          3036: 
        !          3037:       if (left == false_rtx || right == false_rtx)
        !          3038:        {
        !          3039:          obstack_free (rtl_obstack, spacer);
        !          3040:          return false_rtx;
        !          3041:        }
        !          3042:       else if (left == true_rtx)
        !          3043:        {
        !          3044:          return right;
        !          3045:        }
        !          3046:       else if (right == true_rtx)
        !          3047:        {
        !          3048:          return left;
        !          3049:        }
        !          3050:       /* See if all or all but one of the insn's alternatives are specified
        !          3051:         in this tree.  Optimize if so.  */
        !          3052: 
        !          3053:       else if (insn_code >= 0
        !          3054:               && (GET_CODE (left) == AND
        !          3055:                   || (GET_CODE (left) == NOT
        !          3056:                       && GET_CODE (XEXP (left, 0)) == EQ_ATTR
        !          3057:                       && XSTR (XEXP (left, 0), 0) == alternative_name)
        !          3058:                   || GET_CODE (right) == AND
        !          3059:                   || (GET_CODE (right) == NOT
        !          3060:                       && GET_CODE (XEXP (right, 0)) == EQ_ATTR
        !          3061:                       && XSTR (XEXP (right, 0), 0) == alternative_name)))
        !          3062:        {
        !          3063:          i = compute_alternative_mask (exp, AND);
        !          3064:          if (i & ~insn_alternatives[insn_code])
        !          3065:            fatal ("Illegal alternative specified for pattern number %d",
        !          3066:                   insn_index);
        !          3067: 
        !          3068:          /* If all alternatives are excluded, this is false. */
        !          3069:          i ^= insn_alternatives[insn_code];
        !          3070:          if (i == 0)
        !          3071:            return false_rtx;
        !          3072:          else if ((i & (i - 1)) == 0 && insn_alternatives[insn_code] > 1)
        !          3073:            {
        !          3074:              /* If just one excluded, AND a comparison with that one to the
        !          3075:                 front of the tree.  The others will be eliminated by
        !          3076:                 optimization.  We do not want to do this if the insn has one
        !          3077:                 alternative and we have tested none of them!  */
        !          3078:              left = make_alternative_compare (i);
        !          3079:              right = simplify_and_tree (exp, &left, insn_code, insn_index);
        !          3080:              newexp = attr_rtx (AND, left, right);
        !          3081: 
        !          3082:              return SIMPLIFY_TEST_EXP (newexp, insn_code, insn_index);
        !          3083:            }
        !          3084:        }
        !          3085: 
        !          3086:       if (left != XEXP (exp, 0) || right != XEXP (exp, 1))
        !          3087:        {
        !          3088:          newexp = attr_rtx (AND, left, right);
        !          3089:          return SIMPLIFY_TEST_EXP (newexp, insn_code, insn_index);
        !          3090:        }
        !          3091:       break;
        !          3092: 
        !          3093:     case IOR:
        !          3094:       left = SIMPLIFY_TEST_EXP (XEXP (exp, 0), insn_code, insn_index);
        !          3095:       SIMPLIFY_ALTERNATIVE (left);
        !          3096:       if (left == true_rtx)
        !          3097:        {
        !          3098:          obstack_free (rtl_obstack, spacer);
        !          3099:          return true_rtx;
        !          3100:        }
        !          3101:       right = SIMPLIFY_TEST_EXP (XEXP (exp, 1), insn_code, insn_index);
        !          3102:       SIMPLIFY_ALTERNATIVE (right);
        !          3103:       if (right == true_rtx)
        !          3104:        {
        !          3105:          obstack_free (rtl_obstack, spacer);
        !          3106:          return true_rtx;
        !          3107:        }
        !          3108: 
        !          3109:       right = simplify_or_tree (right, &left, insn_code, insn_index);
        !          3110:       if (left == XEXP (exp, 0) && right == XEXP (exp, 1))
        !          3111:        left = simplify_or_tree (left, &right, insn_code, insn_index);
        !          3112: 
        !          3113:       if (right == true_rtx || left == true_rtx)
        !          3114:        {
        !          3115:          obstack_free (rtl_obstack, spacer);
        !          3116:          return true_rtx;
        !          3117:        }
        !          3118:       else if (left == false_rtx)
        !          3119:        {
        !          3120:          return right;
        !          3121:        }
        !          3122:       else if (right == false_rtx)
        !          3123:        {
        !          3124:          return left;
        !          3125:        }
        !          3126: 
        !          3127:       /* Test for simple cases where the distributive law is useful.  I.e.,
        !          3128:            convert (ior (and (x) (y))
        !          3129:                         (and (x) (z)))
        !          3130:            to      (and (x)
        !          3131:                         (ior (y) (z)))
        !          3132:        */
        !          3133: 
        !          3134:       else if (GET_CODE (left) == AND && GET_CODE (right) == AND
        !          3135:          && attr_equal_p (XEXP (left, 0), XEXP (right, 0)))
        !          3136:        {
        !          3137:          newexp = attr_rtx (IOR, XEXP (left, 1), XEXP (right, 1));
        !          3138: 
        !          3139:          left = XEXP (left, 0);
        !          3140:          right = newexp;
        !          3141:          newexp = attr_rtx (AND, left, right);
        !          3142:          return SIMPLIFY_TEST_EXP (newexp, insn_code, insn_index);
        !          3143:        }
        !          3144: 
        !          3145:       /* See if all or all but one of the insn's alternatives are specified
        !          3146:         in this tree.  Optimize if so.  */
        !          3147: 
        !          3148:       else if (insn_code >= 0
        !          3149:          && (GET_CODE (left) == IOR
        !          3150:              || (GET_CODE (left) == EQ_ATTR
        !          3151:                  && XSTR (left, 0) == alternative_name)
        !          3152:              || GET_CODE (right) == IOR
        !          3153:              || (GET_CODE (right) == EQ_ATTR
        !          3154:                  && XSTR (right, 0) == alternative_name)))
        !          3155:        {
        !          3156:          i = compute_alternative_mask (exp, IOR);
        !          3157:          if (i & ~insn_alternatives[insn_code])
        !          3158:            fatal ("Illegal alternative specified for pattern number %d",
        !          3159:                   insn_index);
        !          3160: 
        !          3161:          /* If all alternatives are included, this is true. */
        !          3162:          i ^= insn_alternatives[insn_code];
        !          3163:          if (i == 0)
        !          3164:            return true_rtx;
        !          3165:          else if ((i & (i - 1)) == 0 && insn_alternatives[insn_code] > 1)
        !          3166:            {
        !          3167:              /* If just one excluded, IOR a comparison with that one to the
        !          3168:                 front of the tree.  The others will be eliminated by
        !          3169:                 optimization.  We do not want to do this if the insn has one
        !          3170:                 alternative and we have tested none of them!  */
        !          3171:              left = make_alternative_compare (i);
        !          3172:              right = simplify_and_tree (exp, &left, insn_code, insn_index);
        !          3173:              newexp = attr_rtx (IOR, attr_rtx (NOT, left), right);
        !          3174: 
        !          3175:              return SIMPLIFY_TEST_EXP (newexp, insn_code, insn_index);
        !          3176:            }
        !          3177:        }
        !          3178: 
        !          3179:       if (left != XEXP (exp, 0) || right != XEXP (exp, 1))
        !          3180:        {
        !          3181:          newexp = attr_rtx (IOR, left, right);
        !          3182:          return SIMPLIFY_TEST_EXP (newexp, insn_code, insn_index);
        !          3183:        }
        !          3184:       break;
        !          3185: 
        !          3186:     case NOT:
        !          3187:       if (GET_CODE (XEXP (exp, 0)) == NOT)
        !          3188:        {
        !          3189:          left = SIMPLIFY_TEST_EXP (XEXP (XEXP (exp, 0), 0),
        !          3190:                                    insn_code, insn_index);
        !          3191:          SIMPLIFY_ALTERNATIVE (left);
        !          3192:          return left;
        !          3193:        }
        !          3194: 
        !          3195:       left = SIMPLIFY_TEST_EXP (XEXP (exp, 0), insn_code, insn_index);
        !          3196:       SIMPLIFY_ALTERNATIVE (left);
        !          3197:       if (GET_CODE (left) == NOT)
        !          3198:        return XEXP (left, 0);
        !          3199: 
        !          3200:       if (left == false_rtx)
        !          3201:        {
        !          3202:          obstack_free (rtl_obstack, spacer);
        !          3203:          return true_rtx;
        !          3204:        }
        !          3205:       else if (left == true_rtx)
        !          3206:        {
        !          3207:          obstack_free (rtl_obstack, spacer);
        !          3208:          return false_rtx;
        !          3209:        }
        !          3210: 
        !          3211:       /* Try to apply De`Morgan's laws.  */
        !          3212:       else if (GET_CODE (left) == IOR)
        !          3213:        {
        !          3214:          newexp = attr_rtx (AND,
        !          3215:                             attr_rtx (NOT, XEXP (left, 0)),
        !          3216:                             attr_rtx (NOT, XEXP (left, 1)));
        !          3217: 
        !          3218:          newexp = SIMPLIFY_TEST_EXP (newexp, insn_code, insn_index);
        !          3219:        }
        !          3220:       else if (GET_CODE (left) == AND)
        !          3221:        {
        !          3222:          newexp = attr_rtx (IOR,
        !          3223:                             attr_rtx (NOT, XEXP (left, 0)),
        !          3224:                             attr_rtx (NOT, XEXP (left, 1)));
        !          3225: 
        !          3226:          newexp = SIMPLIFY_TEST_EXP (newexp, insn_code, insn_index);
        !          3227:        }
        !          3228:       else if (left != XEXP (exp, 0))
        !          3229:        {
        !          3230:          newexp = attr_rtx (NOT, left);
        !          3231:        }
        !          3232:       break;
        !          3233: 
        !          3234:     case EQ_ATTR:
        !          3235:       if (current_alternative_string && XSTR (exp, 0) == alternative_name)
        !          3236:        return (XSTR (exp, 1) == current_alternative_string
        !          3237:                ? true_rtx : false_rtx);
        !          3238:        
        !          3239:       /* Look at the value for this insn code in the specified attribute.
        !          3240:         We normally can replace this comparison with the condition that
        !          3241:         would give this insn the values being tested for.   */
        !          3242:       if (XSTR (exp, 0) != alternative_name
        !          3243:          && (attr = find_attr (XSTR (exp, 0), 0)) != NULL)
        !          3244:        for (av = attr->first_value; av; av = av->next)
        !          3245:          for (ie = av->first_insn; ie; ie = ie->next)
        !          3246:            if (ie->insn_code == insn_code)
        !          3247:              return evaluate_eq_attr (exp, av->value, insn_code, insn_index);
        !          3248:     }
        !          3249: 
        !          3250:   /* We have already simplified this expression.  Simplifying it again
        !          3251:      won't buy anything unless we weren't given a valid insn code
        !          3252:      to process (i.e., we are canonicalizing something.).  */
        !          3253:   if (insn_code != -2 /* Seems wrong: && current_alternative_string.  */
        !          3254:       && ! RTX_UNCHANGING_P (newexp))
        !          3255:     return copy_rtx_unchanging (newexp);
        !          3256: 
        !          3257:   return newexp;
        !          3258: }
        !          3259: 
        !          3260: /* Optimize the attribute lists by seeing if we can determine conditional
        !          3261:    values from the known values of other attributes.  This will save subroutine
        !          3262:    calls during the compilation.  */
        !          3263: 
        !          3264: static void
        !          3265: optimize_attrs ()
        !          3266: {
        !          3267:   struct attr_desc *attr;
        !          3268:   struct attr_value *av;
        !          3269:   struct insn_ent *ie;
        !          3270:   rtx newexp;
        !          3271:   int something_changed = 1;
        !          3272:   int i;
        !          3273:   struct attr_value_list { struct attr_value *av;
        !          3274:                           struct insn_ent *ie;
        !          3275:                           struct attr_desc * attr;
        !          3276:                           struct attr_value_list *next; };
        !          3277:   struct attr_value_list **insn_code_values;
        !          3278:   struct attr_value_list *iv;
        !          3279: 
        !          3280:   /* For each insn code, make a list of all the insn_ent's for it,
        !          3281:      for all values for all attributes.  */
        !          3282: 
        !          3283:   /* Make 2 extra elements, for "code" values -2 and -1.  */
        !          3284:   insn_code_values
        !          3285:     = (struct attr_value_list **) alloca ((insn_code_number + 2)
        !          3286:                                          * sizeof (struct attr_value_list *));
        !          3287:   bzero (insn_code_values,
        !          3288:         (insn_code_number + 2) * sizeof (struct attr_value_list *));
        !          3289:   /* Offset the table address so we can index by -2 or -1.  */
        !          3290:   insn_code_values += 2;
        !          3291: 
        !          3292:   for (i = 0; i < MAX_ATTRS_INDEX; i++)
        !          3293:     for (attr = attrs[i]; attr; attr = attr->next)
        !          3294:       for (av = attr->first_value; av; av = av->next)
        !          3295:        for (ie = av->first_insn; ie; ie = ie->next)
        !          3296:          {
        !          3297:            iv = ((struct attr_value_list *)
        !          3298:                  alloca (sizeof (struct attr_value_list)));
        !          3299:            iv->attr = attr;
        !          3300:            iv->av = av;
        !          3301:            iv->ie = ie;
        !          3302:            iv->next = insn_code_values[ie->insn_code];
        !          3303:            insn_code_values[ie->insn_code] = iv;
        !          3304:          }
        !          3305: 
        !          3306:   /* Process one insn code at a time.  */
        !          3307:   for (i = -2; i < insn_code_number; i++)
        !          3308:     {
        !          3309:       /* Clear the MEM_IN_STRUCT_P flag everywhere relevant.
        !          3310:         We use it to mean "already simplified for this insn".  */
        !          3311:       for (iv = insn_code_values[i]; iv; iv = iv->next)
        !          3312:        clear_struct_flag (iv->av->value);
        !          3313: 
        !          3314:       /* Loop until nothing changes for one iteration.  */
        !          3315:       something_changed = 1;
        !          3316:       while (something_changed)
        !          3317:        {
        !          3318:          something_changed = 0;
        !          3319:          for (iv = insn_code_values[i]; iv; iv = iv->next)
        !          3320:            {
        !          3321:              struct obstack *old = rtl_obstack;
        !          3322:              char *spacer = (char *) obstack_finish (temp_obstack);
        !          3323: 
        !          3324:              attr = iv->attr;
        !          3325:              av = iv->av;
        !          3326:              ie = iv->ie;
        !          3327:              if (GET_CODE (av->value) != COND)
        !          3328:                continue;
        !          3329: 
        !          3330:              rtl_obstack = temp_obstack;
        !          3331: #if 0 /* This was intended as a speed up, but it was slower.  */
        !          3332:              if (insn_n_alternatives[ie->insn_code] > 6
        !          3333:                  && count_sub_rtxs (av->value, 200) >= 200)
        !          3334:                newexp = simplify_by_alternatives (av->value, ie->insn_code,
        !          3335:                                                   ie->insn_index);
        !          3336:              else
        !          3337: #endif
        !          3338:                newexp = simplify_cond (av->value, ie->insn_code,
        !          3339:                                        ie->insn_index);
        !          3340: 
        !          3341:              rtl_obstack = old;
        !          3342:              if (newexp != av->value)
        !          3343:                {
        !          3344:                  newexp = attr_copy_rtx (newexp);
        !          3345:                  remove_insn_ent (av, ie);
        !          3346:                  av = get_attr_value (newexp, attr, ie->insn_code);
        !          3347:                  iv->av = av;
        !          3348:                  insert_insn_ent (av, ie);
        !          3349:                  something_changed = 1;
        !          3350:                }
        !          3351:              obstack_free (temp_obstack, spacer);
        !          3352:            }
        !          3353:        }
        !          3354:     }
        !          3355: }
        !          3356: 
        !          3357: #if 0
        !          3358: static rtx
        !          3359: simplify_by_alternatives (exp, insn_code, insn_index)
        !          3360:      rtx exp;
        !          3361:      int insn_code, insn_index;
        !          3362: {
        !          3363:   int i;
        !          3364:   int len = insn_n_alternatives[insn_code];
        !          3365:   rtx newexp = rtx_alloc (COND);
        !          3366:   rtx ultimate;
        !          3367: 
        !          3368: 
        !          3369:   XVEC (newexp, 0) = rtvec_alloc (len * 2);
        !          3370: 
        !          3371:   /* It will not matter what value we use as the default value
        !          3372:      of the new COND, since that default will never be used.
        !          3373:      Choose something of the right type.  */
        !          3374:   for (ultimate = exp; GET_CODE (ultimate) == COND;)
        !          3375:     ultimate = XEXP (ultimate, 1);
        !          3376:   XEXP (newexp, 1) = ultimate;
        !          3377: 
        !          3378:   for (i = 0; i < insn_n_alternatives[insn_code]; i++)
        !          3379:     {
        !          3380:       current_alternative_string = attr_numeral (i);
        !          3381:       XVECEXP (newexp, 0, i * 2) = make_alternative_compare (1 << i);
        !          3382:       XVECEXP (newexp, 0, i * 2 + 1)
        !          3383:        = simplify_cond (exp, insn_code, insn_index);
        !          3384:     }
        !          3385: 
        !          3386:   current_alternative_string = 0;
        !          3387:   return simplify_cond (newexp, insn_code, insn_index);
        !          3388: }
        !          3389: #endif
        !          3390: 
        !          3391: /* If EXP is a suitable expression, reorganize it by constructing an
        !          3392:    equivalent expression that is a COND with the tests being all combinations
        !          3393:    of attribute values and the values being simple constants.  */
        !          3394: 
        !          3395: static rtx
        !          3396: simplify_by_exploding (exp)
        !          3397:      rtx exp;
        !          3398: {
        !          3399:   rtx list = 0, link, condexp, defval;
        !          3400:   struct dimension *space;
        !          3401:   rtx *condtest, *condval;
        !          3402:   int i, j, total, ndim = 0;
        !          3403:   int most_tests, num_marks, new_marks;
        !          3404: 
        !          3405:   /* Locate all the EQ_ATTR expressions.  */
        !          3406:   if (! find_and_mark_used_attributes (exp, &list, &ndim) || ndim == 0)
        !          3407:     {
        !          3408:       unmark_used_attributes (list, 0, 0);
        !          3409:       return exp;
        !          3410:     }
        !          3411: 
        !          3412:   /* Create an attribute space from the list of used attributes.  For each
        !          3413:      dimension in the attribute space, record the attribute, list of values
        !          3414:      used, and number of values used.  Add members to the list of values to
        !          3415:      cover the domain of the attribute.  This makes the expanded COND form
        !          3416:      order independent.  */
        !          3417: 
        !          3418:   space = (struct dimension *) alloca (ndim * sizeof (struct dimension));
        !          3419: 
        !          3420:   total = 1;
        !          3421:   for (ndim = 0; list; ndim++)
        !          3422:     {
        !          3423:       /* Pull the first attribute value from the list and record that
        !          3424:         attribute as another dimension in the attribute space.  */
        !          3425:       char *name = XSTR (XEXP (list, 0), 0);
        !          3426:       rtx *prev;
        !          3427: 
        !          3428:       if ((space[ndim].attr = find_attr (name, 0)) == 0
        !          3429:          || space[ndim].attr->is_numeric)
        !          3430:        {
        !          3431:          unmark_used_attributes (list, space, ndim);
        !          3432:          return exp;
        !          3433:        }
        !          3434: 
        !          3435:       /* Add all remaining attribute values that refer to this attribute.  */
        !          3436:       space[ndim].num_values = 0;
        !          3437:       space[ndim].values = 0;
        !          3438:       prev = &list;
        !          3439:       for (link = list; link; link = *prev)
        !          3440:        if (! strcmp (XSTR (XEXP (link, 0), 0), name))
        !          3441:          {
        !          3442:            space[ndim].num_values++;
        !          3443:            *prev = XEXP (link, 1);
        !          3444:            XEXP (link, 1) = space[ndim].values;
        !          3445:            space[ndim].values = link;
        !          3446:          }
        !          3447:        else
        !          3448:          prev = &XEXP (link, 1);
        !          3449: 
        !          3450:       /* Add sufficient members to the list of values to make the list
        !          3451:         mutually exclusive and record the total size of the attribute
        !          3452:         space.  */
        !          3453:       total *= add_values_to_cover (&space[ndim]);
        !          3454:     }
        !          3455: 
        !          3456:   /* Sort the attribute space so that the attributes go from non-constant
        !          3457:      to constant and from most values to least values.  */
        !          3458:   for (i = 0; i < ndim; i++)
        !          3459:     for (j = ndim - 1; j > i; j--)
        !          3460:       if ((space[j-1].attr->is_const && !space[j].attr->is_const)
        !          3461:          || space[j-1].num_values < space[j].num_values)
        !          3462:        {
        !          3463:          struct dimension tmp;
        !          3464:          tmp = space[j];
        !          3465:          space[j] = space[j-1];
        !          3466:          space[j-1] = tmp;
        !          3467:        }
        !          3468: 
        !          3469:   /* Establish the initial current value.  */
        !          3470:   for (i = 0; i < ndim; i++)
        !          3471:     space[i].current_value = space[i].values;
        !          3472: 
        !          3473:   condtest = (rtx *) alloca (total * sizeof (rtx));
        !          3474:   condval = (rtx *) alloca (total * sizeof (rtx));
        !          3475: 
        !          3476:   /* Expand the tests and values by iterating over all values in the
        !          3477:      attribute space.  */
        !          3478:   for (i = 0;; i++)
        !          3479:     {
        !          3480:       condtest[i] = test_for_current_value (space, ndim);
        !          3481:       condval[i] = simplify_with_current_value (exp, space, ndim);
        !          3482:       if (! increment_current_value (space, ndim))
        !          3483:        break;
        !          3484:     }
        !          3485:   if (i != total - 1)
        !          3486:     abort ();
        !          3487: 
        !          3488:   /* We are now finished with the original expression.  */
        !          3489:   unmark_used_attributes (0, space, ndim);
        !          3490: 
        !          3491:   /* Find the most used constant value and make that the default.  */
        !          3492:   most_tests = -1;
        !          3493:   for (i = num_marks = 0; i < total; i++)
        !          3494:     if (GET_CODE (condval[i]) == CONST_STRING
        !          3495:        && ! MEM_VOLATILE_P (condval[i]))
        !          3496:       {
        !          3497:        /* Mark the unmarked constant value and count how many are marked.  */
        !          3498:        MEM_VOLATILE_P (condval[i]) = 1;
        !          3499:        for (j = new_marks = 0; j < total; j++)
        !          3500:          if (GET_CODE (condval[j]) == CONST_STRING
        !          3501:              && MEM_VOLATILE_P (condval[j]))
        !          3502:            new_marks++;
        !          3503:        if (new_marks - num_marks > most_tests)
        !          3504:          {
        !          3505:            most_tests = new_marks - num_marks;
        !          3506:            defval = condval[i];
        !          3507:          }
        !          3508:        num_marks = new_marks;
        !          3509:       }
        !          3510:   /* Clear all the marks.  */
        !          3511:   for (i = 0; i < total; i++)
        !          3512:     MEM_VOLATILE_P (condval[i]) = 0;
        !          3513: 
        !          3514:   /* Give up if nothing is constant.  */
        !          3515:   if (num_marks == 0)
        !          3516:     return exp;
        !          3517: 
        !          3518:   /* If all values are the default, use that.  */
        !          3519:   if (total == most_tests)
        !          3520:     return defval;
        !          3521: 
        !          3522:   /* Make a COND with the most common constant value the default.  (A more
        !          3523:      complex method where tests with the same value were combined didn't
        !          3524:      seem to improve things.)  */
        !          3525:   condexp = rtx_alloc (COND);
        !          3526:   XVEC (condexp, 0) = rtvec_alloc ((total - most_tests) * 2);
        !          3527:   XEXP (condexp, 1) = defval;
        !          3528:   for (i = j = 0; i < total; i++)
        !          3529:     if (condval[i] != defval)
        !          3530:       {
        !          3531:        XVECEXP (condexp, 0, 2 * j) = condtest[i];
        !          3532:        XVECEXP (condexp, 0, 2 * j + 1) = condval[i];
        !          3533:        j++;
        !          3534:       }
        !          3535: 
        !          3536:   return condexp;
        !          3537: }
        !          3538: 
        !          3539: /* Set the MEM_VOLATILE_P flag for all EQ_ATTR expressions in EXP and
        !          3540:    verify that EXP can be simplified to a constant term if all the EQ_ATTR
        !          3541:    tests have known value.  */
        !          3542: 
        !          3543: static int
        !          3544: find_and_mark_used_attributes (exp, terms, nterms)
        !          3545:      rtx exp, *terms;
        !          3546:      int *nterms;
        !          3547: {
        !          3548:   int i;
        !          3549: 
        !          3550:   switch (GET_CODE (exp))
        !          3551:     {
        !          3552:     case EQ_ATTR:
        !          3553:       if (! MEM_VOLATILE_P (exp))
        !          3554:        {
        !          3555:          rtx link = rtx_alloc (EXPR_LIST);
        !          3556:          XEXP (link, 0) = exp;
        !          3557:          XEXP (link, 1) = *terms;
        !          3558:          *terms = link;
        !          3559:          *nterms += 1;
        !          3560:          MEM_VOLATILE_P (exp) = 1;
        !          3561:        }
        !          3562:     case CONST_STRING:
        !          3563:       return 1;
        !          3564: 
        !          3565:     case IF_THEN_ELSE:
        !          3566:       if (! find_and_mark_used_attributes (XEXP (exp, 2), terms, nterms))
        !          3567:        return 0;
        !          3568:     case IOR:
        !          3569:     case AND:
        !          3570:       if (! find_and_mark_used_attributes (XEXP (exp, 1), terms, nterms))
        !          3571:        return 0;
        !          3572:     case NOT:
        !          3573:       if (! find_and_mark_used_attributes (XEXP (exp, 0), terms, nterms))
        !          3574:        return 0;
        !          3575:       return 1;
        !          3576: 
        !          3577:     case COND:
        !          3578:       for (i = 0; i < XVECLEN (exp, 0); i++)
        !          3579:        if (! find_and_mark_used_attributes (XVECEXP (exp, 0, i), terms, nterms))
        !          3580:          return 0;
        !          3581:       if (! find_and_mark_used_attributes (XEXP (exp, 1), terms, nterms))
        !          3582:        return 0;
        !          3583:       return 1;
        !          3584:     }
        !          3585: 
        !          3586:   return 0;
        !          3587: }
        !          3588: 
        !          3589: /* Clear the MEM_VOLATILE_P flag in all EQ_ATTR expressions on LIST and
        !          3590:    in the values of the NDIM-dimensional attribute space SPACE.  */
        !          3591: 
        !          3592: static void
        !          3593: unmark_used_attributes (list, space, ndim)
        !          3594:      rtx list;
        !          3595:      struct dimension *space;
        !          3596:      int ndim;
        !          3597: {
        !          3598:   rtx link, exp;
        !          3599:   int i;
        !          3600: 
        !          3601:   for (i = 0; i < ndim; i++)
        !          3602:     unmark_used_attributes (space[i].values, 0, 0);
        !          3603: 
        !          3604:   for (link = list; link; link = XEXP (link, 1))
        !          3605:     {
        !          3606:       exp = XEXP (link, 0);
        !          3607:       if (GET_CODE (exp) == EQ_ATTR)
        !          3608:        MEM_VOLATILE_P (exp) = 0;
        !          3609:     }
        !          3610: }
        !          3611: 
        !          3612: /* Update the attribute dimension DIM so that all values of the attribute
        !          3613:    are tested.  Return the updated number of values.  */
        !          3614: 
        !          3615: static int
        !          3616: add_values_to_cover (dim)
        !          3617:      struct dimension *dim;
        !          3618: {
        !          3619:   struct attr_value *av;
        !          3620:   rtx exp, link, *prev;
        !          3621:   int nalt = 0;
        !          3622: 
        !          3623:   for (av = dim->attr->first_value; av; av = av->next)
        !          3624:     if (GET_CODE (av->value) == CONST_STRING)
        !          3625:       nalt++;
        !          3626: 
        !          3627:   if (nalt < dim->num_values)
        !          3628:     abort ();
        !          3629:   else if (nalt == dim->num_values)
        !          3630:     ; /* Ok.  */
        !          3631:   else if (nalt * 2 < dim->num_values * 3)
        !          3632:     {
        !          3633:       /* Most all the values of the attribute are used, so add all the unused
        !          3634:         values.  */
        !          3635:       prev = &dim->values;
        !          3636:       for (link = dim->values; link; link = *prev)
        !          3637:        prev = &XEXP (link, 1);
        !          3638: 
        !          3639:       for (av = dim->attr->first_value; av; av = av->next)
        !          3640:        if (GET_CODE (av->value) == CONST_STRING)
        !          3641:          {
        !          3642:            exp = attr_eq (dim->attr->name, XSTR (av->value, 0));
        !          3643:            if (MEM_VOLATILE_P (exp))
        !          3644:              continue;
        !          3645: 
        !          3646:            link = rtx_alloc (EXPR_LIST);
        !          3647:            XEXP (link, 0) = exp;
        !          3648:            XEXP (link, 1) = 0;
        !          3649:            *prev = link;
        !          3650:            prev = &XEXP (link, 1);
        !          3651:          }
        !          3652:       dim->num_values = nalt;
        !          3653:     }
        !          3654:   else
        !          3655:     {
        !          3656:       rtx orexp = false_rtx;
        !          3657: 
        !          3658:       /* Very few values are used, so compute a mutually exclusive
        !          3659:         expression.  (We could do this for numeric values if that becomes
        !          3660:         important.)  */
        !          3661:       prev = &dim->values;
        !          3662:       for (link = dim->values; link; link = *prev)
        !          3663:        {
        !          3664:          orexp = insert_right_side (IOR, orexp, XEXP (link, 0), -2, -2);
        !          3665:          prev = &XEXP (link, 1);
        !          3666:        }
        !          3667:       link = rtx_alloc (EXPR_LIST);
        !          3668:       XEXP (link, 0) = attr_rtx (NOT, orexp);
        !          3669:       XEXP (link, 1) = 0;
        !          3670:       *prev = link;
        !          3671:       dim->num_values++;
        !          3672:     }
        !          3673:   return dim->num_values;
        !          3674: }
        !          3675: 
        !          3676: /* Increment the current value for the NDIM-dimensional attribute space SPACE
        !          3677:    and return FALSE if the increment overflowed.  */
        !          3678: 
        !          3679: static int
        !          3680: increment_current_value (space, ndim)
        !          3681:      struct dimension *space;
        !          3682:      int ndim;
        !          3683: {
        !          3684:   int i;
        !          3685: 
        !          3686:   for (i = ndim - 1; i >= 0; i--)
        !          3687:     {
        !          3688:       if ((space[i].current_value = XEXP (space[i].current_value, 1)) == 0)
        !          3689:        space[i].current_value = space[i].values;
        !          3690:       else
        !          3691:        return 1;
        !          3692:     }
        !          3693:   return 0;
        !          3694: }
        !          3695: 
        !          3696: /* Construct an expression corresponding to the current value for the
        !          3697:    NDIM-dimensional attribute space SPACE.  */
        !          3698: 
        !          3699: static rtx
        !          3700: test_for_current_value (space, ndim)
        !          3701:      struct dimension *space;
        !          3702:      int ndim;
        !          3703: {
        !          3704:   int i;
        !          3705:   rtx exp = true_rtx;
        !          3706: 
        !          3707:   for (i = 0; i < ndim; i++)
        !          3708:     exp = insert_right_side (AND, exp, XEXP (space[i].current_value, 0),
        !          3709:                             -2, -2);
        !          3710: 
        !          3711:   return exp;
        !          3712: }
        !          3713: 
        !          3714: /* Given the current value of the NDIM-dimensional attribute space SPACE,
        !          3715:    set the corresponding EQ_ATTR expressions to that value and reduce
        !          3716:    the expression EXP as much as possible.  On input [and output], all
        !          3717:    known EQ_ATTR expressions are set to FALSE.  */
        !          3718: 
        !          3719: static rtx
        !          3720: simplify_with_current_value (exp, space, ndim)
        !          3721:      rtx exp;
        !          3722:      struct dimension *space;
        !          3723:      int ndim;
        !          3724: {
        !          3725:   int i;
        !          3726:   rtx x;
        !          3727: 
        !          3728:   /* Mark each current value as TRUE.  */
        !          3729:   for (i = 0; i < ndim; i++)
        !          3730:     {
        !          3731:       x = XEXP (space[i].current_value, 0);
        !          3732:       if (GET_CODE (x) == EQ_ATTR)
        !          3733:        MEM_VOLATILE_P (x) = 0;
        !          3734:     }
        !          3735: 
        !          3736:   exp = simplify_with_current_value_aux (exp);
        !          3737: 
        !          3738:   /* Change each current value back to FALSE.  */
        !          3739:   for (i = 0; i < ndim; i++)
        !          3740:     {
        !          3741:       x = XEXP (space[i].current_value, 0);
        !          3742:       if (GET_CODE (x) == EQ_ATTR)
        !          3743:        MEM_VOLATILE_P (x) = 1;
        !          3744:     }
        !          3745: 
        !          3746:   return exp;
        !          3747: }
        !          3748: 
        !          3749: /* Reduce the expression EXP based on the MEM_VOLATILE_P settings of
        !          3750:    all EQ_ATTR expressions.  */
        !          3751: 
        !          3752: static rtx
        !          3753: simplify_with_current_value_aux (exp)
        !          3754:      rtx exp;
        !          3755: {
        !          3756:   register int i;
        !          3757:   rtx cond;
        !          3758: 
        !          3759:   switch (GET_CODE (exp))
        !          3760:     {
        !          3761:     case EQ_ATTR:
        !          3762:       if (MEM_VOLATILE_P (exp))
        !          3763:        return false_rtx;
        !          3764:       else
        !          3765:        return true_rtx;
        !          3766:     case CONST_STRING:
        !          3767:       return exp;
        !          3768: 
        !          3769:     case IF_THEN_ELSE:
        !          3770:       cond = simplify_with_current_value_aux (XEXP (exp, 0));
        !          3771:       if (cond == true_rtx)
        !          3772:        return simplify_with_current_value_aux (XEXP (exp, 1));
        !          3773:       else if (cond == false_rtx)
        !          3774:        return simplify_with_current_value_aux (XEXP (exp, 2));
        !          3775:       else
        !          3776:        return attr_rtx (IF_THEN_ELSE, cond,
        !          3777:                         simplify_with_current_value_aux (XEXP (exp, 1)),
        !          3778:                         simplify_with_current_value_aux (XEXP (exp, 2)));
        !          3779: 
        !          3780:     case IOR:
        !          3781:       cond = simplify_with_current_value_aux (XEXP (exp, 1));
        !          3782:       if (cond == true_rtx)
        !          3783:        return cond;
        !          3784:       else if (cond == false_rtx)
        !          3785:        return simplify_with_current_value_aux (XEXP (exp, 0));
        !          3786:       else
        !          3787:        return attr_rtx (IOR, cond,
        !          3788:                         simplify_with_current_value_aux (XEXP (exp, 0)));
        !          3789: 
        !          3790:     case AND:
        !          3791:       cond = simplify_with_current_value_aux (XEXP (exp, 1));
        !          3792:       if (cond == true_rtx)
        !          3793:        return simplify_with_current_value_aux (XEXP (exp, 0));
        !          3794:       else if (cond == false_rtx)
        !          3795:        return cond;
        !          3796:       else
        !          3797:        return attr_rtx (AND, cond,
        !          3798:                         simplify_with_current_value_aux (XEXP (exp, 0)));
        !          3799: 
        !          3800:     case NOT:
        !          3801:       cond = simplify_with_current_value_aux (XEXP (exp, 0));
        !          3802:       if (cond == true_rtx)
        !          3803:        return false_rtx;
        !          3804:       else if (cond == false_rtx)
        !          3805:        return true_rtx;
        !          3806:       else
        !          3807:        return attr_rtx (NOT, cond);
        !          3808: 
        !          3809:     case COND:
        !          3810:       for (i = 0; i < XVECLEN (exp, 0); i += 2)
        !          3811:        {
        !          3812:          cond = simplify_with_current_value_aux (XVECEXP (exp, 0, i));
        !          3813:          if (cond == true_rtx)
        !          3814:            return simplify_with_current_value_aux (XVECEXP (exp, 0, i + 1));
        !          3815:          else if (cond == false_rtx)
        !          3816:            continue;
        !          3817:          else
        !          3818:            abort (); /* With all EQ_ATTR's of known value, a case should
        !          3819:                         have been selected.  */
        !          3820:        }
        !          3821:       return simplify_with_current_value_aux (XEXP (exp, 1));
        !          3822:     }
        !          3823:   abort ();
        !          3824: }
        !          3825: 
        !          3826: /* Clear the MEM_IN_STRUCT_P flag in EXP and its subexpressions.  */
        !          3827: 
        !          3828: static void
        !          3829: clear_struct_flag (x)
        !          3830:      rtx x;
        !          3831: {
        !          3832:   register int i;
        !          3833:   register int j;
        !          3834:   register enum rtx_code code;
        !          3835:   register char *fmt;
        !          3836: 
        !          3837:   MEM_IN_STRUCT_P (x) = 0;
        !          3838:   if (RTX_UNCHANGING_P (x))
        !          3839:     return;
        !          3840: 
        !          3841:   code = GET_CODE (x);
        !          3842: 
        !          3843:   switch (code)
        !          3844:     {
        !          3845:     case REG:
        !          3846:     case QUEUED:
        !          3847:     case CONST_INT:
        !          3848:     case CONST_DOUBLE:
        !          3849:     case SYMBOL_REF:
        !          3850:     case CODE_LABEL:
        !          3851:     case PC:
        !          3852:     case CC0:
        !          3853:     case EQ_ATTR:
        !          3854:     case ATTR_FLAG:
        !          3855:       return;
        !          3856:     }
        !          3857: 
        !          3858:   /* Compare the elements.  If any pair of corresponding elements
        !          3859:      fail to match, return 0 for the whole things.  */
        !          3860: 
        !          3861:   fmt = GET_RTX_FORMAT (code);
        !          3862:   for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
        !          3863:     {
        !          3864:       switch (fmt[i])
        !          3865:        {
        !          3866:        case 'V':
        !          3867:        case 'E':
        !          3868:          for (j = 0; j < XVECLEN (x, i); j++)
        !          3869:            clear_struct_flag (XVECEXP (x, i, j));
        !          3870:          break;
        !          3871: 
        !          3872:        case 'e':
        !          3873:          clear_struct_flag (XEXP (x, i));
        !          3874:          break;
        !          3875:        }
        !          3876:     }
        !          3877: }
        !          3878: 
        !          3879: /* Return the number of RTX objects making up the expression X.
        !          3880:    But if we count more more than MAX objects, stop counting.  */
        !          3881: 
        !          3882: static int
        !          3883: count_sub_rtxs (x, max)
        !          3884:      rtx x;
        !          3885:      int max;
        !          3886: {
        !          3887:   register int i;
        !          3888:   register int j;
        !          3889:   register enum rtx_code code;
        !          3890:   register char *fmt;
        !          3891:   int total = 0;
        !          3892: 
        !          3893:   code = GET_CODE (x);
        !          3894: 
        !          3895:   switch (code)
        !          3896:     {
        !          3897:     case REG:
        !          3898:     case QUEUED:
        !          3899:     case CONST_INT:
        !          3900:     case CONST_DOUBLE:
        !          3901:     case SYMBOL_REF:
        !          3902:     case CODE_LABEL:
        !          3903:     case PC:
        !          3904:     case CC0:
        !          3905:     case EQ_ATTR:
        !          3906:     case ATTR_FLAG:
        !          3907:       return 1;
        !          3908:     }
        !          3909: 
        !          3910:   /* Compare the elements.  If any pair of corresponding elements
        !          3911:      fail to match, return 0 for the whole things.  */
        !          3912: 
        !          3913:   fmt = GET_RTX_FORMAT (code);
        !          3914:   for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
        !          3915:     {
        !          3916:       if (total >= max)
        !          3917:        return total;
        !          3918: 
        !          3919:       switch (fmt[i])
        !          3920:        {
        !          3921:        case 'V':
        !          3922:        case 'E':
        !          3923:          for (j = 0; j < XVECLEN (x, i); j++)
        !          3924:            total += count_sub_rtxs (XVECEXP (x, i, j), max);
        !          3925:          break;
        !          3926: 
        !          3927:        case 'e':
        !          3928:          total += count_sub_rtxs (XEXP (x, i), max);
        !          3929:          break;
        !          3930:        }
        !          3931:     }
        !          3932:   return total;
        !          3933: 
        !          3934: }
        !          3935: 
        !          3936: /* Create table entries for DEFINE_ATTR.  */
        !          3937: 
        !          3938: static void
        !          3939: gen_attr (exp)
        !          3940:      rtx exp;
        !          3941: {
        !          3942:   struct attr_desc *attr;
        !          3943:   struct attr_value *av;
        !          3944:   char *name_ptr;
        !          3945:   char *p;
        !          3946: 
        !          3947:   /* Make a new attribute structure.  Check for duplicate by looking at
        !          3948:      attr->default_val, since it is initialized by this routine.  */
        !          3949:   attr = find_attr (XSTR (exp, 0), 1);
        !          3950:   if (attr->default_val)
        !          3951:     fatal ("Duplicate definition for `%s' attribute", attr->name);
        !          3952: 
        !          3953:   if (*XSTR (exp, 1) == '\0')
        !          3954:       attr->is_numeric = 1;
        !          3955:   else
        !          3956:     {
        !          3957:       name_ptr = XSTR (exp, 1);
        !          3958:       while ((p = next_comma_elt (&name_ptr)) != NULL)
        !          3959:        {
        !          3960:          av = (struct attr_value *) oballoc (sizeof (struct attr_value));
        !          3961:          av->value = attr_rtx (CONST_STRING, p);
        !          3962:          av->next = attr->first_value;
        !          3963:          attr->first_value = av;
        !          3964:          av->first_insn = NULL;
        !          3965:          av->num_insns = 0;
        !          3966:          av->has_asm_insn = 0;
        !          3967:        }
        !          3968:     }
        !          3969: 
        !          3970:   if (GET_CODE (XEXP (exp, 2)) == CONST)
        !          3971:     {
        !          3972:       attr->is_const = 1;
        !          3973:       if (attr->is_numeric)
        !          3974:        fatal ("Constant attributes may not take numeric values");
        !          3975:       /* Get rid of the CONST node.  It is allowed only at top-level.  */
        !          3976:       XEXP (exp, 2) = XEXP (XEXP (exp, 2), 0);
        !          3977:     }
        !          3978: 
        !          3979:   if (! strcmp (attr->name, "length") && ! attr->is_numeric)
        !          3980:     fatal ("`length' attribute must take numeric values");
        !          3981: 
        !          3982:   /* Set up the default value. */
        !          3983:   XEXP (exp, 2) = check_attr_value (XEXP (exp, 2), attr);
        !          3984:   attr->default_val = get_attr_value (XEXP (exp, 2), attr, -2);
        !          3985: }
        !          3986: 
        !          3987: /* Given a pattern for DEFINE_PEEPHOLE or DEFINE_INSN, return the number of
        !          3988:    alternatives in the constraints.  Assume all MATCH_OPERANDs have the same
        !          3989:    number of alternatives as this should be checked elsewhere.  */
        !          3990: 
        !          3991: static int
        !          3992: count_alternatives (exp)
        !          3993:      rtx exp;
        !          3994: {
        !          3995:   int i, j, n;
        !          3996:   char *fmt;
        !          3997:   
        !          3998:   if (GET_CODE (exp) == MATCH_OPERAND)
        !          3999:     return n_comma_elts (XSTR (exp, 2));
        !          4000: 
        !          4001:   for (i = 0, fmt = GET_RTX_FORMAT (GET_CODE (exp));
        !          4002:        i < GET_RTX_LENGTH (GET_CODE (exp)); i++)
        !          4003:     switch (*fmt++)
        !          4004:       {
        !          4005:       case 'e':
        !          4006:       case 'u':
        !          4007:        n = count_alternatives (XEXP (exp, i));
        !          4008:        if (n)
        !          4009:          return n;
        !          4010:        break;
        !          4011: 
        !          4012:       case 'E':
        !          4013:       case 'V':
        !          4014:        if (XVEC (exp, i) != NULL)
        !          4015:          for (j = 0; j < XVECLEN (exp, i); j++)
        !          4016:            {
        !          4017:              n = count_alternatives (XVECEXP (exp, i, j));
        !          4018:              if (n)
        !          4019:                return n;
        !          4020:            }
        !          4021:       }
        !          4022: 
        !          4023:   return 0;
        !          4024: }
        !          4025: 
        !          4026: /* Returns non-zero if the given expression contains an EQ_ATTR with the
        !          4027:    `alternative' attribute.  */
        !          4028: 
        !          4029: static int
        !          4030: compares_alternatives_p (exp)
        !          4031:      rtx exp;
        !          4032: {
        !          4033:   int i, j;
        !          4034:   char *fmt;
        !          4035: 
        !          4036:   if (GET_CODE (exp) == EQ_ATTR && XSTR (exp, 0) == alternative_name)
        !          4037:     return 1;
        !          4038: 
        !          4039:   for (i = 0, fmt = GET_RTX_FORMAT (GET_CODE (exp));
        !          4040:        i < GET_RTX_LENGTH (GET_CODE (exp)); i++)
        !          4041:     switch (*fmt++)
        !          4042:       {
        !          4043:       case 'e':
        !          4044:       case 'u':
        !          4045:        if (compares_alternatives_p (XEXP (exp, i)))
        !          4046:          return 1;
        !          4047:        break;
        !          4048: 
        !          4049:       case 'E':
        !          4050:        for (j = 0; j < XVECLEN (exp, i); j++)
        !          4051:          if (compares_alternatives_p (XVECEXP (exp, i, j)))
        !          4052:            return 1;
        !          4053:        break;
        !          4054:       }
        !          4055: 
        !          4056:   return 0;
        !          4057: }
        !          4058: 
        !          4059: /* Returns non-zero is INNER is contained in EXP.  */
        !          4060: 
        !          4061: static int
        !          4062: contained_in_p (inner, exp)
        !          4063:      rtx inner;
        !          4064:      rtx exp;
        !          4065: {
        !          4066:   int i, j;
        !          4067:   char *fmt;
        !          4068: 
        !          4069:   if (rtx_equal_p (inner, exp))
        !          4070:     return 1;
        !          4071: 
        !          4072:   for (i = 0, fmt = GET_RTX_FORMAT (GET_CODE (exp));
        !          4073:        i < GET_RTX_LENGTH (GET_CODE (exp)); i++)
        !          4074:     switch (*fmt++)
        !          4075:       {
        !          4076:       case 'e':
        !          4077:       case 'u':
        !          4078:        if (contained_in_p (inner, XEXP (exp, i)))
        !          4079:          return 1;
        !          4080:        break;
        !          4081: 
        !          4082:       case 'E':
        !          4083:        for (j = 0; j < XVECLEN (exp, i); j++)
        !          4084:          if (contained_in_p (inner, XVECEXP (exp, i, j)))
        !          4085:            return 1;
        !          4086:        break;
        !          4087:       }
        !          4088: 
        !          4089:   return 0;
        !          4090: }
        !          4091:       
        !          4092: /* Process DEFINE_PEEPHOLE, DEFINE_INSN, and DEFINE_ASM_ATTRIBUTES.  */
        !          4093: 
        !          4094: static void
        !          4095: gen_insn (exp)
        !          4096:      rtx exp;
        !          4097: {
        !          4098:   struct insn_def *id;
        !          4099: 
        !          4100:   id = (struct insn_def *) oballoc (sizeof (struct insn_def));
        !          4101:   id->next = defs;
        !          4102:   defs = id;
        !          4103:   id->def = exp;
        !          4104: 
        !          4105:   switch (GET_CODE (exp))
        !          4106:     {
        !          4107:     case DEFINE_INSN:
        !          4108:       id->insn_code = insn_code_number++;
        !          4109:       id->insn_index = insn_index_number++;
        !          4110:       id->num_alternatives = count_alternatives (exp);
        !          4111:       if (id->num_alternatives == 0)
        !          4112:        id->num_alternatives = 1;
        !          4113:       id->vec_idx = 4;
        !          4114:       break;
        !          4115: 
        !          4116:     case DEFINE_PEEPHOLE:
        !          4117:       id->insn_code = insn_code_number++;
        !          4118:       id->insn_index = insn_index_number++;
        !          4119:       id->num_alternatives = count_alternatives (exp);
        !          4120:       if (id->num_alternatives == 0)
        !          4121:        id->num_alternatives = 1;
        !          4122:       id->vec_idx = 3;
        !          4123:       break;
        !          4124: 
        !          4125:     case DEFINE_ASM_ATTRIBUTES:
        !          4126:       id->insn_code = -1;
        !          4127:       id->insn_index = -1;
        !          4128:       id->num_alternatives = 1;
        !          4129:       id->vec_idx = 0;
        !          4130:       got_define_asm_attributes = 1;
        !          4131:       break;
        !          4132:     }
        !          4133: }
        !          4134: 
        !          4135: /* Process a DEFINE_DELAY.  Validate the vector length, check if annul
        !          4136:    true or annul false is specified, and make a `struct delay_desc'.  */
        !          4137: 
        !          4138: static void
        !          4139: gen_delay (def)
        !          4140:      rtx def;
        !          4141: {
        !          4142:   struct delay_desc *delay;
        !          4143:   int i;
        !          4144: 
        !          4145:   if (XVECLEN (def, 1) % 3 != 0)
        !          4146:     fatal ("Number of elements in DEFINE_DELAY must be multiple of three.");
        !          4147: 
        !          4148:   for (i = 0; i < XVECLEN (def, 1); i += 3)
        !          4149:     {
        !          4150:       if (XVECEXP (def, 1, i + 1))
        !          4151:        have_annul_true = 1;
        !          4152:       if (XVECEXP (def, 1, i + 2))
        !          4153:        have_annul_false = 1;
        !          4154:     }
        !          4155:   
        !          4156:   delay = (struct delay_desc *) oballoc (sizeof (struct delay_desc));
        !          4157:   delay->def = def;
        !          4158:   delay->num = ++num_delays;
        !          4159:   delay->next = delays;
        !          4160:   delays = delay;
        !          4161: }
        !          4162: 
        !          4163: /* Process a DEFINE_FUNCTION_UNIT.  
        !          4164: 
        !          4165:    This gives information about a function unit contained in the CPU.
        !          4166:    We fill in a `struct function_unit_op' and a `struct function_unit'
        !          4167:    with information used later by `expand_unit'.  */
        !          4168: 
        !          4169: static void
        !          4170: gen_unit (def)
        !          4171:      rtx def;
        !          4172: {
        !          4173:   struct function_unit *unit;
        !          4174:   struct function_unit_op *op;
        !          4175:   char *name = XSTR (def, 0);
        !          4176:   int multiplicity = XINT (def, 1);
        !          4177:   int simultaneity = XINT (def, 2);
        !          4178:   rtx condexp = XEXP (def, 3);
        !          4179:   int ready_cost = MAX (XINT (def, 4), 1);
        !          4180:   int issue_delay = MAX (XINT (def, 5), 1);
        !          4181: 
        !          4182:   /* See if we have already seen this function unit.  If so, check that
        !          4183:      the multiplicity and simultaneity values are the same.  If not, make
        !          4184:      a structure for this function unit.  */
        !          4185:   for (unit = units; unit; unit = unit->next)
        !          4186:     if (! strcmp (unit->name, name))
        !          4187:       {
        !          4188:        if (unit->multiplicity != multiplicity
        !          4189:            || unit->simultaneity != simultaneity)
        !          4190:          fatal ("Differing specifications given for `%s' function unit.",
        !          4191:                 unit->name);
        !          4192:        break;
        !          4193:       }
        !          4194: 
        !          4195:   if (unit == 0)
        !          4196:     {
        !          4197:       unit = (struct function_unit *) oballoc (sizeof (struct function_unit));
        !          4198:       unit->name = name;
        !          4199:       unit->multiplicity = multiplicity;
        !          4200:       unit->simultaneity = simultaneity;
        !          4201:       unit->issue_delay.min = unit->issue_delay.max = issue_delay;
        !          4202:       unit->num = num_units++;
        !          4203:       unit->num_opclasses = 0;
        !          4204:       unit->condexp = false_rtx;
        !          4205:       unit->ops = 0;
        !          4206:       unit->next = units;
        !          4207:       units = unit;
        !          4208:     }
        !          4209: 
        !          4210:   /* Make a new operation class structure entry and initialize it.  */
        !          4211:   op = (struct function_unit_op *) oballoc (sizeof (struct function_unit_op));
        !          4212:   op->condexp = condexp;
        !          4213:   op->num = unit->num_opclasses++;
        !          4214:   op->ready = ready_cost;
        !          4215:   op->issue_delay = issue_delay;
        !          4216:   op->next = unit->ops;
        !          4217:   unit->ops = op;
        !          4218: 
        !          4219:   /* Set our issue expression based on whether or not an optional conflict
        !          4220:      vector was specified.  */
        !          4221:   if (XVEC (def, 6))
        !          4222:     {
        !          4223:       /* Compute the IOR of all the specified expressions.  */
        !          4224:       rtx orexp = false_rtx;
        !          4225:       int i;
        !          4226: 
        !          4227:       for (i = 0; i < XVECLEN (def, 6); i++)
        !          4228:        orexp = insert_right_side (IOR, orexp, XVECEXP (def, 6, i), -2, -2);
        !          4229: 
        !          4230:       op->conflict_exp = orexp;
        !          4231:       extend_range (&unit->issue_delay, 1, issue_delay);
        !          4232:     }
        !          4233:   else
        !          4234:     {
        !          4235:       op->conflict_exp = true_rtx;
        !          4236:       extend_range (&unit->issue_delay, issue_delay, issue_delay);
        !          4237:     }
        !          4238: 
        !          4239:   /* Merge our conditional into that of the function unit so we can determine
        !          4240:      which insns are used by the function unit.  */
        !          4241:   unit->condexp = insert_right_side (IOR, unit->condexp, op->condexp, -2, -2);
        !          4242: }
        !          4243: 
        !          4244: /* Given a piece of RTX, print a C expression to test it's truth value.
        !          4245:    We use AND and IOR both for logical and bit-wise operations, so 
        !          4246:    interpret them as logical unless they are inside a comparison expression.
        !          4247:    The second operand of this function will be non-zero in that case.  */
        !          4248: 
        !          4249: static void
        !          4250: write_test_expr (exp, in_comparison)
        !          4251:      rtx exp;
        !          4252:      int in_comparison;
        !          4253: {
        !          4254:   int comparison_operator = 0;
        !          4255:   RTX_CODE code;
        !          4256:   struct attr_desc *attr;
        !          4257: 
        !          4258:   /* In order not to worry about operator precedence, surround our part of
        !          4259:      the expression with parentheses.  */
        !          4260: 
        !          4261:   printf ("(");
        !          4262:   code = GET_CODE (exp);
        !          4263:   switch (code)
        !          4264:     {
        !          4265:     /* Binary operators.  */
        !          4266:     case EQ: case NE:
        !          4267:     case GE: case GT: case GEU: case GTU:
        !          4268:     case LE: case LT: case LEU: case LTU:
        !          4269:       comparison_operator = 1;
        !          4270: 
        !          4271:     case PLUS:   case MINUS:  case MULT:     case DIV:      case MOD:
        !          4272:     case AND:    case IOR:    case XOR:
        !          4273:     case LSHIFT: case ASHIFT: case LSHIFTRT: case ASHIFTRT:
        !          4274:       write_test_expr (XEXP (exp, 0), in_comparison || comparison_operator);
        !          4275:       switch (code)
        !          4276:         {
        !          4277:        case EQ:
        !          4278:          printf (" == ");
        !          4279:          break;
        !          4280:        case NE:
        !          4281:          printf (" != ");
        !          4282:          break;
        !          4283:        case GE:
        !          4284:          printf (" >= ");
        !          4285:          break;
        !          4286:        case GT:
        !          4287:          printf (" > ");
        !          4288:          break;
        !          4289:        case GEU:
        !          4290:          printf (" >= (unsigned) ");
        !          4291:          break;
        !          4292:        case GTU:
        !          4293:          printf (" > (unsigned) ");
        !          4294:          break;
        !          4295:        case LE:
        !          4296:          printf (" <= ");
        !          4297:          break;
        !          4298:        case LT:
        !          4299:          printf (" < ");
        !          4300:          break;
        !          4301:        case LEU:
        !          4302:          printf (" <= (unsigned) ");
        !          4303:          break;
        !          4304:        case LTU:
        !          4305:          printf (" < (unsigned) ");
        !          4306:          break;
        !          4307:        case PLUS:
        !          4308:          printf (" + ");
        !          4309:          break;
        !          4310:        case MINUS:
        !          4311:          printf (" - ");
        !          4312:          break;
        !          4313:        case MULT:
        !          4314:          printf (" * ");
        !          4315:          break;
        !          4316:        case DIV:
        !          4317:          printf (" / ");
        !          4318:          break;
        !          4319:        case MOD:
        !          4320:          printf (" %% ");
        !          4321:          break;
        !          4322:        case AND:
        !          4323:          if (in_comparison)
        !          4324:            printf (" & ");
        !          4325:          else
        !          4326:            printf (" && ");
        !          4327:          break;
        !          4328:        case IOR:
        !          4329:          if (in_comparison)
        !          4330:            printf (" | ");
        !          4331:          else
        !          4332:            printf (" || ");
        !          4333:          break;
        !          4334:        case XOR:
        !          4335:          printf (" ^ ");
        !          4336:          break;
        !          4337:        case LSHIFT:
        !          4338:        case ASHIFT:
        !          4339:          printf (" << ");
        !          4340:          break;
        !          4341:        case LSHIFTRT:
        !          4342:        case ASHIFTRT:
        !          4343:          printf (" >> ");
        !          4344:          break;
        !          4345:         }
        !          4346: 
        !          4347:       write_test_expr (XEXP (exp, 1), in_comparison || comparison_operator);
        !          4348:       break;
        !          4349: 
        !          4350:     case NOT:
        !          4351:       /* Special-case (not (eq_attrq "alternative" "x")) */
        !          4352:       if (! in_comparison && GET_CODE (XEXP (exp, 0)) == EQ_ATTR
        !          4353:          && XSTR (XEXP (exp, 0), 0) == alternative_name)
        !          4354:        {
        !          4355:          printf ("which_alternative != %s", XSTR (XEXP (exp, 0), 1));
        !          4356:          break;
        !          4357:        }
        !          4358: 
        !          4359:       /* Otherwise, fall through to normal unary operator.  */
        !          4360: 
        !          4361:     /* Unary operators.  */   
        !          4362:     case ABS:  case NEG:
        !          4363:       switch (code)
        !          4364:        {
        !          4365:        case NOT:
        !          4366:          if (in_comparison)
        !          4367:            printf ("~ ");
        !          4368:          else
        !          4369:            printf ("! ");
        !          4370:          break;
        !          4371:        case ABS:
        !          4372:          printf ("abs ");
        !          4373:          break;
        !          4374:        case NEG:
        !          4375:          printf ("-");
        !          4376:          break;
        !          4377:        }
        !          4378: 
        !          4379:       write_test_expr (XEXP (exp, 0), in_comparison);
        !          4380:       break;
        !          4381: 
        !          4382:     /* Comparison test of an attribute with a value.  Most of these will
        !          4383:        have been removed by optimization.   Handle "alternative"
        !          4384:        specially and give error if EQ_ATTR present inside a comparison.  */
        !          4385:     case EQ_ATTR:
        !          4386:       if (in_comparison)
        !          4387:        fatal ("EQ_ATTR not valid inside comparison");
        !          4388: 
        !          4389:       if (XSTR (exp, 0) == alternative_name)
        !          4390:        {
        !          4391:          printf ("which_alternative == %s", XSTR (exp, 1));
        !          4392:          break;
        !          4393:        }
        !          4394: 
        !          4395:       attr = find_attr (XSTR (exp, 0), 0);
        !          4396:       if (! attr) abort ();
        !          4397: 
        !          4398:       /* Now is the time to expand the value of a constant attribute.  */
        !          4399:       if (attr->is_const)
        !          4400:        {
        !          4401:          write_test_expr (evaluate_eq_attr (exp, attr->default_val->value,
        !          4402:                                             -2, -2),
        !          4403:                           in_comparison);
        !          4404:        }
        !          4405:       else
        !          4406:        {
        !          4407:          printf ("get_attr_%s (insn) == ", attr->name);
        !          4408:          write_attr_valueq (attr, XSTR (exp, 1)); 
        !          4409:        }
        !          4410:       break;
        !          4411: 
        !          4412:     /* Comparison test of flags for define_delays.  */
        !          4413:     case ATTR_FLAG:
        !          4414:       if (in_comparison)
        !          4415:        fatal ("ATTR_FLAG not valid inside comparison");
        !          4416:       printf ("(flags & ATTR_FLAG_%s) != 0", XSTR (exp, 0));
        !          4417:       break;
        !          4418: 
        !          4419:     /* See if an operand matches a predicate.  */
        !          4420:     case MATCH_OPERAND:
        !          4421:       /* If only a mode is given, just ensure the mode matches the operand.
        !          4422:         If neither a mode nor predicate is given, error.  */
        !          4423:      if (XSTR (exp, 1) == NULL || *XSTR (exp, 1) == '\0')
        !          4424:        {
        !          4425:          if (GET_MODE (exp) == VOIDmode)
        !          4426:            fatal ("Null MATCH_OPERAND specified as test");
        !          4427:          else
        !          4428:            printf ("GET_MODE (operands[%d]) == %smode",
        !          4429:                    XINT (exp, 0), GET_MODE_NAME (GET_MODE (exp)));
        !          4430:        }
        !          4431:       else
        !          4432:        printf ("%s (operands[%d], %smode)",
        !          4433:                XSTR (exp, 1), XINT (exp, 0), GET_MODE_NAME (GET_MODE (exp)));
        !          4434:       break;
        !          4435: 
        !          4436:     /* Constant integer. */
        !          4437:     case CONST_INT:
        !          4438: #if HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_INT
        !          4439:       printf ("%d", XWINT (exp, 0));
        !          4440: #else
        !          4441:       printf ("%ld", XWINT (exp, 0));
        !          4442: #endif
        !          4443:       break;
        !          4444: 
        !          4445:     /* A random C expression. */
        !          4446:     case SYMBOL_REF:
        !          4447:       printf ("%s", XSTR (exp, 0));
        !          4448:       break;
        !          4449: 
        !          4450:     /* The address of the branch target.  */
        !          4451:     case MATCH_DUP:
        !          4452:       printf ("insn_addresses[INSN_UID (JUMP_LABEL (insn))]");
        !          4453:       break;
        !          4454: 
        !          4455:     /* The address of the current insn.  It would be more consistent with
        !          4456:        other usage to make this the address of the NEXT insn, but this gets
        !          4457:        too confusing because of the ambiguity regarding the length of the
        !          4458:        current insn.  */
        !          4459:     case PC:
        !          4460:       printf ("insn_current_address");
        !          4461:       break;
        !          4462: 
        !          4463:     default:
        !          4464:       fatal ("bad RTX code `%s' in attribute calculation\n",
        !          4465:             GET_RTX_NAME (code));
        !          4466:     }
        !          4467: 
        !          4468:   printf (")");
        !          4469: }
        !          4470: 
        !          4471: /* Given an attribute value, return the maximum CONST_STRING argument
        !          4472:    encountered.  It is assumed that they are all numeric.  */
        !          4473: 
        !          4474: static int
        !          4475: max_attr_value (exp)
        !          4476:      rtx exp;
        !          4477: {
        !          4478:   int current_max = 0;
        !          4479:   int n;
        !          4480:   int i;
        !          4481: 
        !          4482:   if (GET_CODE (exp) == CONST_STRING)
        !          4483:     return atoi (XSTR (exp, 0));
        !          4484: 
        !          4485:   else if (GET_CODE (exp) == COND)
        !          4486:     {
        !          4487:       for (i = 0; i < XVECLEN (exp, 0); i += 2)
        !          4488:        {
        !          4489:          n = max_attr_value (XVECEXP (exp, 0, i + 1));
        !          4490:          if (n > current_max)
        !          4491:            current_max = n;
        !          4492:        }
        !          4493: 
        !          4494:       n = max_attr_value (XEXP (exp, 1));
        !          4495:       if (n > current_max)
        !          4496:        current_max = n;
        !          4497:     }
        !          4498: 
        !          4499:   else if (GET_CODE (exp) == IF_THEN_ELSE)
        !          4500:     {
        !          4501:       current_max = max_attr_value (XEXP (exp, 1));
        !          4502:       n = max_attr_value (XEXP (exp, 2));
        !          4503:       if (n > current_max)
        !          4504:        current_max = n;
        !          4505:     }
        !          4506: 
        !          4507:   else
        !          4508:     abort ();
        !          4509: 
        !          4510:   return current_max;
        !          4511: }
        !          4512: 
        !          4513: /* Scan an attribute value, possibly a conditional, and record what actions
        !          4514:    will be required to do any conditional tests in it.
        !          4515: 
        !          4516:    Specifically, set
        !          4517:        `must_extract'    if we need to extract the insn operands
        !          4518:        `must_constrain'  if we must compute `which_alternative'
        !          4519:        `address_used'    if an address expression was used
        !          4520:        `length_used'     if an (eq_attr "length" ...) was used
        !          4521:  */
        !          4522: 
        !          4523: static void
        !          4524: walk_attr_value (exp)
        !          4525:      rtx exp;
        !          4526: {
        !          4527:   register int i, j;
        !          4528:   register char *fmt;
        !          4529:   RTX_CODE code;
        !          4530: 
        !          4531:   if (exp == NULL)
        !          4532:     return;
        !          4533: 
        !          4534:   code = GET_CODE (exp);
        !          4535:   switch (code)
        !          4536:     {
        !          4537:     case SYMBOL_REF:
        !          4538:       if (! RTX_UNCHANGING_P (exp))
        !          4539:        /* Since this is an arbitrary expression, it can look at anything.
        !          4540:           However, constant expressions do not depend on any particular
        !          4541:           insn.  */
        !          4542:        must_extract = must_constrain = 1;
        !          4543:       return;
        !          4544: 
        !          4545:     case MATCH_OPERAND:
        !          4546:       must_extract = 1;
        !          4547:       return;
        !          4548: 
        !          4549:     case EQ_ATTR:
        !          4550:       if (XSTR (exp, 0) == alternative_name)
        !          4551:        must_extract = must_constrain = 1;
        !          4552:       else if (strcmp (XSTR (exp, 0), "length") == 0)
        !          4553:        length_used = 1;
        !          4554:       return;
        !          4555: 
        !          4556:     case MATCH_DUP:
        !          4557:     case PC:
        !          4558:       address_used = 1;
        !          4559:       return;
        !          4560: 
        !          4561:     case ATTR_FLAG:
        !          4562:       return;
        !          4563:     }
        !          4564: 
        !          4565:   for (i = 0, fmt = GET_RTX_FORMAT (code); i < GET_RTX_LENGTH (code); i++)
        !          4566:     switch (*fmt++)
        !          4567:       {
        !          4568:       case 'e':
        !          4569:       case 'u':
        !          4570:        walk_attr_value (XEXP (exp, i));
        !          4571:        break;
        !          4572: 
        !          4573:       case 'E':
        !          4574:        if (XVEC (exp, i) != NULL)
        !          4575:          for (j = 0; j < XVECLEN (exp, i); j++)
        !          4576:            walk_attr_value (XVECEXP (exp, i, j));
        !          4577:        break;
        !          4578:       }
        !          4579: }
        !          4580: 
        !          4581: /* Write out a function to obtain the attribute for a given INSN.  */
        !          4582: 
        !          4583: static void
        !          4584: write_attr_get (attr)
        !          4585:      struct attr_desc *attr;
        !          4586: {
        !          4587:   struct attr_value *av, *common_av;
        !          4588: 
        !          4589:   /* Find the most used attribute value.  Handle that as the `default' of the
        !          4590:      switch we will generate. */
        !          4591:   common_av = find_most_used (attr);
        !          4592: 
        !          4593:   /* Write out start of function, then all values with explicit `case' lines,
        !          4594:      then a `default', then the value with the most uses.  */
        !          4595:   if (!attr->is_numeric)
        !          4596:     printf ("enum attr_%s\n", attr->name);
        !          4597:   else if (attr->unsigned_p)
        !          4598:     printf ("unsigned int\n");
        !          4599:   else
        !          4600:     printf ("int\n");
        !          4601: 
        !          4602:   /* If the attribute name starts with a star, the remainder is the name of
        !          4603:      the subroutine to use, instead of `get_attr_...'.  */
        !          4604:   if (attr->name[0] == '*')
        !          4605:     printf ("%s (insn)\n", &attr->name[1]);
        !          4606:   else if (attr->is_const == 0)
        !          4607:     printf ("get_attr_%s (insn)\n", attr->name);
        !          4608:   else
        !          4609:     {
        !          4610:       printf ("get_attr_%s ()\n", attr->name);
        !          4611:       printf ("{\n");
        !          4612: 
        !          4613:       for (av = attr->first_value; av; av = av->next)
        !          4614:        if (av->num_insns != 0)
        !          4615:          write_attr_set (attr, 2, av->value, "return", ";",
        !          4616:                          true_rtx, av->first_insn->insn_code,
        !          4617:                          av->first_insn->insn_index);
        !          4618: 
        !          4619:       printf ("}\n\n");
        !          4620:       return;
        !          4621:     }
        !          4622:   printf ("     rtx insn;\n");
        !          4623:   printf ("{\n");
        !          4624:   printf ("  switch (recog_memoized (insn))\n");
        !          4625:   printf ("    {\n");
        !          4626: 
        !          4627:   for (av = attr->first_value; av; av = av->next)
        !          4628:     if (av != common_av)
        !          4629:       write_attr_case (attr, av, 1, "return", ";", 4, true_rtx);
        !          4630: 
        !          4631:   write_attr_case (attr, common_av, 0, "return", ";", 4, true_rtx);
        !          4632:   printf ("    }\n}\n\n");
        !          4633: }
        !          4634: 
        !          4635: /* Given an AND tree of known true terms (because we are inside an `if' with
        !          4636:    that as the condition or are in an `else' clause) and an expression,
        !          4637:    replace any known true terms with TRUE.  Use `simplify_and_tree' to do
        !          4638:    the bulk of the work.  */
        !          4639: 
        !          4640: static rtx
        !          4641: eliminate_known_true (known_true, exp, insn_code, insn_index)
        !          4642:      rtx known_true;
        !          4643:      rtx exp;
        !          4644:      int insn_code, insn_index;
        !          4645: {
        !          4646:   rtx term;
        !          4647: 
        !          4648:   known_true = SIMPLIFY_TEST_EXP (known_true, insn_code, insn_index);
        !          4649: 
        !          4650:   if (GET_CODE (known_true) == AND)
        !          4651:     {
        !          4652:       exp = eliminate_known_true (XEXP (known_true, 0), exp,
        !          4653:                                  insn_code, insn_index);
        !          4654:       exp = eliminate_known_true (XEXP (known_true, 1), exp,
        !          4655:                                  insn_code, insn_index);
        !          4656:     }
        !          4657:   else
        !          4658:     {
        !          4659:       term = known_true;
        !          4660:       exp = simplify_and_tree (exp, &term, insn_code, insn_index);
        !          4661:     }
        !          4662: 
        !          4663:   return exp;
        !          4664: }
        !          4665: 
        !          4666: /* Write out a series of tests and assignment statements to perform tests and
        !          4667:    sets of an attribute value.  We are passed an indentation amount and prefix
        !          4668:    and suffix strings to write around each attribute value (e.g., "return"
        !          4669:    and ";").  */
        !          4670: 
        !          4671: static void
        !          4672: write_attr_set (attr, indent, value, prefix, suffix, known_true,
        !          4673:                insn_code, insn_index)
        !          4674:      struct attr_desc *attr;
        !          4675:      int indent;
        !          4676:      rtx value;
        !          4677:      char *prefix;
        !          4678:      char *suffix;
        !          4679:      rtx known_true;
        !          4680:      int insn_code, insn_index;
        !          4681: {
        !          4682:   if (GET_CODE (value) == CONST_STRING)
        !          4683:     {
        !          4684:       write_indent (indent);
        !          4685:       printf ("%s ", prefix);
        !          4686:       write_attr_value (attr, value);
        !          4687:       printf ("%s\n", suffix);
        !          4688:     }
        !          4689:   else if (GET_CODE (value) == COND)
        !          4690:     {
        !          4691:       /* Assume the default value will be the default of the COND unless we
        !          4692:         find an always true expression.  */
        !          4693:       rtx default_val = XEXP (value, 1);
        !          4694:       rtx our_known_true = known_true;
        !          4695:       rtx newexp;
        !          4696:       int first_if = 1;
        !          4697:       int i;
        !          4698: 
        !          4699:       for (i = 0; i < XVECLEN (value, 0); i += 2)
        !          4700:        {
        !          4701:          rtx testexp;
        !          4702:          rtx inner_true;
        !          4703: 
        !          4704:          testexp = eliminate_known_true (our_known_true,
        !          4705:                                          XVECEXP (value, 0, i),
        !          4706:                                          insn_code, insn_index);
        !          4707:          newexp = attr_rtx (NOT, testexp);
        !          4708:          newexp  = insert_right_side (AND, our_known_true, newexp,
        !          4709:                                       insn_code, insn_index);
        !          4710: 
        !          4711:          /* If the test expression is always true or if the next `known_true'
        !          4712:             expression is always false, this is the last case, so break
        !          4713:             out and let this value be the `else' case.  */
        !          4714:          if (testexp == true_rtx || newexp == false_rtx)
        !          4715:            {
        !          4716:              default_val = XVECEXP (value, 0, i + 1);
        !          4717:              break;
        !          4718:            }
        !          4719: 
        !          4720:          /* Compute the expression to pass to our recursive call as being
        !          4721:             known true.  */
        !          4722:          inner_true = insert_right_side (AND, our_known_true,
        !          4723:                                          testexp, insn_code, insn_index);
        !          4724: 
        !          4725:          /* If this is always false, skip it.  */
        !          4726:          if (inner_true == false_rtx)
        !          4727:            continue;
        !          4728: 
        !          4729:          write_indent (indent);
        !          4730:          printf ("%sif ", first_if ? "" : "else ");
        !          4731:          first_if = 0;
        !          4732:          write_test_expr (testexp, 0);
        !          4733:          printf ("\n");
        !          4734:          write_indent (indent + 2);
        !          4735:          printf ("{\n");
        !          4736: 
        !          4737:          write_attr_set (attr, indent + 4,  
        !          4738:                          XVECEXP (value, 0, i + 1), prefix, suffix,
        !          4739:                          inner_true, insn_code, insn_index);
        !          4740:          write_indent (indent + 2);
        !          4741:          printf ("}\n");
        !          4742:          our_known_true = newexp;
        !          4743:        }
        !          4744: 
        !          4745:       if (! first_if)
        !          4746:        {
        !          4747:          write_indent (indent);
        !          4748:          printf ("else\n");
        !          4749:          write_indent (indent + 2);
        !          4750:          printf ("{\n");
        !          4751:        }
        !          4752: 
        !          4753:       write_attr_set (attr, first_if ? indent : indent + 4, default_val,
        !          4754:                      prefix, suffix, our_known_true, insn_code, insn_index);
        !          4755: 
        !          4756:       if (! first_if)
        !          4757:        {
        !          4758:          write_indent (indent + 2);
        !          4759:          printf ("}\n");
        !          4760:        }
        !          4761:     }
        !          4762:   else
        !          4763:     abort ();
        !          4764: }
        !          4765: 
        !          4766: /* Write out the computation for one attribute value.  */
        !          4767: 
        !          4768: static void
        !          4769: write_attr_case (attr, av, write_case_lines, prefix, suffix, indent,
        !          4770:                 known_true)
        !          4771:      struct attr_desc *attr;
        !          4772:      struct attr_value *av;
        !          4773:      int write_case_lines;
        !          4774:      char *prefix, *suffix;
        !          4775:      int indent;
        !          4776:      rtx known_true;
        !          4777: {
        !          4778:   struct insn_ent *ie;
        !          4779: 
        !          4780:   if (av->num_insns == 0)
        !          4781:     return;
        !          4782: 
        !          4783:   if (av->has_asm_insn)
        !          4784:     {
        !          4785:       write_indent (indent);
        !          4786:       printf ("case -1:\n");
        !          4787:       write_indent (indent + 2);
        !          4788:       printf ("if (GET_CODE (PATTERN (insn)) != ASM_INPUT\n");
        !          4789:       write_indent (indent + 2);
        !          4790:       printf ("    && asm_noperands (PATTERN (insn)) < 0)\n");
        !          4791:       write_indent (indent + 2);
        !          4792:       printf ("  fatal_insn_not_found (insn);\n");
        !          4793:     }
        !          4794: 
        !          4795:   if (write_case_lines)
        !          4796:     {
        !          4797:       for (ie = av->first_insn; ie; ie = ie->next)
        !          4798:        if (ie->insn_code != -1)
        !          4799:          {
        !          4800:            write_indent (indent);
        !          4801:            printf ("case %d:\n", ie->insn_code);
        !          4802:          }
        !          4803:     }
        !          4804:   else
        !          4805:     {
        !          4806:       write_indent (indent);
        !          4807:       printf ("default:\n");
        !          4808:     }
        !          4809: 
        !          4810:   /* See what we have to do to output this value.  */
        !          4811:   must_extract = must_constrain = address_used = 0;
        !          4812:   walk_attr_value (av->value);
        !          4813: 
        !          4814:   if (must_extract)
        !          4815:     {
        !          4816:       write_indent (indent + 2);
        !          4817:       printf ("insn_extract (insn);\n");
        !          4818:     }
        !          4819: 
        !          4820:   if (must_constrain)
        !          4821:     {
        !          4822: #ifdef REGISTER_CONSTRAINTS
        !          4823:       write_indent (indent + 2);
        !          4824:       printf ("if (! constrain_operands (INSN_CODE (insn), reload_completed))\n");
        !          4825:       write_indent (indent + 2);
        !          4826:       printf ("  fatal_insn_not_found (insn);\n");
        !          4827: #endif
        !          4828:     }
        !          4829: 
        !          4830:   write_attr_set (attr, indent + 2, av->value, prefix, suffix,
        !          4831:                  known_true, av->first_insn->insn_code,
        !          4832:                  av->first_insn->insn_index);
        !          4833: 
        !          4834:   if (strncmp (prefix, "return", 6))
        !          4835:     {
        !          4836:       write_indent (indent + 2);
        !          4837:       printf ("break;\n");
        !          4838:     }
        !          4839:   printf ("\n");
        !          4840: }
        !          4841: 
        !          4842: /* Utilities to write names in various forms.  */
        !          4843: 
        !          4844: static void
        !          4845: write_attr_valueq (attr, s)
        !          4846:      struct attr_desc *attr;
        !          4847:      char *s;
        !          4848: {
        !          4849:   if (attr->is_numeric)
        !          4850:     {
        !          4851:       printf ("%s", s);
        !          4852:       /* Make the blockage range values easier to read.  */
        !          4853:       if (strlen (s) > 1)
        !          4854:        printf (" /* 0x%x */", atoi (s));
        !          4855:     }
        !          4856:   else
        !          4857:     {
        !          4858:       write_upcase (attr->name);
        !          4859:       printf ("_");
        !          4860:       write_upcase (s);
        !          4861:     }
        !          4862: }
        !          4863: 
        !          4864: static void
        !          4865: write_attr_value (attr, value)
        !          4866:      struct attr_desc *attr;
        !          4867:      rtx value;
        !          4868: {
        !          4869:   if (GET_CODE (value) != CONST_STRING)
        !          4870:     abort ();
        !          4871: 
        !          4872:   write_attr_valueq (attr, XSTR (value, 0));
        !          4873: }
        !          4874: 
        !          4875: static void
        !          4876: write_upcase (str)
        !          4877:      char *str;
        !          4878: {
        !          4879:   while (*str)
        !          4880:     if (*str < 'a' || *str > 'z')
        !          4881:       printf ("%c", *str++);
        !          4882:     else
        !          4883:       printf ("%c", *str++ - 'a' + 'A');
        !          4884: }
        !          4885: 
        !          4886: static void
        !          4887: write_indent (indent)
        !          4888:      int indent;
        !          4889: {
        !          4890:   for (; indent > 8; indent -= 8)
        !          4891:     printf ("\t");
        !          4892: 
        !          4893:   for (; indent; indent--)
        !          4894:     printf (" ");
        !          4895: }
        !          4896: 
        !          4897: /* Write a subroutine that is given an insn that requires a delay slot, a
        !          4898:    delay slot ordinal, and a candidate insn.  It returns non-zero if the
        !          4899:    candidate can be placed in the specified delay slot of the insn.
        !          4900: 
        !          4901:    We can write as many as three subroutines.  `eligible_for_delay'
        !          4902:    handles normal delay slots, `eligible_for_annul_true' indicates that
        !          4903:    the specified insn can be annulled if the branch is true, and likewise
        !          4904:    for `eligible_for_annul_false'.
        !          4905: 
        !          4906:    KIND is a string distinguishing these three cases ("delay", "annul_true",
        !          4907:    or "annul_false").  */
        !          4908: 
        !          4909: static void
        !          4910: write_eligible_delay (kind)
        !          4911:      char *kind;
        !          4912: {
        !          4913:   struct delay_desc *delay;
        !          4914:   int max_slots;
        !          4915:   char str[50];
        !          4916:   struct attr_desc *attr;
        !          4917:   struct attr_value *av, *common_av;
        !          4918:   int i;
        !          4919: 
        !          4920:   /* Compute the maximum number of delay slots required.  We use the delay
        !          4921:      ordinal times this number plus one, plus the slot number as an index into
        !          4922:      the appropriate predicate to test.  */
        !          4923: 
        !          4924:   for (delay = delays, max_slots = 0; delay; delay = delay->next)
        !          4925:     if (XVECLEN (delay->def, 1) / 3 > max_slots)
        !          4926:       max_slots = XVECLEN (delay->def, 1) / 3;
        !          4927: 
        !          4928:   /* Write function prelude.  */
        !          4929: 
        !          4930:   printf ("int\n");
        !          4931:   printf ("eligible_for_%s (delay_insn, slot, candidate_insn, flags)\n", 
        !          4932:           kind);
        !          4933:   printf ("     rtx delay_insn;\n");
        !          4934:   printf ("     int slot;\n");
        !          4935:   printf ("     rtx candidate_insn;\n");
        !          4936:   printf ("     int flags;\n");
        !          4937:   printf ("{\n");
        !          4938:   printf ("  rtx insn;\n");
        !          4939:   printf ("\n");
        !          4940:   printf ("  if (slot >= %d)\n", max_slots);
        !          4941:   printf ("    abort ();\n");
        !          4942:   printf ("\n");
        !          4943: 
        !          4944:   /* If more than one delay type, find out which type the delay insn is.  */
        !          4945: 
        !          4946:   if (num_delays > 1)
        !          4947:     {
        !          4948:       attr = find_attr ("*delay_type", 0);
        !          4949:       if (! attr) abort ();
        !          4950:       common_av = find_most_used (attr);
        !          4951: 
        !          4952:       printf ("  insn = delay_insn;\n");
        !          4953:       printf ("  switch (recog_memoized (insn))\n");
        !          4954:       printf ("    {\n");
        !          4955: 
        !          4956:       sprintf (str, " * %d;\n      break;", max_slots);
        !          4957:       for (av = attr->first_value; av; av = av->next)
        !          4958:        if (av != common_av)
        !          4959:          write_attr_case (attr, av, 1, "slot +=", str, 4, true_rtx);
        !          4960: 
        !          4961:       write_attr_case (attr, common_av, 0, "slot +=", str, 4, true_rtx);
        !          4962:       printf ("    }\n\n");
        !          4963: 
        !          4964:       /* Ensure matched.  Otherwise, shouldn't have been called.  */
        !          4965:       printf ("  if (slot < %d)\n", max_slots);
        !          4966:       printf ("    abort ();\n\n");
        !          4967:     }
        !          4968: 
        !          4969:   /* If just one type of delay slot, write simple switch.  */
        !          4970:   if (num_delays == 1 && max_slots == 1)
        !          4971:     {
        !          4972:       printf ("  insn = candidate_insn;\n");
        !          4973:       printf ("  switch (recog_memoized (insn))\n");
        !          4974:       printf ("    {\n");
        !          4975: 
        !          4976:       attr = find_attr ("*delay_1_0", 0);
        !          4977:       if (! attr) abort ();
        !          4978:       common_av = find_most_used (attr);
        !          4979: 
        !          4980:       for (av = attr->first_value; av; av = av->next)
        !          4981:        if (av != common_av)
        !          4982:          write_attr_case (attr, av, 1, "return", ";", 4, true_rtx);
        !          4983: 
        !          4984:       write_attr_case (attr, common_av, 0, "return", ";", 4, true_rtx);
        !          4985:       printf ("    }\n");
        !          4986:     }
        !          4987: 
        !          4988:   else
        !          4989:     {
        !          4990:       /* Write a nested CASE.  The first indicates which condition we need to
        !          4991:         test, and the inner CASE tests the condition.  */
        !          4992:       printf ("  insn = candidate_insn;\n");
        !          4993:       printf ("  switch (slot)\n");
        !          4994:       printf ("    {\n");
        !          4995: 
        !          4996:       for (delay = delays; delay; delay = delay->next)
        !          4997:        for (i = 0; i < XVECLEN (delay->def, 1); i += 3)
        !          4998:          {
        !          4999:            printf ("    case %d:\n",
        !          5000:                    (i / 3) + (num_delays == 1 ? 0 : delay->num * max_slots));
        !          5001:            printf ("      switch (recog_memoized (insn))\n");
        !          5002:            printf ("\t{\n");
        !          5003: 
        !          5004:            sprintf (str, "*%s_%d_%d", kind, delay->num, i / 3);
        !          5005:            attr = find_attr (str, 0);
        !          5006:            if (! attr) abort ();
        !          5007:            common_av = find_most_used (attr);
        !          5008: 
        !          5009:            for (av = attr->first_value; av; av = av->next)
        !          5010:              if (av != common_av)
        !          5011:                write_attr_case (attr, av, 1, "return", ";", 8, true_rtx);
        !          5012: 
        !          5013:            write_attr_case (attr, common_av, 0, "return", ";", 8, true_rtx);
        !          5014:            printf ("      }\n");
        !          5015:          }
        !          5016: 
        !          5017:       printf ("    default:\n");
        !          5018:       printf ("      abort ();\n");     
        !          5019:       printf ("    }\n");
        !          5020:     }
        !          5021: 
        !          5022:   printf ("}\n\n");
        !          5023: }
        !          5024: 
        !          5025: /* Write routines to compute conflict cost for function units.  Then write a
        !          5026:    table describing the available function units.  */
        !          5027: 
        !          5028: static void
        !          5029: write_function_unit_info ()
        !          5030: {
        !          5031:   struct function_unit *unit;
        !          5032:   int i;
        !          5033: 
        !          5034:   /* Write out conflict routines for function units.  Don't bother writing
        !          5035:      one if there is only one issue delay value.  */
        !          5036: 
        !          5037:   for (unit = units; unit; unit = unit->next)
        !          5038:     {
        !          5039:       if (unit->needs_blockage_function)
        !          5040:        write_complex_function (unit, "blockage", "block");
        !          5041: 
        !          5042:       /* If the minimum and maximum conflict costs are the same, there
        !          5043:         is only one value, so we don't need a function.  */
        !          5044:       if (! unit->needs_conflict_function)
        !          5045:        {
        !          5046:          unit->default_cost = make_numeric_value (unit->issue_delay.max);
        !          5047:          continue;
        !          5048:        }
        !          5049: 
        !          5050:       /* The function first computes the case from the candidate insn.  */
        !          5051:       unit->default_cost = make_numeric_value (0);
        !          5052:       write_complex_function (unit, "conflict_cost", "cost");
        !          5053:     }
        !          5054: 
        !          5055:   /* Now that all functions have been written, write the table describing
        !          5056:      the function units.   The name is included for documentation purposes
        !          5057:      only.  */
        !          5058: 
        !          5059:   printf ("struct function_unit_desc function_units[] = {\n");
        !          5060: 
        !          5061:   /* Write out the descriptions in numeric order, but don't force that order
        !          5062:      on the list.  Doing so increases the runtime of genattrtab.c.  */
        !          5063:   for (i = 0; i < num_units; i++)
        !          5064:     {
        !          5065:       for (unit = units; unit; unit = unit->next)
        !          5066:        if (unit->num == i)
        !          5067:          break;
        !          5068: 
        !          5069:       printf ("  {\"%s\", %d, %d, %d, %s, %d, %s_unit_ready_cost, ",
        !          5070:              unit->name, 1 << unit->num, unit->multiplicity,
        !          5071:              unit->simultaneity, XSTR (unit->default_cost, 0),
        !          5072:              unit->issue_delay.max, unit->name);
        !          5073: 
        !          5074:       if (unit->needs_conflict_function)
        !          5075:        printf ("%s_unit_conflict_cost, ", unit->name);
        !          5076:       else
        !          5077:        printf ("0, ");
        !          5078: 
        !          5079:       printf ("%d, ", unit->max_blockage);
        !          5080: 
        !          5081:       if (unit->needs_range_function)
        !          5082:        printf ("%s_unit_blockage_range, ", unit->name);
        !          5083:       else
        !          5084:        printf ("0, ");
        !          5085: 
        !          5086:       if (unit->needs_blockage_function)
        !          5087:        printf ("%s_unit_blockage", unit->name);
        !          5088:       else
        !          5089:        printf ("0");
        !          5090: 
        !          5091:       printf ("}, \n");
        !          5092:     }
        !          5093: 
        !          5094:   printf ("};\n\n");
        !          5095: }
        !          5096: 
        !          5097: static void
        !          5098: write_complex_function (unit, name, connection)
        !          5099:      struct function_unit *unit;
        !          5100:      char *name, *connection;
        !          5101: {
        !          5102:   struct attr_desc *case_attr, *attr;
        !          5103:   struct attr_value *av, *common_av;
        !          5104:   rtx value;
        !          5105:   char *str;
        !          5106:   int using_case;
        !          5107:   int i;
        !          5108: 
        !          5109:   printf ("static int\n");
        !          5110:   printf ("%s_unit_%s (executing_insn, candidate_insn)\n",
        !          5111:          unit->name, name);
        !          5112:   printf ("     rtx executing_insn;\n");
        !          5113:   printf ("     rtx candidate_insn;\n");
        !          5114:   printf ("{\n");
        !          5115:   printf ("  rtx insn;\n");
        !          5116:   printf ("  int casenum;\n\n");
        !          5117:   printf ("  insn = candidate_insn;\n");
        !          5118:   printf ("  switch (recog_memoized (insn))\n");
        !          5119:   printf ("    {\n");
        !          5120: 
        !          5121:   /* Write the `switch' statement to get the case value.  */
        !          5122:   str = (char *) alloca (strlen (unit->name) + strlen (name) + strlen (connection) + 10);
        !          5123:   sprintf (str, "*%s_cases", unit->name);
        !          5124:   case_attr = find_attr (str, 0);
        !          5125:   if (! case_attr) abort ();
        !          5126:   common_av = find_most_used (case_attr);
        !          5127: 
        !          5128:   for (av = case_attr->first_value; av; av = av->next)
        !          5129:     if (av != common_av)
        !          5130:       write_attr_case (case_attr, av, 1,
        !          5131:                       "casenum =", ";", 4, unit->condexp);
        !          5132: 
        !          5133:   write_attr_case (case_attr, common_av, 0,
        !          5134:                   "casenum =", ";", 4, unit->condexp);
        !          5135:   printf ("    }\n\n");
        !          5136: 
        !          5137:   /* Now write an outer switch statement on each case.  Then write
        !          5138:      the tests on the executing function within each.  */
        !          5139:   printf ("  insn = executing_insn;\n");
        !          5140:   printf ("  switch (casenum)\n");
        !          5141:   printf ("    {\n");
        !          5142: 
        !          5143:   for (i = 0; i < unit->num_opclasses; i++)
        !          5144:     {
        !          5145:       /* Ensure using this case.  */
        !          5146:       using_case = 0;
        !          5147:       for (av = case_attr->first_value; av; av = av->next)
        !          5148:        if (av->num_insns
        !          5149:            && contained_in_p (make_numeric_value (i), av->value))
        !          5150:          using_case = 1;
        !          5151: 
        !          5152:       if (! using_case)
        !          5153:        continue;
        !          5154: 
        !          5155:       printf ("    case %d:\n", i);
        !          5156:       sprintf (str, "*%s_%s_%d", unit->name, connection, i);
        !          5157:       attr = find_attr (str, 0);
        !          5158:       if (! attr) abort ();
        !          5159: 
        !          5160:       /* If single value, just write it.  */
        !          5161:       value = find_single_value (attr);
        !          5162:       if (value)
        !          5163:        write_attr_set (attr, 6, value, "return", ";\n", true_rtx, -2, -2);
        !          5164:       else
        !          5165:        {
        !          5166:          common_av = find_most_used (attr);
        !          5167:          printf ("      switch (recog_memoized (insn))\n");
        !          5168:          printf ("\t{\n");
        !          5169: 
        !          5170:          for (av = attr->first_value; av; av = av->next)
        !          5171:            if (av != common_av)
        !          5172:              write_attr_case (attr, av, 1,
        !          5173:                               "return", ";", 8, unit->condexp);
        !          5174: 
        !          5175:          write_attr_case (attr, common_av, 0,
        !          5176:                           "return", ";", 8, unit->condexp);
        !          5177:          printf ("      }\n\n");
        !          5178:        }
        !          5179:     }
        !          5180: 
        !          5181:   printf ("    }\n}\n\n");
        !          5182: }
        !          5183: 
        !          5184: /* This page contains miscellaneous utility routines.  */
        !          5185: 
        !          5186: /* Given a string, return the number of comma-separated elements in it.
        !          5187:    Return 0 for the null string.  */
        !          5188: 
        !          5189: static int
        !          5190: n_comma_elts (s)
        !          5191:      char *s;
        !          5192: {
        !          5193:   int n;
        !          5194: 
        !          5195:   if (*s == '\0')
        !          5196:     return 0;
        !          5197: 
        !          5198:   for (n = 1; *s; s++)
        !          5199:     if (*s == ',')
        !          5200:       n++;
        !          5201: 
        !          5202:   return n;
        !          5203: }
        !          5204: 
        !          5205: /* Given a pointer to a (char *), return a malloc'ed string containing the
        !          5206:    next comma-separated element.  Advance the pointer to after the string
        !          5207:    scanned, or the end-of-string.  Return NULL if at end of string.  */
        !          5208: 
        !          5209: static char *
        !          5210: next_comma_elt (pstr)
        !          5211:      char **pstr;
        !          5212: {
        !          5213:   char *out_str;
        !          5214:   char *p;
        !          5215: 
        !          5216:   if (**pstr == '\0')
        !          5217:     return NULL;
        !          5218: 
        !          5219:   /* Find end of string to compute length.  */
        !          5220:   for (p = *pstr; *p != ',' && *p != '\0'; p++)
        !          5221:     ;
        !          5222: 
        !          5223:   out_str = attr_string (*pstr, p - *pstr);
        !          5224:   *pstr = p;
        !          5225: 
        !          5226:   if (**pstr == ',')
        !          5227:     (*pstr)++;
        !          5228: 
        !          5229:   return out_str;
        !          5230: }
        !          5231: 
        !          5232: /* Return a `struct attr_desc' pointer for a given named attribute.  If CREATE
        !          5233:    is non-zero, build a new attribute, if one does not exist.  */
        !          5234: 
        !          5235: static struct attr_desc *
        !          5236: find_attr (name, create)
        !          5237:      char *name;
        !          5238:      int create;
        !          5239: {
        !          5240:   struct attr_desc *attr;
        !          5241:   int index;
        !          5242: 
        !          5243:   /* Before we resort to using `strcmp', see if the string address matches
        !          5244:      anywhere.  In most cases, it should have been canonicalized to do so.  */
        !          5245:   if (name == alternative_name)
        !          5246:     return NULL;
        !          5247: 
        !          5248:   index = name[0] & (MAX_ATTRS_INDEX - 1);
        !          5249:   for (attr = attrs[index]; attr; attr = attr->next)
        !          5250:     if (name == attr->name)
        !          5251:       return attr;
        !          5252: 
        !          5253:   /* Otherwise, do it the slow way.  */
        !          5254:   for (attr = attrs[index]; attr; attr = attr->next)
        !          5255:     if (name[0] == attr->name[0] && ! strcmp (name, attr->name))
        !          5256:       return attr;
        !          5257: 
        !          5258:   if (! create)
        !          5259:     return NULL;
        !          5260: 
        !          5261:   attr = (struct attr_desc *) oballoc (sizeof (struct attr_desc));
        !          5262:   attr->name = attr_string (name, strlen (name));
        !          5263:   attr->first_value = attr->default_val = NULL;
        !          5264:   attr->is_numeric = attr->negative_ok = attr->is_const = attr->is_special = 0;
        !          5265:   attr->next = attrs[index];
        !          5266:   attrs[index] = attr;
        !          5267: 
        !          5268:   return attr;
        !          5269: }
        !          5270: 
        !          5271: /* Create internal attribute with the given default value.  */
        !          5272: 
        !          5273: static void
        !          5274: make_internal_attr (name, value, special)
        !          5275:      char *name;
        !          5276:      rtx value;
        !          5277:      int special;
        !          5278: {
        !          5279:   struct attr_desc *attr;
        !          5280: 
        !          5281:   attr = find_attr (name, 1);
        !          5282:   if (attr->default_val)
        !          5283:     abort ();
        !          5284: 
        !          5285:   attr->is_numeric = 1;
        !          5286:   attr->is_const = 0;
        !          5287:   attr->is_special = (special & 1) != 0;
        !          5288:   attr->negative_ok = (special & 2) != 0;
        !          5289:   attr->unsigned_p = (special & 4) != 0;
        !          5290:   attr->default_val = get_attr_value (value, attr, -2);
        !          5291: }
        !          5292: 
        !          5293: /* Find the most used value of an attribute.  */
        !          5294: 
        !          5295: static struct attr_value *
        !          5296: find_most_used (attr)
        !          5297:      struct attr_desc *attr;
        !          5298: {
        !          5299:   struct attr_value *av;
        !          5300:   struct attr_value *most_used;
        !          5301:   int nuses;
        !          5302: 
        !          5303:   most_used = NULL;
        !          5304:   nuses = -1;
        !          5305: 
        !          5306:   for (av = attr->first_value; av; av = av->next)
        !          5307:     if (av->num_insns > nuses)
        !          5308:       nuses = av->num_insns, most_used = av;
        !          5309: 
        !          5310:   return most_used;
        !          5311: }
        !          5312: 
        !          5313: /* If an attribute only has a single value used, return it.  Otherwise
        !          5314:    return NULL.  */
        !          5315: 
        !          5316: static rtx
        !          5317: find_single_value (attr)
        !          5318:      struct attr_desc *attr;
        !          5319: {
        !          5320:   struct attr_value *av;
        !          5321:   rtx unique_value;
        !          5322: 
        !          5323:   unique_value = NULL;
        !          5324:   for (av = attr->first_value; av; av = av->next)
        !          5325:     if (av->num_insns)
        !          5326:       {
        !          5327:        if (unique_value)
        !          5328:          return NULL;
        !          5329:        else
        !          5330:          unique_value = av->value;
        !          5331:       }
        !          5332: 
        !          5333:   return unique_value;
        !          5334: }
        !          5335: 
        !          5336: /* Return (attr_value "n") */
        !          5337: 
        !          5338: static rtx
        !          5339: make_numeric_value (n)
        !          5340:      int n;
        !          5341: {
        !          5342:   static rtx int_values[20];
        !          5343:   rtx exp;
        !          5344:   char *p;
        !          5345: 
        !          5346:   if (n < 0)
        !          5347:     abort ();
        !          5348: 
        !          5349:   if (n < 20 && int_values[n])
        !          5350:     return int_values[n];
        !          5351: 
        !          5352:   p = attr_printf (MAX_DIGITS, "%d", n);
        !          5353:   exp = attr_rtx (CONST_STRING, p);
        !          5354: 
        !          5355:   if (n < 20)
        !          5356:     int_values[n] = exp;
        !          5357: 
        !          5358:   return exp;
        !          5359: }
        !          5360: 
        !          5361: static void
        !          5362: extend_range (range, min, max)
        !          5363:      struct range *range;
        !          5364:      int min;
        !          5365:      int max;
        !          5366: {
        !          5367:   if (range->min > min) range->min = min;
        !          5368:   if (range->max < max) range->max = max;
        !          5369: }
        !          5370: 
        !          5371: char *
        !          5372: xrealloc (ptr, size)
        !          5373:      char *ptr;
        !          5374:      unsigned size;
        !          5375: {
        !          5376:   char *result = (char *) realloc (ptr, size);
        !          5377:   if (!result)
        !          5378:     fatal ("virtual memory exhausted");
        !          5379:   return result;
        !          5380: }
        !          5381: 
        !          5382: char *
        !          5383: xmalloc (size)
        !          5384:      unsigned size;
        !          5385: {
        !          5386:   register char *val = (char *) malloc (size);
        !          5387: 
        !          5388:   if (val == 0)
        !          5389:     fatal ("virtual memory exhausted");
        !          5390:   return val;
        !          5391: }
        !          5392: 
        !          5393: static rtx
        !          5394: copy_rtx_unchanging (orig)
        !          5395:      register rtx orig;
        !          5396: {
        !          5397: #if 0
        !          5398:   register rtx copy;
        !          5399:   register RTX_CODE code;
        !          5400: #endif
        !          5401: 
        !          5402:   if (RTX_UNCHANGING_P (orig) || MEM_IN_STRUCT_P (orig))
        !          5403:     return orig;
        !          5404: 
        !          5405:   MEM_IN_STRUCT_P (orig) = 1;
        !          5406:   return orig;
        !          5407: 
        !          5408: #if 0
        !          5409:   code = GET_CODE (orig);
        !          5410:   switch (code)
        !          5411:     {
        !          5412:     case CONST_INT:
        !          5413:     case CONST_DOUBLE:
        !          5414:     case SYMBOL_REF:
        !          5415:     case CODE_LABEL:
        !          5416:       return orig;
        !          5417:     }
        !          5418: 
        !          5419:   copy = rtx_alloc (code);
        !          5420:   PUT_MODE (copy, GET_MODE (orig));
        !          5421:   RTX_UNCHANGING_P (copy) = 1;
        !          5422:   
        !          5423:   bcopy (&XEXP (orig, 0), &XEXP (copy, 0),
        !          5424:         GET_RTX_LENGTH (GET_CODE (copy)) * sizeof (rtx));
        !          5425:   return copy;
        !          5426: #endif
        !          5427: }
        !          5428: 
        !          5429: static void
        !          5430: fatal (s, a1, a2)
        !          5431:      char *s;
        !          5432: {
        !          5433:   fprintf (stderr, "genattrtab: ");
        !          5434:   fprintf (stderr, s, a1, a2);
        !          5435:   fprintf (stderr, "\n");
        !          5436:   exit (FATAL_EXIT_CODE);
        !          5437: }
        !          5438: 
        !          5439: /* More 'friendly' abort that prints the line and file.
        !          5440:    config.h can #define abort fancy_abort if you like that sort of thing.  */
        !          5441: 
        !          5442: void
        !          5443: fancy_abort ()
        !          5444: {
        !          5445:   fatal ("Internal gcc abort.");
        !          5446: }
        !          5447: 
        !          5448: /* Determine if an insn has a constant number of delay slots, i.e., the
        !          5449:    number of delay slots is not a function of the length of the insn.  */
        !          5450: 
        !          5451: void
        !          5452: write_const_num_delay_slots ()
        !          5453: {
        !          5454:   struct attr_desc *attr = find_attr ("*num_delay_slots", 0);
        !          5455:   struct attr_value *av;
        !          5456:   struct insn_ent *ie;
        !          5457:   int i;
        !          5458: 
        !          5459:   if (attr)
        !          5460:     {
        !          5461:       printf ("int\nconst_num_delay_slots (insn)\n");
        !          5462:       printf ("     rtx insn;\n");
        !          5463:       printf ("{\n");
        !          5464:       printf ("  switch (recog_memoized (insn))\n");
        !          5465:       printf ("    {\n");
        !          5466: 
        !          5467:       for (av = attr->first_value; av; av = av->next)
        !          5468:        {
        !          5469:          length_used = 0;
        !          5470:          walk_attr_value (av->value);
        !          5471:          if (length_used)
        !          5472:            {
        !          5473:              for (ie = av->first_insn; ie; ie = ie->next)
        !          5474:              if (ie->insn_code != -1)
        !          5475:                printf ("    case %d:\n", ie->insn_code);
        !          5476:              printf ("      return 0;\n");
        !          5477:            }
        !          5478:        }
        !          5479: 
        !          5480:       printf ("    default:\n");
        !          5481:       printf ("      return 1;\n");
        !          5482:       printf ("    }\n}\n");
        !          5483:     }
        !          5484: }
        !          5485: 
        !          5486: 
        !          5487: int
        !          5488: main (argc, argv)
        !          5489:      int argc;
        !          5490:      char **argv;
        !          5491: {
        !          5492:   rtx desc;
        !          5493:   FILE *infile;
        !          5494:   register int c;
        !          5495:   struct attr_desc *attr;
        !          5496:   struct insn_def *id;
        !          5497:   rtx tem;
        !          5498:   int i;
        !          5499: 
        !          5500: #ifdef RLIMIT_STACK
        !          5501:   /* Get rid of any avoidable limit on stack size.  */
        !          5502:   {
        !          5503:     struct rlimit rlim;
        !          5504: 
        !          5505:     /* Set the stack limit huge so that alloca does not fail. */
        !          5506:     getrlimit (RLIMIT_STACK, &rlim);
        !          5507:     rlim.rlim_cur = rlim.rlim_max;
        !          5508:     setrlimit (RLIMIT_STACK, &rlim);
        !          5509:   }
        !          5510: #endif /* RLIMIT_STACK defined */
        !          5511: 
        !          5512:   obstack_init (rtl_obstack);
        !          5513:   obstack_init (hash_obstack);
        !          5514:   obstack_init (temp_obstack);
        !          5515: 
        !          5516:   if (argc <= 1)
        !          5517:     fatal ("No input file name.");
        !          5518: 
        !          5519:   infile = fopen (argv[1], "r");
        !          5520:   if (infile == 0)
        !          5521:     {
        !          5522:       perror (argv[1]);
        !          5523:       exit (FATAL_EXIT_CODE);
        !          5524:     }
        !          5525: 
        !          5526:   init_rtl ();
        !          5527: 
        !          5528:   /* Set up true and false rtx's */
        !          5529:   true_rtx = rtx_alloc (CONST_INT);
        !          5530:   XWINT (true_rtx, 0) = 1;
        !          5531:   false_rtx = rtx_alloc (CONST_INT);
        !          5532:   XWINT (false_rtx, 0) = 0;
        !          5533:   RTX_UNCHANGING_P (true_rtx) = RTX_UNCHANGING_P (false_rtx) = 1;
        !          5534:   RTX_INTEGRATED_P (true_rtx) = RTX_INTEGRATED_P (false_rtx) = 1;
        !          5535: 
        !          5536:   alternative_name = attr_string ("alternative", strlen ("alternative"));
        !          5537: 
        !          5538:   printf ("/* Generated automatically by the program `genattrtab'\n\
        !          5539: from the machine description file `md'.  */\n\n");
        !          5540: 
        !          5541:   /* Read the machine description.  */
        !          5542: 
        !          5543:   while (1)
        !          5544:     {
        !          5545:       c = read_skip_spaces (infile);
        !          5546:       if (c == EOF)
        !          5547:        break;
        !          5548:       ungetc (c, infile);
        !          5549: 
        !          5550:       desc = read_rtx (infile);
        !          5551:       if (GET_CODE (desc) == DEFINE_INSN
        !          5552:          || GET_CODE (desc) == DEFINE_PEEPHOLE
        !          5553:          || GET_CODE (desc) == DEFINE_ASM_ATTRIBUTES)
        !          5554:        gen_insn (desc);
        !          5555: 
        !          5556:       else if (GET_CODE (desc) == DEFINE_EXPAND)
        !          5557:        insn_code_number++, insn_index_number++;
        !          5558: 
        !          5559:       else if (GET_CODE (desc) == DEFINE_SPLIT)
        !          5560:        insn_code_number++, insn_index_number++;
        !          5561: 
        !          5562:       else if (GET_CODE (desc) == DEFINE_ATTR)
        !          5563:        {
        !          5564:          gen_attr (desc);
        !          5565:          insn_index_number++;
        !          5566:        }
        !          5567: 
        !          5568:       else if (GET_CODE (desc) == DEFINE_DELAY)
        !          5569:        {
        !          5570:          gen_delay (desc);
        !          5571:          insn_index_number++;
        !          5572:        }
        !          5573: 
        !          5574:       else if (GET_CODE (desc) == DEFINE_FUNCTION_UNIT)
        !          5575:        {
        !          5576:          gen_unit (desc);
        !          5577:          insn_index_number++;
        !          5578:        }
        !          5579:     }
        !          5580: 
        !          5581:   /* If we didn't have a DEFINE_ASM_ATTRIBUTES, make a null one.  */
        !          5582:   if (! got_define_asm_attributes)
        !          5583:     {
        !          5584:       tem = rtx_alloc (DEFINE_ASM_ATTRIBUTES);
        !          5585:       XVEC (tem, 0) = rtvec_alloc (0);
        !          5586:       gen_insn (tem);
        !          5587:     }
        !          5588: 
        !          5589:   /* Expand DEFINE_DELAY information into new attribute.  */
        !          5590:   if (num_delays)
        !          5591:     expand_delays ();
        !          5592: 
        !          5593:   /* Expand DEFINE_FUNCTION_UNIT information into new attributes.  */
        !          5594:   if (num_units)
        !          5595:     expand_units ();
        !          5596: 
        !          5597:   printf ("#include \"config.h\"\n");
        !          5598:   printf ("#include \"rtl.h\"\n");
        !          5599:   printf ("#include \"insn-config.h\"\n");
        !          5600:   printf ("#include \"recog.h\"\n");
        !          5601:   printf ("#include \"regs.h\"\n");
        !          5602:   printf ("#include \"real.h\"\n");
        !          5603:   printf ("#include \"output.h\"\n");
        !          5604:   printf ("#include \"insn-attr.h\"\n");
        !          5605:   printf ("\n");  
        !          5606:   printf ("#define operands recog_operand\n\n");
        !          5607: 
        !          5608:   /* Make `insn_alternatives'.  */
        !          5609:   insn_alternatives = (int *) oballoc (insn_code_number * sizeof (int));
        !          5610:   for (id = defs; id; id = id->next)
        !          5611:     if (id->insn_code >= 0)
        !          5612:       insn_alternatives[id->insn_code] = (1 << id->num_alternatives) - 1;
        !          5613: 
        !          5614:   /* Make `insn_n_alternatives'.  */
        !          5615:   insn_n_alternatives = (int *) oballoc (insn_code_number * sizeof (int));
        !          5616:   for (id = defs; id; id = id->next)
        !          5617:     if (id->insn_code >= 0)
        !          5618:       insn_n_alternatives[id->insn_code] = id->num_alternatives;
        !          5619: 
        !          5620:   /* Prepare to write out attribute subroutines by checking everything stored
        !          5621:      away and building the attribute cases.  */
        !          5622: 
        !          5623:   check_defs ();
        !          5624:   for (i = 0; i < MAX_ATTRS_INDEX; i++)
        !          5625:     for (attr = attrs[i]; attr; attr = attr->next)
        !          5626:       {
        !          5627:        attr->default_val->value
        !          5628:          = check_attr_value (attr->default_val->value, attr);
        !          5629:        fill_attr (attr);
        !          5630:       }
        !          5631: 
        !          5632:   /* Construct extra attributes for `length'.  */
        !          5633:   make_length_attrs ();
        !          5634: 
        !          5635:   /* Perform any possible optimizations to speed up compilation. */
        !          5636:   optimize_attrs ();
        !          5637: 
        !          5638:   /* Now write out all the `gen_attr_...' routines.  Do these before the
        !          5639:      special routines (specifically before write_function_unit_info), so
        !          5640:      that they get defined before they are used.  */
        !          5641: 
        !          5642:   for (i = 0; i < MAX_ATTRS_INDEX; i++)
        !          5643:     for (attr = attrs[i]; attr; attr = attr->next)
        !          5644:       {
        !          5645:        if (! attr->is_special)
        !          5646:          write_attr_get (attr);
        !          5647:       }
        !          5648: 
        !          5649:   /* Write out delay eligibility information, if DEFINE_DELAY present.
        !          5650:      (The function to compute the number of delay slots will be written
        !          5651:      below.)  */
        !          5652:   if (num_delays)
        !          5653:     {
        !          5654:       write_eligible_delay ("delay");
        !          5655:       if (have_annul_true)
        !          5656:        write_eligible_delay ("annul_true");
        !          5657:       if (have_annul_false)
        !          5658:        write_eligible_delay ("annul_false");
        !          5659:     }
        !          5660: 
        !          5661:   /* Write out information about function units.  */
        !          5662:   if (num_units)
        !          5663:     write_function_unit_info ();
        !          5664: 
        !          5665:   /* Write out constant delay slot info */
        !          5666:   write_const_num_delay_slots ();
        !          5667: 
        !          5668:   fflush (stdout);
        !          5669:   exit (ferror (stdout) != 0 ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE);
        !          5670:   /* NOTREACHED */
        !          5671:   return 0;
        !          5672: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.