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