Line data Source code
1 : /* RTL utility routines.
2 : Copyright (C) 1987-2026 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 : "L" like "i", but correctly sized to hold a location_t,
74 : which may be configured as 32- or 64-bit.
75 : "w" an integer of width HOST_BITS_PER_WIDE_INT
76 : prints the integer
77 : "s" a pointer to a string
78 : prints the string
79 : "S" like "s", but optional:
80 : the containing rtx may end before this operand
81 : "T" like "s", but treated specially by the RTL reader;
82 : only found in machine description patterns.
83 : "e" a pointer to an rtl expression
84 : prints the expression
85 : "E" a pointer to a vector that points to a number of rtl expressions
86 : prints a list of the rtl expressions
87 : "V" like "E", but optional:
88 : the containing rtx may end before this operand
89 : "u" a pointer to another insn
90 : prints the uid of the insn.
91 : "b" is a pointer to a bitmap header.
92 : "B" is a basic block pointer.
93 : "t" is a tree pointer.
94 : "r" a register.
95 : "p" is a poly_uint16 offset. */
96 :
97 : #define DEF_RTL_EXPR(ENUM, NAME, FORMAT, CLASS) FORMAT ,
98 : #include "rtl.def" /* rtl expressions are defined here */
99 : #undef DEF_RTL_EXPR
100 : };
101 :
102 : /* Indexed by rtx code, gives a character representing the "class" of
103 : that rtx code. See rtl.def for documentation on the defined classes. */
104 :
105 : const enum rtx_class rtx_class[NUM_RTX_CODE] = {
106 : #define DEF_RTL_EXPR(ENUM, NAME, FORMAT, CLASS) CLASS,
107 : #include "rtl.def" /* rtl expressions are defined here */
108 : #undef DEF_RTL_EXPR
109 : };
110 :
111 : /* Whether rtxs with the given code store data in the hwint field. */
112 :
113 : #define RTX_CODE_HWINT_P_1(ENUM) \
114 : ((ENUM) == CONST_INT || (ENUM) == CONST_DOUBLE \
115 : || (ENUM) == CONST_FIXED || (ENUM) == CONST_WIDE_INT)
116 : #ifdef GENERATOR_FILE
117 : #define RTX_CODE_HWINT_P(ENUM) \
118 : (RTX_CODE_HWINT_P_1 (ENUM) || (ENUM) == EQ_ATTR_ALT)
119 : #else
120 : #define RTX_CODE_HWINT_P RTX_CODE_HWINT_P_1
121 : #endif
122 :
123 : /* Indexed by rtx code, gives the size of the rtx in bytes. */
124 :
125 : const unsigned char rtx_code_size[NUM_RTX_CODE] = {
126 : #define DEF_RTL_EXPR(ENUM, NAME, FORMAT, CLASS) \
127 : (RTX_CODE_HWINT_P (ENUM) \
128 : ? RTX_HDR_SIZE + (sizeof FORMAT - 1) * sizeof (HOST_WIDE_INT) \
129 : : (ENUM) == REG \
130 : ? RTX_HDR_SIZE + sizeof (reg_info) \
131 : : RTX_HDR_SIZE + (sizeof FORMAT - 1) * sizeof (rtunion)),
132 :
133 : #include "rtl.def"
134 : #undef DEF_RTL_EXPR
135 : };
136 :
137 : /* Names for kinds of NOTEs and REG_NOTEs. */
138 :
139 : const char * const note_insn_name[NOTE_INSN_MAX] =
140 : {
141 : #define DEF_INSN_NOTE(NAME) #NAME,
142 : #include "insn-notes.def"
143 : #undef DEF_INSN_NOTE
144 : };
145 :
146 : const char * const reg_note_name[REG_NOTE_MAX] =
147 : {
148 : #define DEF_REG_NOTE(NAME) #NAME,
149 : #include "reg-notes.def"
150 : #undef DEF_REG_NOTE
151 : };
152 :
153 : static size_t rtx_alloc_counts[(int) LAST_AND_UNUSED_RTX_CODE];
154 : static size_t rtx_alloc_sizes[(int) LAST_AND_UNUSED_RTX_CODE];
155 : static size_t rtvec_alloc_counts;
156 : static size_t rtvec_alloc_sizes;
157 :
158 :
159 : /* Allocate an rtx vector of N elements.
160 : Store the length, and initialize all elements to zero. */
161 :
162 : rtvec
163 104967761 : rtvec_alloc (size_t n)
164 : {
165 104967761 : rtvec rt;
166 :
167 : /* rtvec_def.num_elem is an int. */
168 104967761 : gcc_assert (n < INT_MAX);
169 :
170 104967761 : rt = ggc_alloc_rtvec_sized (n);
171 : /* Clear out the vector. */
172 104967761 : memset (&rt->elem[0], 0, n * sizeof (rtx));
173 :
174 104967761 : PUT_NUM_ELEM (rt, n);
175 :
176 104967761 : if (GATHER_STATISTICS)
177 : {
178 : rtvec_alloc_counts++;
179 : rtvec_alloc_sizes += n * sizeof (rtx);
180 : }
181 :
182 104967761 : return rt;
183 : }
184 :
185 : /* Create a bitwise copy of VEC. */
186 :
187 : rtvec
188 2340033 : shallow_copy_rtvec (rtvec vec)
189 : {
190 2340033 : rtvec newvec;
191 2340033 : int n;
192 :
193 2340033 : n = GET_NUM_ELEM (vec);
194 2340033 : newvec = rtvec_alloc (n);
195 2340033 : memcpy (&newvec->elem[0], &vec->elem[0], sizeof (rtx) * n);
196 2340033 : return newvec;
197 : }
198 :
199 : /* Return the number of bytes occupied by rtx value X. */
200 :
201 : unsigned int
202 465187505 : rtx_size (const_rtx x)
203 : {
204 465187505 : if (CONST_WIDE_INT_P (x))
205 0 : return (RTX_HDR_SIZE
206 : + sizeof (struct hwivec_def)
207 0 : + ((CONST_WIDE_INT_NUNITS (x) - 1)
208 0 : * sizeof (HOST_WIDE_INT)));
209 465187505 : if (CONST_POLY_INT_P (x))
210 : return (RTX_HDR_SIZE
211 : + sizeof (struct const_poly_int_def)
212 : + CONST_POLY_INT_COEFFS (x).extra_size ());
213 465187505 : if (GET_CODE (x) == SYMBOL_REF && SYMBOL_REF_HAS_BLOCK_INFO_P (x))
214 : return RTX_HDR_SIZE + sizeof (struct block_symbol);
215 465187505 : return RTX_CODE_SIZE (GET_CODE (x));
216 : }
217 :
218 : /* Allocate an rtx of code CODE with EXTRA bytes in it. The CODE is
219 : stored in the rtx; all the rest is initialized to zero. */
220 :
221 : rtx
222 2785180808 : rtx_alloc_stat_v (RTX_CODE code MEM_STAT_DECL, int extra)
223 : {
224 2785180808 : rtx rt = ggc_alloc_rtx_def_stat (RTX_CODE_SIZE (code) + extra
225 : PASS_MEM_STAT);
226 :
227 2785180808 : rtx_init (rt, code);
228 :
229 2785180808 : if (GATHER_STATISTICS)
230 : {
231 : rtx_alloc_counts[code]++;
232 : rtx_alloc_sizes[code] += RTX_CODE_SIZE (code);
233 : }
234 :
235 2785180808 : return rt;
236 : }
237 :
238 : /* Allocate an rtx of code CODE. The CODE is stored in the rtx;
239 : all the rest is initialized to zero. */
240 :
241 : rtx
242 2784606247 : rtx_alloc (RTX_CODE code MEM_STAT_DECL)
243 : {
244 2784606247 : return rtx_alloc_stat_v (code PASS_MEM_STAT, 0);
245 : }
246 :
247 : /* Write the wide constant X to OUTFILE. */
248 :
249 : void
250 12 : cwi_output_hex (FILE *outfile, const_rtx x)
251 : {
252 12 : int i = CWI_GET_NUM_ELEM (x);
253 12 : gcc_assert (i > 0);
254 12 : if (CWI_ELT (x, i - 1) == 0)
255 : /* The HOST_WIDE_INT_PRINT_HEX prepends a 0x only if the val is
256 : non zero. We want all numbers to have a 0x prefix. */
257 10 : fprintf (outfile, "0x");
258 12 : fprintf (outfile, HOST_WIDE_INT_PRINT_HEX, CWI_ELT (x, --i));
259 36 : while (--i >= 0)
260 12 : fprintf (outfile, HOST_WIDE_INT_PRINT_PADDED_HEX, CWI_ELT (x, i));
261 12 : }
262 :
263 :
264 : /* Return true if ORIG is a sharable CONST. */
265 :
266 : bool
267 47113484 : shared_const_p (const_rtx orig)
268 : {
269 47113484 : gcc_assert (GET_CODE (orig) == CONST);
270 :
271 : /* CONST can be shared if it contains a SYMBOL_REF. If it contains
272 : a LABEL_REF, it isn't sharable. */
273 47113484 : poly_int64 offset;
274 47113484 : return (GET_CODE (XEXP (orig, 0)) == PLUS
275 38131316 : && GET_CODE (XEXP (XEXP (orig, 0), 0)) == SYMBOL_REF
276 84619516 : && poly_int_rtx_p (XEXP (XEXP (orig, 0), 1), &offset));
277 : }
278 :
279 :
280 : /* Create a new copy of an rtx.
281 : Recursively copies the operands of the rtx,
282 : except for those few rtx codes that are sharable. */
283 :
284 : rtx
285 615897394 : copy_rtx (rtx orig)
286 : {
287 615897394 : rtx copy;
288 615897394 : int i, j;
289 615897394 : RTX_CODE code;
290 615897394 : const char *format_ptr;
291 :
292 615897394 : code = GET_CODE (orig);
293 :
294 615897394 : switch (code)
295 : {
296 : case REG:
297 : case DEBUG_EXPR:
298 : case VALUE:
299 : CASE_CONST_ANY:
300 : case SYMBOL_REF:
301 : case CODE_LABEL:
302 : case PC:
303 : case RETURN:
304 : case SIMPLE_RETURN:
305 : case SCRATCH:
306 : /* SCRATCH must be shared because they represent distinct values. */
307 : return orig;
308 277020 : case CLOBBER:
309 : /* Share clobbers of hard registers, but do not share pseudo reg
310 : clobbers or clobbers of hard registers that originated as pseudos.
311 : This is needed to allow safe register renaming. */
312 62982 : if (REG_P (XEXP (orig, 0)) && REGNO (XEXP (orig, 0)) < FIRST_PSEUDO_REGISTER
313 339560 : && ORIGINAL_REGNO (XEXP (orig, 0)) == REGNO (XEXP (orig, 0)))
314 : return orig;
315 : break;
316 :
317 4119938 : case CONST:
318 4119938 : if (shared_const_p (orig))
319 : return orig;
320 : break;
321 :
322 : /* A MEM with a constant address is not sharable. The problem is that
323 : the constant address may need to be reloaded. If the mem is shared,
324 : then reloading one copy of this mem will cause all copies to appear
325 : to have been reloaded. */
326 :
327 : default:
328 : break;
329 : }
330 :
331 : /* Copy the various flags, fields, and other information. We assume
332 : that all fields need copying, and then clear the fields that should
333 : not be copied. That is the sensible default behavior, and forces
334 : us to explicitly document why we are *not* copying a flag. */
335 189857418 : copy = shallow_copy_rtx (orig);
336 :
337 189857418 : format_ptr = GET_RTX_FORMAT (GET_CODE (copy));
338 :
339 565588321 : for (i = 0; i < GET_RTX_LENGTH (GET_CODE (copy)); i++)
340 375730903 : switch (*format_ptr++)
341 : {
342 303285006 : case 'e':
343 303285006 : if (XEXP (orig, i) != NULL)
344 303140059 : XEXP (copy, i) = copy_rtx (XEXP (orig, i));
345 : break;
346 :
347 2294019 : case 'E':
348 2294019 : case 'V':
349 2294019 : if (XVEC (orig, i) != NULL)
350 : {
351 2294019 : XVEC (copy, i) = rtvec_alloc (XVECLEN (orig, i));
352 7068452 : for (j = 0; j < XVECLEN (copy, i); j++)
353 4774433 : XVECEXP (copy, i, j) = copy_rtx (XVECEXP (orig, i, j));
354 : }
355 : break;
356 :
357 : case 't':
358 : case 'w':
359 : case 'i':
360 : case 'L':
361 : case 'p':
362 : case 's':
363 : case 'S':
364 : case 'T':
365 : case 'u':
366 : case 'B':
367 : case '0':
368 : /* These are left unchanged. */
369 : break;
370 :
371 0 : default:
372 0 : gcc_unreachable ();
373 : }
374 : return copy;
375 : }
376 :
377 : /* Create a new copy of an rtx. Only copy just one level. */
378 :
379 : rtx
380 465187505 : shallow_copy_rtx (const_rtx orig MEM_STAT_DECL)
381 : {
382 465187505 : const unsigned int size = rtx_size (orig);
383 465187505 : rtx const copy = ggc_alloc_rtx_def_stat (size PASS_MEM_STAT);
384 465187505 : memcpy (copy, orig, size);
385 465187505 : switch (GET_CODE (orig))
386 : {
387 : /* RTX codes copy_rtx_if_shared_1 considers are shareable,
388 : the used flag is often used for other purposes. */
389 : case REG:
390 : case DEBUG_EXPR:
391 : case VALUE:
392 : CASE_CONST_ANY:
393 : case SYMBOL_REF:
394 : case CODE_LABEL:
395 : case PC:
396 : case RETURN:
397 : case SIMPLE_RETURN:
398 : case SCRATCH:
399 : break;
400 458261888 : default:
401 : /* For all other RTXes clear the used flag on the copy.
402 : CALL_INSN use "used" flag to indicate it's a fake call. */
403 458261888 : if (!INSN_P (orig))
404 458116892 : RTX_FLAG (copy, used) = 0;
405 : break;
406 : }
407 465187505 : return copy;
408 : }
409 :
410 : /* Nonzero when we are generating CONCATs. */
411 : int generating_concat_p;
412 :
413 : /* Nonzero when we are expanding trees to RTL. */
414 : int currently_expanding_to_rtl;
415 :
416 :
417 :
418 : /* Return true if X and Y are identical-looking rtx's.
419 : This is the Lisp function EQUAL for rtx arguments.
420 :
421 : Call CB on each pair of rtx if CB is not NULL.
422 : When the callback returns true, we continue with the new pair. */
423 :
424 : bool
425 5358303397 : rtx_equal_p (const_rtx x, const_rtx y, rtx_equal_p_callback_function cb)
426 : {
427 5358303397 : int i;
428 5358303397 : int j;
429 5358303397 : enum rtx_code code;
430 5358303397 : const char *fmt;
431 5358303397 : rtx nx, ny;
432 :
433 5358303397 : if (x == y)
434 : return true;
435 3999448038 : if (x == 0 || y == 0)
436 : return false;
437 :
438 : /* Invoke the callback first. */
439 3717297132 : if (cb != NULL
440 3717297132 : && ((*cb) (&x, &y, &nx, &ny)))
441 0 : return rtx_equal_p (nx, ny, cb);
442 :
443 3717297132 : code = GET_CODE (x);
444 : /* Rtx's of different codes cannot be equal. */
445 3717297132 : if (code != GET_CODE (y))
446 : return false;
447 :
448 : /* (MULT:SI x y) and (MULT:HI x y) are NOT equivalent.
449 : (REG:SI x) and (REG:HI x) are NOT equivalent. */
450 :
451 1959665400 : if (GET_MODE (x) != GET_MODE (y))
452 : return false;
453 :
454 : /* MEMs referring to different address space are not equivalent. */
455 1388751468 : if (code == MEM && MEM_ADDR_SPACE (x) != MEM_ADDR_SPACE (y))
456 : return false;
457 :
458 : /* Some RTL can be compared nonrecursively. */
459 1385064659 : switch (code)
460 : {
461 893503099 : case REG:
462 893503099 : return (REGNO (x) == REGNO (y));
463 :
464 25421 : case LABEL_REF:
465 25421 : return label_ref_label (x) == label_ref_label (y);
466 :
467 72071666 : case SYMBOL_REF:
468 72071666 : return XSTR (x, 0) == XSTR (y, 0);
469 :
470 : case DEBUG_EXPR:
471 : case VALUE:
472 : case SCRATCH:
473 : CASE_CONST_UNIQUE:
474 : return false;
475 :
476 : case CONST_VECTOR:
477 : if (!same_vector_encodings_p (x, y))
478 : return false;
479 : break;
480 :
481 20945 : case DEBUG_IMPLICIT_PTR:
482 20945 : return DEBUG_IMPLICIT_PTR_DECL (x)
483 20945 : == DEBUG_IMPLICIT_PTR_DECL (y);
484 :
485 0 : case DEBUG_PARAMETER_REF:
486 0 : return DEBUG_PARAMETER_REF_DECL (x)
487 0 : == DEBUG_PARAMETER_REF_DECL (y);
488 :
489 57672 : case ENTRY_VALUE:
490 57672 : return rtx_equal_p (ENTRY_VALUE_EXP (x), ENTRY_VALUE_EXP (y), cb);
491 :
492 : default:
493 : break;
494 : }
495 :
496 : /* Compare the elements. If any pair of corresponding elements
497 : fail to match, return 0 for the whole thing. */
498 :
499 328696132 : fmt = GET_RTX_FORMAT (code);
500 599146109 : for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
501 : {
502 494303198 : switch (fmt[i])
503 : {
504 0 : case 'w':
505 0 : if (XWINT (x, i) != XWINT (y, i))
506 : return false;
507 : break;
508 :
509 44067693 : case 'n':
510 44067693 : case 'i':
511 44067693 : if (XINT (x, i) != XINT (y, i))
512 : return false;
513 : break;
514 :
515 19847 : case 'L':
516 19847 : if (XLOC (x, i) != XLOC (y, i))
517 : return false;
518 : break;
519 :
520 7688436 : case 'p':
521 7688436 : if (maybe_ne (SUBREG_BYTE (x), SUBREG_BYTE (y)))
522 : return false;
523 : break;
524 :
525 6190038 : case 'V':
526 6190038 : case 'E':
527 : /* Two vectors must have the same length. */
528 6190038 : if (XVECLEN (x, i) != XVECLEN (y, i))
529 : return false;
530 :
531 : /* And the corresponding elements must match. */
532 10303069 : for (j = 0; j < XVECLEN (x, i); j++)
533 9065637 : if (!rtx_equal_p (XVECEXP (x, i, j), XVECEXP (y, i, j), cb))
534 : return false;
535 : break;
536 :
537 375479747 : case 'e':
538 375479747 : if (!rtx_equal_p (XEXP (x, i), XEXP (y, i), cb))
539 : return false;
540 : break;
541 :
542 1002 : case 'S':
543 1002 : case 's':
544 1002 : if ((XSTR (x, i) || XSTR (y, i))
545 1002 : && (! XSTR (x, i) || ! XSTR (y, i)
546 1002 : || 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 167467 : rtvec_all_equal_p (const_rtvec vec)
572 : {
573 167467 : 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 167467 : switch (GET_CODE (first))
578 : {
579 167467 : CASE_CONST_UNIQUE:
580 235015 : for (int i = 1, n = GET_NUM_ELEM (vec); i < n; ++i)
581 186842 : 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 3745143 : rtvec_series_p (rtvec vec, poly_int64 start)
598 : {
599 6838122 : for (int i = 0; i < GET_NUM_ELEM (vec); i++)
600 : {
601 5942537 : poly_int64 elt;
602 5942537 : if (!poly_int_rtx_p (RTVEC_ELT (vec, i), &elt)
603 5942537 : || maybe_ne (elt, i + start))
604 3745143 : return false;
605 : }
606 : return true;
607 : }
608 :
609 : /* Return an indication of which type of insn should have X as a body.
610 : In generator files, this can be UNKNOWN if the answer is only known
611 : at (GCC) runtime. Otherwise the value is CODE_LABEL, INSN, CALL_INSN
612 : or JUMP_INSN. */
613 :
614 : enum rtx_code
615 18978077 : classify_insn (rtx x)
616 : {
617 18978077 : if (LABEL_P (x))
618 : return CODE_LABEL;
619 18978077 : if (GET_CODE (x) == CALL)
620 : return CALL_INSN;
621 18978077 : if (ANY_RETURN_P (x))
622 : return JUMP_INSN;
623 18922567 : if (GET_CODE (x) == ASM_OPERANDS && ASM_OPERANDS_LABEL_LENGTH (x))
624 : return JUMP_INSN;
625 18922567 : if (GET_CODE (x) == SET)
626 : {
627 16029037 : if (GET_CODE (SET_DEST (x)) == PC)
628 : return JUMP_INSN;
629 6507274 : else if (GET_CODE (SET_SRC (x)) == CALL)
630 : return CALL_INSN;
631 : else
632 6507274 : return INSN;
633 : }
634 2893530 : if (GET_CODE (x) == PARALLEL)
635 : {
636 2776332 : int j;
637 2776332 : bool has_return_p = false;
638 8944877 : for (j = XVECLEN (x, 0) - 1; j >= 0; j--)
639 6181883 : if (GET_CODE (XVECEXP (x, 0, j)) == CALL)
640 : return CALL_INSN;
641 6180895 : else if (ANY_RETURN_P (XVECEXP (x, 0, j)))
642 : has_return_p = true;
643 6180895 : else if (GET_CODE (XVECEXP (x, 0, j)) == SET
644 3397292 : && GET_CODE (SET_DEST (XVECEXP (x, 0, j))) == PC)
645 : return JUMP_INSN;
646 6173801 : else if (GET_CODE (XVECEXP (x, 0, j)) == SET
647 3390198 : && GET_CODE (SET_SRC (XVECEXP (x, 0, j))) == CALL)
648 : return CALL_INSN;
649 2762994 : if (has_return_p)
650 : return JUMP_INSN;
651 2762994 : if (GET_CODE (XVECEXP (x, 0, 0)) == ASM_OPERANDS
652 33 : && ASM_OPERANDS_LABEL_LENGTH (XVECEXP (x, 0, 0)))
653 1 : return JUMP_INSN;
654 : }
655 : #ifdef GENERATOR_FILE
656 : if (GET_CODE (x) == MATCH_OPERAND
657 : || GET_CODE (x) == MATCH_OPERATOR
658 : || GET_CODE (x) == MATCH_PARALLEL
659 : || GET_CODE (x) == MATCH_OP_DUP
660 : || GET_CODE (x) == MATCH_DUP
661 : || GET_CODE (x) == PARALLEL)
662 : return UNKNOWN;
663 : #endif
664 : return INSN;
665 : }
666 :
667 : /* Comparator of indices based on rtx_alloc_counts. */
668 :
669 : static int
670 0 : rtx_count_cmp (const void *p1, const void *p2)
671 : {
672 0 : const unsigned *n1 = (const unsigned *)p1;
673 0 : const unsigned *n2 = (const unsigned *)p2;
674 :
675 0 : return rtx_alloc_counts[*n1] - rtx_alloc_counts[*n2];
676 : }
677 :
678 : void
679 0 : dump_rtx_statistics (void)
680 : {
681 0 : int total_counts = 0;
682 0 : int total_sizes = 0;
683 :
684 0 : if (! GATHER_STATISTICS)
685 : {
686 0 : fprintf (stderr, "No RTX statistics\n");
687 0 : return;
688 : }
689 :
690 : fprintf (stderr, "\nRTX Kind Count Bytes\n");
691 : fprintf (stderr, "-------------------------------------------\n");
692 :
693 : auto_vec<unsigned> indices (LAST_AND_UNUSED_RTX_CODE);
694 : for (unsigned i = 0; i < LAST_AND_UNUSED_RTX_CODE; i++)
695 : indices.quick_push (i);
696 : indices.qsort (rtx_count_cmp);
697 :
698 : for (unsigned i = 0; i < LAST_AND_UNUSED_RTX_CODE; i++)
699 : {
700 : unsigned j = indices[i];
701 : if (rtx_alloc_counts[j])
702 : {
703 : fprintf (stderr, "%-24s " PRsa (6) " " PRsa (9) "\n",
704 : GET_RTX_NAME (j),
705 : SIZE_AMOUNT (rtx_alloc_counts[j]),
706 : SIZE_AMOUNT (rtx_alloc_sizes[j]));
707 : total_counts += rtx_alloc_counts[j];
708 : total_sizes += rtx_alloc_sizes[j];
709 : }
710 : }
711 :
712 : if (rtvec_alloc_counts)
713 : {
714 : fprintf (stderr, "%-24s " PRsa (6) " " PRsa (9) "\n", "rtvec",
715 : SIZE_AMOUNT (rtvec_alloc_counts),
716 : SIZE_AMOUNT (rtvec_alloc_sizes));
717 : total_counts += rtvec_alloc_counts;
718 : total_sizes += rtvec_alloc_sizes;
719 : }
720 : fprintf (stderr, "-----------------------------------------------\n");
721 : fprintf (stderr, "%-24s " PRsa (6) " " PRsa (9) "\n",
722 : "Total", SIZE_AMOUNT (total_counts),
723 : SIZE_AMOUNT (total_sizes));
724 : fprintf (stderr, "-----------------------------------------------\n");
725 : }
726 :
727 : #if defined ENABLE_RTL_CHECKING && (GCC_VERSION >= 2007)
728 :
729 : /* Disable warnings about missing quoting in GCC diagnostics for
730 : the internal_error calls. Their format strings deliberately don't
731 : follow GCC diagnostic conventions. */
732 : #if __GNUC__ >= 10
733 : #pragma GCC diagnostic push
734 : #pragma GCC diagnostic ignored "-Wformat-diag"
735 : #endif
736 :
737 : void
738 : rtl_check_failed_bounds (const_rtx r, int n, const char *file, int line,
739 : const char *func)
740 : {
741 : internal_error
742 : ("RTL check: access of elt %d of '%s' with last elt %d in %s, at %s:%d",
743 : n, GET_RTX_NAME (GET_CODE (r)), GET_RTX_LENGTH (GET_CODE (r)) - 1,
744 : func, trim_filename (file), line);
745 : }
746 :
747 : void
748 : rtl_check_failed_type1 (const_rtx r, int n, int c1, const char *file, int line,
749 : const char *func)
750 : {
751 : internal_error
752 : ("RTL check: expected elt %d type '%c', have '%c' (rtx %s) in %s, at %s:%d",
753 : n, c1, GET_RTX_FORMAT (GET_CODE (r))[n], GET_RTX_NAME (GET_CODE (r)),
754 : func, trim_filename (file), line);
755 : }
756 :
757 : void
758 : rtl_check_failed_type2 (const_rtx r, int n, int c1, int c2, const char *file,
759 : int line, const char *func)
760 : {
761 : internal_error
762 : ("RTL check: expected elt %d type '%c' or '%c', have '%c' (rtx %s) in %s, at %s:%d",
763 : n, c1, c2, GET_RTX_FORMAT (GET_CODE (r))[n], GET_RTX_NAME (GET_CODE (r)),
764 : func, trim_filename (file), line);
765 : }
766 :
767 : void
768 : rtl_check_failed_code1 (const_rtx r, enum rtx_code code, const char *file,
769 : int line, const char *func)
770 : {
771 : internal_error ("RTL check: expected code '%s', have '%s' in %s, at %s:%d",
772 : GET_RTX_NAME (code), GET_RTX_NAME (GET_CODE (r)), func,
773 : trim_filename (file), line);
774 : }
775 :
776 : void
777 : rtl_check_failed_code2 (const_rtx r, enum rtx_code code1, enum rtx_code code2,
778 : const char *file, int line, const char *func)
779 : {
780 : internal_error
781 : ("RTL check: expected code '%s' or '%s', have '%s' in %s, at %s:%d",
782 : GET_RTX_NAME (code1), GET_RTX_NAME (code2), GET_RTX_NAME (GET_CODE (r)),
783 : func, trim_filename (file), line);
784 : }
785 :
786 : void
787 : rtl_check_failed_code3 (const_rtx r, enum rtx_code code1, enum rtx_code code2,
788 : enum rtx_code code3, const char *file, int line,
789 : const char *func)
790 : {
791 : internal_error
792 : ("RTL check: expected code '%s', '%s' or '%s', have '%s' in %s, at %s:%d",
793 : GET_RTX_NAME (code1), GET_RTX_NAME (code2), GET_RTX_NAME (code3),
794 : GET_RTX_NAME (GET_CODE (r)), func, trim_filename (file), line);
795 : }
796 :
797 : void
798 : rtl_check_failed_code_mode (const_rtx r, enum rtx_code code, machine_mode mode,
799 : bool not_mode, const char *file, int line,
800 : const char *func)
801 : {
802 : internal_error ((not_mode
803 : ? ("RTL check: expected code '%s' and not mode '%s', "
804 : "have code '%s' and mode '%s' in %s, at %s:%d")
805 : : ("RTL check: expected code '%s' and mode '%s', "
806 : "have code '%s' and mode '%s' in %s, at %s:%d")),
807 : GET_RTX_NAME (code), GET_MODE_NAME (mode),
808 : GET_RTX_NAME (GET_CODE (r)), GET_MODE_NAME (GET_MODE (r)),
809 : func, trim_filename (file), line);
810 : }
811 :
812 : #if __GNUC__ >= 10
813 : #pragma GCC diagnostic pop
814 : #endif
815 :
816 : /* Report that line LINE of FILE tried to access the block symbol fields
817 : of a non-block symbol. FUNC is the function that contains the line. */
818 :
819 : void
820 : rtl_check_failed_block_symbol (const char *file, int line, const char *func)
821 : {
822 : internal_error
823 : ("RTL check: attempt to treat non-block symbol as a block symbol "
824 : "in %s, at %s:%d", func, trim_filename (file), line);
825 : }
826 :
827 : /* XXX Maybe print the vector? */
828 : void
829 : cwi_check_failed_bounds (const_rtx x, int n, const char *file, int line,
830 : const char *func)
831 : {
832 : internal_error
833 : ("RTL check: access of hwi elt %d of vector with last elt %d in %s, at %s:%d",
834 : n, CWI_GET_NUM_ELEM (x) - 1, func, trim_filename (file), line);
835 : }
836 :
837 : /* XXX Maybe print the vector? */
838 : void
839 : rtvec_check_failed_bounds (const_rtvec r, int n, const char *file, int line,
840 : const char *func)
841 : {
842 : internal_error
843 : ("RTL check: access of elt %d of vector with last elt %d in %s, at %s:%d",
844 : n, GET_NUM_ELEM (r) - 1, func, trim_filename (file), line);
845 : }
846 : #endif /* ENABLE_RTL_CHECKING */
847 :
848 : #if defined ENABLE_RTL_FLAG_CHECKING
849 : void
850 0 : rtl_check_failed_flag (const char *name, const_rtx r, const char *file,
851 : int line, const char *func)
852 : {
853 0 : internal_error
854 0 : ("RTL flag check: %s used with unexpected rtx code '%s' in %s, at %s:%d",
855 0 : name, GET_RTX_NAME (GET_CODE (r)), func, trim_filename (file), line);
856 : }
857 : #endif /* ENABLE_RTL_FLAG_CHECKING */
|