Branch data Line data Source code
1 : : /* RTL utility routines.
2 : : Copyright (C) 1987-2025 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 : 101145140 : rtvec_alloc (size_t n)
164 : : {
165 : 101145140 : rtvec rt;
166 : :
167 : : /* rtvec_def.num_elem is an int. */
168 : 101145140 : gcc_assert (n < INT_MAX);
169 : :
170 : 101145140 : rt = ggc_alloc_rtvec_sized (n);
171 : : /* Clear out the vector. */
172 : 101145140 : memset (&rt->elem[0], 0, n * sizeof (rtx));
173 : :
174 : 101145140 : PUT_NUM_ELEM (rt, n);
175 : :
176 : 101145140 : if (GATHER_STATISTICS)
177 : : {
178 : : rtvec_alloc_counts++;
179 : : rtvec_alloc_sizes += n * sizeof (rtx);
180 : : }
181 : :
182 : 101145140 : return rt;
183 : : }
184 : :
185 : : /* Create a bitwise copy of VEC. */
186 : :
187 : : rtvec
188 : 2165141 : shallow_copy_rtvec (rtvec vec)
189 : : {
190 : 2165141 : rtvec newvec;
191 : 2165141 : int n;
192 : :
193 : 2165141 : n = GET_NUM_ELEM (vec);
194 : 2165141 : newvec = rtvec_alloc (n);
195 : 2165141 : memcpy (&newvec->elem[0], &vec->elem[0], sizeof (rtx) * n);
196 : 2165141 : return newvec;
197 : : }
198 : :
199 : : /* Return the number of bytes occupied by rtx value X. */
200 : :
201 : : unsigned int
202 : 418505164 : rtx_size (const_rtx x)
203 : : {
204 : 418505164 : 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 : 418505164 : 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 : 418505164 : if (GET_CODE (x) == SYMBOL_REF && SYMBOL_REF_HAS_BLOCK_INFO_P (x))
214 : : return RTX_HDR_SIZE + sizeof (struct block_symbol);
215 : 418505164 : 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 : 2504012773 : rtx_alloc_stat_v (RTX_CODE code MEM_STAT_DECL, int extra)
223 : : {
224 : 2504012773 : rtx rt = ggc_alloc_rtx_def_stat (RTX_CODE_SIZE (code) + extra
225 : : PASS_MEM_STAT);
226 : :
227 : 2504012773 : rtx_init (rt, code);
228 : :
229 : 2504012773 : if (GATHER_STATISTICS)
230 : : {
231 : : rtx_alloc_counts[code]++;
232 : : rtx_alloc_sizes[code] += RTX_CODE_SIZE (code);
233 : : }
234 : :
235 : 2504012773 : 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 : 2503400468 : rtx_alloc (RTX_CODE code MEM_STAT_DECL)
243 : : {
244 : 2503400468 : 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 : 43252451 : shared_const_p (const_rtx orig)
268 : : {
269 : 43252451 : 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 : 43252451 : poly_int64 offset;
274 : 43252451 : return (GET_CODE (XEXP (orig, 0)) == PLUS
275 : 34815583 : && GET_CODE (XEXP (XEXP (orig, 0), 0)) == SYMBOL_REF
276 : 77483048 : && 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 : 554813707 : copy_rtx (rtx orig)
286 : : {
287 : 554813707 : rtx copy;
288 : 554813707 : int i, j;
289 : 554813707 : RTX_CODE code;
290 : 554813707 : const char *format_ptr;
291 : :
292 : 554813707 : code = GET_CODE (orig);
293 : :
294 : 554813707 : 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 : 233330 : 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 : 80706 : if (REG_P (XEXP (orig, 0)) && REGNO (XEXP (orig, 0)) < FIRST_PSEUDO_REGISTER
313 : 314036 : && ORIGINAL_REGNO (XEXP (orig, 0)) == REGNO (XEXP (orig, 0)))
314 : : return orig;
315 : : break;
316 : :
317 : 3815912 : case CONST:
318 : 3815912 : 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 : 169922376 : copy = shallow_copy_rtx (orig);
336 : :
337 : 169922376 : format_ptr = GET_RTX_FORMAT (GET_CODE (copy));
338 : :
339 : 506751988 : for (i = 0; i < GET_RTX_LENGTH (GET_CODE (copy)); i++)
340 : 336829612 : switch (*format_ptr++)
341 : : {
342 : 271841162 : case 'e':
343 : 271841162 : if (XEXP (orig, i) != NULL)
344 : 271617163 : XEXP (copy, i) = copy_rtx (XEXP (orig, i));
345 : : break;
346 : :
347 : 2093106 : case 'E':
348 : 2093106 : case 'V':
349 : 2093106 : if (XVEC (orig, i) != NULL)
350 : : {
351 : 2093106 : XVEC (copy, i) = rtvec_alloc (XVECLEN (orig, i));
352 : 6371778 : for (j = 0; j < XVECLEN (copy, i); j++)
353 : 4278672 : 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 : 418505164 : shallow_copy_rtx (const_rtx orig MEM_STAT_DECL)
381 : : {
382 : 418505164 : const unsigned int size = rtx_size (orig);
383 : 418505164 : rtx const copy = ggc_alloc_rtx_def_stat (size PASS_MEM_STAT);
384 : 418505164 : memcpy (copy, orig, size);
385 : 418505164 : 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 : 411833892 : 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 : 411833892 : if (!INSN_P (orig))
404 : 411609893 : RTX_FLAG (copy, used) = 0;
405 : : break;
406 : : }
407 : 418505164 : 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 : 4847787812 : rtx_equal_p (const_rtx x, const_rtx y, rtx_equal_p_callback_function cb)
426 : : {
427 : 4847787812 : int i;
428 : 4847787812 : int j;
429 : 4847787812 : enum rtx_code code;
430 : 4847787812 : const char *fmt;
431 : 4847787812 : rtx nx, ny;
432 : :
433 : 4847787812 : if (x == y)
434 : : return true;
435 : 3598608908 : if (x == 0 || y == 0)
436 : : return false;
437 : :
438 : : /* Invoke the callback first. */
439 : 3341744956 : if (cb != NULL
440 : 3341744956 : && ((*cb) (&x, &y, &nx, &ny)))
441 : 0 : return rtx_equal_p (nx, ny, cb);
442 : :
443 : 3341744956 : code = GET_CODE (x);
444 : : /* Rtx's of different codes cannot be equal. */
445 : 3341744956 : 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 : 1760363207 : if (GET_MODE (x) != GET_MODE (y))
452 : : return false;
453 : :
454 : : /* MEMs referring to different address space are not equivalent. */
455 : 1240571427 : if (code == MEM && MEM_ADDR_SPACE (x) != MEM_ADDR_SPACE (y))
456 : : return false;
457 : :
458 : : /* Some RTL can be compared nonrecursively. */
459 : 1237643132 : switch (code)
460 : : {
461 : 810073093 : case REG:
462 : 810073093 : return (REGNO (x) == REGNO (y));
463 : :
464 : 24192 : case LABEL_REF:
465 : 24192 : return label_ref_label (x) == label_ref_label (y);
466 : :
467 : 65328581 : case SYMBOL_REF:
468 : 65328581 : 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 : 14455 : case DEBUG_IMPLICIT_PTR:
482 : 14455 : return DEBUG_IMPLICIT_PTR_DECL (x)
483 : 14455 : == 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 : 42864 : case ENTRY_VALUE:
490 : 42864 : 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 : 281277263 : fmt = GET_RTX_FORMAT (code);
500 : 510311270 : for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
501 : : {
502 : 422643941 : switch (fmt[i])
503 : : {
504 : 0 : case 'w':
505 : 0 : if (XWINT (x, i) != XWINT (y, i))
506 : : return false;
507 : : break;
508 : :
509 : 38135136 : case 'n':
510 : 38135136 : case 'i':
511 : 38135136 : if (XINT (x, i) != XINT (y, i))
512 : : return false;
513 : : break;
514 : :
515 : 18773 : case 'L':
516 : 18773 : if (XLOC (x, i) != XLOC (y, i))
517 : : return false;
518 : : break;
519 : :
520 : 5126836 : case 'p':
521 : 5126836 : if (maybe_ne (SUBREG_BYTE (x), SUBREG_BYTE (y)))
522 : : return false;
523 : : break;
524 : :
525 : 5200116 : case 'V':
526 : 5200116 : case 'E':
527 : : /* Two vectors must have the same length. */
528 : 5200116 : if (XVECLEN (x, i) != XVECLEN (y, i))
529 : : return false;
530 : :
531 : : /* And the corresponding elements must match. */
532 : 8797278 : for (j = 0; j < XVECLEN (x, i); j++)
533 : 7639748 : if (!rtx_equal_p (XVECEXP (x, i, j), XVECEXP (y, i, j), cb))
534 : : return false;
535 : : break;
536 : :
537 : 320710339 : case 'e':
538 : 320710339 : if (!rtx_equal_p (XEXP (x, i), XEXP (y, i), cb))
539 : : return false;
540 : : break;
541 : :
542 : 120 : case 'S':
543 : 120 : case 's':
544 : 120 : if ((XSTR (x, i) || XSTR (y, i))
545 : 120 : && (! XSTR (x, i) || ! XSTR (y, i)
546 : 120 : || 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 : 168002 : rtvec_all_equal_p (const_rtvec vec)
572 : : {
573 : 168002 : 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 : 168002 : switch (GET_CODE (first))
578 : : {
579 : 168002 : CASE_CONST_UNIQUE:
580 : 232802 : for (int i = 1, n = GET_NUM_ELEM (vec); i < n; ++i)
581 : 178460 : 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 : 583395 : rtvec_series_p (rtvec vec, int start)
598 : : {
599 : 981184 : for (int i = 0; i < GET_NUM_ELEM (vec); i++)
600 : : {
601 : 980181 : rtx x = RTVEC_ELT (vec, i);
602 : 980181 : 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 : 11494394 : classify_insn (rtx x)
615 : : {
616 : 11494394 : if (LABEL_P (x))
617 : : return CODE_LABEL;
618 : 11494394 : if (GET_CODE (x) == CALL)
619 : : return CALL_INSN;
620 : 11494394 : if (ANY_RETURN_P (x))
621 : : return JUMP_INSN;
622 : 11494394 : if (GET_CODE (x) == ASM_OPERANDS && ASM_OPERANDS_LABEL_LENGTH (x))
623 : : return JUMP_INSN;
624 : 11494394 : if (GET_CODE (x) == SET)
625 : : {
626 : 8871389 : if (GET_CODE (SET_DEST (x)) == PC)
627 : : return JUMP_INSN;
628 : 15011 : else if (GET_CODE (SET_SRC (x)) == CALL)
629 : : return CALL_INSN;
630 : : else
631 : 15011 : return INSN;
632 : : }
633 : 2623005 : if (GET_CODE (x) == PARALLEL)
634 : : {
635 : 2586997 : int j;
636 : 2586997 : bool has_return_p = false;
637 : 8330467 : for (j = XVECLEN (x, 0) - 1; j >= 0; j--)
638 : 5743470 : if (GET_CODE (XVECEXP (x, 0, j)) == CALL)
639 : : return CALL_INSN;
640 : 5743470 : else if (ANY_RETURN_P (XVECEXP (x, 0, j)))
641 : : has_return_p = true;
642 : 5743470 : else if (GET_CODE (XVECEXP (x, 0, j)) == SET
643 : 3215591 : && GET_CODE (SET_DEST (XVECEXP (x, 0, j))) == PC)
644 : : return JUMP_INSN;
645 : 5743470 : else if (GET_CODE (XVECEXP (x, 0, j)) == SET
646 : 3215591 : && GET_CODE (SET_SRC (XVECEXP (x, 0, j))) == CALL)
647 : : return CALL_INSN;
648 : 2586997 : if (has_return_p)
649 : : return JUMP_INSN;
650 : 2586997 : 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 */
|