]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/gensupport.c
c++: Handle multiple aggregate overloads [PR95319].
[thirdparty/gcc.git] / gcc / gensupport.c
CommitLineData
3916d6d8 1/* Support routines for the various generation passes.
8d9254fc 2 Copyright (C) 2000-2020 Free Software Foundation, Inc.
c88c0d42 3
1322177d 4 This file is part of GCC.
c88c0d42 5
1322177d
LB
6 GCC is free software; you can redistribute it and/or modify it
7 under the terms of the GNU General Public License as published by
9dcd6f09 8 the Free Software Foundation; either version 3, or (at your option)
c88c0d42
CP
9 any later version.
10
1322177d
LB
11 GCC is distributed in the hope that it will be useful, but WITHOUT
12 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
14 License for more details.
c88c0d42
CP
15
16 You should have received a copy of the GNU General Public License
9dcd6f09
NC
17 along with GCC; see the file COPYING3. If not see
18 <http://www.gnu.org/licenses/>. */
c88c0d42 19
4977bab6 20#include "bconfig.h"
c88c0d42 21#include "system.h"
4977bab6
ZW
22#include "coretypes.h"
23#include "tm.h"
c88c0d42 24#include "rtl.h"
3916d6d8 25#include "obstack.h"
c88c0d42 26#include "errors.h"
10692477 27#include "read-md.h"
c88c0d42 28#include "gensupport.h"
6b8068d6 29#include "vec.h"
c88c0d42 30
477c104e
MK
31#define MAX_OPERANDS 40
32
33static rtx operand_data[MAX_OPERANDS];
34static rtx match_operand_entries_in_pattern[MAX_OPERANDS];
35static char used_operands_numbers[MAX_OPERANDS];
36
3916d6d8 37
c8cf201f
RK
38/* In case some macros used by files we include need it, define this here. */
39int target_flags;
40
2199e5fa
ZW
41int insn_elision = 1;
42
3916d6d8
RH
43static struct obstack obstack;
44struct obstack *rtl_obstack = &obstack;
45
72a35f93
RS
46/* Counter for named patterns and INSN_CODEs. */
47static int insn_sequence_num;
48
49/* Counter for define_splits. */
50static int split_sequence_num;
51
52/* Counter for define_peephole2s. */
53static int peephole2_sequence_num;
3262c1f5
RH
54
55static int predicable_default;
56static const char *predicable_true;
57static const char *predicable_false;
58
477c104e
MK
59static const char *subst_true = "yes";
60static const char *subst_false = "no";
61
2199e5fa
ZW
62static htab_t condition_table;
63
477c104e
MK
64/* We initially queue all patterns, process the define_insn,
65 define_cond_exec and define_subst patterns, then return
66 them one at a time. */
c88c0d42 67
6c1dae73 68class queue_elem
3262c1f5 69{
6c1dae73 70public:
3262c1f5 71 rtx data;
cc472607 72 file_location loc;
99b1c316 73 class queue_elem *next;
f4fde1b3
RS
74 /* In a DEFINE_INSN that came from a DEFINE_INSN_AND_SPLIT or
75 DEFINE_INSN_AND_REWRITE, SPLIT points to the generated DEFINE_SPLIT. */
99b1c316 76 class queue_elem *split;
c88c0d42
CP
77};
78
64aad689
AK
79#define MNEMONIC_ATTR_NAME "mnemonic"
80#define MNEMONIC_HTAB_SIZE 1024
81
99b1c316
MS
82static class queue_elem *define_attr_queue;
83static class queue_elem **define_attr_tail = &define_attr_queue;
84static class queue_elem *define_pred_queue;
85static class queue_elem **define_pred_tail = &define_pred_queue;
86static class queue_elem *define_insn_queue;
87static class queue_elem **define_insn_tail = &define_insn_queue;
88static class queue_elem *define_cond_exec_queue;
89static class queue_elem **define_cond_exec_tail = &define_cond_exec_queue;
90static class queue_elem *define_subst_queue;
91static class queue_elem **define_subst_tail = &define_subst_queue;
92static class queue_elem *other_queue;
93static class queue_elem **other_tail = &other_queue;
94static class queue_elem *define_subst_attr_queue;
95static class queue_elem **define_subst_attr_tail = &define_subst_attr_queue;
c88c0d42 96
58d745ec
RS
97/* Mapping from DEFINE_* rtxes to their location in the source file. */
98static hash_map <rtx, file_location> *rtx_locs;
99
3d7aafde 100static void remove_constraints (rtx);
3d7aafde 101
99b1c316 102static int is_predicable (class queue_elem *);
3d7aafde
AJ
103static void identify_predicable_attribute (void);
104static int n_alternatives (const char *);
105static void collect_insn_data (rtx, int *, int *);
99b1c316
MS
106static const char *alter_test_for_insn (class queue_elem *,
107 class queue_elem *);
3d7aafde 108static char *shift_output_template (char *, const char *, int);
99b1c316
MS
109static const char *alter_output_for_insn (class queue_elem *,
110 class queue_elem *,
3d7aafde 111 int, int);
99b1c316 112static void process_one_cond_exec (class queue_elem *);
3d7aafde 113static void process_define_cond_exec (void);
e543e219 114static void init_predicate_table (void);
0458fe77 115static void record_insn_name (int, const char *);
477c104e 116
99b1c316 117static bool has_subst_attribute (class queue_elem *, class queue_elem *);
477c104e 118static const char * alter_output_for_subst_insn (rtx, int);
99b1c316
MS
119static void alter_attrs_for_subst_insn (class queue_elem *, int);
120static void process_substs_on_one_elem (class queue_elem *,
121 class queue_elem *);
477c104e
MK
122static rtx subst_dup (rtx, int, int);
123static void process_define_subst (void);
124
125static const char * duplicate_alternatives (const char *, int);
126static const char * duplicate_each_alternative (const char * str, int n_dup);
127
128typedef const char * (*constraints_handler_t) (const char *, int);
129static rtx alter_constraints (rtx, int, constraints_handler_t);
a7ba15ca 130static rtx adjust_operands_numbers (rtx);
477c104e 131static rtx replace_duplicating_operands_in_pattern (rtx);
3916d6d8 132\f
10b76d73
RK
133/* Make a version of gen_rtx_CONST_INT so that GEN_INT can be used in
134 the gensupport programs. */
135
136rtx
ef4bddc2 137gen_rtx_CONST_INT (machine_mode ARG_UNUSED (mode),
3d7aafde 138 HOST_WIDE_INT arg)
10b76d73
RK
139{
140 rtx rt = rtx_alloc (CONST_INT);
141
142 XWINT (rt, 0) = arg;
143 return rt;
144}
313d38e3
RS
145
146/* Return the rtx pattern specified by the list of rtxes in a
147 define_insn or define_split. */
148
149rtx
150add_implicit_parallel (rtvec vec)
151{
152 if (GET_NUM_ELEM (vec) == 1)
153 return RTVEC_ELT (vec, 0);
154 else
155 {
156 rtx pattern = rtx_alloc (PARALLEL);
157 XVEC (pattern, 0) = vec;
158 return pattern;
159 }
160}
3916d6d8 161\f
77059241
RS
162/* Predicate handling.
163
164 We construct from the machine description a table mapping each
165 predicate to a list of the rtl codes it can possibly match. The
166 function 'maybe_both_true' uses it to deduce that there are no
167 expressions that can be matches by certain pairs of tree nodes.
168 Also, if a predicate can match only one code, we can hardwire that
169 code into the node testing the predicate.
170
171 Some predicates are flagged as special. validate_pattern will not
172 warn about modeless match_operand expressions if they have a
173 special predicate. Predicates that allow only constants are also
174 treated as special, for this purpose.
175
176 validate_pattern will warn about predicates that allow non-lvalues
177 when they appear in destination operands.
178
179 Calculating the set of rtx codes that can possibly be accepted by a
180 predicate expression EXP requires a three-state logic: any given
181 subexpression may definitively accept a code C (Y), definitively
182 reject a code C (N), or may have an indeterminate effect (I). N
183 and I is N; Y or I is Y; Y and I, N or I are both I. Here are full
184 truth tables.
185
186 a b a&b a|b
187 Y Y Y Y
188 N Y N Y
189 N N N N
190 I Y I Y
191 I N N I
192 I I I I
193
194 We represent Y with 1, N with 0, I with 2. If any code is left in
195 an I state by the complete expression, we must assume that that
196 code can be accepted. */
197
198#define N 0
199#define Y 1
200#define I 2
201
202#define TRISTATE_AND(a,b) \
203 ((a) == I ? ((b) == N ? N : I) : \
204 (b) == I ? ((a) == N ? N : I) : \
205 (a) && (b))
206
207#define TRISTATE_OR(a,b) \
208 ((a) == I ? ((b) == Y ? Y : I) : \
209 (b) == I ? ((a) == Y ? Y : I) : \
210 (a) || (b))
211
212#define TRISTATE_NOT(a) \
213 ((a) == I ? I : !(a))
214
215/* 0 means no warning about that code yet, 1 means warned. */
216static char did_you_mean_codes[NUM_RTX_CODE];
217
218/* Recursively calculate the set of rtx codes accepted by the
c9f84f2e
RS
219 predicate expression EXP, writing the result to CODES. LOC is
220 the .md file location of the directive containing EXP. */
77059241 221
851ee5f4 222void
c9f84f2e 223compute_test_codes (rtx exp, file_location loc, char *codes)
77059241
RS
224{
225 char op0_codes[NUM_RTX_CODE];
226 char op1_codes[NUM_RTX_CODE];
227 char op2_codes[NUM_RTX_CODE];
228 int i;
229
230 switch (GET_CODE (exp))
231 {
232 case AND:
c9f84f2e
RS
233 compute_test_codes (XEXP (exp, 0), loc, op0_codes);
234 compute_test_codes (XEXP (exp, 1), loc, op1_codes);
77059241
RS
235 for (i = 0; i < NUM_RTX_CODE; i++)
236 codes[i] = TRISTATE_AND (op0_codes[i], op1_codes[i]);
237 break;
238
239 case IOR:
c9f84f2e
RS
240 compute_test_codes (XEXP (exp, 0), loc, op0_codes);
241 compute_test_codes (XEXP (exp, 1), loc, op1_codes);
77059241
RS
242 for (i = 0; i < NUM_RTX_CODE; i++)
243 codes[i] = TRISTATE_OR (op0_codes[i], op1_codes[i]);
244 break;
245 case NOT:
c9f84f2e 246 compute_test_codes (XEXP (exp, 0), loc, op0_codes);
77059241
RS
247 for (i = 0; i < NUM_RTX_CODE; i++)
248 codes[i] = TRISTATE_NOT (op0_codes[i]);
249 break;
250
251 case IF_THEN_ELSE:
252 /* a ? b : c accepts the same codes as (a & b) | (!a & c). */
c9f84f2e
RS
253 compute_test_codes (XEXP (exp, 0), loc, op0_codes);
254 compute_test_codes (XEXP (exp, 1), loc, op1_codes);
255 compute_test_codes (XEXP (exp, 2), loc, op2_codes);
77059241
RS
256 for (i = 0; i < NUM_RTX_CODE; i++)
257 codes[i] = TRISTATE_OR (TRISTATE_AND (op0_codes[i], op1_codes[i]),
258 TRISTATE_AND (TRISTATE_NOT (op0_codes[i]),
259 op2_codes[i]));
260 break;
261
262 case MATCH_CODE:
263 /* MATCH_CODE allows a specified list of codes. However, if it
264 does not apply to the top level of the expression, it does not
265 constrain the set of codes for the top level. */
266 if (XSTR (exp, 1)[0] != '\0')
267 {
268 memset (codes, Y, NUM_RTX_CODE);
269 break;
270 }
271
272 memset (codes, N, NUM_RTX_CODE);
273 {
274 const char *next_code = XSTR (exp, 0);
275 const char *code;
276
277 if (*next_code == '\0')
278 {
c9f84f2e 279 error_at (loc, "empty match_code expression");
77059241
RS
280 break;
281 }
282
283 while ((code = scan_comma_elt (&next_code)) != 0)
284 {
285 size_t n = next_code - code;
286 int found_it = 0;
287
288 for (i = 0; i < NUM_RTX_CODE; i++)
289 if (!strncmp (code, GET_RTX_NAME (i), n)
290 && GET_RTX_NAME (i)[n] == '\0')
291 {
292 codes[i] = Y;
293 found_it = 1;
294 break;
295 }
296 if (!found_it)
297 {
c9f84f2e
RS
298 error_at (loc, "match_code \"%.*s\" matches nothing",
299 (int) n, code);
77059241
RS
300 for (i = 0; i < NUM_RTX_CODE; i++)
301 if (!strncasecmp (code, GET_RTX_NAME (i), n)
302 && GET_RTX_NAME (i)[n] == '\0'
303 && !did_you_mean_codes[i])
304 {
305 did_you_mean_codes[i] = 1;
c9f84f2e
RS
306 message_at (loc, "(did you mean \"%s\"?)",
307 GET_RTX_NAME (i));
77059241
RS
308 }
309 }
310 }
311 }
312 break;
313
314 case MATCH_OPERAND:
315 /* MATCH_OPERAND disallows the set of codes that the named predicate
316 disallows, and is indeterminate for the codes that it does allow. */
317 {
318 struct pred_data *p = lookup_predicate (XSTR (exp, 1));
319 if (!p)
320 {
c9f84f2e
RS
321 error_at (loc, "reference to unknown predicate '%s'",
322 XSTR (exp, 1));
77059241
RS
323 break;
324 }
325 for (i = 0; i < NUM_RTX_CODE; i++)
326 codes[i] = p->codes[i] ? I : N;
327 }
328 break;
329
330
331 case MATCH_TEST:
332 /* (match_test WHATEVER) is completely indeterminate. */
333 memset (codes, I, NUM_RTX_CODE);
334 break;
335
336 default:
c9f84f2e
RS
337 error_at (loc, "'%s' cannot be used in predicates or constraints",
338 GET_RTX_NAME (GET_CODE (exp)));
77059241
RS
339 memset (codes, I, NUM_RTX_CODE);
340 break;
341 }
342}
343
344#undef TRISTATE_OR
345#undef TRISTATE_AND
346#undef TRISTATE_NOT
347
348/* Return true if NAME is a valid predicate name. */
349
350static bool
351valid_predicate_name_p (const char *name)
352{
353 const char *p;
354
355 if (!ISALPHA (name[0]) && name[0] != '_')
356 return false;
357 for (p = name + 1; *p; p++)
358 if (!ISALNUM (*p) && *p != '_')
359 return false;
360 return true;
361}
362
cc472607
RS
363/* Process define_predicate directive DESC, which appears at location LOC.
364 Compute the set of codes that can be matched, and record this as a known
365 predicate. */
77059241
RS
366
367static void
cc472607 368process_define_predicate (rtx desc, file_location loc)
77059241
RS
369{
370 struct pred_data *pred;
371 char codes[NUM_RTX_CODE];
372 int i;
373
374 if (!valid_predicate_name_p (XSTR (desc, 0)))
375 {
cc472607
RS
376 error_at (loc, "%s: predicate name must be a valid C function name",
377 XSTR (desc, 0));
77059241
RS
378 return;
379 }
380
381 pred = XCNEW (struct pred_data);
382 pred->name = XSTR (desc, 0);
383 pred->exp = XEXP (desc, 1);
384 pred->c_block = XSTR (desc, 2);
385 if (GET_CODE (desc) == DEFINE_SPECIAL_PREDICATE)
386 pred->special = true;
387
c9f84f2e 388 compute_test_codes (XEXP (desc, 1), loc, codes);
77059241
RS
389
390 for (i = 0; i < NUM_RTX_CODE; i++)
391 if (codes[i] != N)
392 add_predicate_code (pred, (enum rtx_code) i);
393
394 add_predicate (pred);
395}
396#undef I
397#undef N
398#undef Y
399\f
a406f566
MM
400/* Queue PATTERN on LIST_TAIL. Return the address of the new queue
401 element. */
3262c1f5 402
99b1c316
MS
403static class queue_elem *
404queue_pattern (rtx pattern, class queue_elem ***list_tail,
cc472607 405 file_location loc)
3262c1f5 406{
99b1c316 407 class queue_elem *e = XNEW (class queue_elem);
3262c1f5 408 e->data = pattern;
cc472607 409 e->loc = loc;
3262c1f5 410 e->next = NULL;
a406f566 411 e->split = NULL;
3262c1f5
RH
412 **list_tail = e;
413 *list_tail = &e->next;
a406f566 414 return e;
3262c1f5
RH
415}
416
477c104e
MK
417/* Remove element ELEM from QUEUE. */
418static void
99b1c316 419remove_from_queue (class queue_elem *elem, class queue_elem **queue)
477c104e 420{
99b1c316 421 class queue_elem *prev, *e;
477c104e
MK
422 prev = NULL;
423 for (e = *queue; e ; e = e->next)
424 {
425 if (e == elem)
426 break;
427 prev = e;
428 }
429 if (e == NULL)
430 return;
431
432 if (prev)
433 prev->next = elem->next;
434 else
435 *queue = elem->next;
436}
437
0bddee8e
BS
438/* Build a define_attr for an binary attribute with name NAME and
439 possible values "yes" and "no", and queue it. */
440static void
441add_define_attr (const char *name)
442{
99b1c316 443 class queue_elem *e = XNEW (class queue_elem);
0bddee8e
BS
444 rtx t1 = rtx_alloc (DEFINE_ATTR);
445 XSTR (t1, 0) = name;
446 XSTR (t1, 1) = "no,yes";
447 XEXP (t1, 2) = rtx_alloc (CONST_STRING);
448 XSTR (XEXP (t1, 2), 0) = "yes";
449 e->data = t1;
3814e880 450 e->loc = file_location ("built-in", -1, -1);
0bddee8e
BS
451 e->next = define_attr_queue;
452 define_attr_queue = e;
453
454}
455
c88c0d42
CP
456/* Recursively remove constraints from an rtx. */
457
458static void
3d7aafde 459remove_constraints (rtx part)
c88c0d42 460{
b3694847
SS
461 int i, j;
462 const char *format_ptr;
c88c0d42
CP
463
464 if (part == 0)
465 return;
466
467 if (GET_CODE (part) == MATCH_OPERAND)
468 XSTR (part, 2) = "";
469 else if (GET_CODE (part) == MATCH_SCRATCH)
470 XSTR (part, 1) = "";
471
472 format_ptr = GET_RTX_FORMAT (GET_CODE (part));
473
474 for (i = 0; i < GET_RTX_LENGTH (GET_CODE (part)); i++)
475 switch (*format_ptr++)
476 {
477 case 'e':
478 case 'u':
479 remove_constraints (XEXP (part, i));
480 break;
481 case 'E':
482 if (XVEC (part, i) != NULL)
483 for (j = 0; j < XVECLEN (part, i); j++)
484 remove_constraints (XVECEXP (part, i, j));
485 break;
486 }
487}
488
f4fde1b3
RS
489/* Recursively replace MATCH_OPERANDs with MATCH_DUPs and MATCH_OPERATORs
490 with MATCH_OP_DUPs in X. */
491
492static rtx
493replace_operands_with_dups (rtx x)
494{
495 if (x == 0)
496 return x;
497
498 rtx newx;
499 if (GET_CODE (x) == MATCH_OPERAND)
500 {
501 newx = rtx_alloc (MATCH_DUP);
502 XINT (newx, 0) = XINT (x, 0);
d281492d 503 x = newx;
f4fde1b3
RS
504 }
505 else if (GET_CODE (x) == MATCH_OPERATOR)
506 {
507 newx = rtx_alloc (MATCH_OP_DUP);
508 XINT (newx, 0) = XINT (x, 0);
509 XVEC (newx, 1) = XVEC (x, 2);
d281492d 510 x = newx;
f4fde1b3
RS
511 }
512 else
513 newx = shallow_copy_rtx (x);
514
515 const char *format_ptr = GET_RTX_FORMAT (GET_CODE (x));
516 for (int i = 0; i < GET_RTX_LENGTH (GET_CODE (x)); i++)
517 switch (*format_ptr++)
518 {
519 case 'e':
520 case 'u':
521 XEXP (newx, i) = replace_operands_with_dups (XEXP (x, i));
522 break;
523 case 'E':
524 if (XVEC (x, i) != NULL)
525 {
526 XVEC (newx, i) = rtvec_alloc (XVECLEN (x, i));
527 for (int j = 0; j < XVECLEN (x, i); j++)
528 XVECEXP (newx, i, j)
529 = replace_operands_with_dups (XVECEXP (x, i, j));
530 }
531 break;
532 }
533 return newx;
534}
535
536/* Convert matching pattern VEC from a DEFINE_INSN_AND_REWRITE into
537 a sequence that should be generated by the splitter. */
538
539static rtvec
540gen_rewrite_sequence (rtvec vec)
541{
542 rtvec new_vec = rtvec_alloc (1);
543 rtx x = add_implicit_parallel (vec);
544 RTVEC_ELT (new_vec, 0) = replace_operands_with_dups (x);
545 return new_vec;
546}
547
d91edf86 548/* Process a top level rtx in some way, queuing as appropriate. */
c88c0d42
CP
549
550static void
cc472607 551process_rtx (rtx desc, file_location loc)
3262c1f5
RH
552{
553 switch (GET_CODE (desc))
554 {
555 case DEFINE_INSN:
cc472607 556 queue_pattern (desc, &define_insn_tail, loc);
3262c1f5
RH
557 break;
558
559 case DEFINE_COND_EXEC:
cc472607 560 queue_pattern (desc, &define_cond_exec_tail, loc);
3262c1f5
RH
561 break;
562
477c104e 563 case DEFINE_SUBST:
cc472607 564 queue_pattern (desc, &define_subst_tail, loc);
477c104e
MK
565 break;
566
567 case DEFINE_SUBST_ATTR:
cc472607 568 queue_pattern (desc, &define_subst_attr_tail, loc);
477c104e
MK
569 break;
570
3262c1f5 571 case DEFINE_ATTR:
8f4fe86c 572 case DEFINE_ENUM_ATTR:
cc472607 573 queue_pattern (desc, &define_attr_tail, loc);
3262c1f5
RH
574 break;
575
e543e219
ZW
576 case DEFINE_PREDICATE:
577 case DEFINE_SPECIAL_PREDICATE:
cc472607 578 process_define_predicate (desc, loc);
77059241
RS
579 /* Fall through. */
580
f38840db
ZW
581 case DEFINE_CONSTRAINT:
582 case DEFINE_REGISTER_CONSTRAINT:
583 case DEFINE_MEMORY_CONSTRAINT:
9eb1ca69 584 case DEFINE_SPECIAL_MEMORY_CONSTRAINT:
f38840db 585 case DEFINE_ADDRESS_CONSTRAINT:
cc472607 586 queue_pattern (desc, &define_pred_tail, loc);
e543e219
ZW
587 break;
588
3262c1f5 589 case DEFINE_INSN_AND_SPLIT:
f4fde1b3 590 case DEFINE_INSN_AND_REWRITE:
3262c1f5
RH
591 {
592 const char *split_cond;
20217ac1
KG
593 rtx split;
594 rtvec attr;
de4bfbcb 595 int i;
99b1c316
MS
596 class queue_elem *insn_elem;
597 class queue_elem *split_elem;
f4fde1b3 598 int split_code = (GET_CODE (desc) == DEFINE_INSN_AND_REWRITE ? 5 : 6);
3262c1f5 599
dc297297 600 /* Create a split with values from the insn_and_split. */
3262c1f5 601 split = rtx_alloc (DEFINE_SPLIT);
de4bfbcb
RH
602
603 i = XVECLEN (desc, 1);
fbd40359 604 XVEC (split, 0) = rtvec_alloc (i);
de4bfbcb
RH
605 while (--i >= 0)
606 {
607 XVECEXP (split, 0, i) = copy_rtx (XVECEXP (desc, 1, i));
608 remove_constraints (XVECEXP (split, 0, i));
609 }
3262c1f5
RH
610
611 /* If the split condition starts with "&&", append it to the
612 insn condition to create the new split condition. */
613 split_cond = XSTR (desc, 4);
614 if (split_cond[0] == '&' && split_cond[1] == '&')
7445392c 615 {
b78027d1
DM
616 rtx_reader_ptr->copy_md_ptr_loc (split_cond + 2, split_cond);
617 split_cond = rtx_reader_ptr->join_c_conditions (XSTR (desc, 2),
618 split_cond + 2);
7445392c 619 }
f4fde1b3
RS
620 else if (GET_CODE (desc) == DEFINE_INSN_AND_REWRITE)
621 error_at (loc, "the rewrite condition must start with `&&'");
3262c1f5 622 XSTR (split, 1) = split_cond;
f4fde1b3
RS
623 if (GET_CODE (desc) == DEFINE_INSN_AND_REWRITE)
624 XVEC (split, 2) = gen_rewrite_sequence (XVEC (desc, 1));
625 else
626 XVEC (split, 2) = XVEC (desc, 5);
627 XSTR (split, 3) = XSTR (desc, split_code);
3262c1f5
RH
628
629 /* Fix up the DEFINE_INSN. */
f4fde1b3 630 attr = XVEC (desc, split_code + 1);
3262c1f5 631 PUT_CODE (desc, DEFINE_INSN);
ee138cf8 632 XVEC (desc, 4) = attr;
3262c1f5
RH
633
634 /* Queue them. */
cc472607
RS
635 insn_elem = queue_pattern (desc, &define_insn_tail, loc);
636 split_elem = queue_pattern (split, &other_tail, loc);
a406f566 637 insn_elem->split = split_elem;
3262c1f5
RH
638 break;
639 }
640
641 default:
cc472607 642 queue_pattern (desc, &other_tail, loc);
3262c1f5 643 break;
c88c0d42
CP
644 }
645}
3916d6d8 646\f
3262c1f5
RH
647/* Return true if attribute PREDICABLE is true for ELEM, which holds
648 a DEFINE_INSN. */
649
650static int
99b1c316 651is_predicable (class queue_elem *elem)
3262c1f5
RH
652{
653 rtvec vec = XVEC (elem->data, 4);
654 const char *value;
655 int i;
656
657 if (! vec)
658 return predicable_default;
659
660 for (i = GET_NUM_ELEM (vec) - 1; i >= 0; --i)
661 {
662 rtx sub = RTVEC_ELT (vec, i);
663 switch (GET_CODE (sub))
664 {
665 case SET_ATTR:
666 if (strcmp (XSTR (sub, 0), "predicable") == 0)
667 {
668 value = XSTR (sub, 1);
669 goto found;
670 }
671 break;
672
673 case SET_ATTR_ALTERNATIVE:
674 if (strcmp (XSTR (sub, 0), "predicable") == 0)
675 {
cc472607 676 error_at (elem->loc, "multiple alternatives for `predicable'");
3262c1f5
RH
677 return 0;
678 }
679 break;
680
681 case SET:
682 if (GET_CODE (SET_DEST (sub)) != ATTR
683 || strcmp (XSTR (SET_DEST (sub), 0), "predicable") != 0)
684 break;
685 sub = SET_SRC (sub);
686 if (GET_CODE (sub) == CONST_STRING)
687 {
688 value = XSTR (sub, 0);
689 goto found;
690 }
691
692 /* ??? It would be possible to handle this if we really tried.
693 It's not easy though, and I'm not going to bother until it
694 really proves necessary. */
cc472607 695 error_at (elem->loc, "non-constant value for `predicable'");
3262c1f5
RH
696 return 0;
697
698 default:
b2d59f6f 699 gcc_unreachable ();
3262c1f5
RH
700 }
701 }
702
703 return predicable_default;
704
705 found:
0bddee8e
BS
706 /* Find out which value we're looking at. Multiple alternatives means at
707 least one is predicable. */
3262c1f5 708 if (strchr (value, ',') != NULL)
0bddee8e 709 return 1;
3262c1f5
RH
710 if (strcmp (value, predicable_true) == 0)
711 return 1;
712 if (strcmp (value, predicable_false) == 0)
713 return 0;
714
cc472607 715 error_at (elem->loc, "unknown value `%s' for `predicable' attribute", value);
3262c1f5
RH
716 return 0;
717}
718
477c104e
MK
719/* Find attribute SUBST in ELEM and assign NEW_VALUE to it. */
720static void
99b1c316
MS
721change_subst_attribute (class queue_elem *elem,
722 class queue_elem *subst_elem,
477c104e
MK
723 const char *new_value)
724{
725 rtvec attrs_vec = XVEC (elem->data, 4);
726 const char *subst_name = XSTR (subst_elem->data, 0);
727 int i;
728
729 if (! attrs_vec)
730 return;
731
732 for (i = GET_NUM_ELEM (attrs_vec) - 1; i >= 0; --i)
733 {
734 rtx cur_attr = RTVEC_ELT (attrs_vec, i);
735 if (GET_CODE (cur_attr) != SET_ATTR)
736 continue;
737 if (strcmp (XSTR (cur_attr, 0), subst_name) == 0)
738 {
739 XSTR (cur_attr, 1) = new_value;
740 return;
741 }
742 }
743}
744
745/* Return true if ELEM has the attribute with the name of DEFINE_SUBST
746 represented by SUBST_ELEM and this attribute has value SUBST_TRUE.
747 DEFINE_SUBST isn't applied to patterns without such attribute. In other
748 words, we suppose the default value of the attribute to be 'no' since it is
5764ee3c 749 always generated automatically in read-rtl.c. */
477c104e 750static bool
99b1c316 751has_subst_attribute (class queue_elem *elem, class queue_elem *subst_elem)
477c104e
MK
752{
753 rtvec attrs_vec = XVEC (elem->data, 4);
754 const char *value, *subst_name = XSTR (subst_elem->data, 0);
755 int i;
756
757 if (! attrs_vec)
758 return false;
759
760 for (i = GET_NUM_ELEM (attrs_vec) - 1; i >= 0; --i)
761 {
762 rtx cur_attr = RTVEC_ELT (attrs_vec, i);
763 switch (GET_CODE (cur_attr))
764 {
765 case SET_ATTR:
766 if (strcmp (XSTR (cur_attr, 0), subst_name) == 0)
767 {
768 value = XSTR (cur_attr, 1);
769 goto found;
770 }
771 break;
772
773 case SET:
774 if (GET_CODE (SET_DEST (cur_attr)) != ATTR
775 || strcmp (XSTR (SET_DEST (cur_attr), 0), subst_name) != 0)
776 break;
777 cur_attr = SET_SRC (cur_attr);
778 if (GET_CODE (cur_attr) == CONST_STRING)
779 {
780 value = XSTR (cur_attr, 0);
781 goto found;
782 }
783
784 /* Only (set_attr "subst" "yes/no") and
785 (set (attr "subst" (const_string "yes/no")))
786 are currently allowed. */
cc472607 787 error_at (elem->loc, "unsupported value for `%s'", subst_name);
477c104e
MK
788 return false;
789
790 case SET_ATTR_ALTERNATIVE:
12f78d8b
KT
791 if (strcmp (XSTR (cur_attr, 0), subst_name) == 0)
792 error_at (elem->loc,
793 "%s: `set_attr_alternative' is unsupported by "
794 "`define_subst'", XSTR (elem->data, 0));
477c104e
MK
795 return false;
796
797
798 default:
799 gcc_unreachable ();
800 }
801 }
802
803 return false;
804
805 found:
806 if (strcmp (value, subst_true) == 0)
807 return true;
808 if (strcmp (value, subst_false) == 0)
809 return false;
810
cc472607
RS
811 error_at (elem->loc, "unknown value `%s' for `%s' attribute",
812 value, subst_name);
477c104e
MK
813 return false;
814}
815
816/* Compare RTL-template of original define_insn X to input RTL-template of
817 define_subst PT. Return 1 if the templates match, 0 otherwise.
818 During the comparison, the routine also fills global_array OPERAND_DATA. */
819static bool
cc472607 820subst_pattern_match (rtx x, rtx pt, file_location loc)
477c104e
MK
821{
822 RTX_CODE code, code_pt;
823 int i, j, len;
824 const char *fmt, *pred_name;
825
826 code = GET_CODE (x);
827 code_pt = GET_CODE (pt);
828
829 if (code_pt == MATCH_OPERAND)
830 {
831 /* MATCH_DUP, and MATCH_OP_DUP don't have a specified mode, so we
832 always accept them. */
833 if (GET_MODE (pt) != VOIDmode && GET_MODE (x) != GET_MODE (pt)
834 && (code != MATCH_DUP && code != MATCH_OP_DUP))
835 return false; /* Modes don't match. */
836
837 if (code == MATCH_OPERAND)
838 {
839 pred_name = XSTR (pt, 1);
840 if (pred_name[0] != 0)
841 {
842 const struct pred_data *pred_pt = lookup_predicate (pred_name);
843 if (!pred_pt || pred_pt != lookup_predicate (XSTR (x, 1)))
844 return false; /* Predicates don't match. */
845 }
846 }
847
848 gcc_assert (XINT (pt, 0) >= 0 && XINT (pt, 0) < MAX_OPERANDS);
849 operand_data[XINT (pt, 0)] = x;
850 return true;
851 }
852
853 if (code_pt == MATCH_OPERATOR)
854 {
855 int x_vecexp_pos = -1;
856
857 /* Compare modes. */
858 if (GET_MODE (pt) != VOIDmode && GET_MODE (x) != GET_MODE (pt))
859 return false;
860
861 /* In case X is also match_operator, compare predicates. */
862 if (code == MATCH_OPERATOR)
863 {
864 pred_name = XSTR (pt, 1);
865 if (pred_name[0] != 0)
866 {
867 const struct pred_data *pred_pt = lookup_predicate (pred_name);
868 if (!pred_pt || pred_pt != lookup_predicate (XSTR (x, 1)))
869 return false;
870 }
871 }
872
873 /* Compare operands.
874 MATCH_OPERATOR in input template could match in original template
875 either 1) MATCH_OPERAND, 2) UNSPEC, 3) ordinary operation (like PLUS).
876 In the first case operands are at (XVECEXP (x, 2, j)), in the second
877 - at (XVECEXP (x, 0, j)), in the last one - (XEXP (x, j)).
878 X_VECEXP_POS variable shows, where to look for these operands. */
879 if (code == UNSPEC
880 || code == UNSPEC_VOLATILE)
881 x_vecexp_pos = 0;
882 else if (code == MATCH_OPERATOR)
883 x_vecexp_pos = 2;
884 else
885 x_vecexp_pos = -1;
886
887 /* MATCH_OPERATOR or UNSPEC case. */
888 if (x_vecexp_pos >= 0)
889 {
890 /* Compare operands number in X and PT. */
891 if (XVECLEN (x, x_vecexp_pos) != XVECLEN (pt, 2))
892 return false;
893 for (j = 0; j < XVECLEN (pt, 2); j++)
894 if (!subst_pattern_match (XVECEXP (x, x_vecexp_pos, j),
cc472607 895 XVECEXP (pt, 2, j), loc))
477c104e
MK
896 return false;
897 }
898
899 /* Ordinary operator. */
900 else
901 {
902 /* Compare operands number in X and PT.
903 We count operands differently for X and PT since we compare
904 an operator (with operands directly in RTX) and MATCH_OPERATOR
905 (that has a vector with operands). */
906 if (GET_RTX_LENGTH (code) != XVECLEN (pt, 2))
907 return false;
908 for (j = 0; j < XVECLEN (pt, 2); j++)
cc472607 909 if (!subst_pattern_match (XEXP (x, j), XVECEXP (pt, 2, j), loc))
477c104e
MK
910 return false;
911 }
912
913 /* Store the operand to OPERAND_DATA array. */
914 gcc_assert (XINT (pt, 0) >= 0 && XINT (pt, 0) < MAX_OPERANDS);
915 operand_data[XINT (pt, 0)] = x;
916 return true;
917 }
918
919 if (code_pt == MATCH_PAR_DUP
920 || code_pt == MATCH_DUP
921 || code_pt == MATCH_OP_DUP
922 || code_pt == MATCH_SCRATCH
923 || code_pt == MATCH_PARALLEL)
924 {
925 /* Currently interface for these constructions isn't defined -
926 probably they aren't needed in input template of define_subst at all.
927 So, for now their usage in define_subst is forbidden. */
cc472607
RS
928 error_at (loc, "%s cannot be used in define_subst",
929 GET_RTX_NAME (code_pt));
477c104e
MK
930 }
931
932 gcc_assert (code != MATCH_PAR_DUP
933 && code_pt != MATCH_DUP
934 && code_pt != MATCH_OP_DUP
935 && code_pt != MATCH_SCRATCH
936 && code_pt != MATCH_PARALLEL
937 && code_pt != MATCH_OPERAND
938 && code_pt != MATCH_OPERATOR);
939 /* If PT is none of the handled above, then we match only expressions with
940 the same code in X. */
941 if (code != code_pt)
942 return false;
943
944 fmt = GET_RTX_FORMAT (code_pt);
945 len = GET_RTX_LENGTH (code_pt);
946
947 for (i = 0; i < len; i++)
948 {
949 if (fmt[i] == '0')
950 break;
951
952 switch (fmt[i])
953 {
91914e56 954 case 'r': case 'p': case 'i': case 'w': case 's':
477c104e
MK
955 continue;
956
957 case 'e': case 'u':
cc472607 958 if (!subst_pattern_match (XEXP (x, i), XEXP (pt, i), loc))
477c104e
MK
959 return false;
960 break;
961 case 'E':
962 {
963 if (XVECLEN (x, i) != XVECLEN (pt, i))
964 return false;
965 for (j = 0; j < XVECLEN (pt, i); j++)
cc472607
RS
966 if (!subst_pattern_match (XVECEXP (x, i, j),
967 XVECEXP (pt, i, j), loc))
477c104e
MK
968 return false;
969 break;
970 }
971 default:
972 gcc_unreachable ();
973 }
974 }
975
976 return true;
977}
978
3262c1f5
RH
979/* Examine the attribute "predicable"; discover its boolean values
980 and its default. */
981
982static void
3d7aafde 983identify_predicable_attribute (void)
3262c1f5 984{
99b1c316 985 class queue_elem *elem;
d6edb99e 986 char *p_true, *p_false;
3262c1f5 987 const char *value;
3262c1f5
RH
988
989 /* Look for the DEFINE_ATTR for `predicable', which must exist. */
990 for (elem = define_attr_queue; elem ; elem = elem->next)
991 if (strcmp (XSTR (elem->data, 0), "predicable") == 0)
992 goto found;
993
cc472607
RS
994 error_at (define_cond_exec_queue->loc,
995 "attribute `predicable' not defined");
3262c1f5
RH
996 return;
997
998 found:
999 value = XSTR (elem->data, 1);
1dcd444b 1000 p_false = xstrdup (value);
d6edb99e
ZW
1001 p_true = strchr (p_false, ',');
1002 if (p_true == NULL || strchr (++p_true, ',') != NULL)
3262c1f5 1003 {
cc472607 1004 error_at (elem->loc, "attribute `predicable' is not a boolean");
04695783 1005 free (p_false);
3262c1f5
RH
1006 return;
1007 }
d6edb99e 1008 p_true[-1] = '\0';
3262c1f5 1009
d6edb99e
ZW
1010 predicable_true = p_true;
1011 predicable_false = p_false;
3262c1f5
RH
1012
1013 switch (GET_CODE (XEXP (elem->data, 2)))
1014 {
1015 case CONST_STRING:
1016 value = XSTR (XEXP (elem->data, 2), 0);
1017 break;
1018
1019 case CONST:
cc472607 1020 error_at (elem->loc, "attribute `predicable' cannot be const");
04695783 1021 free (p_false);
3262c1f5
RH
1022 return;
1023
1024 default:
cc472607
RS
1025 error_at (elem->loc,
1026 "attribute `predicable' must have a constant default");
04695783 1027 free (p_false);
3262c1f5
RH
1028 return;
1029 }
1030
d6edb99e 1031 if (strcmp (value, p_true) == 0)
3262c1f5 1032 predicable_default = 1;
d6edb99e 1033 else if (strcmp (value, p_false) == 0)
3262c1f5
RH
1034 predicable_default = 0;
1035 else
1036 {
cc472607
RS
1037 error_at (elem->loc, "unknown value `%s' for `predicable' attribute",
1038 value);
04695783 1039 free (p_false);
3262c1f5
RH
1040 }
1041}
1042
1043/* Return the number of alternatives in constraint S. */
1044
1045static int
3d7aafde 1046n_alternatives (const char *s)
3262c1f5
RH
1047{
1048 int n = 1;
1049
1050 if (s)
1051 while (*s)
1052 n += (*s++ == ',');
1053
1054 return n;
1055}
1056
477c104e
MK
1057/* The routine scans rtl PATTERN, find match_operand in it and counts
1058 number of alternatives. If PATTERN contains several match_operands
1059 with different number of alternatives, error is emitted, and the
1060 routine returns 0. If all match_operands in PATTERN have the same
1061 number of alternatives, it's stored in N_ALT, and the routine returns 1.
cc472607 1062 LOC is the location of PATTERN, for error reporting. */
477c104e 1063static int
cc472607 1064get_alternatives_number (rtx pattern, int *n_alt, file_location loc)
477c104e
MK
1065{
1066 const char *fmt;
1067 enum rtx_code code;
1068 int i, j, len;
1069
1070 if (!n_alt)
1071 return 0;
1072
1073 code = GET_CODE (pattern);
1074 switch (code)
1075 {
1076 case MATCH_OPERAND:
1077 i = n_alternatives (XSTR (pattern, 2));
1078 /* n_alternatives returns 1 if constraint string is empty -
1079 here we fix it up. */
1080 if (!*(XSTR (pattern, 2)))
1081 i = 0;
1082 if (*n_alt <= 0)
1083 *n_alt = i;
1084
1085 else if (i && i != *n_alt)
1086 {
cc472607
RS
1087 error_at (loc, "wrong number of alternatives in operand %d",
1088 XINT (pattern, 0));
477c104e
MK
1089 return 0;
1090 }
1091
1092 default:
1093 break;
1094 }
1095
1096 fmt = GET_RTX_FORMAT (code);
1097 len = GET_RTX_LENGTH (code);
1098 for (i = 0; i < len; i++)
1099 {
1100 switch (fmt[i])
1101 {
1102 case 'e': case 'u':
cc472607
RS
1103 if (!get_alternatives_number (XEXP (pattern, i), n_alt, loc))
1104 return 0;
477c104e
MK
1105 break;
1106
1107 case 'V':
1108 if (XVEC (pattern, i) == NULL)
1109 break;
191816a3 1110 /* FALLTHRU */
477c104e
MK
1111
1112 case 'E':
1113 for (j = XVECLEN (pattern, i) - 1; j >= 0; --j)
cc472607
RS
1114 if (!get_alternatives_number (XVECEXP (pattern, i, j), n_alt, loc))
1115 return 0;
477c104e
MK
1116 break;
1117
91914e56
RS
1118 case 'r': case 'p': case 'i': case 'w':
1119 case '0': case 's': case 'S': case 'T':
477c104e
MK
1120 break;
1121
1122 default:
1123 gcc_unreachable ();
1124 }
1125 }
1126 return 1;
1127}
1128
3262c1f5
RH
1129/* Determine how many alternatives there are in INSN, and how many
1130 operands. */
1131
1132static void
3d7aafde 1133collect_insn_data (rtx pattern, int *palt, int *pmax)
3262c1f5
RH
1134{
1135 const char *fmt;
1136 enum rtx_code code;
1137 int i, j, len;
1138
1139 code = GET_CODE (pattern);
1140 switch (code)
1141 {
1142 case MATCH_OPERAND:
b7e2dd6f
BS
1143 case MATCH_SCRATCH:
1144 i = n_alternatives (XSTR (pattern, code == MATCH_SCRATCH ? 1 : 2));
892ecf92 1145 *palt = (i > *palt ? i : *palt);
5d3cc252 1146 /* Fall through. */
3262c1f5
RH
1147
1148 case MATCH_OPERATOR:
3262c1f5 1149 case MATCH_PARALLEL:
3262c1f5
RH
1150 i = XINT (pattern, 0);
1151 if (i > *pmax)
1152 *pmax = i;
1153 break;
1154
1155 default:
1156 break;
1157 }
1158
1159 fmt = GET_RTX_FORMAT (code);
1160 len = GET_RTX_LENGTH (code);
1161 for (i = 0; i < len; i++)
1162 {
1163 switch (fmt[i])
1164 {
1165 case 'e': case 'u':
1166 collect_insn_data (XEXP (pattern, i), palt, pmax);
1167 break;
1168
1169 case 'V':
1170 if (XVEC (pattern, i) == NULL)
1171 break;
5d3cc252 1172 /* Fall through. */
3262c1f5
RH
1173 case 'E':
1174 for (j = XVECLEN (pattern, i) - 1; j >= 0; --j)
1175 collect_insn_data (XVECEXP (pattern, i, j), palt, pmax);
1176 break;
1177
91914e56
RS
1178 case 'r': case 'p': case 'i': case 'w':
1179 case '0': case 's': case 'S': case 'T':
3262c1f5
RH
1180 break;
1181
1182 default:
b2d59f6f 1183 gcc_unreachable ();
3262c1f5
RH
1184 }
1185 }
1186}
1187
1188static rtx
cc472607
RS
1189alter_predicate_for_insn (rtx pattern, int alt, int max_op,
1190 file_location loc)
3262c1f5
RH
1191{
1192 const char *fmt;
1193 enum rtx_code code;
1194 int i, j, len;
1195
1196 code = GET_CODE (pattern);
1197 switch (code)
1198 {
1199 case MATCH_OPERAND:
1200 {
1201 const char *c = XSTR (pattern, 2);
1202
1203 if (n_alternatives (c) != 1)
1204 {
cc472607
RS
1205 error_at (loc, "too many alternatives for operand %d",
1206 XINT (pattern, 0));
3262c1f5
RH
1207 return NULL;
1208 }
1209
1210 /* Replicate C as needed to fill out ALT alternatives. */
1211 if (c && *c && alt > 1)
1212 {
1213 size_t c_len = strlen (c);
1214 size_t len = alt * (c_len + 1);
477c104e 1215 char *new_c = XNEWVEC (char, len);
3262c1f5
RH
1216
1217 memcpy (new_c, c, c_len);
1218 for (i = 1; i < alt; ++i)
1219 {
1220 new_c[i * (c_len + 1) - 1] = ',';
1221 memcpy (&new_c[i * (c_len + 1)], c, c_len);
1222 }
1223 new_c[len - 1] = '\0';
1224 XSTR (pattern, 2) = new_c;
1225 }
1226 }
5d3cc252 1227 /* Fall through. */
3262c1f5
RH
1228
1229 case MATCH_OPERATOR:
1230 case MATCH_SCRATCH:
1231 case MATCH_PARALLEL:
3262c1f5
RH
1232 XINT (pattern, 0) += max_op;
1233 break;
1234
1235 default:
1236 break;
1237 }
1238
1239 fmt = GET_RTX_FORMAT (code);
1240 len = GET_RTX_LENGTH (code);
1241 for (i = 0; i < len; i++)
1242 {
1243 rtx r;
1244
1245 switch (fmt[i])
1246 {
1247 case 'e': case 'u':
cc472607 1248 r = alter_predicate_for_insn (XEXP (pattern, i), alt, max_op, loc);
3262c1f5
RH
1249 if (r == NULL)
1250 return r;
1251 break;
1252
1253 case 'E':
1254 for (j = XVECLEN (pattern, i) - 1; j >= 0; --j)
1255 {
1256 r = alter_predicate_for_insn (XVECEXP (pattern, i, j),
cc472607 1257 alt, max_op, loc);
3262c1f5
RH
1258 if (r == NULL)
1259 return r;
1260 }
1261 break;
1262
91914e56 1263 case 'r': case 'p': case 'i': case 'w': case '0': case 's':
3262c1f5
RH
1264 break;
1265
1266 default:
b2d59f6f 1267 gcc_unreachable ();
3262c1f5
RH
1268 }
1269 }
1270
1271 return pattern;
1272}
1273
477c104e
MK
1274/* Duplicate constraints in PATTERN. If pattern is from original
1275 rtl-template, we need to duplicate each alternative - for that we
1276 need to use duplicate_each_alternative () as a functor ALTER.
1277 If pattern is from output-pattern of define_subst, we need to
1278 duplicate constraints in another way - with duplicate_alternatives ().
1279 N_DUP is multiplication factor. */
1280static rtx
1281alter_constraints (rtx pattern, int n_dup, constraints_handler_t alter)
1282{
1283 const char *fmt;
1284 enum rtx_code code;
1285 int i, j, len;
1286
1287 code = GET_CODE (pattern);
1288 switch (code)
1289 {
1290 case MATCH_OPERAND:
1291 XSTR (pattern, 2) = alter (XSTR (pattern, 2), n_dup);
1292 break;
1293
1294 default:
1295 break;
1296 }
1297
1298 fmt = GET_RTX_FORMAT (code);
1299 len = GET_RTX_LENGTH (code);
1300 for (i = 0; i < len; i++)
1301 {
1302 rtx r;
1303
1304 switch (fmt[i])
1305 {
1306 case 'e': case 'u':
1307 r = alter_constraints (XEXP (pattern, i), n_dup, alter);
1308 if (r == NULL)
1309 return r;
1310 break;
1311
1312 case 'E':
1313 for (j = XVECLEN (pattern, i) - 1; j >= 0; --j)
1314 {
1315 r = alter_constraints (XVECEXP (pattern, i, j), n_dup, alter);
1316 if (r == NULL)
1317 return r;
1318 }
1319 break;
1320
91914e56 1321 case 'r': case 'p': case 'i': case 'w': case '0': case 's':
477c104e
MK
1322 break;
1323
1324 default:
1325 break;
1326 }
1327 }
1328
1329 return pattern;
1330}
1331
3262c1f5 1332static const char *
99b1c316
MS
1333alter_test_for_insn (class queue_elem *ce_elem,
1334 class queue_elem *insn_elem)
3262c1f5 1335{
b78027d1
DM
1336 return rtx_reader_ptr->join_c_conditions (XSTR (ce_elem->data, 1),
1337 XSTR (insn_elem->data, 2));
3262c1f5
RH
1338}
1339
0bddee8e
BS
1340/* Modify VAL, which is an attribute expression for the "enabled" attribute,
1341 to take "ce_enabled" into account. Return the new expression. */
1342static rtx
1343modify_attr_enabled_ce (rtx val)
1344{
1345 rtx eq_attr, str;
1346 rtx ite;
1347 eq_attr = rtx_alloc (EQ_ATTR);
1348 ite = rtx_alloc (IF_THEN_ELSE);
1349 str = rtx_alloc (CONST_STRING);
1350
1351 XSTR (eq_attr, 0) = "ce_enabled";
1352 XSTR (eq_attr, 1) = "yes";
1353 XSTR (str, 0) = "no";
1354 XEXP (ite, 0) = eq_attr;
1355 XEXP (ite, 1) = val;
1356 XEXP (ite, 2) = str;
1357
1358 return ite;
1359}
1360
1361/* Alter the attribute vector of INSN, which is a COND_EXEC variant created
1362 from a define_insn pattern. We must modify the "predicable" attribute
1363 to be named "ce_enabled", and also change any "enabled" attribute that's
1364 present so that it takes ce_enabled into account.
1365 We rely on the fact that INSN was created with copy_rtx, and modify data
1366 in-place. */
1367
1368static void
1369alter_attrs_for_insn (rtx insn)
1370{
1371 static bool global_changes_made = false;
1372 rtvec vec = XVEC (insn, 4);
1373 rtvec new_vec;
1374 rtx val, set;
1375 int num_elem;
1376 int predicable_idx = -1;
1377 int enabled_idx = -1;
1378 int i;
1379
1380 if (! vec)
1381 return;
1382
1383 num_elem = GET_NUM_ELEM (vec);
1384 for (i = num_elem - 1; i >= 0; --i)
1385 {
1386 rtx sub = RTVEC_ELT (vec, i);
1387 switch (GET_CODE (sub))
1388 {
1389 case SET_ATTR:
1390 if (strcmp (XSTR (sub, 0), "predicable") == 0)
1391 {
1392 predicable_idx = i;
1393 XSTR (sub, 0) = "ce_enabled";
1394 }
1395 else if (strcmp (XSTR (sub, 0), "enabled") == 0)
1396 {
1397 enabled_idx = i;
1398 XSTR (sub, 0) = "nonce_enabled";
1399 }
1400 break;
1401
1402 case SET_ATTR_ALTERNATIVE:
1403 if (strcmp (XSTR (sub, 0), "predicable") == 0)
1404 /* We already give an error elsewhere. */
1405 return;
1406 else if (strcmp (XSTR (sub, 0), "enabled") == 0)
1407 {
1408 enabled_idx = i;
1409 XSTR (sub, 0) = "nonce_enabled";
1410 }
1411 break;
1412
1413 case SET:
1414 if (GET_CODE (SET_DEST (sub)) != ATTR)
1415 break;
1416 if (strcmp (XSTR (SET_DEST (sub), 0), "predicable") == 0)
1417 {
1418 sub = SET_SRC (sub);
1419 if (GET_CODE (sub) == CONST_STRING)
1420 {
1421 predicable_idx = i;
1422 XSTR (sub, 0) = "ce_enabled";
1423 }
1424 else
1425 /* We already give an error elsewhere. */
1426 return;
1427 break;
1428 }
1429 if (strcmp (XSTR (SET_DEST (sub), 0), "enabled") == 0)
1430 {
1431 enabled_idx = i;
1432 XSTR (SET_DEST (sub), 0) = "nonce_enabled";
1433 }
1434 break;
1435
1436 default:
1437 gcc_unreachable ();
1438 }
1439 }
1440 if (predicable_idx == -1)
1441 return;
1442
1443 if (!global_changes_made)
1444 {
99b1c316 1445 class queue_elem *elem;
477c104e 1446
0bddee8e
BS
1447 global_changes_made = true;
1448 add_define_attr ("ce_enabled");
1449 add_define_attr ("nonce_enabled");
1450
1451 for (elem = define_attr_queue; elem ; elem = elem->next)
1452 if (strcmp (XSTR (elem->data, 0), "enabled") == 0)
1453 {
1454 XEXP (elem->data, 2)
1455 = modify_attr_enabled_ce (XEXP (elem->data, 2));
1456 }
1457 }
1458 if (enabled_idx == -1)
1459 return;
1460
1461 new_vec = rtvec_alloc (num_elem + 1);
1462 for (i = 0; i < num_elem; i++)
1463 RTVEC_ELT (new_vec, i) = RTVEC_ELT (vec, i);
1464 val = rtx_alloc (IF_THEN_ELSE);
1465 XEXP (val, 0) = rtx_alloc (EQ_ATTR);
1466 XEXP (val, 1) = rtx_alloc (CONST_STRING);
1467 XEXP (val, 2) = rtx_alloc (CONST_STRING);
1468 XSTR (XEXP (val, 0), 0) = "nonce_enabled";
1469 XSTR (XEXP (val, 0), 1) = "yes";
1470 XSTR (XEXP (val, 1), 0) = "yes";
1471 XSTR (XEXP (val, 2), 0) = "no";
1472 set = rtx_alloc (SET);
1473 SET_DEST (set) = rtx_alloc (ATTR);
1474 XSTR (SET_DEST (set), 0) = "enabled";
1475 SET_SRC (set) = modify_attr_enabled_ce (val);
1476 RTVEC_ELT (new_vec, i) = set;
1477 XVEC (insn, 4) = new_vec;
1478}
1479
477c104e
MK
1480/* As number of constraints is changed after define_subst, we need to
1481 process attributes as well - we need to duplicate them the same way
1482 that we duplicated constraints in original pattern
1483 ELEM is a queue element, containing our rtl-template,
1484 N_DUP - multiplication factor. */
1485static void
99b1c316 1486alter_attrs_for_subst_insn (class queue_elem * elem, int n_dup)
3262c1f5 1487{
477c104e
MK
1488 rtvec vec = XVEC (elem->data, 4);
1489 int num_elem;
1490 int i;
1491
1492 if (n_dup < 2 || ! vec)
1493 return;
1494
1495 num_elem = GET_NUM_ELEM (vec);
1496 for (i = num_elem - 1; i >= 0; --i)
3262c1f5 1497 {
477c104e
MK
1498 rtx sub = RTVEC_ELT (vec, i);
1499 switch (GET_CODE (sub))
3262c1f5 1500 {
477c104e
MK
1501 case SET_ATTR:
1502 if (strchr (XSTR (sub, 1), ',') != NULL)
1503 XSTR (sub, 1) = duplicate_alternatives (XSTR (sub, 1), n_dup);
1504 break;
1505
1506 case SET_ATTR_ALTERNATIVE:
1507 case SET:
cc472607
RS
1508 error_at (elem->loc,
1509 "%s: `define_subst' does not support attributes "
1510 "assigned by `set' and `set_attr_alternative'",
1511 XSTR (elem->data, 0));
477c104e
MK
1512 return;
1513
1514 default:
1515 gcc_unreachable ();
1516 }
1517 }
1518}
1519
1520/* Adjust all of the operand numbers in SRC to match the shift they'll
1521 get from an operand displacement of DISP. Return a pointer after the
1522 adjusted string. */
1523
1524static char *
1525shift_output_template (char *dest, const char *src, int disp)
1526{
1527 while (*src)
1528 {
1529 char c = *src++;
1530 *dest++ = c;
1531 if (c == '%')
1532 {
1533 c = *src++;
1534 if (ISDIGIT ((unsigned char) c))
1535 c += disp;
1536 else if (ISALPHA (c))
1537 {
53ed1a12 1538 *dest++ = c;
1ad463f4 1539 c = *src++ + disp;
3262c1f5 1540 }
53ed1a12 1541 *dest++ = c;
3262c1f5
RH
1542 }
1543 }
1544
53ed1a12 1545 return dest;
3262c1f5
RH
1546}
1547
1548static const char *
99b1c316
MS
1549alter_output_for_insn (class queue_elem *ce_elem,
1550 class queue_elem *insn_elem,
3d7aafde 1551 int alt, int max_op)
3262c1f5
RH
1552{
1553 const char *ce_out, *insn_out;
53ed1a12 1554 char *result, *p;
3262c1f5
RH
1555 size_t len, ce_len, insn_len;
1556
1557 /* ??? Could coordinate with genoutput to not duplicate code here. */
1558
1559 ce_out = XSTR (ce_elem->data, 2);
66621f9e 1560 insn_out = XTMPL (insn_elem->data, 3);
3262c1f5
RH
1561 if (!ce_out || *ce_out == '\0')
1562 return insn_out;
1563
1564 ce_len = strlen (ce_out);
1565 insn_len = strlen (insn_out);
1566
1567 if (*insn_out == '*')
1568 /* You must take care of the predicate yourself. */
1569 return insn_out;
1570
1571 if (*insn_out == '@')
1572 {
1573 len = (ce_len + 1) * alt + insn_len + 1;
477c104e 1574 p = result = XNEWVEC (char, len);
3262c1f5
RH
1575
1576 do
1577 {
1578 do
1579 *p++ = *insn_out++;
1580 while (ISSPACE ((unsigned char) *insn_out));
1581
1582 if (*insn_out != '#')
1583 {
1584 p = shift_output_template (p, ce_out, max_op);
1585 *p++ = ' ';
1586 }
1587
1588 do
1589 *p++ = *insn_out++;
1590 while (*insn_out && *insn_out != '\n');
1591 }
1592 while (*insn_out);
1593 *p = '\0';
1594 }
1595 else
1596 {
1597 len = ce_len + 1 + insn_len + 1;
53ed1a12 1598 result = XNEWVEC (char, len);
3262c1f5 1599
53ed1a12 1600 p = shift_output_template (result, ce_out, max_op);
3262c1f5
RH
1601 *p++ = ' ';
1602 memcpy (p, insn_out, insn_len + 1);
1603 }
1604
53ed1a12 1605 return result;
3262c1f5
RH
1606}
1607
477c104e
MK
1608/* From string STR "a,b,c" produce "a,b,c,a,b,c,a,b,c", i.e. original
1609 string, duplicated N_DUP times. */
1610
1611static const char *
1612duplicate_alternatives (const char * str, int n_dup)
1613{
1614 int i, len, new_len;
1615 char *result, *sp;
1616 const char *cp;
1617
1618 if (n_dup < 2)
1619 return str;
1620
1621 while (ISSPACE (*str))
1622 str++;
1623
1624 if (*str == '\0')
1625 return str;
1626
1627 cp = str;
1628 len = strlen (str);
1629 new_len = (len + 1) * n_dup;
1630
1631 sp = result = XNEWVEC (char, new_len);
1632
1633 /* Global modifier characters mustn't be duplicated: skip if found. */
1634 if (*cp == '=' || *cp == '+' || *cp == '%')
1635 {
1636 *sp++ = *cp++;
1637 len--;
1638 }
1639
1640 /* Copy original constraints N_DUP times. */
1641 for (i = 0; i < n_dup; i++, sp += len+1)
1642 {
1643 memcpy (sp, cp, len);
1644 *(sp+len) = (i == n_dup - 1) ? '\0' : ',';
1645 }
1646
1647 return result;
1648}
1649
1650/* From string STR "a,b,c" produce "a,a,a,b,b,b,c,c,c", i.e. string where
1651 each alternative from the original string is duplicated N_DUP times. */
1652static const char *
1653duplicate_each_alternative (const char * str, int n_dup)
1654{
1655 int i, len, new_len;
1656 char *result, *sp, *ep, *cp;
1657
1658 if (n_dup < 2)
1659 return str;
1660
1661 while (ISSPACE (*str))
1662 str++;
1663
1664 if (*str == '\0')
1665 return str;
1666
1667 cp = xstrdup (str);
1668
1669 new_len = (strlen (cp) + 1) * n_dup;
1670
1671 sp = result = XNEWVEC (char, new_len);
1672
1673 /* Global modifier characters mustn't be duplicated: skip if found. */
1674 if (*cp == '=' || *cp == '+' || *cp == '%')
1675 *sp++ = *cp++;
1676
1677 do
1678 {
1679 if ((ep = strchr (cp, ',')) != NULL)
1680 *ep++ = '\0';
1681 len = strlen (cp);
1682
1683 /* Copy a constraint N_DUP times. */
1684 for (i = 0; i < n_dup; i++, sp += len + 1)
1685 {
1686 memcpy (sp, cp, len);
1687 *(sp+len) = (ep == NULL && i == n_dup - 1) ? '\0' : ',';
1688 }
1689
1690 cp = ep;
1691 }
1692 while (cp != NULL);
1693
1694 return result;
1695}
1696
1697/* Alter the output of INSN whose pattern was modified by
1698 DEFINE_SUBST. We must replicate output strings according
1699 to the new number of alternatives ALT in substituted pattern.
1700 If ALT equals 1, output has one alternative or defined by C
1701 code, then output is returned without any changes. */
1702
1703static const char *
1704alter_output_for_subst_insn (rtx insn, int alt)
1705{
c5cb7968
JJ
1706 const char *insn_out, *old_out;
1707 char *new_out, *cp;
1708 size_t old_len, new_len;
1709 int j;
477c104e
MK
1710
1711 insn_out = XTMPL (insn, 3);
1712
c5cb7968 1713 if (alt < 2 || *insn_out != '@')
477c104e
MK
1714 return insn_out;
1715
c5cb7968
JJ
1716 old_out = insn_out + 1;
1717 while (ISSPACE (*old_out))
1718 old_out++;
1719 old_len = strlen (old_out);
477c104e 1720
c5cb7968 1721 new_len = alt * (old_len + 1) + 1;
477c104e
MK
1722
1723 new_out = XNEWVEC (char, new_len);
1724 new_out[0] = '@';
1725
c5cb7968 1726 for (j = 0, cp = new_out + 1; j < alt; j++, cp += old_len + 1)
477c104e 1727 {
c5cb7968
JJ
1728 memcpy (cp, old_out, old_len);
1729 cp[old_len] = (j == alt - 1) ? '\0' : '\n';
477c104e
MK
1730 }
1731
1732 return new_out;
1733}
1734
3262c1f5
RH
1735/* Replicate insns as appropriate for the given DEFINE_COND_EXEC. */
1736
1737static void
99b1c316 1738process_one_cond_exec (class queue_elem *ce_elem)
3262c1f5 1739{
99b1c316 1740 class queue_elem *insn_elem;
3262c1f5
RH
1741 for (insn_elem = define_insn_queue; insn_elem ; insn_elem = insn_elem->next)
1742 {
1743 int alternatives, max_operand;
a406f566 1744 rtx pred, insn, pattern, split;
2f6c5b27 1745 char *new_name;
a406f566 1746 int i;
3262c1f5
RH
1747
1748 if (! is_predicable (insn_elem))
1749 continue;
1750
1751 alternatives = 1;
1752 max_operand = -1;
1753 collect_insn_data (insn_elem->data, &alternatives, &max_operand);
1754 max_operand += 1;
1755
1756 if (XVECLEN (ce_elem->data, 0) != 1)
1757 {
cc472607 1758 error_at (ce_elem->loc, "too many patterns in predicate");
3262c1f5
RH
1759 return;
1760 }
1761
1762 pred = copy_rtx (XVECEXP (ce_elem->data, 0, 0));
1763 pred = alter_predicate_for_insn (pred, alternatives, max_operand,
cc472607 1764 ce_elem->loc);
3262c1f5
RH
1765 if (pred == NULL)
1766 return;
1767
1768 /* Construct a new pattern for the new insn. */
1769 insn = copy_rtx (insn_elem->data);
2f6c5b27
SB
1770 new_name = XNEWVAR (char, strlen XSTR (insn_elem->data, 0) + 4);
1771 sprintf (new_name, "*p %s", XSTR (insn_elem->data, 0));
1772 XSTR (insn, 0) = new_name;
3262c1f5
RH
1773 pattern = rtx_alloc (COND_EXEC);
1774 XEXP (pattern, 0) = pred;
313d38e3
RS
1775 XEXP (pattern, 1) = add_implicit_parallel (XVEC (insn, 1));
1776 XVEC (insn, 1) = rtvec_alloc (1);
1777 XVECEXP (insn, 1, 0) = pattern;
3262c1f5 1778
aadaf24e
KT
1779 if (XVEC (ce_elem->data, 3) != NULL)
1780 {
1781 rtvec attributes = rtvec_alloc (XVECLEN (insn, 4)
1782 + XVECLEN (ce_elem->data, 3));
1783 int i = 0;
1784 int j = 0;
1785 for (i = 0; i < XVECLEN (insn, 4); i++)
1786 RTVEC_ELT (attributes, i) = XVECEXP (insn, 4, i);
1787
1788 for (j = 0; j < XVECLEN (ce_elem->data, 3); j++, i++)
1789 RTVEC_ELT (attributes, i) = XVECEXP (ce_elem->data, 3, j);
1790
1791 XVEC (insn, 4) = attributes;
1792 }
1793
3262c1f5 1794 XSTR (insn, 2) = alter_test_for_insn (ce_elem, insn_elem);
66621f9e 1795 XTMPL (insn, 3) = alter_output_for_insn (ce_elem, insn_elem,
3262c1f5 1796 alternatives, max_operand);
0bddee8e 1797 alter_attrs_for_insn (insn);
3262c1f5
RH
1798
1799 /* Put the new pattern on the `other' list so that it
1800 (a) is not reprocessed by other define_cond_exec patterns
1801 (b) appears after all normal define_insn patterns.
1802
1803 ??? B is debatable. If one has normal insns that match
1804 cond_exec patterns, they will be preferred over these
1805 generated patterns. Whether this matters in practice, or if
1806 it's a good thing, or whether we should thread these new
1807 patterns into the define_insn chain just after their generator
1808 is something we'll have to experiment with. */
1809
cc472607 1810 queue_pattern (insn, &other_tail, insn_elem->loc);
a406f566
MM
1811
1812 if (!insn_elem->split)
1813 continue;
1814
1815 /* If the original insn came from a define_insn_and_split,
9cf737f8 1816 generate a new split to handle the predicated insn. */
a406f566
MM
1817 split = copy_rtx (insn_elem->split->data);
1818 /* Predicate the pattern matched by the split. */
1819 pattern = rtx_alloc (COND_EXEC);
1820 XEXP (pattern, 0) = pred;
313d38e3
RS
1821 XEXP (pattern, 1) = add_implicit_parallel (XVEC (split, 0));
1822 XVEC (split, 0) = rtvec_alloc (1);
1823 XVECEXP (split, 0, 0) = pattern;
1824
a406f566
MM
1825 /* Predicate all of the insns generated by the split. */
1826 for (i = 0; i < XVECLEN (split, 2); i++)
1827 {
1828 pattern = rtx_alloc (COND_EXEC);
1829 XEXP (pattern, 0) = pred;
1830 XEXP (pattern, 1) = XVECEXP (split, 2, i);
1831 XVECEXP (split, 2, i) = pattern;
1832 }
1833 /* Add the new split to the queue. */
cc472607 1834 queue_pattern (split, &other_tail, insn_elem->split->loc);
3262c1f5
RH
1835 }
1836}
1837
477c104e
MK
1838/* Try to apply define_substs to the given ELEM.
1839 Only define_substs, specified via attributes would be applied.
1840 If attribute, requiring define_subst, is set, but no define_subst
1841 was applied, ELEM would be deleted. */
1842
1843static void
99b1c316
MS
1844process_substs_on_one_elem (class queue_elem *elem,
1845 class queue_elem *queue)
477c104e 1846{
99b1c316 1847 class queue_elem *subst_elem;
477c104e
MK
1848 int i, j, patterns_match;
1849
1850 for (subst_elem = define_subst_queue;
1851 subst_elem; subst_elem = subst_elem->next)
1852 {
1853 int alternatives, alternatives_subst;
1854 rtx subst_pattern;
1855 rtvec subst_pattern_vec;
1856
1857 if (!has_subst_attribute (elem, subst_elem))
1858 continue;
1859
1860 /* Compare original rtl-pattern from define_insn with input
1861 pattern from define_subst.
1862 Also, check if numbers of alternatives are the same in all
1863 match_operands. */
1864 if (XVECLEN (elem->data, 1) != XVECLEN (subst_elem->data, 1))
1865 continue;
1866 patterns_match = 1;
1867 alternatives = -1;
1868 alternatives_subst = -1;
1869 for (j = 0; j < XVECLEN (elem->data, 1); j++)
1870 {
1871 if (!subst_pattern_match (XVECEXP (elem->data, 1, j),
1872 XVECEXP (subst_elem->data, 1, j),
cc472607 1873 subst_elem->loc))
477c104e
MK
1874 {
1875 patterns_match = 0;
1876 break;
1877 }
1878
1879 if (!get_alternatives_number (XVECEXP (elem->data, 1, j),
cc472607 1880 &alternatives, subst_elem->loc))
477c104e
MK
1881 {
1882 patterns_match = 0;
1883 break;
1884 }
1885 }
1886
1887 /* Check if numbers of alternatives are the same in all
1888 match_operands in output template of define_subst. */
1889 for (j = 0; j < XVECLEN (subst_elem->data, 3); j++)
1890 {
1891 if (!get_alternatives_number (XVECEXP (subst_elem->data, 3, j),
1892 &alternatives_subst,
cc472607 1893 subst_elem->loc))
477c104e
MK
1894 {
1895 patterns_match = 0;
1896 break;
1897 }
1898 }
1899
1900 if (!patterns_match)
1901 continue;
1902
1903 /* Clear array in which we save occupied indexes of operands. */
1904 memset (used_operands_numbers, 0, sizeof (used_operands_numbers));
1905
1906 /* Create a pattern, based on the output one from define_subst. */
1907 subst_pattern_vec = rtvec_alloc (XVECLEN (subst_elem->data, 3));
1908 for (j = 0; j < XVECLEN (subst_elem->data, 3); j++)
1909 {
1910 subst_pattern = copy_rtx (XVECEXP (subst_elem->data, 3, j));
1911
1912 /* Duplicate constraints in substitute-pattern. */
1913 subst_pattern = alter_constraints (subst_pattern, alternatives,
1914 duplicate_each_alternative);
1915
a7ba15ca 1916 subst_pattern = adjust_operands_numbers (subst_pattern);
477c104e
MK
1917
1918 /* Substitute match_dup and match_op_dup in the new pattern and
1919 duplicate constraints. */
1920 subst_pattern = subst_dup (subst_pattern, alternatives,
1921 alternatives_subst);
1922
1923 replace_duplicating_operands_in_pattern (subst_pattern);
1924
1925 /* We don't need any constraints in DEFINE_EXPAND. */
1926 if (GET_CODE (elem->data) == DEFINE_EXPAND)
1927 remove_constraints (subst_pattern);
1928
a7ba15ca 1929 RTVEC_ELT (subst_pattern_vec, j) = subst_pattern;
477c104e
MK
1930 }
1931 XVEC (elem->data, 1) = subst_pattern_vec;
1932
1933 for (i = 0; i < MAX_OPERANDS; i++)
1934 match_operand_entries_in_pattern[i] = NULL;
1935
1936 if (GET_CODE (elem->data) == DEFINE_INSN)
1937 {
1938 XTMPL (elem->data, 3) =
1939 alter_output_for_subst_insn (elem->data, alternatives_subst);
1940 alter_attrs_for_subst_insn (elem, alternatives_subst);
1941 }
1942
1943 /* Recalculate condition, joining conditions from original and
1944 DEFINE_SUBST input patterns. */
b78027d1
DM
1945 XSTR (elem->data, 2)
1946 = rtx_reader_ptr->join_c_conditions (XSTR (subst_elem->data, 2),
1947 XSTR (elem->data, 2));
477c104e
MK
1948 /* Mark that subst was applied by changing attribute from "yes"
1949 to "no". */
1950 change_subst_attribute (elem, subst_elem, subst_false);
1951 }
1952
1953 /* If ELEM contains a subst attribute with value "yes", then we
1954 expected that a subst would be applied, but it wasn't - so,
1955 we need to remove that elementto avoid duplicating. */
1956 for (subst_elem = define_subst_queue;
1957 subst_elem; subst_elem = subst_elem->next)
1958 {
1959 if (has_subst_attribute (elem, subst_elem))
1960 {
1961 remove_from_queue (elem, &queue);
1962 return;
1963 }
1964 }
1965}
1966
1967/* This is a subroutine of mark_operands_used_in_match_dup.
1968 This routine is marks all MATCH_OPERANDs inside PATTERN as occupied. */
1969static void
1970mark_operands_from_match_dup (rtx pattern)
1971{
1972 const char *fmt;
1973 int i, j, len, opno;
1974
1975 if (GET_CODE (pattern) == MATCH_OPERAND
1976 || GET_CODE (pattern) == MATCH_OPERATOR
1977 || GET_CODE (pattern) == MATCH_PARALLEL)
1978 {
1979 opno = XINT (pattern, 0);
1980 gcc_assert (opno >= 0 && opno < MAX_OPERANDS);
1981 used_operands_numbers [opno] = 1;
1982 }
1983 fmt = GET_RTX_FORMAT (GET_CODE (pattern));
1984 len = GET_RTX_LENGTH (GET_CODE (pattern));
1985 for (i = 0; i < len; i++)
1986 {
1987 switch (fmt[i])
1988 {
1989 case 'e': case 'u':
1990 mark_operands_from_match_dup (XEXP (pattern, i));
1991 break;
1992 case 'E':
1993 for (j = XVECLEN (pattern, i) - 1; j >= 0; --j)
1994 mark_operands_from_match_dup (XVECEXP (pattern, i, j));
1995 break;
1996 }
1997 }
1998}
1999
a7ba15ca 2000/* This is a subroutine of adjust_operands_numbers.
477c104e
MK
2001 It goes through all expressions in PATTERN and when MATCH_DUP is
2002 met, all MATCH_OPERANDs inside it is marked as occupied. The
2003 process of marking is done by routin mark_operands_from_match_dup. */
2004static void
2005mark_operands_used_in_match_dup (rtx pattern)
2006{
2007 const char *fmt;
2008 int i, j, len, opno;
2009
2010 if (GET_CODE (pattern) == MATCH_DUP)
2011 {
2012 opno = XINT (pattern, 0);
2013 gcc_assert (opno >= 0 && opno < MAX_OPERANDS);
2014 mark_operands_from_match_dup (operand_data[opno]);
2015 return;
2016 }
2017 fmt = GET_RTX_FORMAT (GET_CODE (pattern));
2018 len = GET_RTX_LENGTH (GET_CODE (pattern));
2019 for (i = 0; i < len; i++)
2020 {
2021 switch (fmt[i])
2022 {
2023 case 'e': case 'u':
2024 mark_operands_used_in_match_dup (XEXP (pattern, i));
2025 break;
2026 case 'E':
2027 for (j = XVECLEN (pattern, i) - 1; j >= 0; --j)
2028 mark_operands_used_in_match_dup (XVECEXP (pattern, i, j));
2029 break;
2030 }
2031 }
2032}
2033
2034/* This is subroutine of renumerate_operands_in_pattern.
2035 It finds first not-occupied operand-index. */
2036static int
2037find_first_unused_number_of_operand ()
2038{
2039 int i;
2040 for (i = 0; i < MAX_OPERANDS; i++)
2041 if (!used_operands_numbers[i])
2042 return i;
2043 return MAX_OPERANDS;
2044}
2045
a7ba15ca
AK
2046/* This is subroutine of adjust_operands_numbers.
2047 It visits all expressions in PATTERN and assigns not-occupied
2048 operand indexes to MATCH_OPERANDs and MATCH_OPERATORs of this
2049 PATTERN. */
477c104e
MK
2050static void
2051renumerate_operands_in_pattern (rtx pattern)
2052{
2053 const char *fmt;
2054 enum rtx_code code;
2055 int i, j, len, new_opno;
2056 code = GET_CODE (pattern);
2057
2058 if (code == MATCH_OPERAND
2059 || code == MATCH_OPERATOR)
2060 {
2061 new_opno = find_first_unused_number_of_operand ();
2062 gcc_assert (new_opno >= 0 && new_opno < MAX_OPERANDS);
2063 XINT (pattern, 0) = new_opno;
2064 used_operands_numbers [new_opno] = 1;
2065 }
2066
2067 fmt = GET_RTX_FORMAT (GET_CODE (pattern));
2068 len = GET_RTX_LENGTH (GET_CODE (pattern));
2069 for (i = 0; i < len; i++)
2070 {
2071 switch (fmt[i])
2072 {
2073 case 'e': case 'u':
2074 renumerate_operands_in_pattern (XEXP (pattern, i));
2075 break;
2076 case 'E':
2077 for (j = XVECLEN (pattern, i) - 1; j >= 0; --j)
2078 renumerate_operands_in_pattern (XVECEXP (pattern, i, j));
2079 break;
2080 }
2081 }
2082}
2083
a7ba15ca
AK
2084/* If output pattern of define_subst contains MATCH_DUP, then this
2085 expression would be replaced with the pattern, matched with
2086 MATCH_OPERAND from input pattern. This pattern could contain any
2087 number of MATCH_OPERANDs, MATCH_OPERATORs etc., so it's possible
2088 that a MATCH_OPERAND from output_pattern (if any) would have the
2089 same number, as MATCH_OPERAND from copied pattern. To avoid such
2090 indexes overlapping, we assign new indexes to MATCH_OPERANDs,
2091 laying in the output pattern outside of MATCH_DUPs. */
2092static rtx
2093adjust_operands_numbers (rtx pattern)
2094{
2095 mark_operands_used_in_match_dup (pattern);
2096
2097 renumerate_operands_in_pattern (pattern);
2098
2099 return pattern;
2100}
477c104e
MK
2101
2102/* Generate RTL expression
2103 (match_dup OPNO)
2104 */
2105static rtx
2106generate_match_dup (int opno)
2107{
2108 rtx return_rtx = rtx_alloc (MATCH_DUP);
2109 PUT_CODE (return_rtx, MATCH_DUP);
2110 XINT (return_rtx, 0) = opno;
2111 return return_rtx;
2112}
2113
2114/* This routine checks all match_operands in PATTERN and if some of
2115 have the same index, it replaces all of them except the first one to
2116 match_dup.
2117 Usually, match_operands with the same indexes are forbidden, but
2118 after define_subst copy an RTL-expression from original template,
2119 indexes of existed and just-copied match_operands could coincide.
2120 To fix it, we replace one of them with match_dup. */
2121static rtx
2122replace_duplicating_operands_in_pattern (rtx pattern)
2123{
2124 const char *fmt;
2125 int i, j, len, opno;
2126 rtx mdup;
2127
2128 if (GET_CODE (pattern) == MATCH_OPERAND)
2129 {
2130 opno = XINT (pattern, 0);
2131 gcc_assert (opno >= 0 && opno < MAX_OPERANDS);
2132 if (match_operand_entries_in_pattern[opno] == NULL)
2133 {
2134 match_operand_entries_in_pattern[opno] = pattern;
2135 return NULL;
2136 }
2137 else
2138 {
2139 /* Compare predicates before replacing with match_dup. */
2140 if (strcmp (XSTR (pattern, 1),
2141 XSTR (match_operand_entries_in_pattern[opno], 1)))
2142 {
2143 error ("duplicated match_operands with different predicates were"
2144 " found.");
2145 return NULL;
2146 }
2147 return generate_match_dup (opno);
2148 }
2149 }
2150 fmt = GET_RTX_FORMAT (GET_CODE (pattern));
2151 len = GET_RTX_LENGTH (GET_CODE (pattern));
2152 for (i = 0; i < len; i++)
2153 {
2154 switch (fmt[i])
2155 {
2156 case 'e': case 'u':
2157 mdup = replace_duplicating_operands_in_pattern (XEXP (pattern, i));
2158 if (mdup)
2159 XEXP (pattern, i) = mdup;
2160 break;
2161 case 'E':
2162 for (j = XVECLEN (pattern, i) - 1; j >= 0; --j)
2163 {
2164 mdup =
2165 replace_duplicating_operands_in_pattern (XVECEXP
2166 (pattern, i, j));
2167 if (mdup)
2168 XVECEXP (pattern, i, j) = mdup;
2169 }
2170 break;
2171 }
2172 }
2173 return NULL;
2174}
2175
2176/* The routine modifies given input PATTERN of define_subst, replacing
2177 MATCH_DUP and MATCH_OP_DUP with operands from define_insn original
2178 pattern, whose operands are stored in OPERAND_DATA array.
2179 It also duplicates constraints in operands - constraints from
2180 define_insn operands are duplicated N_SUBST_ALT times, constraints
2181 from define_subst operands are duplicated N_ALT times.
2182 After the duplication, returned output rtl-pattern contains every
2183 combination of input constraints Vs constraints from define_subst
2184 output. */
2185static rtx
2186subst_dup (rtx pattern, int n_alt, int n_subst_alt)
2187{
2188 const char *fmt;
2189 enum rtx_code code;
2190 int i, j, len, opno;
2191
2192 code = GET_CODE (pattern);
2193 switch (code)
2194 {
2195 case MATCH_DUP:
2196 case MATCH_OP_DUP:
2197 opno = XINT (pattern, 0);
2198
2199 gcc_assert (opno >= 0 && opno < MAX_OPERANDS);
2200
2201 if (operand_data[opno])
2202 {
2203 pattern = copy_rtx (operand_data[opno]);
2204
2205 /* Duplicate constraints. */
2206 pattern = alter_constraints (pattern, n_subst_alt,
2207 duplicate_alternatives);
2208 }
2209 break;
2210
2211 default:
2212 break;
2213 }
2214
2215 fmt = GET_RTX_FORMAT (GET_CODE (pattern));
2216 len = GET_RTX_LENGTH (GET_CODE (pattern));
2217 for (i = 0; i < len; i++)
2218 {
2219 switch (fmt[i])
2220 {
2221 case 'e': case 'u':
2222 if (code != MATCH_DUP && code != MATCH_OP_DUP)
2223 XEXP (pattern, i) = subst_dup (XEXP (pattern, i),
2224 n_alt, n_subst_alt);
2225 break;
2226 case 'V':
2227 if (XVEC (pattern, i) == NULL)
2228 break;
191816a3 2229 /* FALLTHRU */
477c104e 2230 case 'E':
c7b3b99f
PCC
2231 if (code != MATCH_DUP && code != MATCH_OP_DUP)
2232 for (j = XVECLEN (pattern, i) - 1; j >= 0; --j)
477c104e
MK
2233 XVECEXP (pattern, i, j) = subst_dup (XVECEXP (pattern, i, j),
2234 n_alt, n_subst_alt);
2235 break;
2236
91914e56
RS
2237 case 'r': case 'p': case 'i': case 'w':
2238 case '0': case 's': case 'S': case 'T':
477c104e
MK
2239 break;
2240
2241 default:
2242 gcc_unreachable ();
2243 }
2244 }
2245 return pattern;
2246}
2247
3262c1f5
RH
2248/* If we have any DEFINE_COND_EXEC patterns, expand the DEFINE_INSN
2249 patterns appropriately. */
2250
2251static void
3d7aafde 2252process_define_cond_exec (void)
3262c1f5 2253{
99b1c316 2254 class queue_elem *elem;
3262c1f5
RH
2255
2256 identify_predicable_attribute ();
bb933490 2257 if (have_error)
3262c1f5
RH
2258 return;
2259
2260 for (elem = define_cond_exec_queue; elem ; elem = elem->next)
2261 process_one_cond_exec (elem);
2262}
477c104e
MK
2263
2264/* If we have any DEFINE_SUBST patterns, expand DEFINE_INSN and
2265 DEFINE_EXPAND patterns appropriately. */
2266
2267static void
2268process_define_subst (void)
2269{
99b1c316 2270 class queue_elem *elem, *elem_attr;
477c104e
MK
2271
2272 /* Check if each define_subst has corresponding define_subst_attr. */
2273 for (elem = define_subst_queue; elem ; elem = elem->next)
2274 {
2275 for (elem_attr = define_subst_attr_queue;
2276 elem_attr;
2277 elem_attr = elem_attr->next)
2278 if (strcmp (XSTR (elem->data, 0), XSTR (elem_attr->data, 1)) == 0)
2279 goto found;
2280
cc472607
RS
2281 error_at (elem->loc,
2282 "%s: `define_subst' must have at least one "
2283 "corresponding `define_subst_attr'",
2284 XSTR (elem->data, 0));
21c0a521
DM
2285 return;
2286
477c104e
MK
2287 found:
2288 continue;
2289 }
2290
2291 for (elem = define_insn_queue; elem ; elem = elem->next)
2292 process_substs_on_one_elem (elem, define_insn_queue);
2293 for (elem = other_queue; elem ; elem = elem->next)
2294 {
2295 if (GET_CODE (elem->data) != DEFINE_EXPAND)
2296 continue;
2297 process_substs_on_one_elem (elem, other_queue);
2298 }
2299}
600ab3fc 2300\f
812b1403
DM
2301/* A subclass of rtx_reader which reads .md files and calls process_rtx on
2302 the top-level elements. */
04d8aa70 2303
812b1403
DM
2304class gen_reader : public rtx_reader
2305{
2306 public:
51b86113 2307 gen_reader () : rtx_reader (false) {}
812b1403
DM
2308 void handle_unknown_directive (file_location, const char *);
2309};
2310
2311void
2312gen_reader::handle_unknown_directive (file_location loc, const char *rtx_name)
04d8aa70 2313{
6b8068d6
TS
2314 auto_vec<rtx, 32> subrtxs;
2315 if (!read_rtx (rtx_name, &subrtxs))
2316 return;
04d8aa70 2317
6b8068d6
TS
2318 rtx x;
2319 unsigned int i;
2320 FOR_EACH_VEC_ELT (subrtxs, i, x)
cc472607 2321 process_rtx (x, loc);
04d8aa70
AM
2322}
2323
64aad689
AK
2324/* Comparison function for the mnemonic hash table. */
2325
2326static int
2327htab_eq_string (const void *s1, const void *s2)
2328{
2329 return strcmp ((const char*)s1, (const char*)s2) == 0;
2330}
2331
2332/* Add mnemonic STR with length LEN to the mnemonic hash table
5764ee3c 2333 MNEMONIC_HTAB. A trailing zero end character is appended to STR
64aad689
AK
2334 and a permanent heap copy of STR is created. */
2335
2336static void
c240b3e0 2337add_mnemonic_string (htab_t mnemonic_htab, const char *str, size_t len)
64aad689
AK
2338{
2339 char *new_str;
2340 void **slot;
2341 char *str_zero = (char*)alloca (len + 1);
2342
2343 memcpy (str_zero, str, len);
2344 str_zero[len] = '\0';
2345
2346 slot = htab_find_slot (mnemonic_htab, str_zero, INSERT);
2347
2348 if (*slot)
2349 return;
2350
2351 /* Not found; create a permanent copy and add it to the hash table. */
2352 new_str = XNEWVAR (char, len + 1);
2353 memcpy (new_str, str_zero, len + 1);
2354 *slot = new_str;
2355}
2356
2357/* Scan INSN for mnemonic strings and add them to the mnemonic hash
2358 table in MNEMONIC_HTAB.
2359
2360 The mnemonics cannot be found if they are emitted using C code.
2361
2362 If a mnemonic string contains ';' or a newline the string assumed
2363 to consist of more than a single instruction. The attribute value
2364 will then be set to the user defined default value. */
2365
2366static void
2367gen_mnemonic_setattr (htab_t mnemonic_htab, rtx insn)
2368{
2369 const char *template_code, *cp;
2370 int i;
2371 int vec_len;
2372 rtx set_attr;
2373 char *attr_name;
2374 rtvec new_vec;
b78027d1 2375 struct obstack *string_obstack = rtx_reader_ptr->get_string_obstack ();
64aad689
AK
2376
2377 template_code = XTMPL (insn, 3);
2378
2379 /* Skip patterns which use C code to emit the template. */
2380 if (template_code[0] == '*')
2381 return;
2382
2383 if (template_code[0] == '@')
2384 cp = &template_code[1];
2385 else
2386 cp = &template_code[0];
2387
2388 for (i = 0; *cp; )
2389 {
2390 const char *ep, *sp;
c240b3e0 2391 size_t size = 0;
64aad689
AK
2392
2393 while (ISSPACE (*cp))
2394 cp++;
2395
2396 for (ep = sp = cp; !IS_VSPACE (*ep) && *ep != '\0'; ++ep)
2397 if (!ISSPACE (*ep))
2398 sp = ep + 1;
2399
2400 if (i > 0)
b78027d1 2401 obstack_1grow (string_obstack, ',');
64aad689
AK
2402
2403 while (cp < sp && ((*cp >= '0' && *cp <= '9')
2404 || (*cp >= 'a' && *cp <= 'z')))
2405
2406 {
b78027d1 2407 obstack_1grow (string_obstack, *cp);
64aad689
AK
2408 cp++;
2409 size++;
2410 }
2411
2412 while (cp < sp)
2413 {
2414 if (*cp == ';' || (*cp == '\\' && cp[1] == 'n'))
2415 {
2416 /* Don't set a value if there are more than one
2417 instruction in the string. */
b78027d1 2418 obstack_blank_fast (string_obstack, -size);
64aad689
AK
2419 size = 0;
2420
2421 cp = sp;
2422 break;
2423 }
2424 cp++;
2425 }
2426 if (size == 0)
b78027d1 2427 obstack_1grow (string_obstack, '*');
64aad689
AK
2428 else
2429 add_mnemonic_string (mnemonic_htab,
b78027d1 2430 (char *) obstack_next_free (string_obstack) - size,
64aad689
AK
2431 size);
2432 i++;
2433 }
2434
2435 /* An insn definition might emit an empty string. */
b78027d1 2436 if (obstack_object_size (string_obstack) == 0)
64aad689
AK
2437 return;
2438
b78027d1 2439 obstack_1grow (string_obstack, '\0');
64aad689
AK
2440
2441 set_attr = rtx_alloc (SET_ATTR);
b78027d1 2442 XSTR (set_attr, 1) = XOBFINISH (string_obstack, char *);
64aad689
AK
2443 attr_name = XNEWVAR (char, strlen (MNEMONIC_ATTR_NAME) + 1);
2444 strcpy (attr_name, MNEMONIC_ATTR_NAME);
2445 XSTR (set_attr, 0) = attr_name;
2446
2447 if (!XVEC (insn, 4))
2448 vec_len = 0;
2449 else
2450 vec_len = XVECLEN (insn, 4);
2451
2452 new_vec = rtvec_alloc (vec_len + 1);
2453 for (i = 0; i < vec_len; i++)
2454 RTVEC_ELT (new_vec, i) = XVECEXP (insn, 4, i);
2455 RTVEC_ELT (new_vec, vec_len) = set_attr;
2456 XVEC (insn, 4) = new_vec;
2457}
2458
2459/* This function is called for the elements in the mnemonic hashtable
2460 and generates a comma separated list of the mnemonics. */
2461
2462static int
2463mnemonic_htab_callback (void **slot, void *info ATTRIBUTE_UNUSED)
2464{
b78027d1
DM
2465 struct obstack *string_obstack = rtx_reader_ptr->get_string_obstack ();
2466
2467 obstack_grow (string_obstack, (char*) *slot, strlen ((char*) *slot));
2468 obstack_1grow (string_obstack, ',');
64aad689
AK
2469 return 1;
2470}
2471
2472/* Generate (set_attr "mnemonic" "..") RTXs and append them to every
2473 insn definition in case the back end requests it by defining the
2474 mnemonic attribute. The values for the attribute will be extracted
2475 from the output patterns of the insn definitions as far as
2476 possible. */
2477
2478static void
2479gen_mnemonic_attr (void)
2480{
99b1c316 2481 class queue_elem *elem;
64aad689
AK
2482 rtx mnemonic_attr = NULL;
2483 htab_t mnemonic_htab;
2484 const char *str, *p;
2485 int i;
b78027d1 2486 struct obstack *string_obstack = rtx_reader_ptr->get_string_obstack ();
64aad689
AK
2487
2488 if (have_error)
2489 return;
2490
2491 /* Look for the DEFINE_ATTR for `mnemonic'. */
2492 for (elem = define_attr_queue; elem != *define_attr_tail; elem = elem->next)
2493 if (GET_CODE (elem->data) == DEFINE_ATTR
2494 && strcmp (XSTR (elem->data, 0), MNEMONIC_ATTR_NAME) == 0)
2495 {
2496 mnemonic_attr = elem->data;
2497 break;
2498 }
2499
2500 /* A (define_attr "mnemonic" "...") indicates that the back-end
2501 wants a mnemonic attribute to be generated. */
2502 if (!mnemonic_attr)
2503 return;
2504
2505 mnemonic_htab = htab_create_alloc (MNEMONIC_HTAB_SIZE, htab_hash_string,
2506 htab_eq_string, 0, xcalloc, free);
2507
2508 for (elem = define_insn_queue; elem; elem = elem->next)
2509 {
2510 rtx insn = elem->data;
2511 bool found = false;
2512
2513 /* Check if the insn definition already has
5db40447 2514 (set_attr "mnemonic" ...) or (set (attr "mnemonic") ...). */
64aad689
AK
2515 if (XVEC (insn, 4))
2516 for (i = 0; i < XVECLEN (insn, 4); i++)
5db40447
AK
2517 {
2518 rtx set_attr = XVECEXP (insn, 4, i);
2519
2520 switch (GET_CODE (set_attr))
2521 {
2522 case SET_ATTR:
2523 case SET_ATTR_ALTERNATIVE:
2524 if (strcmp (XSTR (set_attr, 0), MNEMONIC_ATTR_NAME) == 0)
2525 found = true;
2526 break;
2527 case SET:
2528 if (GET_CODE (SET_DEST (set_attr)) == ATTR
2529 && strcmp (XSTR (SET_DEST (set_attr), 0),
2530 MNEMONIC_ATTR_NAME) == 0)
2531 found = true;
2532 break;
2533 default:
2534 break;
2535 }
2536 }
64aad689
AK
2537
2538 if (!found)
2539 gen_mnemonic_setattr (mnemonic_htab, insn);
2540 }
2541
2542 /* Add the user defined values to the hash table. */
2543 str = XSTR (mnemonic_attr, 1);
2544 while ((p = scan_comma_elt (&str)) != NULL)
2545 add_mnemonic_string (mnemonic_htab, p, str - p);
2546
2547 htab_traverse (mnemonic_htab, mnemonic_htab_callback, NULL);
2548
2549 /* Replace the last ',' with the zero end character. */
b78027d1
DM
2550 *((char *) obstack_next_free (string_obstack) - 1) = '\0';
2551 XSTR (mnemonic_attr, 1) = XOBFINISH (string_obstack, char *);
64aad689
AK
2552}
2553
477c104e
MK
2554/* Check if there are DEFINE_ATTRs with the same name. */
2555static void
2556check_define_attr_duplicates ()
2557{
99b1c316 2558 class queue_elem *elem;
477c104e
MK
2559 htab_t attr_htab;
2560 char * attr_name;
2561 void **slot;
2562
2563 attr_htab = htab_create (500, htab_hash_string, htab_eq_string, NULL);
2564
2565 for (elem = define_attr_queue; elem; elem = elem->next)
2566 {
2567 attr_name = xstrdup (XSTR (elem->data, 0));
2568
2569 slot = htab_find_slot (attr_htab, attr_name, INSERT);
2570
2571 /* Duplicate. */
2572 if (*slot)
2573 {
cc472607 2574 error_at (elem->loc, "redefinition of attribute '%s'", attr_name);
477c104e
MK
2575 htab_delete (attr_htab);
2576 return;
2577 }
2578
2579 *slot = attr_name;
2580 }
2581
2582 htab_delete (attr_htab);
2583}
2584
04d8aa70
AM
2585/* The entry point for initializing the reader. */
2586
812b1403 2587rtx_reader *
66b0fe8f 2588init_rtx_reader_args_cb (int argc, const char **argv,
600ab3fc 2589 bool (*parse_opt) (const char *))
04d8aa70 2590{
1c7352cd
ZW
2591 /* Prepare to read input. */
2592 condition_table = htab_create (500, hash_c_test, cmp_c_test, NULL);
e543e219 2593 init_predicate_table ();
3916d6d8 2594 obstack_init (rtl_obstack);
e714561a
SB
2595
2596 /* Start at 1, to make 0 available for CODE_FOR_nothing. */
72a35f93
RS
2597 insn_sequence_num = 1;
2598
2599 /* These sequences are not used as indices, so can start at 1 also. */
2600 split_sequence_num = 1;
2601 peephole2_sequence_num = 1;
1c7352cd 2602
812b1403
DM
2603 gen_reader *reader = new gen_reader ();
2604 reader->read_md_files (argc, argv, parse_opt);
3262c1f5 2605
477c104e
MK
2606 if (define_attr_queue != NULL)
2607 check_define_attr_duplicates ();
2608
3262c1f5
RH
2609 /* Process define_cond_exec patterns. */
2610 if (define_cond_exec_queue != NULL)
2611 process_define_cond_exec ();
2612
477c104e
MK
2613 /* Process define_subst patterns. */
2614 if (define_subst_queue != NULL)
2615 process_define_subst ();
2616
64aad689
AK
2617 if (define_attr_queue != NULL)
2618 gen_mnemonic_attr ();
2619
812b1403
DM
2620 if (have_error)
2621 {
2622 delete reader;
2623 return NULL;
2624 }
2625
2626 return reader;
3262c1f5
RH
2627}
2628
f9942f4e
ZW
2629/* Programs that don't have their own options can use this entry point
2630 instead. */
812b1403 2631rtx_reader *
66b0fe8f 2632init_rtx_reader_args (int argc, const char **argv)
f9942f4e 2633{
600ab3fc 2634 return init_rtx_reader_args_cb (argc, argv, 0);
f9942f4e
ZW
2635}
2636\f
5d2d3e43
RS
2637/* Try to read a single rtx from the file. Return true on success,
2638 describing it in *INFO. */
3262c1f5 2639
5d2d3e43
RS
2640bool
2641read_md_rtx (md_rtx_info *info)
3262c1f5 2642{
72a35f93
RS
2643 int truth, *counter;
2644 rtx def;
3262c1f5 2645
2199e5fa
ZW
2646 /* Discard insn patterns which we know can never match (because
2647 their C test is provably always false). If insn_elision is
2648 false, our caller needs to see all the patterns. Note that the
2649 elided patterns are never counted by the sequence numbering; it
1a84c183 2650 is the caller's responsibility, when insn_elision is false, not
2199e5fa 2651 to use elided pattern numbers for anything. */
72a35f93
RS
2652 do
2653 {
99b1c316 2654 class queue_elem **queue, *elem;
72a35f93
RS
2655
2656 /* Read all patterns from a given queue before moving on to the next. */
2657 if (define_attr_queue != NULL)
2658 queue = &define_attr_queue;
2659 else if (define_pred_queue != NULL)
2660 queue = &define_pred_queue;
2661 else if (define_insn_queue != NULL)
2662 queue = &define_insn_queue;
2663 else if (other_queue != NULL)
2664 queue = &other_queue;
2665 else
2666 return false;
2667
2668 elem = *queue;
2669 *queue = elem->next;
2670 def = elem->data;
2671 info->def = def;
2672 info->loc = elem->loc;
2673 free (elem);
2674
2675 truth = maybe_eval_c_test (get_c_test (def));
2676 }
2677 while (truth == 0 && insn_elision);
2678
2679 /* Perform code-specific processing and pick the appropriate sequence
2680 number counter. */
2681 switch (GET_CODE (def))
c88c0d42 2682 {
3262c1f5
RH
2683 case DEFINE_INSN:
2684 case DEFINE_EXPAND:
72a35f93 2685 /* insn_sequence_num is used here so the name table will match caller's
0458fe77 2686 idea of insn numbering, whether or not elision is active. */
72a35f93
RS
2687 record_insn_name (insn_sequence_num, XSTR (def, 0));
2688
2689 /* Fall through. */
2690 case DEFINE_PEEPHOLE:
2691 counter = &insn_sequence_num;
2199e5fa
ZW
2692 break;
2693
3262c1f5 2694 case DEFINE_SPLIT:
72a35f93
RS
2695 counter = &split_sequence_num;
2696 break;
2697
3262c1f5 2698 case DEFINE_PEEPHOLE2:
72a35f93 2699 counter = &peephole2_sequence_num;
3262c1f5
RH
2700 break;
2701
2702 default:
72a35f93 2703 counter = NULL;
3262c1f5 2704 break;
c88c0d42
CP
2705 }
2706
72a35f93
RS
2707 if (counter)
2708 {
2709 info->index = *counter;
2710 if (truth != 0)
2711 *counter += 1;
2712 }
2713 else
2714 info->index = -1;
2715
58d745ec
RS
2716 if (!rtx_locs)
2717 rtx_locs = new hash_map <rtx, file_location>;
2718 rtx_locs->put (info->def, info->loc);
2719
5d2d3e43 2720 return true;
c88c0d42 2721}
9a5834ae 2722
58d745ec
RS
2723/* Return the file location of DEFINE_* rtx X, which was previously
2724 returned by read_md_rtx. */
2725file_location
2726get_file_location (rtx x)
2727{
2728 gcc_assert (rtx_locs);
2729 file_location *entry = rtx_locs->get (x);
2730 gcc_assert (entry);
2731 return *entry;
2732}
2733
ba0ee63d
RS
2734/* Return the number of possible INSN_CODEs. Only meaningful once the
2735 whole file has been processed. */
2736unsigned int
2737get_num_insn_codes ()
2738{
72a35f93 2739 return insn_sequence_num;
ba0ee63d
RS
2740}
2741
d1427a17
RS
2742/* Return the C test that says whether definition rtx DEF can be used,
2743 or "" if it can be used unconditionally. */
2744
2745const char *
2746get_c_test (rtx x)
2747{
2748 switch (GET_CODE (x))
2749 {
2750 case DEFINE_INSN:
2751 case DEFINE_EXPAND:
2752 case DEFINE_SUBST:
2753 return XSTR (x, 2);
2754
2755 case DEFINE_SPLIT:
2756 case DEFINE_PEEPHOLE:
2757 case DEFINE_PEEPHOLE2:
2758 return XSTR (x, 1);
2759
2760 default:
2761 return "";
2762 }
2763}
2764
2199e5fa
ZW
2765/* Helper functions for insn elision. */
2766
2767/* Compute a hash function of a c_test structure, which is keyed
2768 by its ->expr field. */
2769hashval_t
3d7aafde 2770hash_c_test (const void *x)
2199e5fa
ZW
2771{
2772 const struct c_test *a = (const struct c_test *) x;
2773 const unsigned char *base, *s = (const unsigned char *) a->expr;
2774 hashval_t hash;
2775 unsigned char c;
2776 unsigned int len;
2777
2778 base = s;
2779 hash = 0;
2780
2781 while ((c = *s++) != '\0')
2782 {
2783 hash += c + (c << 17);
2784 hash ^= hash >> 2;
2785 }
2786
2787 len = s - base;
2788 hash += len + (len << 17);
2789 hash ^= hash >> 2;
2790
2791 return hash;
2792}
2793
2794/* Compare two c_test expression structures. */
2795int
3d7aafde 2796cmp_c_test (const void *x, const void *y)
2199e5fa
ZW
2797{
2798 const struct c_test *a = (const struct c_test *) x;
2799 const struct c_test *b = (const struct c_test *) y;
2800
2801 return !strcmp (a->expr, b->expr);
2802}
2803
2804/* Given a string representing a C test expression, look it up in the
2805 condition_table and report whether or not its value is known
2806 at compile time. Returns a tristate: 1 for known true, 0 for
2807 known false, -1 for unknown. */
2808int
3d7aafde 2809maybe_eval_c_test (const char *expr)
2199e5fa
ZW
2810{
2811 const struct c_test *test;
2812 struct c_test dummy;
2813
52831d13 2814 if (expr[0] == 0)
2199e5fa
ZW
2815 return 1;
2816
2199e5fa 2817 dummy.expr = expr;
5d038c4c 2818 test = (const struct c_test *)htab_find (condition_table, &dummy);
1c7352cd
ZW
2819 if (!test)
2820 return -1;
2199e5fa
ZW
2821 return test->value;
2822}
2823
1c7352cd
ZW
2824/* Record the C test expression EXPR in the condition_table, with
2825 value VAL. Duplicates clobber previous entries. */
2826
2827void
2828add_c_test (const char *expr, int value)
2829{
2830 struct c_test *test;
2831
2832 if (expr[0] == 0)
2833 return;
2834
2835 test = XNEW (struct c_test);
2836 test->expr = expr;
2837 test->value = value;
2838
2839 *(htab_find_slot (condition_table, test, INSERT)) = test;
2840}
2841
2842/* For every C test, call CALLBACK with two arguments: a pointer to
2843 the condition structure and INFO. Stops when CALLBACK returns zero. */
2844void
2845traverse_c_tests (htab_trav callback, void *info)
2846{
2847 if (condition_table)
2848 htab_traverse (condition_table, callback, info);
2849}
2850
e543e219
ZW
2851/* Helper functions for define_predicate and define_special_predicate
2852 processing. Shared between genrecog.c and genpreds.c. */
2853
2854static htab_t predicate_table;
2855struct pred_data *first_predicate;
2856static struct pred_data **last_predicate = &first_predicate;
2857
2858static hashval_t
2859hash_struct_pred_data (const void *ptr)
2860{
2861 return htab_hash_string (((const struct pred_data *)ptr)->name);
2862}
2863
2864static int
2865eq_struct_pred_data (const void *a, const void *b)
2866{
2867 return !strcmp (((const struct pred_data *)a)->name,
2868 ((const struct pred_data *)b)->name);
2869}
2870
2871struct pred_data *
2872lookup_predicate (const char *name)
2873{
2874 struct pred_data key;
2875 key.name = name;
cceb1885 2876 return (struct pred_data *) htab_find (predicate_table, &key);
e543e219
ZW
2877}
2878
e663da80
RS
2879/* Record that predicate PRED can accept CODE. */
2880
2881void
2882add_predicate_code (struct pred_data *pred, enum rtx_code code)
2883{
2884 if (!pred->codes[code])
2885 {
2886 pred->num_codes++;
2887 pred->codes[code] = true;
2888
2889 if (GET_RTX_CLASS (code) != RTX_CONST_OBJ)
2890 pred->allows_non_const = true;
2891
2892 if (code != REG
2893 && code != SUBREG
2894 && code != MEM
2895 && code != CONCAT
2896 && code != PARALLEL
a8fd4225 2897 && code != STRICT_LOW_PART
4822d9cb 2898 && code != ZERO_EXTRACT
a8fd4225 2899 && code != SCRATCH)
e663da80
RS
2900 pred->allows_non_lvalue = true;
2901
2902 if (pred->num_codes == 1)
2903 pred->singleton = code;
2904 else if (pred->num_codes == 2)
2905 pred->singleton = UNKNOWN;
2906 }
2907}
2908
e543e219
ZW
2909void
2910add_predicate (struct pred_data *pred)
2911{
2912 void **slot = htab_find_slot (predicate_table, pred, INSERT);
2913 if (*slot)
2914 {
2915 error ("duplicate predicate definition for '%s'", pred->name);
2916 return;
2917 }
2918 *slot = pred;
2919 *last_predicate = pred;
2920 last_predicate = &pred->next;
2921}
2922
2923/* This array gives the initial content of the predicate table. It
c2acaf06 2924 has entries for all predicates defined in recog.c. */
e543e219 2925
ebce9df7 2926struct std_pred_table
e543e219
ZW
2927{
2928 const char *name;
ebce9df7 2929 bool special;
e663da80 2930 bool allows_const_p;
e543e219
ZW
2931 RTX_CODE codes[NUM_RTX_CODE];
2932};
2933
ebce9df7 2934static const struct std_pred_table std_preds[] = {
e663da80 2935 {"general_operand", false, true, {SUBREG, REG, MEM}},
0060d7d7
RS
2936 {"address_operand", true, true, {SUBREG, REG, MEM, PLUS, MINUS, MULT,
2937 ZERO_EXTEND, SIGN_EXTEND, AND}},
e663da80
RS
2938 {"register_operand", false, false, {SUBREG, REG}},
2939 {"pmode_register_operand", true, false, {SUBREG, REG}},
2940 {"scratch_operand", false, false, {SCRATCH, REG}},
81f40b79 2941 {"immediate_operand", false, true, {UNKNOWN}},
e663da80 2942 {"const_int_operand", false, false, {CONST_INT}},
807e902e
KZ
2943#if TARGET_SUPPORTS_WIDE_INT
2944 {"const_scalar_int_operand", false, false, {CONST_INT, CONST_WIDE_INT}},
2945 {"const_double_operand", false, false, {CONST_DOUBLE}},
2946#else
e663da80 2947 {"const_double_operand", false, false, {CONST_INT, CONST_DOUBLE}},
807e902e 2948#endif
e663da80
RS
2949 {"nonimmediate_operand", false, false, {SUBREG, REG, MEM}},
2950 {"nonmemory_operand", false, true, {SUBREG, REG}},
2951 {"push_operand", false, false, {MEM}},
2952 {"pop_operand", false, false, {MEM}},
2953 {"memory_operand", false, false, {SUBREG, MEM}},
2954 {"indirect_operand", false, false, {SUBREG, MEM}},
c6963675
PB
2955 {"ordered_comparison_operator", false, false, {EQ, NE,
2956 LE, LT, GE, GT,
2957 LEU, LTU, GEU, GTU}},
e663da80
RS
2958 {"comparison_operator", false, false, {EQ, NE,
2959 LE, LT, GE, GT,
2960 LEU, LTU, GEU, GTU,
2961 UNORDERED, ORDERED,
2962 UNEQ, UNGE, UNGT,
2963 UNLE, UNLT, LTGT}}
e543e219 2964};
ebce9df7 2965#define NUM_KNOWN_STD_PREDS ARRAY_SIZE (std_preds)
e543e219
ZW
2966
2967/* Initialize the table of predicate definitions, starting with
c2acaf06 2968 the information we have on generic predicates. */
e543e219
ZW
2969
2970static void
2971init_predicate_table (void)
2972{
2973 size_t i, j;
2974 struct pred_data *pred;
2975
2976 predicate_table = htab_create_alloc (37, hash_struct_pred_data,
2977 eq_struct_pred_data, 0,
2978 xcalloc, free);
2979
ebce9df7 2980 for (i = 0; i < NUM_KNOWN_STD_PREDS; i++)
e543e219 2981 {
cceb1885 2982 pred = XCNEW (struct pred_data);
ebce9df7
PB
2983 pred->name = std_preds[i].name;
2984 pred->special = std_preds[i].special;
e543e219 2985
ebce9df7 2986 for (j = 0; std_preds[i].codes[j] != 0; j++)
e663da80
RS
2987 add_predicate_code (pred, std_preds[i].codes[j]);
2988
2989 if (std_preds[i].allows_const_p)
2990 for (j = 0; j < NUM_RTX_CODE; j++)
2991 if (GET_RTX_CLASS (j) == RTX_CONST_OBJ)
bbbbb16a 2992 add_predicate_code (pred, (enum rtx_code) j);
b8698a0f 2993
e543e219
ZW
2994 add_predicate (pred);
2995 }
e543e219 2996}
0458fe77
ZW
2997\f
2998/* These functions allow linkage with print-rtl.c. Also, some generators
2999 like to annotate their output with insn names. */
3000
3001/* Holds an array of names indexed by insn_code_number. */
3002static char **insn_name_ptr = 0;
3003static int insn_name_ptr_size = 0;
3004
3005const char *
3006get_insn_name (int code)
3007{
3008 if (code < insn_name_ptr_size)
3009 return insn_name_ptr[code];
3010 else
3011 return NULL;
3012}
3013
3014static void
3015record_insn_name (int code, const char *name)
3016{
3017 static const char *last_real_name = "insn";
3018 static int last_real_code = 0;
8ad97cfc 3019 char *new_name;
0458fe77
ZW
3020
3021 if (insn_name_ptr_size <= code)
3022 {
3023 int new_size;
3024 new_size = (insn_name_ptr_size ? insn_name_ptr_size * 2 : 512);
7cbb2a85 3025 insn_name_ptr = XRESIZEVEC (char *, insn_name_ptr, new_size);
0458fe77 3026 memset (insn_name_ptr + insn_name_ptr_size, 0,
c3284718 3027 sizeof (char *) * (new_size - insn_name_ptr_size));
0458fe77
ZW
3028 insn_name_ptr_size = new_size;
3029 }
3030
3031 if (!name || name[0] == '\0')
3032 {
8ad97cfc
KG
3033 new_name = XNEWVAR (char, strlen (last_real_name) + 10);
3034 sprintf (new_name, "%s+%d", last_real_name, code - last_real_code);
0458fe77
ZW
3035 }
3036 else
3037 {
8ad97cfc 3038 last_real_name = new_name = xstrdup (name);
0458fe77
ZW
3039 last_real_code = code;
3040 }
3041
8ad97cfc 3042 insn_name_ptr[code] = new_name;
0458fe77 3043}
e792559a
RS
3044\f
3045/* Make STATS describe the operands that appear in rtx X. */
3046
3047static void
3048get_pattern_stats_1 (struct pattern_stats *stats, rtx x)
3049{
3050 RTX_CODE code;
3051 int i;
3052 int len;
3053 const char *fmt;
3054
3055 if (x == NULL_RTX)
3056 return;
3057
3058 code = GET_CODE (x);
3059 switch (code)
3060 {
3061 case MATCH_OPERAND:
3062 case MATCH_OPERATOR:
3063 case MATCH_PARALLEL:
3064 stats->max_opno = MAX (stats->max_opno, XINT (x, 0));
3065 break;
3066
3067 case MATCH_DUP:
3068 case MATCH_OP_DUP:
3069 case MATCH_PAR_DUP:
3070 stats->num_dups++;
3071 stats->max_dup_opno = MAX (stats->max_dup_opno, XINT (x, 0));
3072 break;
3073
3074 case MATCH_SCRATCH:
d5a216fa
JJ
3075 if (stats->min_scratch_opno == -1)
3076 stats->min_scratch_opno = XINT (x, 0);
3077 else
3078 stats->min_scratch_opno = MIN (stats->min_scratch_opno, XINT (x, 0));
e792559a
RS
3079 stats->max_scratch_opno = MAX (stats->max_scratch_opno, XINT (x, 0));
3080 break;
3081
3082 default:
3083 break;
3084 }
3085
3086 fmt = GET_RTX_FORMAT (code);
3087 len = GET_RTX_LENGTH (code);
3088 for (i = 0; i < len; i++)
3089 {
3090 if (fmt[i] == 'e' || fmt[i] == 'u')
3091 get_pattern_stats_1 (stats, XEXP (x, i));
3092 else if (fmt[i] == 'E')
3093 {
3094 int j;
3095 for (j = 0; j < XVECLEN (x, i); j++)
3096 get_pattern_stats_1 (stats, XVECEXP (x, i, j));
3097 }
3098 }
3099}
3100
3101/* Make STATS describe the operands that appear in instruction pattern
3102 PATTERN. */
3103
3104void
3105get_pattern_stats (struct pattern_stats *stats, rtvec pattern)
3106{
3107 int i, len;
3108
3109 stats->max_opno = -1;
3110 stats->max_dup_opno = -1;
d5a216fa 3111 stats->min_scratch_opno = -1;
e792559a
RS
3112 stats->max_scratch_opno = -1;
3113 stats->num_dups = 0;
3114
3115 len = GET_NUM_ELEM (pattern);
3116 for (i = 0; i < len; i++)
3117 get_pattern_stats_1 (stats, RTVEC_ELT (pattern, i));
3118
3119 stats->num_generator_args = stats->max_opno + 1;
3120 stats->num_insn_operands = MAX (stats->max_opno,
3121 stats->max_scratch_opno) + 1;
3122 stats->num_operand_vars = MAX (stats->max_opno,
3123 MAX (stats->max_dup_opno,
3124 stats->max_scratch_opno)) + 1;
3125}
3beaff21 3126
9d8895c9
RS
3127/* Return the emit_* function that should be used for pattern X, or NULL
3128 if we can't pick a particular type at compile time and should instead
3129 fall back to "emit". */
3beaff21
RS
3130
3131const char *
3132get_emit_function (rtx x)
3133{
3134 switch (classify_insn (x))
3135 {
3136 case INSN:
3137 return "emit_insn";
3138
3139 case CALL_INSN:
3140 return "emit_call_insn";
3141
3142 case JUMP_INSN:
3143 return "emit_jump_insn";
3144
3145 case UNKNOWN:
9d8895c9 3146 return NULL;
3beaff21
RS
3147
3148 default:
3149 gcc_unreachable ();
3150 }
3151}
3152
3153/* Return true if we must emit a barrier after pattern X. */
3154
3155bool
3156needs_barrier_p (rtx x)
3157{
3158 return (GET_CODE (x) == SET
3159 && GET_CODE (SET_DEST (x)) == PC
3160 && GET_CODE (SET_SRC (x)) == LABEL_REF);
3161}
886456e2
RS
3162
3163#define NS "NULL"
3164#define ZS "'\\0'"
3165#define OPTAB_CL(o, p, c, b, l) { #o, p, #b, ZS, #l, o, c, UNKNOWN, 1 },
3166#define OPTAB_CX(o, p) { #o, p, NULL, NULL, NULL, o, UNKNOWN, UNKNOWN, 1 },
3167#define OPTAB_CD(o, p) { #o, p, NS, ZS, NS, o, UNKNOWN, UNKNOWN, 2 },
3168#define OPTAB_NL(o, p, c, b, s, l) { #o, p, #b, #s, #l, o, c, c, 3 },
3169#define OPTAB_NC(o, p, c) { #o, p, NS, ZS, NS, o, c, c, 3 },
3170#define OPTAB_NX(o, p) { #o, p, NULL, NULL, NULL, o, UNKNOWN, UNKNOWN, 3 },
3171#define OPTAB_VL(o, p, c, b, s, l) { #o, p, #b, #s, #l, o, c, UNKNOWN, 3 },
3172#define OPTAB_VC(o, p, c) { #o, p, NS, ZS, NS, o, c, UNKNOWN, 3 },
3173#define OPTAB_VX(o, p) { #o, p, NULL, NULL, NULL, o, UNKNOWN, UNKNOWN, 3 },
3174#define OPTAB_DC(o, p, c) { #o, p, NS, ZS, NS, o, c, c, 4 },
3175#define OPTAB_D(o, p) { #o, p, NS, ZS, NS, o, UNKNOWN, UNKNOWN, 4 },
3176
3177/* An array of all optabs. Note that the same optab can appear more
3178 than once, with a different pattern. */
3179optab_def optabs[] = {
3180 { "unknown_optab", NULL, NS, ZS, NS, unknown_optab, UNKNOWN, UNKNOWN, 0 },
3181#include "optabs.def"
3182};
3183
3184/* The number of entries in optabs[]. */
3185unsigned int num_optabs = ARRAY_SIZE (optabs);
3186
3187#undef OPTAB_CL
3188#undef OPTAB_CX
3189#undef OPTAB_CD
3190#undef OPTAB_NL
3191#undef OPTAB_NC
3192#undef OPTAB_NX
3193#undef OPTAB_VL
3194#undef OPTAB_VC
3195#undef OPTAB_VX
3196#undef OPTAB_DC
3197#undef OPTAB_D
3198
3199/* Return true if instruction NAME matches pattern PAT, storing information
3200 about the match in P if so. */
3201
3202static bool
3203match_pattern (optab_pattern *p, const char *name, const char *pat)
3204{
3205 bool force_float = false;
3206 bool force_int = false;
3207 bool force_partial_int = false;
3208 bool force_fixed = false;
3209
3210 if (pat == NULL)
3211 return false;
3212 for (; ; ++pat)
3213 {
3214 if (*pat != '$')
3215 {
3216 if (*pat != *name++)
3217 return false;
3218 if (*pat == '\0')
3219 return true;
3220 continue;
3221 }
3222 switch (*++pat)
3223 {
3224 case 'I':
3225 force_int = 1;
3226 break;
3227 case 'P':
3228 force_partial_int = 1;
3229 break;
3230 case 'F':
3231 force_float = 1;
3232 break;
3233 case 'Q':
3234 force_fixed = 1;
3235 break;
3236
3237 case 'a':
3238 case 'b':
3239 {
3240 int i;
3241
3242 /* This loop will stop at the first prefix match, so
3243 look through the modes in reverse order, in case
3244 there are extra CC modes and CC is a prefix of the
3245 CC modes (as it should be). */
3246 for (i = (MAX_MACHINE_MODE) - 1; i >= 0; i--)
3247 {
3248 const char *p, *q;
3249 for (p = GET_MODE_NAME (i), q = name; *p; p++, q++)
3250 if (TOLOWER (*p) != *q)
3251 break;
3252 if (*p == 0
3253 && (! force_int || mode_class[i] == MODE_INT
3254 || mode_class[i] == MODE_VECTOR_INT)
3255 && (! force_partial_int
3256 || mode_class[i] == MODE_INT
3257 || mode_class[i] == MODE_PARTIAL_INT
3258 || mode_class[i] == MODE_VECTOR_INT)
3259 && (! force_float
3260 || mode_class[i] == MODE_FLOAT
3261 || mode_class[i] == MODE_DECIMAL_FLOAT
3262 || mode_class[i] == MODE_COMPLEX_FLOAT
3263 || mode_class[i] == MODE_VECTOR_FLOAT)
3264 && (! force_fixed
3265 || mode_class[i] == MODE_FRACT
3266 || mode_class[i] == MODE_UFRACT
3267 || mode_class[i] == MODE_ACCUM
3268 || mode_class[i] == MODE_UACCUM
3269 || mode_class[i] == MODE_VECTOR_FRACT
3270 || mode_class[i] == MODE_VECTOR_UFRACT
3271 || mode_class[i] == MODE_VECTOR_ACCUM
3272 || mode_class[i] == MODE_VECTOR_UACCUM))
3273 break;
3274 }
3275
3276 if (i < 0)
3277 return false;
3278 name += strlen (GET_MODE_NAME (i));
3279 if (*pat == 'a')
3280 p->m1 = i;
3281 else
3282 p->m2 = i;
3283
3284 force_int = false;
3285 force_partial_int = false;
3286 force_float = false;
3287 force_fixed = false;
3288 }
3289 break;
3290
3291 default:
3292 gcc_unreachable ();
3293 }
3294 }
3295}
3296
3297/* Return true if NAME is the name of an optab, describing it in P if so. */
3298
3299bool
3300find_optab (optab_pattern *p, const char *name)
3301{
3302 if (*name == 0 || *name == '*')
3303 return false;
3304
3305 /* See if NAME matches one of the patterns we have for the optabs
3306 we know about. */
3307 for (unsigned int pindex = 0; pindex < ARRAY_SIZE (optabs); pindex++)
3308 {
3309 p->m1 = p->m2 = 0;
3310 if (match_pattern (p, name, optabs[pindex].pattern))
3311 {
3312 p->name = name;
3313 p->op = optabs[pindex].op;
3314 p->sort_num = (p->op << 16) | (p->m2 << 8) | p->m1;
3315 return true;
3316 }
3317 }
3318 return false;
3319}