]>
Commit | Line | Data |
---|---|---|
875d8740 | 1 | /* RTL utility routines. |
d353bf18 | 2 | Copyright (C) 1987-2015 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. |
92 | "r" a register. */ | |
759bebca | 93 | |
94 | #define DEF_RTL_EXPR(ENUM, NAME, FORMAT, CLASS) FORMAT , | |
95 | #include "rtl.def" /* rtl expressions are defined here */ | |
96 | #undef DEF_RTL_EXPR | |
97 | }; | |
98 | ||
99 | /* Indexed by rtx code, gives a character representing the "class" of | |
100 | that rtx code. See rtl.def for documentation on the defined classes. */ | |
101 | ||
6720e96c | 102 | const enum rtx_class rtx_class[NUM_RTX_CODE] = { |
f220c8f0 | 103 | #define DEF_RTL_EXPR(ENUM, NAME, FORMAT, CLASS) CLASS, |
759bebca | 104 | #include "rtl.def" /* rtl expressions are defined here */ |
105 | #undef DEF_RTL_EXPR | |
106 | }; | |
107 | ||
bf6b5685 | 108 | /* Indexed by rtx code, gives the size of the rtx in bytes. */ |
109 | ||
f2d0e9f1 | 110 | const unsigned char rtx_code_size[NUM_RTX_CODE] = { |
bf6b5685 | 111 | #define DEF_RTL_EXPR(ENUM, NAME, FORMAT, CLASS) \ |
9a37e9c6 | 112 | (((ENUM) == CONST_INT || (ENUM) == CONST_DOUBLE \ |
e913b5cd | 113 | || (ENUM) == CONST_FIXED || (ENUM) == CONST_WIDE_INT) \ |
bf6b5685 | 114 | ? RTX_HDR_SIZE + (sizeof FORMAT - 1) * sizeof (HOST_WIDE_INT) \ |
15183fd2 | 115 | : (ENUM) == REG \ |
116 | ? RTX_HDR_SIZE + sizeof (reg_info) \ | |
bf6b5685 | 117 | : RTX_HDR_SIZE + (sizeof FORMAT - 1) * sizeof (rtunion)), |
118 | ||
119 | #include "rtl.def" | |
120 | #undef DEF_RTL_EXPR | |
121 | }; | |
122 | ||
759bebca | 123 | /* Names for kinds of NOTEs and REG_NOTEs. */ |
124 | ||
ad4583d9 | 125 | const char * const note_insn_name[NOTE_INSN_MAX] = |
f220c8f0 | 126 | { |
30f4db0d | 127 | #define DEF_INSN_NOTE(NAME) #NAME, |
128 | #include "insn-notes.def" | |
129 | #undef DEF_INSN_NOTE | |
f220c8f0 | 130 | }; |
131 | ||
30f4db0d | 132 | const char * const reg_note_name[REG_NOTE_MAX] = |
f220c8f0 | 133 | { |
30f4db0d | 134 | #define DEF_REG_NOTE(NAME) #NAME, |
135 | #include "reg-notes.def" | |
136 | #undef DEF_REG_NOTE | |
f220c8f0 | 137 | }; |
759bebca | 138 | |
86736f9e | 139 | static int rtx_alloc_counts[(int) LAST_AND_UNUSED_RTX_CODE]; |
140 | static int rtx_alloc_sizes[(int) LAST_AND_UNUSED_RTX_CODE]; | |
141 | static int rtvec_alloc_counts; | |
142 | static int rtvec_alloc_sizes; | |
86736f9e | 143 | |
ad87de1e | 144 | \f |
759bebca | 145 | /* Allocate an rtx vector of N elements. |
146 | Store the length, and initialize all elements to zero. */ | |
147 | ||
148 | rtvec | |
3ad4992f | 149 | rtvec_alloc (int n) |
759bebca | 150 | { |
151 | rtvec rt; | |
f220c8f0 | 152 | |
ba72912a | 153 | rt = ggc_alloc_rtvec_sized (n); |
aab2cf92 | 154 | /* Clear out the vector. */ |
791ceafe | 155 | memset (&rt->elem[0], 0, n * sizeof (rtx)); |
759bebca | 156 | |
53d3f913 | 157 | PUT_NUM_ELEM (rt, n); |
86736f9e | 158 | |
ecd52ea9 | 159 | if (GATHER_STATISTICS) |
160 | { | |
161 | rtvec_alloc_counts++; | |
162 | rtvec_alloc_sizes += n * sizeof (rtx); | |
163 | } | |
86736f9e | 164 | |
759bebca | 165 | return rt; |
166 | } | |
167 | ||
b447ca78 | 168 | /* Create a bitwise copy of VEC. */ |
169 | ||
170 | rtvec | |
171 | shallow_copy_rtvec (rtvec vec) | |
172 | { | |
173 | rtvec newvec; | |
174 | int n; | |
175 | ||
176 | n = GET_NUM_ELEM (vec); | |
177 | newvec = rtvec_alloc (n); | |
178 | memcpy (&newvec->elem[0], &vec->elem[0], sizeof (rtx) * n); | |
179 | return newvec; | |
180 | } | |
181 | ||
f2d0e9f1 | 182 | /* Return the number of bytes occupied by rtx value X. */ |
183 | ||
184 | unsigned int | |
dd9b9fc5 | 185 | rtx_size (const_rtx x) |
f2d0e9f1 | 186 | { |
e913b5cd | 187 | if (CONST_WIDE_INT_P (x)) |
188 | return (RTX_HDR_SIZE | |
189 | + sizeof (struct hwivec_def) | |
190 | + ((CONST_WIDE_INT_NUNITS (x) - 1) | |
191 | * sizeof (HOST_WIDE_INT))); | |
6617cbc1 | 192 | if (GET_CODE (x) == SYMBOL_REF && SYMBOL_REF_HAS_BLOCK_INFO_P (x)) |
f2d0e9f1 | 193 | return RTX_HDR_SIZE + sizeof (struct block_symbol); |
194 | return RTX_CODE_SIZE (GET_CODE (x)); | |
195 | } | |
196 | ||
e913b5cd | 197 | /* Allocate an rtx of code CODE with EXTRA bytes in it. The CODE is |
198 | stored in the rtx; all the rest is initialized to zero. */ | |
759bebca | 199 | |
200 | rtx | |
e913b5cd | 201 | rtx_alloc_stat_v (RTX_CODE code MEM_STAT_DECL, int extra) |
759bebca | 202 | { |
e913b5cd | 203 | rtx rt = ggc_alloc_rtx_def_stat (RTX_CODE_SIZE (code) + extra |
204 | PASS_MEM_STAT); | |
1bfd55c5 | 205 | |
791ceafe | 206 | /* We want to clear everything up to the FLD array. Normally, this |
207 | is one int, but we don't want to assume that and it isn't very | |
208 | portable anyway; this is. */ | |
b56b76ec | 209 | |
bf6b5685 | 210 | memset (rt, 0, RTX_HDR_SIZE); |
759bebca | 211 | PUT_CODE (rt, code); |
86736f9e | 212 | |
ecd52ea9 | 213 | if (GATHER_STATISTICS) |
214 | { | |
215 | rtx_alloc_counts[code]++; | |
216 | rtx_alloc_sizes[code] += RTX_CODE_SIZE (code); | |
217 | } | |
86736f9e | 218 | |
759bebca | 219 | return rt; |
220 | } | |
c49a29c7 | 221 | |
e913b5cd | 222 | /* Allocate an rtx of code CODE. The CODE is stored in the rtx; |
223 | all the rest is initialized to zero. */ | |
224 | ||
225 | rtx | |
226 | rtx_alloc_stat (RTX_CODE code MEM_STAT_DECL) | |
227 | { | |
228 | return rtx_alloc_stat_v (code PASS_MEM_STAT, 0); | |
229 | } | |
230 | ||
05c25ee6 | 231 | /* Write the wide constant X to OUTFILE. */ |
e913b5cd | 232 | |
233 | void | |
05c25ee6 | 234 | cwi_output_hex (FILE *outfile, const_rtx x) |
e913b5cd | 235 | { |
05c25ee6 | 236 | int i = CWI_GET_NUM_ELEM (x); |
e913b5cd | 237 | gcc_assert (i > 0); |
b3fba3cd | 238 | if (CWI_ELT (x, i - 1) == 0) |
cc69d08a | 239 | /* The HOST_WIDE_INT_PRINT_HEX prepends a 0x only if the val is |
240 | non zero. We want all numbers to have a 0x prefix. */ | |
e913b5cd | 241 | fprintf (outfile, "0x"); |
05c25ee6 | 242 | fprintf (outfile, HOST_WIDE_INT_PRINT_HEX, CWI_ELT (x, --i)); |
e913b5cd | 243 | while (--i >= 0) |
05c25ee6 | 244 | fprintf (outfile, HOST_WIDE_INT_PRINT_PADDED_HEX, CWI_ELT (x, i)); |
e913b5cd | 245 | } |
246 | ||
759bebca | 247 | \f |
3072d30e | 248 | /* Return true if ORIG is a sharable CONST. */ |
249 | ||
250 | bool | |
dd9b9fc5 | 251 | shared_const_p (const_rtx orig) |
3072d30e | 252 | { |
253 | gcc_assert (GET_CODE (orig) == CONST); | |
48e1416a | 254 | |
3072d30e | 255 | /* CONST can be shared if it contains a SYMBOL_REF. If it contains |
256 | a LABEL_REF, it isn't sharable. */ | |
257 | return (GET_CODE (XEXP (orig, 0)) == PLUS | |
258 | && GET_CODE (XEXP (XEXP (orig, 0), 0)) == SYMBOL_REF | |
9af5ce0c | 259 | && CONST_INT_P (XEXP (XEXP (orig, 0), 1))); |
3072d30e | 260 | } |
261 | ||
262 | ||
759bebca | 263 | /* Create a new copy of an rtx. |
264 | Recursively copies the operands of the rtx, | |
265 | except for those few rtx codes that are sharable. */ | |
266 | ||
267 | rtx | |
3ad4992f | 268 | copy_rtx (rtx orig) |
759bebca | 269 | { |
19cb6b50 | 270 | rtx copy; |
271 | int i, j; | |
272 | RTX_CODE code; | |
273 | const char *format_ptr; | |
759bebca | 274 | |
275 | code = GET_CODE (orig); | |
276 | ||
277 | switch (code) | |
278 | { | |
279 | case REG: | |
688ff29b | 280 | case DEBUG_EXPR: |
281 | case VALUE: | |
0349edce | 282 | CASE_CONST_ANY: |
759bebca | 283 | case SYMBOL_REF: |
284 | case CODE_LABEL: | |
285 | case PC: | |
286 | case CC0: | |
1a860023 | 287 | case RETURN: |
9cb2517e | 288 | case SIMPLE_RETURN: |
42e57659 | 289 | case SCRATCH: |
a92771b8 | 290 | /* SCRATCH must be shared because they represent distinct values. */ |
759bebca | 291 | return orig; |
c09425a0 | 292 | case CLOBBER: |
b291008a | 293 | /* Share clobbers of hard registers (like cc0), but do not share pseudo reg |
294 | clobbers or clobbers of hard registers that originated as pseudos. | |
295 | This is needed to allow safe register renaming. */ | |
296 | if (REG_P (XEXP (orig, 0)) && REGNO (XEXP (orig, 0)) < FIRST_PSEUDO_REGISTER | |
297 | && ORIGINAL_REGNO (XEXP (orig, 0)) == REGNO (XEXP (orig, 0))) | |
c09425a0 | 298 | return orig; |
299 | break; | |
42e57659 | 300 | |
301 | case CONST: | |
3072d30e | 302 | if (shared_const_p (orig)) |
42e57659 | 303 | return orig; |
304 | break; | |
305 | ||
b4495254 | 306 | /* A MEM with a constant address is not sharable. The problem is that |
307 | the constant address may need to be reloaded. If the mem is shared, | |
308 | then reloading one copy of this mem will cause all copies to appear | |
309 | to have been reloaded. */ | |
0dbd1c74 | 310 | |
311 | default: | |
312 | break; | |
759bebca | 313 | } |
314 | ||
f2d0e9f1 | 315 | /* Copy the various flags, fields, and other information. We assume |
316 | that all fields need copying, and then clear the fields that should | |
59241190 | 317 | not be copied. That is the sensible default behavior, and forces |
318 | us to explicitly document why we are *not* copying a flag. */ | |
f2d0e9f1 | 319 | copy = shallow_copy_rtx (orig); |
59241190 | 320 | |
321 | /* We do not copy the USED flag, which is used as a mark bit during | |
322 | walks over the RTL. */ | |
e7f75e15 | 323 | RTX_FLAG (copy, used) = 0; |
59241190 | 324 | |
759bebca | 325 | format_ptr = GET_RTX_FORMAT (GET_CODE (copy)); |
326 | ||
327 | for (i = 0; i < GET_RTX_LENGTH (GET_CODE (copy)); i++) | |
f2d0e9f1 | 328 | switch (*format_ptr++) |
329 | { | |
330 | case 'e': | |
331 | if (XEXP (orig, i) != NULL) | |
332 | XEXP (copy, i) = copy_rtx (XEXP (orig, i)); | |
333 | break; | |
334 | ||
335 | case 'E': | |
336 | case 'V': | |
337 | if (XVEC (orig, i) != NULL) | |
338 | { | |
339 | XVEC (copy, i) = rtvec_alloc (XVECLEN (orig, i)); | |
340 | for (j = 0; j < XVECLEN (copy, i); j++) | |
341 | XVECEXP (copy, i, j) = copy_rtx (XVECEXP (orig, i, j)); | |
342 | } | |
343 | break; | |
344 | ||
345 | case 't': | |
346 | case 'w': | |
347 | case 'i': | |
348 | case 's': | |
349 | case 'S': | |
350 | case 'T': | |
351 | case 'u': | |
352 | case 'B': | |
353 | case '0': | |
354 | /* These are left unchanged. */ | |
355 | break; | |
356 | ||
357 | default: | |
358 | gcc_unreachable (); | |
359 | } | |
759bebca | 360 | return copy; |
759bebca | 361 | } |
57ff0c05 | 362 | |
363 | /* Create a new copy of an rtx. Only copy just one level. */ | |
2a631e19 | 364 | |
57ff0c05 | 365 | rtx |
dd9b9fc5 | 366 | shallow_copy_rtx_stat (const_rtx orig MEM_STAT_DECL) |
57ff0c05 | 367 | { |
dd9b9fc5 | 368 | const unsigned int size = rtx_size (orig); |
5cc13354 | 369 | rtx const copy = ggc_alloc_rtx_def_stat (size PASS_MEM_STAT); |
f7f3687c | 370 | return (rtx) memcpy (copy, orig, size); |
57ff0c05 | 371 | } |
759bebca | 372 | \f |
316bc009 | 373 | /* Nonzero when we are generating CONCATs. */ |
374 | int generating_concat_p; | |
723c0ee7 | 375 | |
376 | /* Nonzero when we are expanding trees to RTL. */ | |
377 | int currently_expanding_to_rtl; | |
378 | ||
140cb7e4 | 379 | \f |
e1ab7874 | 380 | |
48e1416a | 381 | /* Same as rtx_equal_p, but call CB on each pair of rtx if CB is not NULL. |
331cf53a | 382 | When the callback returns true, we continue with the new pair. |
383 | Whenever changing this function check if rtx_equal_p below doesn't need | |
384 | changing as well. */ | |
140cb7e4 | 385 | |
386 | int | |
e1ab7874 | 387 | rtx_equal_p_cb (const_rtx x, const_rtx y, rtx_equal_p_callback_function cb) |
140cb7e4 | 388 | { |
19cb6b50 | 389 | int i; |
390 | int j; | |
391 | enum rtx_code code; | |
392 | const char *fmt; | |
e1ab7874 | 393 | rtx nx, ny; |
140cb7e4 | 394 | |
395 | if (x == y) | |
396 | return 1; | |
397 | if (x == 0 || y == 0) | |
398 | return 0; | |
399 | ||
e1ab7874 | 400 | /* Invoke the callback first. */ |
401 | if (cb != NULL | |
402 | && ((*cb) (&x, &y, &nx, &ny))) | |
403 | return rtx_equal_p_cb (nx, ny, cb); | |
404 | ||
140cb7e4 | 405 | code = GET_CODE (x); |
406 | /* Rtx's of different codes cannot be equal. */ | |
407 | if (code != GET_CODE (y)) | |
408 | return 0; | |
409 | ||
410 | /* (MULT:SI x y) and (MULT:HI x y) are NOT equivalent. | |
411 | (REG:SI x) and (REG:HI x) are NOT equivalent. */ | |
412 | ||
413 | if (GET_MODE (x) != GET_MODE (y)) | |
414 | return 0; | |
415 | ||
04ec15fa | 416 | /* MEMs referring to different address space are not equivalent. */ |
bd1a81f7 | 417 | if (code == MEM && MEM_ADDR_SPACE (x) != MEM_ADDR_SPACE (y)) |
418 | return 0; | |
419 | ||
73f5c1e3 | 420 | /* Some RTL can be compared nonrecursively. */ |
421 | switch (code) | |
422 | { | |
423 | case REG: | |
011e6b51 | 424 | return (REGNO (x) == REGNO (y)); |
73f5c1e3 | 425 | |
426 | case LABEL_REF: | |
b49f2e4b | 427 | return LABEL_REF_LABEL (x) == LABEL_REF_LABEL (y); |
73f5c1e3 | 428 | |
429 | case SYMBOL_REF: | |
430 | return XSTR (x, 0) == XSTR (y, 0); | |
431 | ||
688ff29b | 432 | case DEBUG_EXPR: |
9845d120 | 433 | case VALUE: |
73f5c1e3 | 434 | case SCRATCH: |
0349edce | 435 | CASE_CONST_UNIQUE: |
73f5c1e3 | 436 | return 0; |
437 | ||
f9c61ef7 | 438 | case DEBUG_IMPLICIT_PTR: |
439 | return DEBUG_IMPLICIT_PTR_DECL (x) | |
440 | == DEBUG_IMPLICIT_PTR_DECL (y); | |
441 | ||
841424cc | 442 | case DEBUG_PARAMETER_REF: |
443 | return DEBUG_PARAMETER_REF_DECL (x) | |
643a814a | 444 | == DEBUG_PARAMETER_REF_DECL (y); |
841424cc | 445 | |
a5701bde | 446 | case ENTRY_VALUE: |
447 | return rtx_equal_p_cb (ENTRY_VALUE_EXP (x), ENTRY_VALUE_EXP (y), cb); | |
448 | ||
73f5c1e3 | 449 | default: |
450 | break; | |
451 | } | |
140cb7e4 | 452 | |
453 | /* Compare the elements. If any pair of corresponding elements | |
e487406e | 454 | fail to match, return 0 for the whole thing. */ |
140cb7e4 | 455 | |
456 | fmt = GET_RTX_FORMAT (code); | |
457 | for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--) | |
458 | { | |
459 | switch (fmt[i]) | |
460 | { | |
461 | case 'w': | |
462 | if (XWINT (x, i) != XWINT (y, i)) | |
463 | return 0; | |
464 | break; | |
3a54beaf | 465 | |
140cb7e4 | 466 | case 'n': |
467 | case 'i': | |
468 | if (XINT (x, i) != XINT (y, i)) | |
6675c1b7 | 469 | { |
470 | #ifndef GENERATOR_FILE | |
471 | if (((code == ASM_OPERANDS && i == 6) | |
472 | || (code == ASM_INPUT && i == 1)) | |
5169661d | 473 | && XINT (x, i) == XINT (y, i)) |
6675c1b7 | 474 | break; |
475 | #endif | |
476 | return 0; | |
477 | } | |
140cb7e4 | 478 | break; |
479 | ||
480 | case 'V': | |
481 | case 'E': | |
482 | /* Two vectors must have the same length. */ | |
483 | if (XVECLEN (x, i) != XVECLEN (y, i)) | |
484 | return 0; | |
485 | ||
486 | /* And the corresponding elements must match. */ | |
487 | for (j = 0; j < XVECLEN (x, i); j++) | |
48e1416a | 488 | if (rtx_equal_p_cb (XVECEXP (x, i, j), |
e1ab7874 | 489 | XVECEXP (y, i, j), cb) == 0) |
140cb7e4 | 490 | return 0; |
491 | break; | |
492 | ||
493 | case 'e': | |
e1ab7874 | 494 | if (rtx_equal_p_cb (XEXP (x, i), XEXP (y, i), cb) == 0) |
140cb7e4 | 495 | return 0; |
496 | break; | |
497 | ||
498 | case 'S': | |
499 | case 's': | |
100e94da | 500 | if ((XSTR (x, i) || XSTR (y, i)) |
501 | && (! XSTR (x, i) || ! XSTR (y, i) | |
502 | || strcmp (XSTR (x, i), XSTR (y, i)))) | |
140cb7e4 | 503 | return 0; |
504 | break; | |
505 | ||
506 | case 'u': | |
507 | /* These are just backpointers, so they don't matter. */ | |
508 | break; | |
509 | ||
510 | case '0': | |
511 | case 't': | |
512 | break; | |
513 | ||
514 | /* It is believed that rtx's at this level will never | |
515 | contain anything but integers and other rtx's, | |
516 | except for within LABEL_REFs and SYMBOL_REFs. */ | |
517 | default: | |
04e579b6 | 518 | gcc_unreachable (); |
140cb7e4 | 519 | } |
520 | } | |
521 | return 1; | |
522 | } | |
86736f9e | 523 | |
e1ab7874 | 524 | /* Return 1 if X and Y are identical-looking rtx's. |
331cf53a | 525 | This is the Lisp function EQUAL for rtx arguments. |
526 | Whenever changing this function check if rtx_equal_p_cb above doesn't need | |
527 | changing as well. */ | |
e1ab7874 | 528 | |
529 | int | |
530 | rtx_equal_p (const_rtx x, const_rtx y) | |
531 | { | |
331cf53a | 532 | int i; |
533 | int j; | |
534 | enum rtx_code code; | |
535 | const char *fmt; | |
536 | ||
537 | if (x == y) | |
538 | return 1; | |
539 | if (x == 0 || y == 0) | |
540 | return 0; | |
541 | ||
542 | code = GET_CODE (x); | |
543 | /* Rtx's of different codes cannot be equal. */ | |
544 | if (code != GET_CODE (y)) | |
545 | return 0; | |
546 | ||
547 | /* (MULT:SI x y) and (MULT:HI x y) are NOT equivalent. | |
548 | (REG:SI x) and (REG:HI x) are NOT equivalent. */ | |
549 | ||
550 | if (GET_MODE (x) != GET_MODE (y)) | |
551 | return 0; | |
552 | ||
04ec15fa | 553 | /* MEMs referring to different address space are not equivalent. */ |
bd1a81f7 | 554 | if (code == MEM && MEM_ADDR_SPACE (x) != MEM_ADDR_SPACE (y)) |
555 | return 0; | |
556 | ||
331cf53a | 557 | /* Some RTL can be compared nonrecursively. */ |
558 | switch (code) | |
559 | { | |
560 | case REG: | |
561 | return (REGNO (x) == REGNO (y)); | |
562 | ||
563 | case LABEL_REF: | |
b49f2e4b | 564 | return LABEL_REF_LABEL (x) == LABEL_REF_LABEL (y); |
331cf53a | 565 | |
566 | case SYMBOL_REF: | |
567 | return XSTR (x, 0) == XSTR (y, 0); | |
568 | ||
688ff29b | 569 | case DEBUG_EXPR: |
9845d120 | 570 | case VALUE: |
331cf53a | 571 | case SCRATCH: |
0349edce | 572 | CASE_CONST_UNIQUE: |
331cf53a | 573 | return 0; |
574 | ||
f9c61ef7 | 575 | case DEBUG_IMPLICIT_PTR: |
576 | return DEBUG_IMPLICIT_PTR_DECL (x) | |
577 | == DEBUG_IMPLICIT_PTR_DECL (y); | |
578 | ||
841424cc | 579 | case DEBUG_PARAMETER_REF: |
580 | return DEBUG_PARAMETER_REF_DECL (x) | |
581 | == DEBUG_PARAMETER_REF_DECL (y); | |
582 | ||
a5701bde | 583 | case ENTRY_VALUE: |
584 | return rtx_equal_p (ENTRY_VALUE_EXP (x), ENTRY_VALUE_EXP (y)); | |
585 | ||
331cf53a | 586 | default: |
587 | break; | |
588 | } | |
589 | ||
590 | /* Compare the elements. If any pair of corresponding elements | |
591 | fail to match, return 0 for the whole thing. */ | |
592 | ||
593 | fmt = GET_RTX_FORMAT (code); | |
594 | for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--) | |
595 | { | |
596 | switch (fmt[i]) | |
597 | { | |
598 | case 'w': | |
599 | if (XWINT (x, i) != XWINT (y, i)) | |
600 | return 0; | |
601 | break; | |
602 | ||
603 | case 'n': | |
604 | case 'i': | |
605 | if (XINT (x, i) != XINT (y, i)) | |
6675c1b7 | 606 | { |
607 | #ifndef GENERATOR_FILE | |
608 | if (((code == ASM_OPERANDS && i == 6) | |
609 | || (code == ASM_INPUT && i == 1)) | |
5169661d | 610 | && XINT (x, i) == XINT (y, i)) |
6675c1b7 | 611 | break; |
612 | #endif | |
613 | return 0; | |
614 | } | |
331cf53a | 615 | break; |
616 | ||
617 | case 'V': | |
618 | case 'E': | |
619 | /* Two vectors must have the same length. */ | |
620 | if (XVECLEN (x, i) != XVECLEN (y, i)) | |
621 | return 0; | |
622 | ||
623 | /* And the corresponding elements must match. */ | |
624 | for (j = 0; j < XVECLEN (x, i); j++) | |
625 | if (rtx_equal_p (XVECEXP (x, i, j), XVECEXP (y, i, j)) == 0) | |
626 | return 0; | |
627 | break; | |
628 | ||
629 | case 'e': | |
630 | if (rtx_equal_p (XEXP (x, i), XEXP (y, i)) == 0) | |
631 | return 0; | |
632 | break; | |
633 | ||
634 | case 'S': | |
635 | case 's': | |
636 | if ((XSTR (x, i) || XSTR (y, i)) | |
637 | && (! XSTR (x, i) || ! XSTR (y, i) | |
638 | || strcmp (XSTR (x, i), XSTR (y, i)))) | |
639 | return 0; | |
640 | break; | |
641 | ||
642 | case 'u': | |
643 | /* These are just backpointers, so they don't matter. */ | |
644 | break; | |
645 | ||
646 | case '0': | |
647 | case 't': | |
648 | break; | |
649 | ||
650 | /* It is believed that rtx's at this level will never | |
651 | contain anything but integers and other rtx's, | |
652 | except for within LABEL_REFs and SYMBOL_REFs. */ | |
653 | default: | |
654 | gcc_unreachable (); | |
655 | } | |
656 | } | |
657 | return 1; | |
e1ab7874 | 658 | } |
659 | ||
03acb861 | 660 | /* Return an indication of which type of insn should have X as a body. |
661 | In generator files, this can be UNKNOWN if the answer is only known | |
662 | at (GCC) runtime. Otherwise the value is CODE_LABEL, INSN, CALL_INSN | |
663 | or JUMP_INSN. */ | |
664 | ||
665 | enum rtx_code | |
666 | classify_insn (rtx x) | |
667 | { | |
668 | if (LABEL_P (x)) | |
669 | return CODE_LABEL; | |
670 | if (GET_CODE (x) == CALL) | |
671 | return CALL_INSN; | |
672 | if (ANY_RETURN_P (x)) | |
673 | return JUMP_INSN; | |
674 | if (GET_CODE (x) == SET) | |
675 | { | |
676 | if (GET_CODE (SET_DEST (x)) == PC) | |
677 | return JUMP_INSN; | |
678 | else if (GET_CODE (SET_SRC (x)) == CALL) | |
679 | return CALL_INSN; | |
680 | else | |
681 | return INSN; | |
682 | } | |
683 | if (GET_CODE (x) == PARALLEL) | |
684 | { | |
685 | int j; | |
10a13d5e | 686 | bool has_return_p = false; |
03acb861 | 687 | for (j = XVECLEN (x, 0) - 1; j >= 0; j--) |
688 | if (GET_CODE (XVECEXP (x, 0, j)) == CALL) | |
689 | return CALL_INSN; | |
d987e663 | 690 | else if (ANY_RETURN_P (XVECEXP (x, 0, j))) |
10a13d5e | 691 | has_return_p = true; |
03acb861 | 692 | else if (GET_CODE (XVECEXP (x, 0, j)) == SET |
693 | && GET_CODE (SET_DEST (XVECEXP (x, 0, j))) == PC) | |
694 | return JUMP_INSN; | |
695 | else if (GET_CODE (XVECEXP (x, 0, j)) == SET | |
696 | && GET_CODE (SET_SRC (XVECEXP (x, 0, j))) == CALL) | |
697 | return CALL_INSN; | |
10a13d5e | 698 | if (has_return_p) |
699 | return JUMP_INSN; | |
03acb861 | 700 | } |
701 | #ifdef GENERATOR_FILE | |
702 | if (GET_CODE (x) == MATCH_OPERAND | |
703 | || GET_CODE (x) == MATCH_OPERATOR | |
704 | || GET_CODE (x) == MATCH_PARALLEL | |
705 | || GET_CODE (x) == MATCH_OP_DUP | |
706 | || GET_CODE (x) == MATCH_DUP | |
707 | || GET_CODE (x) == PARALLEL) | |
708 | return UNKNOWN; | |
709 | #endif | |
710 | return INSN; | |
711 | } | |
712 | ||
2e2fd8fe | 713 | void |
714 | dump_rtx_statistics (void) | |
86736f9e | 715 | { |
86736f9e | 716 | int i; |
717 | int total_counts = 0; | |
718 | int total_sizes = 0; | |
ecd52ea9 | 719 | |
720 | if (! GATHER_STATISTICS) | |
721 | { | |
722 | fprintf (stderr, "No RTX statistics\n"); | |
723 | return; | |
724 | } | |
725 | ||
86736f9e | 726 | fprintf (stderr, "\nRTX Kind Count Bytes\n"); |
727 | fprintf (stderr, "---------------------------------------\n"); | |
728 | for (i = 0; i < LAST_AND_UNUSED_RTX_CODE; i++) | |
729 | if (rtx_alloc_counts[i]) | |
730 | { | |
731 | fprintf (stderr, "%-20s %7d %10d\n", GET_RTX_NAME (i), | |
732 | rtx_alloc_counts[i], rtx_alloc_sizes[i]); | |
733 | total_counts += rtx_alloc_counts[i]; | |
734 | total_sizes += rtx_alloc_sizes[i]; | |
735 | } | |
736 | if (rtvec_alloc_counts) | |
737 | { | |
738 | fprintf (stderr, "%-20s %7d %10d\n", "rtvec", | |
739 | rtvec_alloc_counts, rtvec_alloc_sizes); | |
740 | total_counts += rtvec_alloc_counts; | |
741 | total_sizes += rtvec_alloc_sizes; | |
742 | } | |
743 | fprintf (stderr, "---------------------------------------\n"); | |
744 | fprintf (stderr, "%-20s %7d %10d\n", | |
745 | "Total", total_counts, total_sizes); | |
746 | fprintf (stderr, "---------------------------------------\n"); | |
86736f9e | 747 | } |
140cb7e4 | 748 | \f |
0c4e40c5 | 749 | #if defined ENABLE_RTL_CHECKING && (GCC_VERSION >= 2007) |
25999090 | 750 | void |
dd9b9fc5 | 751 | rtl_check_failed_bounds (const_rtx r, int n, const char *file, int line, |
3ad4992f | 752 | const char *func) |
25999090 | 753 | { |
0fc48b82 | 754 | internal_error |
1e5fcbe2 | 755 | ("RTL check: access of elt %d of '%s' with last elt %d in %s, at %s:%d", |
0fc48b82 | 756 | n, GET_RTX_NAME (GET_CODE (r)), GET_RTX_LENGTH (GET_CODE (r)) - 1, |
757 | func, trim_filename (file), line); | |
25999090 | 758 | } |
759 | ||
760 | void | |
dd9b9fc5 | 761 | rtl_check_failed_type1 (const_rtx r, int n, int c1, const char *file, int line, |
3ad4992f | 762 | const char *func) |
25999090 | 763 | { |
0fc48b82 | 764 | internal_error |
765 | ("RTL check: expected elt %d type '%c', have '%c' (rtx %s) in %s, at %s:%d", | |
766 | n, c1, GET_RTX_FORMAT (GET_CODE (r))[n], GET_RTX_NAME (GET_CODE (r)), | |
767 | func, trim_filename (file), line); | |
25999090 | 768 | } |
769 | ||
770 | void | |
dd9b9fc5 | 771 | rtl_check_failed_type2 (const_rtx r, int n, int c1, int c2, const char *file, |
3ad4992f | 772 | int line, const char *func) |
25999090 | 773 | { |
0fc48b82 | 774 | internal_error |
775 | ("RTL check: expected elt %d type '%c' or '%c', have '%c' (rtx %s) in %s, at %s:%d", | |
776 | n, c1, c2, GET_RTX_FORMAT (GET_CODE (r))[n], GET_RTX_NAME (GET_CODE (r)), | |
777 | func, trim_filename (file), line); | |
25999090 | 778 | } |
779 | ||
005d995b | 780 | void |
dd9b9fc5 | 781 | rtl_check_failed_code1 (const_rtx r, enum rtx_code code, const char *file, |
3ad4992f | 782 | int line, const char *func) |
005d995b | 783 | { |
1e5fcbe2 | 784 | internal_error ("RTL check: expected code '%s', have '%s' in %s, at %s:%d", |
0fc48b82 | 785 | GET_RTX_NAME (code), GET_RTX_NAME (GET_CODE (r)), func, |
786 | trim_filename (file), line); | |
005d995b | 787 | } |
788 | ||
789 | void | |
dd9b9fc5 | 790 | rtl_check_failed_code2 (const_rtx r, enum rtx_code code1, enum rtx_code code2, |
3ad4992f | 791 | const char *file, int line, const char *func) |
005d995b | 792 | { |
0fc48b82 | 793 | internal_error |
1e5fcbe2 | 794 | ("RTL check: expected code '%s' or '%s', have '%s' in %s, at %s:%d", |
0fc48b82 | 795 | GET_RTX_NAME (code1), GET_RTX_NAME (code2), GET_RTX_NAME (GET_CODE (r)), |
a194077b | 796 | func, trim_filename (file), line); |
005d995b | 797 | } |
798 | ||
e8aaae4e | 799 | void |
3754d046 | 800 | rtl_check_failed_code_mode (const_rtx r, enum rtx_code code, machine_mode mode, |
e8aaae4e | 801 | bool not_mode, const char *file, int line, |
802 | const char *func) | |
803 | { | |
804 | internal_error ((not_mode | |
805 | ? ("RTL check: expected code '%s' and not mode '%s', " | |
806 | "have code '%s' and mode '%s' in %s, at %s:%d") | |
807 | : ("RTL check: expected code '%s' and mode '%s', " | |
808 | "have code '%s' and mode '%s' in %s, at %s:%d")), | |
809 | GET_RTX_NAME (code), GET_MODE_NAME (mode), | |
810 | GET_RTX_NAME (GET_CODE (r)), GET_MODE_NAME (GET_MODE (r)), | |
811 | func, trim_filename (file), line); | |
812 | } | |
813 | ||
f2d0e9f1 | 814 | /* Report that line LINE of FILE tried to access the block symbol fields |
815 | of a non-block symbol. FUNC is the function that contains the line. */ | |
816 | ||
817 | void | |
818 | rtl_check_failed_block_symbol (const char *file, int line, const char *func) | |
819 | { | |
820 | internal_error | |
821 | ("RTL check: attempt to treat non-block symbol as a block symbol " | |
822 | "in %s, at %s:%d", func, trim_filename (file), line); | |
823 | } | |
824 | ||
e913b5cd | 825 | /* XXX Maybe print the vector? */ |
826 | void | |
05c25ee6 | 827 | cwi_check_failed_bounds (const_rtx x, int n, const char *file, int line, |
828 | const char *func) | |
e913b5cd | 829 | { |
830 | internal_error | |
831 | ("RTL check: access of hwi elt %d of vector with last elt %d in %s, at %s:%d", | |
05c25ee6 | 832 | n, CWI_GET_NUM_ELEM (x) - 1, func, trim_filename (file), line); |
e913b5cd | 833 | } |
834 | ||
25999090 | 835 | /* XXX Maybe print the vector? */ |
836 | void | |
dd9b9fc5 | 837 | rtvec_check_failed_bounds (const_rtvec r, int n, const char *file, int line, |
3ad4992f | 838 | const char *func) |
25999090 | 839 | { |
0fc48b82 | 840 | internal_error |
841 | ("RTL check: access of elt %d of vector with last elt %d in %s, at %s:%d", | |
842 | n, GET_NUM_ELEM (r) - 1, func, trim_filename (file), line); | |
25999090 | 843 | } |
0c4e40c5 | 844 | #endif /* ENABLE_RTL_CHECKING */ |
e7f75e15 | 845 | |
846 | #if defined ENABLE_RTL_FLAG_CHECKING | |
847 | void | |
dd9b9fc5 | 848 | rtl_check_failed_flag (const char *name, const_rtx r, const char *file, |
3ad4992f | 849 | int line, const char *func) |
e7f75e15 | 850 | { |
851 | internal_error | |
1e5fcbe2 | 852 | ("RTL flag check: %s used with unexpected rtx code '%s' in %s, at %s:%d", |
3c6858c6 | 853 | name, GET_RTX_NAME (GET_CODE (r)), func, trim_filename (file), line); |
e7f75e15 | 854 | } |
855 | #endif /* ENABLE_RTL_FLAG_CHECKING */ |