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