]>
Commit | Line | Data |
---|---|---|
875d8740 | 1 | /* RTL utility routines. |
fbd26352 | 2 | Copyright (C) 1987-2019 Free Software Foundation, Inc. |
759bebca | 3 | |
f12b58b3 | 4 | This file is part of GCC. |
759bebca | 5 | |
f12b58b3 | 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 | |
8c4c00c1 | 8 | Software Foundation; either version 3, or (at your option) any later |
f12b58b3 | 9 | version. |
759bebca | 10 | |
f12b58b3 | 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. | |
759bebca | 15 | |
16 | You should have received a copy of the GNU General Public License | |
8c4c00c1 | 17 | along with GCC; see the file COPYING3. If not see |
18 | <http://www.gnu.org/licenses/>. */ | |
759bebca | 19 | |
690ff52f | 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 | |
759bebca | 25 | #include "config.h" |
690ff52f | 26 | #endif |
27 | ||
405711de | 28 | #include "system.h" |
805e22b2 | 29 | #include "coretypes.h" |
30 | #include "tm.h" | |
881f903e | 31 | #include "rtl.h" |
690abe5d | 32 | #ifdef GENERATOR_FILE |
33 | # include "errors.h" | |
34 | #else | |
bb1f44ab | 35 | # include "rtlhash.h" |
0b205f4c | 36 | # include "diagnostic-core.h" |
690abe5d | 37 | #endif |
759bebca | 38 | |
759bebca | 39 | \f |
40 | /* Indexed by rtx code, gives number of operands for an rtx with that code. | |
0e3985ee | 41 | Does NOT include rtx header data (code and links). */ |
759bebca | 42 | |
0e3985ee | 43 | #define DEF_RTL_EXPR(ENUM, NAME, FORMAT, CLASS) sizeof FORMAT - 1 , |
44 | ||
1af5f160 | 45 | const unsigned char rtx_length[NUM_RTX_CODE] = { |
0e3985ee | 46 | #include "rtl.def" |
47 | }; | |
48 | ||
49 | #undef DEF_RTL_EXPR | |
759bebca | 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 | ||
1af5f160 | 55 | const char * const rtx_name[NUM_RTX_CODE] = { |
759bebca | 56 | #include "rtl.def" /* rtl expressions are documented here */ |
57 | }; | |
58 | ||
59 | #undef DEF_RTL_EXPR | |
60 | ||
759bebca | 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 | |
4bbea254 | 63 | each character describes one operand. */ |
759bebca | 64 | |
1af5f160 | 65 | const char * const rtx_format[NUM_RTX_CODE] = { |
759bebca | 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' | |
d3115c90 | 73 | "w" an integer of width HOST_BITS_PER_WIDE_INT |
74 | prints the integer | |
759bebca | 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 | |
aa4c562d | 79 | "T" like "s", but treated specially by the RTL reader; |
80 | only found in machine description patterns. | |
759bebca | 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 | |
a3426c4c | 88 | prints the uid of the insn. |
89 | "b" is a pointer to a bitmap header. | |
c849df63 | 90 | "B" is a basic block pointer. |
15183fd2 | 91 | "t" is a tree pointer. |
9edf7ea8 | 92 | "r" a register. |
93 | "p" is a poly_uint16 offset. */ | |
759bebca | 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 | ||
6720e96c | 103 | const enum rtx_class rtx_class[NUM_RTX_CODE] = { |
f220c8f0 | 104 | #define DEF_RTL_EXPR(ENUM, NAME, FORMAT, CLASS) CLASS, |
759bebca | 105 | #include "rtl.def" /* rtl expressions are defined here */ |
106 | #undef DEF_RTL_EXPR | |
107 | }; | |
108 | ||
93bb6f9c | 109 | /* Whether rtxs with the given code 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 | ||
bf6b5685 | 121 | /* Indexed by rtx code, gives the size of the rtx in bytes. */ |
122 | ||
f2d0e9f1 | 123 | const unsigned char rtx_code_size[NUM_RTX_CODE] = { |
bf6b5685 | 124 | #define DEF_RTL_EXPR(ENUM, NAME, FORMAT, CLASS) \ |
93bb6f9c | 125 | (RTX_CODE_HWINT_P (ENUM) \ |
bf6b5685 | 126 | ? RTX_HDR_SIZE + (sizeof FORMAT - 1) * sizeof (HOST_WIDE_INT) \ |
15183fd2 | 127 | : (ENUM) == REG \ |
128 | ? RTX_HDR_SIZE + sizeof (reg_info) \ | |
bf6b5685 | 129 | : RTX_HDR_SIZE + (sizeof FORMAT - 1) * sizeof (rtunion)), |
130 | ||
131 | #include "rtl.def" | |
132 | #undef DEF_RTL_EXPR | |
133 | }; | |
134 | ||
759bebca | 135 | /* Names for kinds of NOTEs and REG_NOTEs. */ |
136 | ||
ad4583d9 | 137 | const char * const note_insn_name[NOTE_INSN_MAX] = |
f220c8f0 | 138 | { |
30f4db0d | 139 | #define DEF_INSN_NOTE(NAME) #NAME, |
140 | #include "insn-notes.def" | |
141 | #undef DEF_INSN_NOTE | |
f220c8f0 | 142 | }; |
143 | ||
30f4db0d | 144 | const char * const reg_note_name[REG_NOTE_MAX] = |
f220c8f0 | 145 | { |
30f4db0d | 146 | #define DEF_REG_NOTE(NAME) #NAME, |
147 | #include "reg-notes.def" | |
148 | #undef DEF_REG_NOTE | |
f220c8f0 | 149 | }; |
759bebca | 150 | |
7a413494 | 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; | |
86736f9e | 155 | |
ad87de1e | 156 | \f |
759bebca | 157 | /* Allocate an rtx vector of N elements. |
158 | Store the length, and initialize all elements to zero. */ | |
159 | ||
160 | rtvec | |
3ad4992f | 161 | rtvec_alloc (int n) |
759bebca | 162 | { |
163 | rtvec rt; | |
f220c8f0 | 164 | |
ba72912a | 165 | rt = ggc_alloc_rtvec_sized (n); |
aab2cf92 | 166 | /* Clear out the vector. */ |
791ceafe | 167 | memset (&rt->elem[0], 0, n * sizeof (rtx)); |
759bebca | 168 | |
53d3f913 | 169 | PUT_NUM_ELEM (rt, n); |
86736f9e | 170 | |
ecd52ea9 | 171 | if (GATHER_STATISTICS) |
172 | { | |
173 | rtvec_alloc_counts++; | |
174 | rtvec_alloc_sizes += n * sizeof (rtx); | |
175 | } | |
86736f9e | 176 | |
759bebca | 177 | return rt; |
178 | } | |
179 | ||
b447ca78 | 180 | /* Create a bitwise copy of VEC. */ |
181 | ||
182 | rtvec | |
183 | shallow_copy_rtvec (rtvec vec) | |
184 | { | |
185 | rtvec newvec; | |
186 | int n; | |
187 | ||
188 | n = GET_NUM_ELEM (vec); | |
189 | newvec = rtvec_alloc (n); | |
190 | memcpy (&newvec->elem[0], &vec->elem[0], sizeof (rtx) * n); | |
191 | return newvec; | |
192 | } | |
193 | ||
f2d0e9f1 | 194 | /* Return the number of bytes occupied by rtx value X. */ |
195 | ||
196 | unsigned int | |
dd9b9fc5 | 197 | rtx_size (const_rtx x) |
f2d0e9f1 | 198 | { |
e913b5cd | 199 | if (CONST_WIDE_INT_P (x)) |
200 | return (RTX_HDR_SIZE | |
201 | + sizeof (struct hwivec_def) | |
202 | + ((CONST_WIDE_INT_NUNITS (x) - 1) | |
203 | * sizeof (HOST_WIDE_INT))); | |
bbad7cd0 | 204 | if (CONST_POLY_INT_P (x)) |
205 | return (RTX_HDR_SIZE | |
206 | + sizeof (struct const_poly_int_def) | |
207 | + CONST_POLY_INT_COEFFS (x).extra_size ()); | |
6617cbc1 | 208 | if (GET_CODE (x) == SYMBOL_REF && SYMBOL_REF_HAS_BLOCK_INFO_P (x)) |
f2d0e9f1 | 209 | return RTX_HDR_SIZE + sizeof (struct block_symbol); |
210 | return RTX_CODE_SIZE (GET_CODE (x)); | |
211 | } | |
212 | ||
e913b5cd | 213 | /* Allocate an rtx of code CODE with EXTRA bytes in it. The CODE is |
214 | stored in the rtx; all the rest is initialized to zero. */ | |
759bebca | 215 | |
216 | rtx | |
e913b5cd | 217 | rtx_alloc_stat_v (RTX_CODE code MEM_STAT_DECL, int extra) |
759bebca | 218 | { |
e913b5cd | 219 | rtx rt = ggc_alloc_rtx_def_stat (RTX_CODE_SIZE (code) + extra |
220 | PASS_MEM_STAT); | |
1bfd55c5 | 221 | |
791ceafe | 222 | /* We want to clear everything up to the FLD array. Normally, this |
223 | is one int, but we don't want to assume that and it isn't very | |
224 | portable anyway; this is. */ | |
b56b76ec | 225 | |
bf6b5685 | 226 | memset (rt, 0, RTX_HDR_SIZE); |
759bebca | 227 | PUT_CODE (rt, code); |
86736f9e | 228 | |
ecd52ea9 | 229 | if (GATHER_STATISTICS) |
230 | { | |
231 | rtx_alloc_counts[code]++; | |
232 | rtx_alloc_sizes[code] += RTX_CODE_SIZE (code); | |
233 | } | |
86736f9e | 234 | |
759bebca | 235 | return rt; |
236 | } | |
c49a29c7 | 237 | |
e913b5cd | 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 | |
68095389 | 242 | rtx_alloc (RTX_CODE code MEM_STAT_DECL) |
e913b5cd | 243 | { |
244 | return rtx_alloc_stat_v (code PASS_MEM_STAT, 0); | |
245 | } | |
246 | ||
05c25ee6 | 247 | /* Write the wide constant X to OUTFILE. */ |
e913b5cd | 248 | |
249 | void | |
05c25ee6 | 250 | cwi_output_hex (FILE *outfile, const_rtx x) |
e913b5cd | 251 | { |
05c25ee6 | 252 | int i = CWI_GET_NUM_ELEM (x); |
e913b5cd | 253 | gcc_assert (i > 0); |
b3fba3cd | 254 | if (CWI_ELT (x, i - 1) == 0) |
cc69d08a | 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. */ | |
e913b5cd | 257 | fprintf (outfile, "0x"); |
05c25ee6 | 258 | fprintf (outfile, HOST_WIDE_INT_PRINT_HEX, CWI_ELT (x, --i)); |
e913b5cd | 259 | while (--i >= 0) |
05c25ee6 | 260 | fprintf (outfile, HOST_WIDE_INT_PRINT_PADDED_HEX, CWI_ELT (x, i)); |
e913b5cd | 261 | } |
262 | ||
759bebca | 263 | \f |
3072d30e | 264 | /* Return true if ORIG is a sharable CONST. */ |
265 | ||
266 | bool | |
dd9b9fc5 | 267 | shared_const_p (const_rtx orig) |
3072d30e | 268 | { |
269 | gcc_assert (GET_CODE (orig) == CONST); | |
48e1416a | 270 | |
3072d30e | 271 | /* CONST can be shared if it contains a SYMBOL_REF. If it contains |
272 | a LABEL_REF, it isn't sharable. */ | |
bbad7cd0 | 273 | poly_int64 offset; |
3072d30e | 274 | return (GET_CODE (XEXP (orig, 0)) == PLUS |
275 | && GET_CODE (XEXP (XEXP (orig, 0), 0)) == SYMBOL_REF | |
bbad7cd0 | 276 | && poly_int_rtx_p (XEXP (XEXP (orig, 0), 1), &offset)); |
3072d30e | 277 | } |
278 | ||
279 | ||
759bebca | 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 | |
3ad4992f | 285 | copy_rtx (rtx orig) |
759bebca | 286 | { |
19cb6b50 | 287 | rtx copy; |
288 | int i, j; | |
289 | RTX_CODE code; | |
290 | const char *format_ptr; | |
759bebca | 291 | |
292 | code = GET_CODE (orig); | |
293 | ||
294 | switch (code) | |
295 | { | |
296 | case REG: | |
688ff29b | 297 | case DEBUG_EXPR: |
298 | case VALUE: | |
0349edce | 299 | CASE_CONST_ANY: |
759bebca | 300 | case SYMBOL_REF: |
301 | case CODE_LABEL: | |
302 | case PC: | |
303 | case CC0: | |
1a860023 | 304 | case RETURN: |
9cb2517e | 305 | case SIMPLE_RETURN: |
42e57659 | 306 | case SCRATCH: |
a92771b8 | 307 | /* SCRATCH must be shared because they represent distinct values. */ |
759bebca | 308 | return orig; |
c09425a0 | 309 | case CLOBBER: |
b291008a | 310 | /* Share clobbers of hard registers (like cc0), but do not share pseudo reg |
311 | clobbers or clobbers of hard registers that originated as pseudos. | |
312 | This is needed to allow safe register renaming. */ | |
313 | if (REG_P (XEXP (orig, 0)) && REGNO (XEXP (orig, 0)) < FIRST_PSEUDO_REGISTER | |
314 | && ORIGINAL_REGNO (XEXP (orig, 0)) == REGNO (XEXP (orig, 0))) | |
c09425a0 | 315 | return orig; |
316 | break; | |
42e57659 | 317 | |
70bdfe23 | 318 | case CLOBBER_HIGH: |
319 | gcc_assert (REG_P (XEXP (orig, 0))); | |
320 | return orig; | |
321 | ||
42e57659 | 322 | case CONST: |
3072d30e | 323 | if (shared_const_p (orig)) |
42e57659 | 324 | return orig; |
325 | break; | |
326 | ||
b4495254 | 327 | /* A MEM with a constant address is not sharable. The problem is that |
328 | the constant address may need to be reloaded. If the mem is shared, | |
329 | then reloading one copy of this mem will cause all copies to appear | |
330 | to have been reloaded. */ | |
0dbd1c74 | 331 | |
332 | default: | |
333 | break; | |
759bebca | 334 | } |
335 | ||
f2d0e9f1 | 336 | /* Copy the various flags, fields, and other information. We assume |
337 | that all fields need copying, and then clear the fields that should | |
59241190 | 338 | not be copied. That is the sensible default behavior, and forces |
339 | us to explicitly document why we are *not* copying a flag. */ | |
f2d0e9f1 | 340 | copy = shallow_copy_rtx (orig); |
59241190 | 341 | |
759bebca | 342 | format_ptr = GET_RTX_FORMAT (GET_CODE (copy)); |
343 | ||
344 | for (i = 0; i < GET_RTX_LENGTH (GET_CODE (copy)); i++) | |
f2d0e9f1 | 345 | switch (*format_ptr++) |
346 | { | |
347 | case 'e': | |
348 | if (XEXP (orig, i) != NULL) | |
349 | XEXP (copy, i) = copy_rtx (XEXP (orig, i)); | |
350 | break; | |
351 | ||
352 | case 'E': | |
353 | case 'V': | |
354 | if (XVEC (orig, i) != NULL) | |
355 | { | |
356 | XVEC (copy, i) = rtvec_alloc (XVECLEN (orig, i)); | |
357 | for (j = 0; j < XVECLEN (copy, i); j++) | |
358 | XVECEXP (copy, i, j) = copy_rtx (XVECEXP (orig, i, j)); | |
359 | } | |
360 | break; | |
361 | ||
362 | case 't': | |
363 | case 'w': | |
364 | case 'i': | |
9edf7ea8 | 365 | case 'p': |
f2d0e9f1 | 366 | case 's': |
367 | case 'S': | |
368 | case 'T': | |
369 | case 'u': | |
370 | case 'B': | |
371 | case '0': | |
372 | /* These are left unchanged. */ | |
373 | break; | |
374 | ||
375 | default: | |
376 | gcc_unreachable (); | |
377 | } | |
759bebca | 378 | return copy; |
759bebca | 379 | } |
57ff0c05 | 380 | |
381 | /* Create a new copy of an rtx. Only copy just one level. */ | |
2a631e19 | 382 | |
57ff0c05 | 383 | rtx |
3523e41a | 384 | shallow_copy_rtx (const_rtx orig MEM_STAT_DECL) |
57ff0c05 | 385 | { |
dd9b9fc5 | 386 | const unsigned int size = rtx_size (orig); |
5cc13354 | 387 | rtx const copy = ggc_alloc_rtx_def_stat (size PASS_MEM_STAT); |
99f9d410 | 388 | memcpy (copy, orig, size); |
389 | switch (GET_CODE (orig)) | |
390 | { | |
391 | /* RTX codes copy_rtx_if_shared_1 considers are shareable, | |
392 | the used flag is often used for other purposes. */ | |
393 | case REG: | |
394 | case DEBUG_EXPR: | |
395 | case VALUE: | |
396 | CASE_CONST_ANY: | |
397 | case SYMBOL_REF: | |
398 | case CODE_LABEL: | |
399 | case PC: | |
400 | case CC0: | |
401 | case RETURN: | |
402 | case SIMPLE_RETURN: | |
403 | case SCRATCH: | |
404 | break; | |
405 | default: | |
406 | /* For all other RTXes clear the used flag on the copy. */ | |
407 | RTX_FLAG (copy, used) = 0; | |
408 | break; | |
409 | } | |
410 | return copy; | |
57ff0c05 | 411 | } |
759bebca | 412 | \f |
316bc009 | 413 | /* Nonzero when we are generating CONCATs. */ |
414 | int generating_concat_p; | |
723c0ee7 | 415 | |
416 | /* Nonzero when we are expanding trees to RTL. */ | |
417 | int currently_expanding_to_rtl; | |
418 | ||
140cb7e4 | 419 | \f |
e1ab7874 | 420 | |
48e1416a | 421 | /* Same as rtx_equal_p, but call CB on each pair of rtx if CB is not NULL. |
331cf53a | 422 | When the callback returns true, we continue with the new pair. |
423 | Whenever changing this function check if rtx_equal_p below doesn't need | |
424 | changing as well. */ | |
140cb7e4 | 425 | |
426 | int | |
e1ab7874 | 427 | rtx_equal_p_cb (const_rtx x, const_rtx y, rtx_equal_p_callback_function cb) |
140cb7e4 | 428 | { |
19cb6b50 | 429 | int i; |
430 | int j; | |
431 | enum rtx_code code; | |
432 | const char *fmt; | |
e1ab7874 | 433 | rtx nx, ny; |
140cb7e4 | 434 | |
435 | if (x == y) | |
436 | return 1; | |
437 | if (x == 0 || y == 0) | |
438 | return 0; | |
439 | ||
e1ab7874 | 440 | /* Invoke the callback first. */ |
441 | if (cb != NULL | |
442 | && ((*cb) (&x, &y, &nx, &ny))) | |
443 | return rtx_equal_p_cb (nx, ny, cb); | |
444 | ||
140cb7e4 | 445 | code = GET_CODE (x); |
446 | /* Rtx's of different codes cannot be equal. */ | |
447 | if (code != GET_CODE (y)) | |
448 | return 0; | |
449 | ||
450 | /* (MULT:SI x y) and (MULT:HI x y) are NOT equivalent. | |
451 | (REG:SI x) and (REG:HI x) are NOT equivalent. */ | |
452 | ||
453 | if (GET_MODE (x) != GET_MODE (y)) | |
454 | return 0; | |
455 | ||
04ec15fa | 456 | /* MEMs referring to different address space are not equivalent. */ |
bd1a81f7 | 457 | if (code == MEM && MEM_ADDR_SPACE (x) != MEM_ADDR_SPACE (y)) |
458 | return 0; | |
459 | ||
73f5c1e3 | 460 | /* Some RTL can be compared nonrecursively. */ |
461 | switch (code) | |
462 | { | |
463 | case REG: | |
011e6b51 | 464 | return (REGNO (x) == REGNO (y)); |
73f5c1e3 | 465 | |
466 | case LABEL_REF: | |
c7799456 | 467 | return label_ref_label (x) == label_ref_label (y); |
73f5c1e3 | 468 | |
469 | case SYMBOL_REF: | |
470 | return XSTR (x, 0) == XSTR (y, 0); | |
471 | ||
688ff29b | 472 | case DEBUG_EXPR: |
9845d120 | 473 | case VALUE: |
73f5c1e3 | 474 | case SCRATCH: |
0349edce | 475 | CASE_CONST_UNIQUE: |
73f5c1e3 | 476 | return 0; |
477 | ||
f9c61ef7 | 478 | case DEBUG_IMPLICIT_PTR: |
479 | return DEBUG_IMPLICIT_PTR_DECL (x) | |
480 | == DEBUG_IMPLICIT_PTR_DECL (y); | |
481 | ||
841424cc | 482 | case DEBUG_PARAMETER_REF: |
483 | return DEBUG_PARAMETER_REF_DECL (x) | |
643a814a | 484 | == DEBUG_PARAMETER_REF_DECL (y); |
841424cc | 485 | |
a5701bde | 486 | case ENTRY_VALUE: |
487 | return rtx_equal_p_cb (ENTRY_VALUE_EXP (x), ENTRY_VALUE_EXP (y), cb); | |
488 | ||
73f5c1e3 | 489 | default: |
490 | break; | |
491 | } | |
140cb7e4 | 492 | |
493 | /* Compare the elements. If any pair of corresponding elements | |
e487406e | 494 | fail to match, return 0 for the whole thing. */ |
140cb7e4 | 495 | |
496 | fmt = GET_RTX_FORMAT (code); | |
497 | for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--) | |
498 | { | |
499 | switch (fmt[i]) | |
500 | { | |
501 | case 'w': | |
502 | if (XWINT (x, i) != XWINT (y, i)) | |
503 | return 0; | |
504 | break; | |
3a54beaf | 505 | |
140cb7e4 | 506 | case 'n': |
507 | case 'i': | |
508 | if (XINT (x, i) != XINT (y, i)) | |
6675c1b7 | 509 | { |
510 | #ifndef GENERATOR_FILE | |
511 | if (((code == ASM_OPERANDS && i == 6) | |
512 | || (code == ASM_INPUT && i == 1)) | |
5169661d | 513 | && XINT (x, i) == XINT (y, i)) |
6675c1b7 | 514 | break; |
515 | #endif | |
516 | return 0; | |
517 | } | |
140cb7e4 | 518 | break; |
519 | ||
9edf7ea8 | 520 | case 'p': |
521 | if (maybe_ne (SUBREG_BYTE (x), SUBREG_BYTE (y))) | |
522 | return 0; | |
523 | break; | |
524 | ||
140cb7e4 | 525 | case 'V': |
526 | case 'E': | |
527 | /* Two vectors must have the same length. */ | |
528 | if (XVECLEN (x, i) != XVECLEN (y, i)) | |
529 | return 0; | |
530 | ||
531 | /* And the corresponding elements must match. */ | |
532 | for (j = 0; j < XVECLEN (x, i); j++) | |
48e1416a | 533 | if (rtx_equal_p_cb (XVECEXP (x, i, j), |
e1ab7874 | 534 | XVECEXP (y, i, j), cb) == 0) |
140cb7e4 | 535 | return 0; |
536 | break; | |
537 | ||
538 | case 'e': | |
e1ab7874 | 539 | if (rtx_equal_p_cb (XEXP (x, i), XEXP (y, i), cb) == 0) |
140cb7e4 | 540 | return 0; |
541 | break; | |
542 | ||
543 | case 'S': | |
544 | case 's': | |
100e94da | 545 | if ((XSTR (x, i) || XSTR (y, i)) |
546 | && (! XSTR (x, i) || ! XSTR (y, i) | |
547 | || strcmp (XSTR (x, i), XSTR (y, i)))) | |
140cb7e4 | 548 | return 0; |
549 | break; | |
550 | ||
551 | case 'u': | |
552 | /* These are just backpointers, so they don't matter. */ | |
553 | break; | |
554 | ||
555 | case '0': | |
556 | case 't': | |
557 | break; | |
558 | ||
559 | /* It is believed that rtx's at this level will never | |
560 | contain anything but integers and other rtx's, | |
561 | except for within LABEL_REFs and SYMBOL_REFs. */ | |
562 | default: | |
04e579b6 | 563 | gcc_unreachable (); |
140cb7e4 | 564 | } |
565 | } | |
566 | return 1; | |
567 | } | |
86736f9e | 568 | |
e1ab7874 | 569 | /* Return 1 if X and Y are identical-looking rtx's. |
331cf53a | 570 | This is the Lisp function EQUAL for rtx arguments. |
571 | Whenever changing this function check if rtx_equal_p_cb above doesn't need | |
572 | changing as well. */ | |
e1ab7874 | 573 | |
574 | int | |
575 | rtx_equal_p (const_rtx x, const_rtx y) | |
576 | { | |
331cf53a | 577 | int i; |
578 | int j; | |
579 | enum rtx_code code; | |
580 | const char *fmt; | |
581 | ||
582 | if (x == y) | |
583 | return 1; | |
584 | if (x == 0 || y == 0) | |
585 | return 0; | |
586 | ||
587 | code = GET_CODE (x); | |
588 | /* Rtx's of different codes cannot be equal. */ | |
589 | if (code != GET_CODE (y)) | |
590 | return 0; | |
591 | ||
592 | /* (MULT:SI x y) and (MULT:HI x y) are NOT equivalent. | |
593 | (REG:SI x) and (REG:HI x) are NOT equivalent. */ | |
594 | ||
595 | if (GET_MODE (x) != GET_MODE (y)) | |
596 | return 0; | |
597 | ||
04ec15fa | 598 | /* MEMs referring to different address space are not equivalent. */ |
bd1a81f7 | 599 | if (code == MEM && MEM_ADDR_SPACE (x) != MEM_ADDR_SPACE (y)) |
600 | return 0; | |
601 | ||
331cf53a | 602 | /* Some RTL can be compared nonrecursively. */ |
603 | switch (code) | |
604 | { | |
605 | case REG: | |
606 | return (REGNO (x) == REGNO (y)); | |
607 | ||
608 | case LABEL_REF: | |
c7799456 | 609 | return label_ref_label (x) == label_ref_label (y); |
331cf53a | 610 | |
611 | case SYMBOL_REF: | |
612 | return XSTR (x, 0) == XSTR (y, 0); | |
613 | ||
688ff29b | 614 | case DEBUG_EXPR: |
9845d120 | 615 | case VALUE: |
331cf53a | 616 | case SCRATCH: |
0349edce | 617 | CASE_CONST_UNIQUE: |
331cf53a | 618 | return 0; |
619 | ||
f9c61ef7 | 620 | case DEBUG_IMPLICIT_PTR: |
621 | return DEBUG_IMPLICIT_PTR_DECL (x) | |
622 | == DEBUG_IMPLICIT_PTR_DECL (y); | |
623 | ||
841424cc | 624 | case DEBUG_PARAMETER_REF: |
625 | return DEBUG_PARAMETER_REF_DECL (x) | |
626 | == DEBUG_PARAMETER_REF_DECL (y); | |
627 | ||
a5701bde | 628 | case ENTRY_VALUE: |
629 | return rtx_equal_p (ENTRY_VALUE_EXP (x), ENTRY_VALUE_EXP (y)); | |
630 | ||
331cf53a | 631 | default: |
632 | break; | |
633 | } | |
634 | ||
635 | /* Compare the elements. If any pair of corresponding elements | |
636 | fail to match, return 0 for the whole thing. */ | |
637 | ||
638 | fmt = GET_RTX_FORMAT (code); | |
639 | for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--) | |
640 | { | |
641 | switch (fmt[i]) | |
642 | { | |
643 | case 'w': | |
644 | if (XWINT (x, i) != XWINT (y, i)) | |
645 | return 0; | |
646 | break; | |
647 | ||
648 | case 'n': | |
649 | case 'i': | |
650 | if (XINT (x, i) != XINT (y, i)) | |
6675c1b7 | 651 | { |
652 | #ifndef GENERATOR_FILE | |
653 | if (((code == ASM_OPERANDS && i == 6) | |
654 | || (code == ASM_INPUT && i == 1)) | |
5169661d | 655 | && XINT (x, i) == XINT (y, i)) |
6675c1b7 | 656 | break; |
657 | #endif | |
658 | return 0; | |
659 | } | |
331cf53a | 660 | break; |
661 | ||
9edf7ea8 | 662 | case 'p': |
663 | if (maybe_ne (SUBREG_BYTE (x), SUBREG_BYTE (y))) | |
664 | return 0; | |
665 | break; | |
666 | ||
331cf53a | 667 | case 'V': |
668 | case 'E': | |
669 | /* Two vectors must have the same length. */ | |
670 | if (XVECLEN (x, i) != XVECLEN (y, i)) | |
671 | return 0; | |
672 | ||
673 | /* And the corresponding elements must match. */ | |
674 | for (j = 0; j < XVECLEN (x, i); j++) | |
675 | if (rtx_equal_p (XVECEXP (x, i, j), XVECEXP (y, i, j)) == 0) | |
676 | return 0; | |
677 | break; | |
678 | ||
679 | case 'e': | |
680 | if (rtx_equal_p (XEXP (x, i), XEXP (y, i)) == 0) | |
681 | return 0; | |
682 | break; | |
683 | ||
684 | case 'S': | |
685 | case 's': | |
686 | if ((XSTR (x, i) || XSTR (y, i)) | |
687 | && (! XSTR (x, i) || ! XSTR (y, i) | |
688 | || strcmp (XSTR (x, i), XSTR (y, i)))) | |
689 | return 0; | |
690 | break; | |
691 | ||
692 | case 'u': | |
693 | /* These are just backpointers, so they don't matter. */ | |
694 | break; | |
695 | ||
696 | case '0': | |
697 | case 't': | |
698 | break; | |
699 | ||
700 | /* It is believed that rtx's at this level will never | |
701 | contain anything but integers and other rtx's, | |
702 | except for within LABEL_REFs and SYMBOL_REFs. */ | |
703 | default: | |
704 | gcc_unreachable (); | |
705 | } | |
706 | } | |
707 | return 1; | |
e1ab7874 | 708 | } |
709 | ||
62fdb8e4 | 710 | /* Return true if all elements of VEC are equal. */ |
711 | ||
712 | bool | |
713 | rtvec_all_equal_p (const_rtvec vec) | |
714 | { | |
715 | const_rtx first = RTVEC_ELT (vec, 0); | |
716 | /* Optimize the important special case of a vector of constants. | |
717 | The main use of this function is to detect whether every element | |
718 | of CONST_VECTOR is the same. */ | |
719 | switch (GET_CODE (first)) | |
720 | { | |
721 | CASE_CONST_UNIQUE: | |
722 | for (int i = 1, n = GET_NUM_ELEM (vec); i < n; ++i) | |
723 | if (first != RTVEC_ELT (vec, i)) | |
724 | return false; | |
725 | return true; | |
726 | ||
727 | default: | |
728 | for (int i = 1, n = GET_NUM_ELEM (vec); i < n; ++i) | |
729 | if (!rtx_equal_p (first, RTVEC_ELT (vec, i))) | |
730 | return false; | |
731 | return true; | |
732 | } | |
733 | } | |
734 | ||
03acb861 | 735 | /* Return an indication of which type of insn should have X as a body. |
736 | In generator files, this can be UNKNOWN if the answer is only known | |
737 | at (GCC) runtime. Otherwise the value is CODE_LABEL, INSN, CALL_INSN | |
738 | or JUMP_INSN. */ | |
739 | ||
740 | enum rtx_code | |
741 | classify_insn (rtx x) | |
742 | { | |
743 | if (LABEL_P (x)) | |
744 | return CODE_LABEL; | |
745 | if (GET_CODE (x) == CALL) | |
746 | return CALL_INSN; | |
747 | if (ANY_RETURN_P (x)) | |
748 | return JUMP_INSN; | |
749 | if (GET_CODE (x) == SET) | |
750 | { | |
751 | if (GET_CODE (SET_DEST (x)) == PC) | |
752 | return JUMP_INSN; | |
753 | else if (GET_CODE (SET_SRC (x)) == CALL) | |
754 | return CALL_INSN; | |
755 | else | |
756 | return INSN; | |
757 | } | |
758 | if (GET_CODE (x) == PARALLEL) | |
759 | { | |
760 | int j; | |
10a13d5e | 761 | bool has_return_p = false; |
03acb861 | 762 | for (j = XVECLEN (x, 0) - 1; j >= 0; j--) |
763 | if (GET_CODE (XVECEXP (x, 0, j)) == CALL) | |
764 | return CALL_INSN; | |
d987e663 | 765 | else if (ANY_RETURN_P (XVECEXP (x, 0, j))) |
10a13d5e | 766 | has_return_p = true; |
03acb861 | 767 | else if (GET_CODE (XVECEXP (x, 0, j)) == SET |
768 | && GET_CODE (SET_DEST (XVECEXP (x, 0, j))) == PC) | |
769 | return JUMP_INSN; | |
770 | else if (GET_CODE (XVECEXP (x, 0, j)) == SET | |
771 | && GET_CODE (SET_SRC (XVECEXP (x, 0, j))) == CALL) | |
772 | return CALL_INSN; | |
10a13d5e | 773 | if (has_return_p) |
774 | return JUMP_INSN; | |
03acb861 | 775 | } |
776 | #ifdef GENERATOR_FILE | |
777 | if (GET_CODE (x) == MATCH_OPERAND | |
778 | || GET_CODE (x) == MATCH_OPERATOR | |
779 | || GET_CODE (x) == MATCH_PARALLEL | |
780 | || GET_CODE (x) == MATCH_OP_DUP | |
781 | || GET_CODE (x) == MATCH_DUP | |
782 | || GET_CODE (x) == PARALLEL) | |
783 | return UNKNOWN; | |
784 | #endif | |
785 | return INSN; | |
786 | } | |
787 | ||
7a413494 | 788 | /* Comparator of indices based on rtx_alloc_counts. */ |
789 | ||
790 | static int | |
791 | rtx_count_cmp (const void *p1, const void *p2) | |
792 | { | |
793 | const unsigned *n1 = (const unsigned *)p1; | |
794 | const unsigned *n2 = (const unsigned *)p2; | |
795 | ||
796 | return rtx_alloc_counts[*n1] - rtx_alloc_counts[*n2]; | |
797 | } | |
798 | ||
2e2fd8fe | 799 | void |
800 | dump_rtx_statistics (void) | |
86736f9e | 801 | { |
86736f9e | 802 | int total_counts = 0; |
803 | int total_sizes = 0; | |
ecd52ea9 | 804 | |
805 | if (! GATHER_STATISTICS) | |
806 | { | |
807 | fprintf (stderr, "No RTX statistics\n"); | |
808 | return; | |
809 | } | |
810 | ||
7a413494 | 811 | fprintf (stderr, "\nRTX Kind Count Bytes\n"); |
812 | fprintf (stderr, "-------------------------------------------\n"); | |
813 | ||
814 | auto_vec<unsigned> indices (LAST_AND_UNUSED_RTX_CODE); | |
815 | for (unsigned i = 0; i < LAST_AND_UNUSED_RTX_CODE; i++) | |
816 | indices.quick_push (i); | |
817 | indices.qsort (rtx_count_cmp); | |
818 | ||
819 | for (unsigned i = 0; i < LAST_AND_UNUSED_RTX_CODE; i++) | |
820 | { | |
821 | unsigned j = indices[i]; | |
822 | if (rtx_alloc_counts[j]) | |
823 | { | |
03fac02c | 824 | fprintf (stderr, "%-24s " PRsa (6) " " PRsa (9) "\n", |
7a413494 | 825 | GET_RTX_NAME (j), |
826 | SIZE_AMOUNT (rtx_alloc_counts[j]), | |
827 | SIZE_AMOUNT (rtx_alloc_sizes[j])); | |
828 | total_counts += rtx_alloc_counts[j]; | |
829 | total_sizes += rtx_alloc_sizes[j]; | |
830 | } | |
831 | } | |
832 | ||
86736f9e | 833 | if (rtvec_alloc_counts) |
834 | { | |
03fac02c | 835 | fprintf (stderr, "%-24s " PRsa (6) " " PRsa (9) "\n", "rtvec", |
7a413494 | 836 | SIZE_AMOUNT (rtvec_alloc_counts), |
837 | SIZE_AMOUNT (rtvec_alloc_sizes)); | |
86736f9e | 838 | total_counts += rtvec_alloc_counts; |
839 | total_sizes += rtvec_alloc_sizes; | |
840 | } | |
7a413494 | 841 | fprintf (stderr, "-----------------------------------------------\n"); |
03fac02c | 842 | fprintf (stderr, "%-24s " PRsa (6) " " PRsa (9) "\n", |
7a413494 | 843 | "Total", SIZE_AMOUNT (total_counts), |
844 | SIZE_AMOUNT (total_sizes)); | |
845 | fprintf (stderr, "-----------------------------------------------\n"); | |
86736f9e | 846 | } |
140cb7e4 | 847 | \f |
0c4e40c5 | 848 | #if defined ENABLE_RTL_CHECKING && (GCC_VERSION >= 2007) |
25999090 | 849 | void |
dd9b9fc5 | 850 | rtl_check_failed_bounds (const_rtx r, int n, const char *file, int line, |
3ad4992f | 851 | const char *func) |
25999090 | 852 | { |
0fc48b82 | 853 | internal_error |
1e5fcbe2 | 854 | ("RTL check: access of elt %d of '%s' with last elt %d in %s, at %s:%d", |
0fc48b82 | 855 | n, GET_RTX_NAME (GET_CODE (r)), GET_RTX_LENGTH (GET_CODE (r)) - 1, |
856 | func, trim_filename (file), line); | |
25999090 | 857 | } |
858 | ||
859 | void | |
dd9b9fc5 | 860 | rtl_check_failed_type1 (const_rtx r, int n, int c1, const char *file, int line, |
3ad4992f | 861 | const char *func) |
25999090 | 862 | { |
0fc48b82 | 863 | internal_error |
864 | ("RTL check: expected elt %d type '%c', have '%c' (rtx %s) in %s, at %s:%d", | |
865 | n, c1, GET_RTX_FORMAT (GET_CODE (r))[n], GET_RTX_NAME (GET_CODE (r)), | |
866 | func, trim_filename (file), line); | |
25999090 | 867 | } |
868 | ||
869 | void | |
dd9b9fc5 | 870 | rtl_check_failed_type2 (const_rtx r, int n, int c1, int c2, const char *file, |
3ad4992f | 871 | int line, const char *func) |
25999090 | 872 | { |
0fc48b82 | 873 | internal_error |
874 | ("RTL check: expected elt %d type '%c' or '%c', have '%c' (rtx %s) in %s, at %s:%d", | |
875 | n, c1, c2, GET_RTX_FORMAT (GET_CODE (r))[n], GET_RTX_NAME (GET_CODE (r)), | |
876 | func, trim_filename (file), line); | |
25999090 | 877 | } |
878 | ||
005d995b | 879 | void |
dd9b9fc5 | 880 | rtl_check_failed_code1 (const_rtx r, enum rtx_code code, const char *file, |
3ad4992f | 881 | int line, const char *func) |
005d995b | 882 | { |
1e5fcbe2 | 883 | internal_error ("RTL check: expected code '%s', have '%s' in %s, at %s:%d", |
0fc48b82 | 884 | GET_RTX_NAME (code), GET_RTX_NAME (GET_CODE (r)), func, |
885 | trim_filename (file), line); | |
005d995b | 886 | } |
887 | ||
888 | void | |
dd9b9fc5 | 889 | rtl_check_failed_code2 (const_rtx r, enum rtx_code code1, enum rtx_code code2, |
3ad4992f | 890 | const char *file, int line, const char *func) |
005d995b | 891 | { |
0fc48b82 | 892 | internal_error |
1e5fcbe2 | 893 | ("RTL check: expected code '%s' or '%s', have '%s' in %s, at %s:%d", |
0fc48b82 | 894 | GET_RTX_NAME (code1), GET_RTX_NAME (code2), GET_RTX_NAME (GET_CODE (r)), |
a194077b | 895 | func, trim_filename (file), line); |
005d995b | 896 | } |
897 | ||
34b780a6 | 898 | void |
899 | rtl_check_failed_code3 (const_rtx r, enum rtx_code code1, enum rtx_code code2, | |
900 | enum rtx_code code3, const char *file, int line, | |
901 | const char *func) | |
902 | { | |
903 | internal_error | |
904 | ("RTL check: expected code '%s', '%s' or '%s', have '%s' in %s, at %s:%d", | |
905 | GET_RTX_NAME (code1), GET_RTX_NAME (code2), GET_RTX_NAME (code3), | |
906 | GET_RTX_NAME (GET_CODE (r)), func, trim_filename (file), line); | |
907 | } | |
908 | ||
e8aaae4e | 909 | void |
3754d046 | 910 | rtl_check_failed_code_mode (const_rtx r, enum rtx_code code, machine_mode mode, |
e8aaae4e | 911 | bool not_mode, const char *file, int line, |
912 | const char *func) | |
913 | { | |
914 | internal_error ((not_mode | |
915 | ? ("RTL check: expected code '%s' and not mode '%s', " | |
916 | "have code '%s' and mode '%s' in %s, at %s:%d") | |
917 | : ("RTL check: expected code '%s' and mode '%s', " | |
918 | "have code '%s' and mode '%s' in %s, at %s:%d")), | |
919 | GET_RTX_NAME (code), GET_MODE_NAME (mode), | |
920 | GET_RTX_NAME (GET_CODE (r)), GET_MODE_NAME (GET_MODE (r)), | |
921 | func, trim_filename (file), line); | |
922 | } | |
923 | ||
f2d0e9f1 | 924 | /* Report that line LINE of FILE tried to access the block symbol fields |
925 | of a non-block symbol. FUNC is the function that contains the line. */ | |
926 | ||
927 | void | |
928 | rtl_check_failed_block_symbol (const char *file, int line, const char *func) | |
929 | { | |
930 | internal_error | |
931 | ("RTL check: attempt to treat non-block symbol as a block symbol " | |
932 | "in %s, at %s:%d", func, trim_filename (file), line); | |
933 | } | |
934 | ||
e913b5cd | 935 | /* XXX Maybe print the vector? */ |
936 | void | |
05c25ee6 | 937 | cwi_check_failed_bounds (const_rtx x, int n, const char *file, int line, |
938 | const char *func) | |
e913b5cd | 939 | { |
940 | internal_error | |
941 | ("RTL check: access of hwi elt %d of vector with last elt %d in %s, at %s:%d", | |
05c25ee6 | 942 | n, CWI_GET_NUM_ELEM (x) - 1, func, trim_filename (file), line); |
e913b5cd | 943 | } |
944 | ||
25999090 | 945 | /* XXX Maybe print the vector? */ |
946 | void | |
dd9b9fc5 | 947 | rtvec_check_failed_bounds (const_rtvec r, int n, const char *file, int line, |
3ad4992f | 948 | const char *func) |
25999090 | 949 | { |
0fc48b82 | 950 | internal_error |
951 | ("RTL check: access of elt %d of vector with last elt %d in %s, at %s:%d", | |
952 | n, GET_NUM_ELEM (r) - 1, func, trim_filename (file), line); | |
25999090 | 953 | } |
0c4e40c5 | 954 | #endif /* ENABLE_RTL_CHECKING */ |
e7f75e15 | 955 | |
956 | #if defined ENABLE_RTL_FLAG_CHECKING | |
957 | void | |
dd9b9fc5 | 958 | rtl_check_failed_flag (const char *name, const_rtx r, const char *file, |
3ad4992f | 959 | int line, const char *func) |
e7f75e15 | 960 | { |
961 | internal_error | |
1e5fcbe2 | 962 | ("RTL flag check: %s used with unexpected rtx code '%s' in %s, at %s:%d", |
3c6858c6 | 963 | name, GET_RTX_NAME (GET_CODE (r)), func, trim_filename (file), line); |
e7f75e15 | 964 | } |
965 | #endif /* ENABLE_RTL_FLAG_CHECKING */ |