Branch data Line data Source code
1 : : /* RTL utility routines.
2 : : Copyright (C) 1987-2024 Free Software Foundation, Inc.
3 : :
4 : : This file is part of GCC.
5 : :
6 : : GCC is free software; you can redistribute it and/or modify it under
7 : : the terms of the GNU General Public License as published by the Free
8 : : Software Foundation; either version 3, or (at your option) any later
9 : : version.
10 : :
11 : : GCC is distributed in the hope that it will be useful, but WITHOUT ANY
12 : : WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 : : FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 : : for more details.
15 : :
16 : : You should have received a copy of the GNU General Public License
17 : : along with GCC; see the file COPYING3. If not see
18 : : <http://www.gnu.org/licenses/>. */
19 : :
20 : : /* This file is compiled twice: once for the generator programs
21 : : once for the compiler. */
22 : : #ifdef GENERATOR_FILE
23 : : #include "bconfig.h"
24 : : #else
25 : : #include "config.h"
26 : : #endif
27 : :
28 : : #include "system.h"
29 : : #include "coretypes.h"
30 : : #include "tm.h"
31 : : #include "rtl.h"
32 : : #ifdef GENERATOR_FILE
33 : : # include "errors.h"
34 : : #else
35 : : # include "rtlhash.h"
36 : : # include "diagnostic-core.h"
37 : : #endif
38 : :
39 : :
40 : : /* Indexed by rtx code, gives number of operands for an rtx with that code.
41 : : Does NOT include rtx header data (code and links). */
42 : :
43 : : #define DEF_RTL_EXPR(ENUM, NAME, FORMAT, CLASS) sizeof FORMAT - 1 ,
44 : :
45 : : const unsigned char rtx_length[NUM_RTX_CODE] = {
46 : : #include "rtl.def"
47 : : };
48 : :
49 : : #undef DEF_RTL_EXPR
50 : :
51 : : /* Indexed by rtx code, gives the name of that kind of rtx, as a C string. */
52 : :
53 : : #define DEF_RTL_EXPR(ENUM, NAME, FORMAT, CLASS) NAME ,
54 : :
55 : : const char * const rtx_name[NUM_RTX_CODE] = {
56 : : #include "rtl.def" /* rtl expressions are documented here */
57 : : };
58 : :
59 : : #undef DEF_RTL_EXPR
60 : :
61 : : /* Indexed by rtx code, gives a sequence of operand-types for
62 : : rtx's of that code. The sequence is a C string in which
63 : : each character describes one operand. */
64 : :
65 : : const char * const rtx_format[NUM_RTX_CODE] = {
66 : : /* "*" undefined.
67 : : can cause a warning message
68 : : "0" field is unused (or used in a phase-dependent manner)
69 : : prints nothing
70 : : "i" an integer
71 : : prints the integer
72 : : "n" like "i", but prints entries from `note_insn_name'
73 : : "w" an integer of width HOST_BITS_PER_WIDE_INT
74 : : prints the integer
75 : : "s" a pointer to a string
76 : : prints the string
77 : : "S" like "s", but optional:
78 : : the containing rtx may end before this operand
79 : : "T" like "s", but treated specially by the RTL reader;
80 : : only found in machine description patterns.
81 : : "e" a pointer to an rtl expression
82 : : prints the expression
83 : : "E" a pointer to a vector that points to a number of rtl expressions
84 : : prints a list of the rtl expressions
85 : : "V" like "E", but optional:
86 : : the containing rtx may end before this operand
87 : : "u" a pointer to another insn
88 : : prints the uid of the insn.
89 : : "b" is a pointer to a bitmap header.
90 : : "B" is a basic block pointer.
91 : : "t" is a tree pointer.
92 : : "r" a register.
93 : : "p" is a poly_uint16 offset. */
94 : :
95 : : #define DEF_RTL_EXPR(ENUM, NAME, FORMAT, CLASS) FORMAT ,
96 : : #include "rtl.def" /* rtl expressions are defined here */
97 : : #undef DEF_RTL_EXPR
98 : : };
99 : :
100 : : /* Indexed by rtx code, gives a character representing the "class" of
101 : : that rtx code. See rtl.def for documentation on the defined classes. */
102 : :
103 : : const enum rtx_class rtx_class[NUM_RTX_CODE] = {
104 : : #define DEF_RTL_EXPR(ENUM, NAME, FORMAT, CLASS) CLASS,
105 : : #include "rtl.def" /* rtl expressions are defined here */
106 : : #undef DEF_RTL_EXPR
107 : : };
108 : :
109 : : /* Whether rtxs with the given code store data in the hwint field. */
110 : :
111 : : #define RTX_CODE_HWINT_P_1(ENUM) \
112 : : ((ENUM) == CONST_INT || (ENUM) == CONST_DOUBLE \
113 : : || (ENUM) == CONST_FIXED || (ENUM) == CONST_WIDE_INT)
114 : : #ifdef GENERATOR_FILE
115 : : #define RTX_CODE_HWINT_P(ENUM) \
116 : : (RTX_CODE_HWINT_P_1 (ENUM) || (ENUM) == EQ_ATTR_ALT)
117 : : #else
118 : : #define RTX_CODE_HWINT_P RTX_CODE_HWINT_P_1
119 : : #endif
120 : :
121 : : /* Indexed by rtx code, gives the size of the rtx in bytes. */
122 : :
123 : : const unsigned char rtx_code_size[NUM_RTX_CODE] = {
124 : : #define DEF_RTL_EXPR(ENUM, NAME, FORMAT, CLASS) \
125 : : (RTX_CODE_HWINT_P (ENUM) \
126 : : ? RTX_HDR_SIZE + (sizeof FORMAT - 1) * sizeof (HOST_WIDE_INT) \
127 : : : (ENUM) == REG \
128 : : ? RTX_HDR_SIZE + sizeof (reg_info) \
129 : : : RTX_HDR_SIZE + (sizeof FORMAT - 1) * sizeof (rtunion)),
130 : :
131 : : #include "rtl.def"
132 : : #undef DEF_RTL_EXPR
133 : : };
134 : :
135 : : /* Names for kinds of NOTEs and REG_NOTEs. */
136 : :
137 : : const char * const note_insn_name[NOTE_INSN_MAX] =
138 : : {
139 : : #define DEF_INSN_NOTE(NAME) #NAME,
140 : : #include "insn-notes.def"
141 : : #undef DEF_INSN_NOTE
142 : : };
143 : :
144 : : const char * const reg_note_name[REG_NOTE_MAX] =
145 : : {
146 : : #define DEF_REG_NOTE(NAME) #NAME,
147 : : #include "reg-notes.def"
148 : : #undef DEF_REG_NOTE
149 : : };
150 : :
151 : : static size_t rtx_alloc_counts[(int) LAST_AND_UNUSED_RTX_CODE];
152 : : static size_t rtx_alloc_sizes[(int) LAST_AND_UNUSED_RTX_CODE];
153 : : static size_t rtvec_alloc_counts;
154 : : static size_t rtvec_alloc_sizes;
155 : :
156 : :
157 : : /* Allocate an rtx vector of N elements.
158 : : Store the length, and initialize all elements to zero. */
159 : :
160 : : rtvec
161 : 96600328 : rtvec_alloc (size_t n)
162 : : {
163 : 96600328 : rtvec rt;
164 : :
165 : : /* rtvec_def.num_elem is an int. */
166 : 96600328 : gcc_assert (n < INT_MAX);
167 : :
168 : 96600328 : rt = ggc_alloc_rtvec_sized (n);
169 : : /* Clear out the vector. */
170 : 96600328 : memset (&rt->elem[0], 0, n * sizeof (rtx));
171 : :
172 : 96600328 : PUT_NUM_ELEM (rt, n);
173 : :
174 : 96600328 : if (GATHER_STATISTICS)
175 : : {
176 : : rtvec_alloc_counts++;
177 : : rtvec_alloc_sizes += n * sizeof (rtx);
178 : : }
179 : :
180 : 96600328 : return rt;
181 : : }
182 : :
183 : : /* Create a bitwise copy of VEC. */
184 : :
185 : : rtvec
186 : 2164636 : shallow_copy_rtvec (rtvec vec)
187 : : {
188 : 2164636 : rtvec newvec;
189 : 2164636 : int n;
190 : :
191 : 2164636 : n = GET_NUM_ELEM (vec);
192 : 2164636 : newvec = rtvec_alloc (n);
193 : 2164636 : memcpy (&newvec->elem[0], &vec->elem[0], sizeof (rtx) * n);
194 : 2164636 : return newvec;
195 : : }
196 : :
197 : : /* Return the number of bytes occupied by rtx value X. */
198 : :
199 : : unsigned int
200 : 391213358 : rtx_size (const_rtx x)
201 : : {
202 : 391213358 : if (CONST_WIDE_INT_P (x))
203 : 0 : return (RTX_HDR_SIZE
204 : : + sizeof (struct hwivec_def)
205 : 0 : + ((CONST_WIDE_INT_NUNITS (x) - 1)
206 : 0 : * sizeof (HOST_WIDE_INT)));
207 : 391213358 : if (CONST_POLY_INT_P (x))
208 : : return (RTX_HDR_SIZE
209 : : + sizeof (struct const_poly_int_def)
210 : : + CONST_POLY_INT_COEFFS (x).extra_size ());
211 : 391213358 : if (GET_CODE (x) == SYMBOL_REF && SYMBOL_REF_HAS_BLOCK_INFO_P (x))
212 : : return RTX_HDR_SIZE + sizeof (struct block_symbol);
213 : 391213358 : return RTX_CODE_SIZE (GET_CODE (x));
214 : : }
215 : :
216 : : /* Allocate an rtx of code CODE with EXTRA bytes in it. The CODE is
217 : : stored in the rtx; all the rest is initialized to zero. */
218 : :
219 : : rtx
220 : 2363310537 : rtx_alloc_stat_v (RTX_CODE code MEM_STAT_DECL, int extra)
221 : : {
222 : 2363310537 : rtx rt = ggc_alloc_rtx_def_stat (RTX_CODE_SIZE (code) + extra
223 : : PASS_MEM_STAT);
224 : :
225 : 2363310537 : rtx_init (rt, code);
226 : :
227 : 2363310537 : if (GATHER_STATISTICS)
228 : : {
229 : : rtx_alloc_counts[code]++;
230 : : rtx_alloc_sizes[code] += RTX_CODE_SIZE (code);
231 : : }
232 : :
233 : 2363310537 : return rt;
234 : : }
235 : :
236 : : /* Allocate an rtx of code CODE. The CODE is stored in the rtx;
237 : : all the rest is initialized to zero. */
238 : :
239 : : rtx
240 : 2362756698 : rtx_alloc (RTX_CODE code MEM_STAT_DECL)
241 : : {
242 : 2362756698 : return rtx_alloc_stat_v (code PASS_MEM_STAT, 0);
243 : : }
244 : :
245 : : /* Write the wide constant X to OUTFILE. */
246 : :
247 : : void
248 : 12 : cwi_output_hex (FILE *outfile, const_rtx x)
249 : : {
250 : 12 : int i = CWI_GET_NUM_ELEM (x);
251 : 12 : gcc_assert (i > 0);
252 : 12 : if (CWI_ELT (x, i - 1) == 0)
253 : : /* The HOST_WIDE_INT_PRINT_HEX prepends a 0x only if the val is
254 : : non zero. We want all numbers to have a 0x prefix. */
255 : 10 : fprintf (outfile, "0x");
256 : 12 : fprintf (outfile, HOST_WIDE_INT_PRINT_HEX, CWI_ELT (x, --i));
257 : 36 : while (--i >= 0)
258 : 12 : fprintf (outfile, HOST_WIDE_INT_PRINT_PADDED_HEX, CWI_ELT (x, i));
259 : 12 : }
260 : :
261 : :
262 : : /* Return true if ORIG is a sharable CONST. */
263 : :
264 : : bool
265 : 41678329 : shared_const_p (const_rtx orig)
266 : : {
267 : 41678329 : gcc_assert (GET_CODE (orig) == CONST);
268 : :
269 : : /* CONST can be shared if it contains a SYMBOL_REF. If it contains
270 : : a LABEL_REF, it isn't sharable. */
271 : 41678329 : poly_int64 offset;
272 : 41678329 : return (GET_CODE (XEXP (orig, 0)) == PLUS
273 : 33523486 : && GET_CODE (XEXP (XEXP (orig, 0), 0)) == SYMBOL_REF
274 : 74651927 : && poly_int_rtx_p (XEXP (XEXP (orig, 0), 1), &offset));
275 : : }
276 : :
277 : :
278 : : /* Create a new copy of an rtx.
279 : : Recursively copies the operands of the rtx,
280 : : except for those few rtx codes that are sharable. */
281 : :
282 : : rtx
283 : 514501195 : copy_rtx (rtx orig)
284 : : {
285 : 514501195 : rtx copy;
286 : 514501195 : int i, j;
287 : 514501195 : RTX_CODE code;
288 : 514501195 : const char *format_ptr;
289 : :
290 : 514501195 : code = GET_CODE (orig);
291 : :
292 : 514501195 : switch (code)
293 : : {
294 : : case REG:
295 : : case DEBUG_EXPR:
296 : : case VALUE:
297 : : CASE_CONST_ANY:
298 : : case SYMBOL_REF:
299 : : case CODE_LABEL:
300 : : case PC:
301 : : case RETURN:
302 : : case SIMPLE_RETURN:
303 : : case SCRATCH:
304 : : /* SCRATCH must be shared because they represent distinct values. */
305 : : return orig;
306 : 217889 : case CLOBBER:
307 : : /* Share clobbers of hard registers, but do not share pseudo reg
308 : : clobbers or clobbers of hard registers that originated as pseudos.
309 : : This is needed to allow safe register renaming. */
310 : 109869 : if (REG_P (XEXP (orig, 0)) && REGNO (XEXP (orig, 0)) < FIRST_PSEUDO_REGISTER
311 : 327758 : && ORIGINAL_REGNO (XEXP (orig, 0)) == REGNO (XEXP (orig, 0)))
312 : : return orig;
313 : : break;
314 : :
315 : 3701977 : case CONST:
316 : 3701977 : if (shared_const_p (orig))
317 : : return orig;
318 : : break;
319 : :
320 : : /* A MEM with a constant address is not sharable. The problem is that
321 : : the constant address may need to be reloaded. If the mem is shared,
322 : : then reloading one copy of this mem will cause all copies to appear
323 : : to have been reloaded. */
324 : :
325 : : default:
326 : : break;
327 : : }
328 : :
329 : : /* Copy the various flags, fields, and other information. We assume
330 : : that all fields need copying, and then clear the fields that should
331 : : not be copied. That is the sensible default behavior, and forces
332 : : us to explicitly document why we are *not* copying a flag. */
333 : 158695109 : copy = shallow_copy_rtx (orig);
334 : :
335 : 158695109 : format_ptr = GET_RTX_FORMAT (GET_CODE (copy));
336 : :
337 : 473210505 : for (i = 0; i < GET_RTX_LENGTH (GET_CODE (copy)); i++)
338 : 314515396 : switch (*format_ptr++)
339 : : {
340 : 252552611 : case 'e':
341 : 252552611 : if (XEXP (orig, i) != NULL)
342 : 252251361 : XEXP (copy, i) = copy_rtx (XEXP (orig, i));
343 : : break;
344 : :
345 : 2067796 : case 'E':
346 : 2067796 : case 'V':
347 : 2067796 : if (XVEC (orig, i) != NULL)
348 : : {
349 : 2067796 : XVEC (copy, i) = rtvec_alloc (XVECLEN (orig, i));
350 : 6185794 : for (j = 0; j < XVECLEN (copy, i); j++)
351 : 4117998 : XVECEXP (copy, i, j) = copy_rtx (XVECEXP (orig, i, j));
352 : : }
353 : : break;
354 : :
355 : : case 't':
356 : : case 'w':
357 : : case 'i':
358 : : case 'p':
359 : : case 's':
360 : : case 'S':
361 : : case 'T':
362 : : case 'u':
363 : : case 'B':
364 : : case '0':
365 : : /* These are left unchanged. */
366 : : break;
367 : :
368 : 0 : default:
369 : 0 : gcc_unreachable ();
370 : : }
371 : : return copy;
372 : : }
373 : :
374 : : /* Create a new copy of an rtx. Only copy just one level. */
375 : :
376 : : rtx
377 : 391213358 : shallow_copy_rtx (const_rtx orig MEM_STAT_DECL)
378 : : {
379 : 391213358 : const unsigned int size = rtx_size (orig);
380 : 391213358 : rtx const copy = ggc_alloc_rtx_def_stat (size PASS_MEM_STAT);
381 : 391213358 : memcpy (copy, orig, size);
382 : 391213358 : switch (GET_CODE (orig))
383 : : {
384 : : /* RTX codes copy_rtx_if_shared_1 considers are shareable,
385 : : the used flag is often used for other purposes. */
386 : : case REG:
387 : : case DEBUG_EXPR:
388 : : case VALUE:
389 : : CASE_CONST_ANY:
390 : : case SYMBOL_REF:
391 : : case CODE_LABEL:
392 : : case PC:
393 : : case RETURN:
394 : : case SIMPLE_RETURN:
395 : : case SCRATCH:
396 : : break;
397 : 384747358 : default:
398 : : /* For all other RTXes clear the used flag on the copy.
399 : : CALL_INSN use "used" flag to indicate it's a fake call. */
400 : 384747358 : if (!INSN_P (orig))
401 : 384446108 : RTX_FLAG (copy, used) = 0;
402 : : break;
403 : : }
404 : 391213358 : return copy;
405 : : }
406 : :
407 : : /* Nonzero when we are generating CONCATs. */
408 : : int generating_concat_p;
409 : :
410 : : /* Nonzero when we are expanding trees to RTL. */
411 : : int currently_expanding_to_rtl;
412 : :
413 : :
414 : :
415 : : /* Return true if X and Y are identical-looking rtx's.
416 : : This is the Lisp function EQUAL for rtx arguments.
417 : :
418 : : Call CB on each pair of rtx if CB is not NULL.
419 : : When the callback returns true, we continue with the new pair. */
420 : :
421 : : bool
422 : 4590620190 : rtx_equal_p (const_rtx x, const_rtx y, rtx_equal_p_callback_function cb)
423 : : {
424 : 4590620190 : int i;
425 : 4590620190 : int j;
426 : 4590620190 : enum rtx_code code;
427 : 4590620190 : const char *fmt;
428 : 4590620190 : rtx nx, ny;
429 : :
430 : 4590620190 : if (x == y)
431 : : return true;
432 : 3385551808 : if (x == 0 || y == 0)
433 : : return false;
434 : :
435 : : /* Invoke the callback first. */
436 : 3138035622 : if (cb != NULL
437 : 3138035622 : && ((*cb) (&x, &y, &nx, &ny)))
438 : 0 : return rtx_equal_p (nx, ny, cb);
439 : :
440 : 3138035622 : code = GET_CODE (x);
441 : : /* Rtx's of different codes cannot be equal. */
442 : 3138035622 : if (code != GET_CODE (y))
443 : : return false;
444 : :
445 : : /* (MULT:SI x y) and (MULT:HI x y) are NOT equivalent.
446 : : (REG:SI x) and (REG:HI x) are NOT equivalent. */
447 : :
448 : 1672038923 : if (GET_MODE (x) != GET_MODE (y))
449 : : return false;
450 : :
451 : : /* MEMs referring to different address space are not equivalent. */
452 : 1168769371 : if (code == MEM && MEM_ADDR_SPACE (x) != MEM_ADDR_SPACE (y))
453 : : return false;
454 : :
455 : : /* Some RTL can be compared nonrecursively. */
456 : 1162811064 : switch (code)
457 : : {
458 : 728946040 : case REG:
459 : 728946040 : return (REGNO (x) == REGNO (y));
460 : :
461 : 4631918 : case LABEL_REF:
462 : 4631918 : return label_ref_label (x) == label_ref_label (y);
463 : :
464 : 62340035 : case SYMBOL_REF:
465 : 62340035 : return XSTR (x, 0) == XSTR (y, 0);
466 : :
467 : : case DEBUG_EXPR:
468 : : case VALUE:
469 : : case SCRATCH:
470 : : CASE_CONST_UNIQUE:
471 : : return false;
472 : :
473 : 3107139 : case CONST_VECTOR:
474 : 3107139 : if (!same_vector_encodings_p (x, y))
475 : : return false;
476 : : break;
477 : :
478 : 2252 : case DEBUG_IMPLICIT_PTR:
479 : 2252 : return DEBUG_IMPLICIT_PTR_DECL (x)
480 : 2252 : == DEBUG_IMPLICIT_PTR_DECL (y);
481 : :
482 : 0 : case DEBUG_PARAMETER_REF:
483 : 0 : return DEBUG_PARAMETER_REF_DECL (x)
484 : 0 : == DEBUG_PARAMETER_REF_DECL (y);
485 : :
486 : 36636 : case ENTRY_VALUE:
487 : 36636 : return rtx_equal_p (ENTRY_VALUE_EXP (x), ENTRY_VALUE_EXP (y), cb);
488 : :
489 : : default:
490 : : break;
491 : : }
492 : :
493 : : /* Compare the elements. If any pair of corresponding elements
494 : : fail to match, return 0 for the whole thing. */
495 : :
496 : 282902445 : fmt = GET_RTX_FORMAT (code);
497 : 492310301 : for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
498 : : {
499 : 417009743 : switch (fmt[i])
500 : : {
501 : 0 : case 'w':
502 : 0 : if (XWINT (x, i) != XWINT (y, i))
503 : : return false;
504 : : break;
505 : :
506 : 38806327 : case 'n':
507 : 38806327 : case 'i':
508 : 38806327 : if (XINT (x, i) != XINT (y, i))
509 : : {
510 : : #ifndef GENERATOR_FILE
511 : : if (((code == ASM_OPERANDS && i == 6)
512 : : || (code == ASM_INPUT && i == 1))
513 : : && XINT (x, i) == XINT (y, i))
514 : : break;
515 : : #endif
516 : : return false;
517 : : }
518 : : break;
519 : :
520 : 4941714 : case 'p':
521 : 4941714 : if (maybe_ne (SUBREG_BYTE (x), SUBREG_BYTE (y)))
522 : : return false;
523 : : break;
524 : :
525 : 5732544 : case 'V':
526 : 5732544 : case 'E':
527 : : /* Two vectors must have the same length. */
528 : 5732544 : if (XVECLEN (x, i) != XVECLEN (y, i))
529 : : return false;
530 : :
531 : : /* And the corresponding elements must match. */
532 : 8819202 : for (j = 0; j < XVECLEN (x, i); j++)
533 : 7713040 : if (!rtx_equal_p (XVECEXP (x, i, j), XVECEXP (y, i, j), cb))
534 : : return false;
535 : : break;
536 : :
537 : 310160229 : case 'e':
538 : 310160229 : if (!rtx_equal_p (XEXP (x, i), XEXP (y, i), cb))
539 : : return false;
540 : : break;
541 : :
542 : 110 : case 'S':
543 : 110 : case 's':
544 : 110 : if ((XSTR (x, i) || XSTR (y, i))
545 : 110 : && (! XSTR (x, i) || ! XSTR (y, i)
546 : 110 : || strcmp (XSTR (x, i), XSTR (y, i))))
547 : : return false;
548 : : break;
549 : :
550 : : case 'u':
551 : : /* These are just backpointers, so they don't matter. */
552 : : break;
553 : :
554 : : case '0':
555 : : case 't':
556 : : break;
557 : :
558 : : /* It is believed that rtx's at this level will never
559 : : contain anything but integers and other rtx's,
560 : : except for within LABEL_REFs and SYMBOL_REFs. */
561 : 0 : default:
562 : 0 : gcc_unreachable ();
563 : : }
564 : : }
565 : : return true;
566 : : }
567 : :
568 : : /* Return true if all elements of VEC are equal. */
569 : :
570 : : bool
571 : 155086 : rtvec_all_equal_p (const_rtvec vec)
572 : : {
573 : 155086 : const_rtx first = RTVEC_ELT (vec, 0);
574 : : /* Optimize the important special case of a vector of constants.
575 : : The main use of this function is to detect whether every element
576 : : of CONST_VECTOR is the same. */
577 : 155086 : switch (GET_CODE (first))
578 : : {
579 : 155086 : CASE_CONST_UNIQUE:
580 : 222951 : for (int i = 1, n = GET_NUM_ELEM (vec); i < n; ++i)
581 : 178038 : if (first != RTVEC_ELT (vec, i))
582 : : return false;
583 : : return true;
584 : :
585 : 0 : default:
586 : 0 : for (int i = 1, n = GET_NUM_ELEM (vec); i < n; ++i)
587 : 0 : if (!rtx_equal_p (first, RTVEC_ELT (vec, i)))
588 : : return false;
589 : : return true;
590 : : }
591 : : }
592 : :
593 : : /* Return true if VEC contains a linear series of integers
594 : : { START, START+1, START+2, ... }. */
595 : :
596 : : bool
597 : 599888 : rtvec_series_p (rtvec vec, int start)
598 : : {
599 : 961447 : for (int i = 0; i < GET_NUM_ELEM (vec); i++)
600 : : {
601 : 960473 : rtx x = RTVEC_ELT (vec, i);
602 : 960473 : if (!CONST_INT_P (x) || INTVAL (x) != i + start)
603 : : return false;
604 : : }
605 : : return true;
606 : : }
607 : :
608 : : /* Return an indication of which type of insn should have X as a body.
609 : : In generator files, this can be UNKNOWN if the answer is only known
610 : : at (GCC) runtime. Otherwise the value is CODE_LABEL, INSN, CALL_INSN
611 : : or JUMP_INSN. */
612 : :
613 : : enum rtx_code
614 : 10970026 : classify_insn (rtx x)
615 : : {
616 : 10970026 : if (LABEL_P (x))
617 : : return CODE_LABEL;
618 : 10970026 : if (GET_CODE (x) == CALL)
619 : : return CALL_INSN;
620 : 10970026 : if (ANY_RETURN_P (x))
621 : : return JUMP_INSN;
622 : 10970026 : if (GET_CODE (x) == ASM_OPERANDS && ASM_OPERANDS_LABEL_LENGTH (x))
623 : : return JUMP_INSN;
624 : 10970026 : if (GET_CODE (x) == SET)
625 : : {
626 : 8391859 : if (GET_CODE (SET_DEST (x)) == PC)
627 : : return JUMP_INSN;
628 : 14610 : else if (GET_CODE (SET_SRC (x)) == CALL)
629 : : return CALL_INSN;
630 : : else
631 : 14610 : return INSN;
632 : : }
633 : 2578167 : if (GET_CODE (x) == PARALLEL)
634 : : {
635 : 2541770 : int j;
636 : 2541770 : bool has_return_p = false;
637 : 8178067 : for (j = XVECLEN (x, 0) - 1; j >= 0; j--)
638 : 5636297 : if (GET_CODE (XVECEXP (x, 0, j)) == CALL)
639 : : return CALL_INSN;
640 : 5636297 : else if (ANY_RETURN_P (XVECEXP (x, 0, j)))
641 : : has_return_p = true;
642 : 5636297 : else if (GET_CODE (XVECEXP (x, 0, j)) == SET
643 : 3158922 : && GET_CODE (SET_DEST (XVECEXP (x, 0, j))) == PC)
644 : : return JUMP_INSN;
645 : 5636297 : else if (GET_CODE (XVECEXP (x, 0, j)) == SET
646 : 3158922 : && GET_CODE (SET_SRC (XVECEXP (x, 0, j))) == CALL)
647 : : return CALL_INSN;
648 : 2541770 : if (has_return_p)
649 : : return JUMP_INSN;
650 : 2541770 : if (GET_CODE (XVECEXP (x, 0, 0)) == ASM_OPERANDS
651 : 33 : && ASM_OPERANDS_LABEL_LENGTH (XVECEXP (x, 0, 0)))
652 : 1 : return JUMP_INSN;
653 : : }
654 : : #ifdef GENERATOR_FILE
655 : : if (GET_CODE (x) == MATCH_OPERAND
656 : : || GET_CODE (x) == MATCH_OPERATOR
657 : : || GET_CODE (x) == MATCH_PARALLEL
658 : : || GET_CODE (x) == MATCH_OP_DUP
659 : : || GET_CODE (x) == MATCH_DUP
660 : : || GET_CODE (x) == PARALLEL)
661 : : return UNKNOWN;
662 : : #endif
663 : : return INSN;
664 : : }
665 : :
666 : : /* Comparator of indices based on rtx_alloc_counts. */
667 : :
668 : : static int
669 : 0 : rtx_count_cmp (const void *p1, const void *p2)
670 : : {
671 : 0 : const unsigned *n1 = (const unsigned *)p1;
672 : 0 : const unsigned *n2 = (const unsigned *)p2;
673 : :
674 : 0 : return rtx_alloc_counts[*n1] - rtx_alloc_counts[*n2];
675 : : }
676 : :
677 : : void
678 : 0 : dump_rtx_statistics (void)
679 : : {
680 : 0 : int total_counts = 0;
681 : 0 : int total_sizes = 0;
682 : :
683 : 0 : if (! GATHER_STATISTICS)
684 : : {
685 : 0 : fprintf (stderr, "No RTX statistics\n");
686 : 0 : return;
687 : : }
688 : :
689 : : fprintf (stderr, "\nRTX Kind Count Bytes\n");
690 : : fprintf (stderr, "-------------------------------------------\n");
691 : :
692 : : auto_vec<unsigned> indices (LAST_AND_UNUSED_RTX_CODE);
693 : : for (unsigned i = 0; i < LAST_AND_UNUSED_RTX_CODE; i++)
694 : : indices.quick_push (i);
695 : : indices.qsort (rtx_count_cmp);
696 : :
697 : : for (unsigned i = 0; i < LAST_AND_UNUSED_RTX_CODE; i++)
698 : : {
699 : : unsigned j = indices[i];
700 : : if (rtx_alloc_counts[j])
701 : : {
702 : : fprintf (stderr, "%-24s " PRsa (6) " " PRsa (9) "\n",
703 : : GET_RTX_NAME (j),
704 : : SIZE_AMOUNT (rtx_alloc_counts[j]),
705 : : SIZE_AMOUNT (rtx_alloc_sizes[j]));
706 : : total_counts += rtx_alloc_counts[j];
707 : : total_sizes += rtx_alloc_sizes[j];
708 : : }
709 : : }
710 : :
711 : : if (rtvec_alloc_counts)
712 : : {
713 : : fprintf (stderr, "%-24s " PRsa (6) " " PRsa (9) "\n", "rtvec",
714 : : SIZE_AMOUNT (rtvec_alloc_counts),
715 : : SIZE_AMOUNT (rtvec_alloc_sizes));
716 : : total_counts += rtvec_alloc_counts;
717 : : total_sizes += rtvec_alloc_sizes;
718 : : }
719 : : fprintf (stderr, "-----------------------------------------------\n");
720 : : fprintf (stderr, "%-24s " PRsa (6) " " PRsa (9) "\n",
721 : : "Total", SIZE_AMOUNT (total_counts),
722 : : SIZE_AMOUNT (total_sizes));
723 : : fprintf (stderr, "-----------------------------------------------\n");
724 : : }
725 : :
726 : : #if defined ENABLE_RTL_CHECKING && (GCC_VERSION >= 2007)
727 : :
728 : : /* Disable warnings about missing quoting in GCC diagnostics for
729 : : the internal_error calls. Their format strings deliberately don't
730 : : follow GCC diagnostic conventions. */
731 : : #if __GNUC__ >= 10
732 : : #pragma GCC diagnostic push
733 : : #pragma GCC diagnostic ignored "-Wformat-diag"
734 : : #endif
735 : :
736 : : void
737 : : rtl_check_failed_bounds (const_rtx r, int n, const char *file, int line,
738 : : const char *func)
739 : : {
740 : : internal_error
741 : : ("RTL check: access of elt %d of '%s' with last elt %d in %s, at %s:%d",
742 : : n, GET_RTX_NAME (GET_CODE (r)), GET_RTX_LENGTH (GET_CODE (r)) - 1,
743 : : func, trim_filename (file), line);
744 : : }
745 : :
746 : : void
747 : : rtl_check_failed_type1 (const_rtx r, int n, int c1, const char *file, int line,
748 : : const char *func)
749 : : {
750 : : internal_error
751 : : ("RTL check: expected elt %d type '%c', have '%c' (rtx %s) in %s, at %s:%d",
752 : : n, c1, GET_RTX_FORMAT (GET_CODE (r))[n], GET_RTX_NAME (GET_CODE (r)),
753 : : func, trim_filename (file), line);
754 : : }
755 : :
756 : : void
757 : : rtl_check_failed_type2 (const_rtx r, int n, int c1, int c2, const char *file,
758 : : int line, const char *func)
759 : : {
760 : : internal_error
761 : : ("RTL check: expected elt %d type '%c' or '%c', have '%c' (rtx %s) in %s, at %s:%d",
762 : : n, c1, c2, GET_RTX_FORMAT (GET_CODE (r))[n], GET_RTX_NAME (GET_CODE (r)),
763 : : func, trim_filename (file), line);
764 : : }
765 : :
766 : : void
767 : : rtl_check_failed_code1 (const_rtx r, enum rtx_code code, const char *file,
768 : : int line, const char *func)
769 : : {
770 : : internal_error ("RTL check: expected code '%s', have '%s' in %s, at %s:%d",
771 : : GET_RTX_NAME (code), GET_RTX_NAME (GET_CODE (r)), func,
772 : : trim_filename (file), line);
773 : : }
774 : :
775 : : void
776 : : rtl_check_failed_code2 (const_rtx r, enum rtx_code code1, enum rtx_code code2,
777 : : const char *file, int line, const char *func)
778 : : {
779 : : internal_error
780 : : ("RTL check: expected code '%s' or '%s', have '%s' in %s, at %s:%d",
781 : : GET_RTX_NAME (code1), GET_RTX_NAME (code2), GET_RTX_NAME (GET_CODE (r)),
782 : : func, trim_filename (file), line);
783 : : }
784 : :
785 : : void
786 : : rtl_check_failed_code3 (const_rtx r, enum rtx_code code1, enum rtx_code code2,
787 : : enum rtx_code code3, const char *file, int line,
788 : : const char *func)
789 : : {
790 : : internal_error
791 : : ("RTL check: expected code '%s', '%s' or '%s', have '%s' in %s, at %s:%d",
792 : : GET_RTX_NAME (code1), GET_RTX_NAME (code2), GET_RTX_NAME (code3),
793 : : GET_RTX_NAME (GET_CODE (r)), func, trim_filename (file), line);
794 : : }
795 : :
796 : : void
797 : : rtl_check_failed_code_mode (const_rtx r, enum rtx_code code, machine_mode mode,
798 : : bool not_mode, const char *file, int line,
799 : : const char *func)
800 : : {
801 : : internal_error ((not_mode
802 : : ? ("RTL check: expected code '%s' and not mode '%s', "
803 : : "have code '%s' and mode '%s' in %s, at %s:%d")
804 : : : ("RTL check: expected code '%s' and mode '%s', "
805 : : "have code '%s' and mode '%s' in %s, at %s:%d")),
806 : : GET_RTX_NAME (code), GET_MODE_NAME (mode),
807 : : GET_RTX_NAME (GET_CODE (r)), GET_MODE_NAME (GET_MODE (r)),
808 : : func, trim_filename (file), line);
809 : : }
810 : :
811 : : #if __GNUC__ >= 10
812 : : #pragma GCC diagnostic pop
813 : : #endif
814 : :
815 : : /* Report that line LINE of FILE tried to access the block symbol fields
816 : : of a non-block symbol. FUNC is the function that contains the line. */
817 : :
818 : : void
819 : : rtl_check_failed_block_symbol (const char *file, int line, const char *func)
820 : : {
821 : : internal_error
822 : : ("RTL check: attempt to treat non-block symbol as a block symbol "
823 : : "in %s, at %s:%d", func, trim_filename (file), line);
824 : : }
825 : :
826 : : /* XXX Maybe print the vector? */
827 : : void
828 : : cwi_check_failed_bounds (const_rtx x, int n, const char *file, int line,
829 : : const char *func)
830 : : {
831 : : internal_error
832 : : ("RTL check: access of hwi elt %d of vector with last elt %d in %s, at %s:%d",
833 : : n, CWI_GET_NUM_ELEM (x) - 1, func, trim_filename (file), line);
834 : : }
835 : :
836 : : /* XXX Maybe print the vector? */
837 : : void
838 : : rtvec_check_failed_bounds (const_rtvec r, int n, const char *file, int line,
839 : : const char *func)
840 : : {
841 : : internal_error
842 : : ("RTL check: access of elt %d of vector with last elt %d in %s, at %s:%d",
843 : : n, GET_NUM_ELEM (r) - 1, func, trim_filename (file), line);
844 : : }
845 : : #endif /* ENABLE_RTL_CHECKING */
846 : :
847 : : #if defined ENABLE_RTL_FLAG_CHECKING
848 : : void
849 : 0 : rtl_check_failed_flag (const char *name, const_rtx r, const char *file,
850 : : int line, const char *func)
851 : : {
852 : 0 : internal_error
853 : 0 : ("RTL flag check: %s used with unexpected rtx code '%s' in %s, at %s:%d",
854 : 0 : name, GET_RTX_NAME (GET_CODE (r)), func, trim_filename (file), line);
855 : : }
856 : : #endif /* ENABLE_RTL_FLAG_CHECKING */
|