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