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 101600241 : rtvec_alloc (size_t n)
164 : {
165 101600241 : rtvec rt;
166 :
167 : /* rtvec_def.num_elem is an int. */
168 101600241 : gcc_assert (n < INT_MAX);
169 :
170 101600241 : rt = ggc_alloc_rtvec_sized (n);
171 : /* Clear out the vector. */
172 101600241 : memset (&rt->elem[0], 0, n * sizeof (rtx));
173 :
174 101600241 : PUT_NUM_ELEM (rt, n);
175 :
176 101600241 : if (GATHER_STATISTICS)
177 : {
178 : rtvec_alloc_counts++;
179 : rtvec_alloc_sizes += n * sizeof (rtx);
180 : }
181 :
182 101600241 : return rt;
183 : }
184 :
185 : /* Create a bitwise copy of VEC. */
186 :
187 : rtvec
188 2258912 : shallow_copy_rtvec (rtvec vec)
189 : {
190 2258912 : rtvec newvec;
191 2258912 : int n;
192 :
193 2258912 : n = GET_NUM_ELEM (vec);
194 2258912 : newvec = rtvec_alloc (n);
195 2258912 : memcpy (&newvec->elem[0], &vec->elem[0], sizeof (rtx) * n);
196 2258912 : return newvec;
197 : }
198 :
199 : /* Return the number of bytes occupied by rtx value X. */
200 :
201 : unsigned int
202 450778001 : rtx_size (const_rtx x)
203 : {
204 450778001 : 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 450778001 : 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 450778001 : if (GET_CODE (x) == SYMBOL_REF && SYMBOL_REF_HAS_BLOCK_INFO_P (x))
214 : return RTX_HDR_SIZE + sizeof (struct block_symbol);
215 450778001 : 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 2696715907 : rtx_alloc_stat_v (RTX_CODE code MEM_STAT_DECL, int extra)
223 : {
224 2696715907 : rtx rt = ggc_alloc_rtx_def_stat (RTX_CODE_SIZE (code) + extra
225 : PASS_MEM_STAT);
226 :
227 2696715907 : rtx_init (rt, code);
228 :
229 2696715907 : if (GATHER_STATISTICS)
230 : {
231 : rtx_alloc_counts[code]++;
232 : rtx_alloc_sizes[code] += RTX_CODE_SIZE (code);
233 : }
234 :
235 2696715907 : 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 2696153830 : rtx_alloc (RTX_CODE code MEM_STAT_DECL)
243 : {
244 2696153830 : 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 48918367 : shared_const_p (const_rtx orig)
268 : {
269 48918367 : 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 48918367 : poly_int64 offset;
274 48918367 : return (GET_CODE (XEXP (orig, 0)) == PLUS
275 40038197 : && GET_CODE (XEXP (XEXP (orig, 0), 0)) == SYMBOL_REF
276 88332230 : && 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 594034399 : copy_rtx (rtx orig)
286 : {
287 594034399 : rtx copy;
288 594034399 : int i, j;
289 594034399 : RTX_CODE code;
290 594034399 : const char *format_ptr;
291 :
292 594034399 : code = GET_CODE (orig);
293 :
294 594034399 : 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 282009 : 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 64978 : if (REG_P (XEXP (orig, 0)) && REGNO (XEXP (orig, 0)) < FIRST_PSEUDO_REGISTER
313 346493 : && ORIGINAL_REGNO (XEXP (orig, 0)) == REGNO (XEXP (orig, 0)))
314 : return orig;
315 : break;
316 :
317 4056293 : case CONST:
318 4056293 : 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 182016573 : copy = shallow_copy_rtx (orig);
336 :
337 182016573 : format_ptr = GET_RTX_FORMAT (GET_CODE (copy));
338 :
339 542543964 : for (i = 0; i < GET_RTX_LENGTH (GET_CODE (copy)); i++)
340 360527391 : switch (*format_ptr++)
341 : {
342 291899935 : case 'e':
343 291899935 : if (XEXP (orig, i) != NULL)
344 291723168 : XEXP (copy, i) = copy_rtx (XEXP (orig, i));
345 : break;
346 :
347 2174786 : case 'E':
348 2174786 : case 'V':
349 2174786 : if (XVEC (orig, i) != NULL)
350 : {
351 2174786 : XVEC (copy, i) = rtvec_alloc (XVECLEN (orig, i));
352 6678061 : for (j = 0; j < XVECLEN (copy, i); j++)
353 4503275 : 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 450778001 : shallow_copy_rtx (const_rtx orig MEM_STAT_DECL)
381 : {
382 450778001 : const unsigned int size = rtx_size (orig);
383 450778001 : rtx const copy = ggc_alloc_rtx_def_stat (size PASS_MEM_STAT);
384 450778001 : memcpy (copy, orig, size);
385 450778001 : 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 444011629 : 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 444011629 : if (!INSN_P (orig))
404 443834862 : RTX_FLAG (copy, used) = 0;
405 : break;
406 : }
407 450778001 : 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 5206907012 : rtx_equal_p (const_rtx x, const_rtx y, rtx_equal_p_callback_function cb)
426 : {
427 5206907012 : int i;
428 5206907012 : int j;
429 5206907012 : enum rtx_code code;
430 5206907012 : const char *fmt;
431 5206907012 : rtx nx, ny;
432 :
433 5206907012 : if (x == y)
434 : return true;
435 3889412498 : if (x == 0 || y == 0)
436 : return false;
437 :
438 : /* Invoke the callback first. */
439 3616731953 : if (cb != NULL
440 3616731953 : && ((*cb) (&x, &y, &nx, &ny)))
441 0 : return rtx_equal_p (nx, ny, cb);
442 :
443 3616731953 : code = GET_CODE (x);
444 : /* Rtx's of different codes cannot be equal. */
445 3616731953 : 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 1899702669 : if (GET_MODE (x) != GET_MODE (y))
452 : return false;
453 :
454 : /* MEMs referring to different address space are not equivalent. */
455 1341165598 : if (code == MEM && MEM_ADDR_SPACE (x) != MEM_ADDR_SPACE (y))
456 : return false;
457 :
458 : /* Some RTL can be compared nonrecursively. */
459 1336479892 : switch (code)
460 : {
461 867056133 : case REG:
462 867056133 : return (REGNO (x) == REGNO (y));
463 :
464 30553 : case LABEL_REF:
465 30553 : return label_ref_label (x) == label_ref_label (y);
466 :
467 68746023 : case SYMBOL_REF:
468 68746023 : 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 18488 : case DEBUG_IMPLICIT_PTR:
482 18488 : return DEBUG_IMPLICIT_PTR_DECL (x)
483 18488 : == 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 62593 : case ENTRY_VALUE:
490 62593 : 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 312751399 : fmt = GET_RTX_FORMAT (code);
500 570309287 : for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
501 : {
502 468550288 : switch (fmt[i])
503 : {
504 0 : case 'w':
505 0 : if (XWINT (x, i) != XWINT (y, i))
506 : return false;
507 : break;
508 :
509 43681824 : case 'n':
510 43681824 : case 'i':
511 43681824 : 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 4675011 : case 'p':
521 4675011 : if (maybe_ne (SUBREG_BYTE (x), SUBREG_BYTE (y)))
522 : return false;
523 : break;
524 :
525 5432461 : case 'V':
526 5432461 : case 'E':
527 : /* Two vectors must have the same length. */
528 5432461 : if (XVECLEN (x, i) != XVECLEN (y, i))
529 : return false;
530 :
531 : /* And the corresponding elements must match. */
532 9312118 : for (j = 0; j < XVECLEN (x, i); j++)
533 8130597 : if (!rtx_equal_p (XVECEXP (x, i, j), XVECEXP (y, i, j), cb))
534 : return false;
535 : break;
536 :
537 355024996 : case 'e':
538 355024996 : if (!rtx_equal_p (XEXP (x, i), XEXP (y, i), cb))
539 : return false;
540 : break;
541 :
542 471 : case 'S':
543 471 : case 's':
544 471 : if ((XSTR (x, i) || XSTR (y, i))
545 471 : && (! XSTR (x, i) || ! XSTR (y, i)
546 471 : || 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 166105 : rtvec_all_equal_p (const_rtvec vec)
572 : {
573 166105 : 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 166105 : switch (GET_CODE (first))
578 : {
579 166105 : CASE_CONST_UNIQUE:
580 231390 : for (int i = 1, n = GET_NUM_ELEM (vec); i < n; ++i)
581 178200 : 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 3046822 : rtvec_series_p (rtvec vec, int start)
598 : {
599 5572273 : for (int i = 0; i < GET_NUM_ELEM (vec); i++)
600 : {
601 4822312 : rtx x = RTVEC_ELT (vec, i);
602 4822312 : 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 18673411 : classify_insn (rtx x)
615 : {
616 18673411 : if (LABEL_P (x))
617 : return CODE_LABEL;
618 18673411 : if (GET_CODE (x) == CALL)
619 : return CALL_INSN;
620 18673411 : if (ANY_RETURN_P (x))
621 : return JUMP_INSN;
622 18618146 : if (GET_CODE (x) == ASM_OPERANDS && ASM_OPERANDS_LABEL_LENGTH (x))
623 : return JUMP_INSN;
624 18618146 : if (GET_CODE (x) == SET)
625 : {
626 15760911 : if (GET_CODE (SET_DEST (x)) == PC)
627 : return JUMP_INSN;
628 6414919 : else if (GET_CODE (SET_SRC (x)) == CALL)
629 : return CALL_INSN;
630 : else
631 6414919 : return INSN;
632 : }
633 2857235 : if (GET_CODE (x) == PARALLEL)
634 : {
635 2741396 : int j;
636 2741396 : bool has_return_p = false;
637 8793630 : for (j = XVECLEN (x, 0) - 1; j >= 0; j--)
638 6066539 : if (GET_CODE (XVECEXP (x, 0, j)) == CALL)
639 : return CALL_INSN;
640 6065469 : else if (ANY_RETURN_P (XVECEXP (x, 0, j)))
641 : has_return_p = true;
642 6065469 : else if (GET_CODE (XVECEXP (x, 0, j)) == SET
643 3327247 : && GET_CODE (SET_DEST (XVECEXP (x, 0, j))) == PC)
644 : return JUMP_INSN;
645 6057441 : else if (GET_CODE (XVECEXP (x, 0, j)) == SET
646 3319219 : && GET_CODE (SET_SRC (XVECEXP (x, 0, j))) == CALL)
647 : return CALL_INSN;
648 2727091 : if (has_return_p)
649 : return JUMP_INSN;
650 2727091 : 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 */
|