]>
Commit | Line | Data |
---|---|---|
2af2dbdc | 1 | /* Compute different info about registers. |
cbe34bb5 | 2 | Copyright (C) 1987-2017 Free Software Foundation, Inc. |
54dac99e | 3 | |
1322177d | 4 | This file is part of GCC. |
54dac99e | 5 | |
1322177d LB |
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 | |
9dcd6f09 | 8 | Software Foundation; either version 3, or (at your option) any later |
1322177d | 9 | version. |
54dac99e | 10 | |
1322177d LB |
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. | |
54dac99e RK |
15 | |
16 | You should have received a copy of the GNU General Public License | |
9dcd6f09 NC |
17 | along with GCC; see the file COPYING3. If not see |
18 | <http://www.gnu.org/licenses/>. */ | |
54dac99e RK |
19 | |
20 | ||
2af2dbdc VM |
21 | /* This file contains regscan pass of the compiler and passes for |
22 | dealing with info about modes of pseudo-registers inside | |
23 | subregisters. It also defines some tables of information about the | |
24 | hardware registers, function init_reg_sets to initialize the | |
25 | tables, and other auxiliary functions to deal with info about | |
26 | registers and their classes. */ | |
54dac99e RK |
27 | |
28 | #include "config.h" | |
670ee920 | 29 | #include "system.h" |
4977bab6 | 30 | #include "coretypes.h" |
c7131fb2 | 31 | #include "backend.h" |
957060b5 | 32 | #include "target.h" |
54dac99e | 33 | #include "rtl.h" |
957060b5 | 34 | #include "tree.h" |
c7131fb2 | 35 | #include "df.h" |
4d0cdd0c | 36 | #include "memmodel.h" |
957060b5 | 37 | #include "tm_p.h" |
957060b5 AM |
38 | #include "insn-config.h" |
39 | #include "regs.h" | |
40 | #include "ira.h" | |
41 | #include "recog.h" | |
42 | #include "diagnostic-core.h" | |
e4600702 | 43 | #include "reload.h" |
d6f4ec51 | 44 | #include "output.h" |
6fb5fa3c | 45 | #include "tree-pass.h" |
6fb5fa3c DB |
46 | |
47 | /* Maximum register number used in this function, plus one. */ | |
48 | ||
49 | int max_regno; | |
54dac99e | 50 | |
6969eb0d RS |
51 | /* Used to cache the results of simplifiable_subregs. SHAPE is the input |
52 | parameter and SIMPLIFIABLE_REGS is the result. */ | |
53 | struct simplifiable_subreg | |
54 | { | |
55 | simplifiable_subreg (const subreg_shape &); | |
56 | ||
57 | subreg_shape shape; | |
58 | HARD_REG_SET simplifiable_regs; | |
59 | }; | |
54dac99e | 60 | \f |
6642445b | 61 | struct target_hard_regs default_target_hard_regs; |
939dcd0d RS |
62 | struct target_regs default_target_regs; |
63 | #if SWITCHABLE_TARGET | |
6642445b | 64 | struct target_hard_regs *this_target_hard_regs = &default_target_hard_regs; |
939dcd0d RS |
65 | struct target_regs *this_target_regs = &default_target_regs; |
66 | #endif | |
67 | ||
6642445b | 68 | /* Data for initializing fixed_regs. */ |
fef511b5 | 69 | static const char initial_fixed_regs[] = FIXED_REGISTERS; |
54dac99e | 70 | |
6642445b | 71 | /* Data for initializing call_used_regs. */ |
fef511b5 | 72 | static const char initial_call_used_regs[] = CALL_USED_REGISTERS; |
fc1296b7 | 73 | |
fc1296b7 | 74 | #ifdef CALL_REALLY_USED_REGISTERS |
6642445b RS |
75 | /* Data for initializing call_really_used_regs. */ |
76 | static const char initial_call_really_used_regs[] = CALL_REALLY_USED_REGISTERS; | |
fc1296b7 | 77 | #endif |
a6a2274a | 78 | |
f6ae6c51 RS |
79 | #ifdef CALL_REALLY_USED_REGISTERS |
80 | #define CALL_REALLY_USED_REGNO_P(X) call_really_used_regs[X] | |
81 | #else | |
82 | #define CALL_REALLY_USED_REGNO_P(X) call_used_regs[X] | |
83 | #endif | |
84 | ||
54dac99e RK |
85 | /* Indexed by hard register number, contains 1 for registers |
86 | that are being used for global register decls. | |
87 | These must be exempt from ordinary flow analysis | |
88 | and are also considered fixed. */ | |
54dac99e | 89 | char global_regs[FIRST_PSEUDO_REGISTER]; |
4e2db584 | 90 | |
1460ec5c | 91 | /* Declaration for the global register. */ |
af6e8467 | 92 | tree global_regs_decl[FIRST_PSEUDO_REGISTER]; |
1460ec5c | 93 | |
f2ecb626 JH |
94 | /* Same information as REGS_INVALIDATED_BY_CALL but in regset form to be used |
95 | in dataflow more conveniently. */ | |
f2ecb626 JH |
96 | regset regs_invalidated_by_call_regset; |
97 | ||
9e582b1d JR |
98 | /* Same information as FIXED_REG_SET but in regset form. */ |
99 | regset fixed_reg_set_regset; | |
100 | ||
f2ecb626 JH |
101 | /* The bitmap_obstack is used to hold some static variables that |
102 | should not be reset after each function is compiled. */ | |
f2ecb626 JH |
103 | static bitmap_obstack persistent_obstack; |
104 | ||
6642445b | 105 | /* Used to initialize reg_alloc_order. */ |
54dac99e | 106 | #ifdef REG_ALLOC_ORDER |
6642445b | 107 | static int initial_reg_alloc_order[FIRST_PSEUDO_REGISTER] = REG_ALLOC_ORDER; |
54dac99e RK |
108 | #endif |
109 | ||
089e575b RS |
110 | /* The same information, but as an array of unsigned ints. We copy from |
111 | these unsigned ints to the table above. We do this so the tm.h files | |
d4845339 RH |
112 | do not have to be aware of the wordsize for machines with <= 64 regs. |
113 | Note that we hard-code 32 here, not HOST_BITS_PER_INT. */ | |
2e0e2b76 | 114 | #define N_REG_INTS \ |
d4845339 | 115 | ((FIRST_PSEUDO_REGISTER + (32 - 1)) / 32) |
2e0e2b76 | 116 | |
a6a2274a | 117 | static const unsigned int_reg_class_contents[N_REG_CLASSES][N_REG_INTS] |
2e0e2b76 | 118 | = REG_CLASS_CONTENTS; |
54dac99e | 119 | |
94134f42 | 120 | /* Array containing all of the register names. */ |
6642445b | 121 | static const char *const initial_reg_names[] = REGISTER_NAMES; |
d05c8ee7 | 122 | |
778f72f2 | 123 | /* Array containing all of the register class names. */ |
778f72f2 RS |
124 | const char * reg_class_names[] = REG_CLASS_NAMES; |
125 | ||
c07c7c9d | 126 | /* No more global register variables may be declared; true once |
2af2dbdc | 127 | reginfo has been initialized. */ |
6c85df69 AH |
128 | static int no_global_reg_vars = 0; |
129 | ||
6fb5fa3c DB |
130 | /* Given a register bitmap, turn on the bits in a HARD_REG_SET that |
131 | correspond to the hard registers, if any, set in that map. This | |
132 | could be done far more efficiently by having all sorts of special-cases | |
133 | with moving single words, but probably isn't worth the trouble. */ | |
6fb5fa3c | 134 | void |
ed7a4b4b | 135 | reg_set_to_hard_reg_set (HARD_REG_SET *to, const_bitmap from) |
6fb5fa3c DB |
136 | { |
137 | unsigned i; | |
138 | bitmap_iterator bi; | |
139 | ||
140 | EXECUTE_IF_SET_IN_BITMAP (from, 0, i, bi) | |
141 | { | |
142 | if (i >= FIRST_PSEUDO_REGISTER) | |
143 | return; | |
144 | SET_HARD_REG_BIT (*to, i); | |
145 | } | |
146 | } | |
147 | ||
77f55879 RS |
148 | /* Function called only once per target_globals to initialize the |
149 | target_hard_regs structure. Once this is done, various switches | |
150 | may override. */ | |
54dac99e | 151 | void |
0c20a65f | 152 | init_reg_sets (void) |
54dac99e | 153 | { |
b3694847 | 154 | int i, j; |
54dac99e | 155 | |
2e0e2b76 CH |
156 | /* First copy the register information from the initial int form into |
157 | the regsets. */ | |
158 | ||
159 | for (i = 0; i < N_REG_CLASSES; i++) | |
160 | { | |
161 | CLEAR_HARD_REG_SET (reg_class_contents[i]); | |
162 | ||
b85946fc | 163 | /* Note that we hard-code 32 here, not HOST_BITS_PER_INT. */ |
2e0e2b76 | 164 | for (j = 0; j < FIRST_PSEUDO_REGISTER; j++) |
b85946fc RH |
165 | if (int_reg_class_contents[i][j / 32] |
166 | & ((unsigned) 1 << (j % 32))) | |
2e0e2b76 CH |
167 | SET_HARD_REG_BIT (reg_class_contents[i], j); |
168 | } | |
169 | ||
fef511b5 SL |
170 | /* Sanity check: make sure the target macros FIXED_REGISTERS and |
171 | CALL_USED_REGISTERS had the right number of initializers. */ | |
172 | gcc_assert (sizeof fixed_regs == sizeof initial_fixed_regs); | |
173 | gcc_assert (sizeof call_used_regs == sizeof initial_call_used_regs); | |
6642445b RS |
174 | #ifdef CALL_REALLY_USED_REGISTERS |
175 | gcc_assert (sizeof call_really_used_regs | |
176 | == sizeof initial_call_really_used_regs); | |
177 | #endif | |
178 | #ifdef REG_ALLOC_ORDER | |
179 | gcc_assert (sizeof reg_alloc_order == sizeof initial_reg_alloc_order); | |
180 | #endif | |
181 | gcc_assert (sizeof reg_names == sizeof initial_reg_names); | |
54dac99e | 182 | |
fef511b5 SL |
183 | memcpy (fixed_regs, initial_fixed_regs, sizeof fixed_regs); |
184 | memcpy (call_used_regs, initial_call_used_regs, sizeof call_used_regs); | |
6642445b RS |
185 | #ifdef CALL_REALLY_USED_REGISTERS |
186 | memcpy (call_really_used_regs, initial_call_really_used_regs, | |
187 | sizeof call_really_used_regs); | |
188 | #endif | |
189 | #ifdef REG_ALLOC_ORDER | |
190 | memcpy (reg_alloc_order, initial_reg_alloc_order, sizeof reg_alloc_order); | |
191 | #endif | |
192 | memcpy (reg_names, initial_reg_names, sizeof reg_names); | |
006b72bf RS |
193 | |
194 | SET_HARD_REG_SET (accessible_reg_set); | |
195 | SET_HARD_REG_SET (operand_reg_set); | |
910bc42d R |
196 | } |
197 | ||
fef511b5 SL |
198 | /* We need to save copies of some of the register information which |
199 | can be munged by command-line switches so we can restore it during | |
200 | subsequent back-end reinitialization. */ | |
fef511b5 SL |
201 | static char saved_fixed_regs[FIRST_PSEUDO_REGISTER]; |
202 | static char saved_call_used_regs[FIRST_PSEUDO_REGISTER]; | |
203 | #ifdef CALL_REALLY_USED_REGISTERS | |
204 | static char saved_call_really_used_regs[FIRST_PSEUDO_REGISTER]; | |
205 | #endif | |
206 | static const char *saved_reg_names[FIRST_PSEUDO_REGISTER]; | |
006b72bf RS |
207 | static HARD_REG_SET saved_accessible_reg_set; |
208 | static HARD_REG_SET saved_operand_reg_set; | |
fef511b5 SL |
209 | |
210 | /* Save the register information. */ | |
fef511b5 SL |
211 | void |
212 | save_register_info (void) | |
213 | { | |
b5deb7b6 SL |
214 | /* Sanity check: make sure the target macros FIXED_REGISTERS and |
215 | CALL_USED_REGISTERS had the right number of initializers. */ | |
fef511b5 SL |
216 | gcc_assert (sizeof fixed_regs == sizeof saved_fixed_regs); |
217 | gcc_assert (sizeof call_used_regs == sizeof saved_call_used_regs); | |
218 | memcpy (saved_fixed_regs, fixed_regs, sizeof fixed_regs); | |
219 | memcpy (saved_call_used_regs, call_used_regs, sizeof call_used_regs); | |
b5deb7b6 SL |
220 | |
221 | /* Likewise for call_really_used_regs. */ | |
222 | #ifdef CALL_REALLY_USED_REGISTERS | |
223 | gcc_assert (sizeof call_really_used_regs | |
fef511b5 SL |
224 | == sizeof saved_call_really_used_regs); |
225 | memcpy (saved_call_really_used_regs, call_really_used_regs, | |
b5deb7b6 SL |
226 | sizeof call_really_used_regs); |
227 | #endif | |
228 | ||
229 | /* And similarly for reg_names. */ | |
fef511b5 SL |
230 | gcc_assert (sizeof reg_names == sizeof saved_reg_names); |
231 | memcpy (saved_reg_names, reg_names, sizeof reg_names); | |
006b72bf RS |
232 | COPY_HARD_REG_SET (saved_accessible_reg_set, accessible_reg_set); |
233 | COPY_HARD_REG_SET (saved_operand_reg_set, operand_reg_set); | |
fef511b5 SL |
234 | } |
235 | ||
236 | /* Restore the register information. */ | |
fef511b5 SL |
237 | static void |
238 | restore_register_info (void) | |
239 | { | |
240 | memcpy (fixed_regs, saved_fixed_regs, sizeof fixed_regs); | |
241 | memcpy (call_used_regs, saved_call_used_regs, sizeof call_used_regs); | |
242 | ||
243 | #ifdef CALL_REALLY_USED_REGISTERS | |
244 | memcpy (call_really_used_regs, saved_call_really_used_regs, | |
245 | sizeof call_really_used_regs); | |
246 | #endif | |
247 | ||
248 | memcpy (reg_names, saved_reg_names, sizeof reg_names); | |
006b72bf RS |
249 | COPY_HARD_REG_SET (accessible_reg_set, saved_accessible_reg_set); |
250 | COPY_HARD_REG_SET (operand_reg_set, saved_operand_reg_set); | |
fef511b5 SL |
251 | } |
252 | ||
253 | /* After switches have been processed, which perhaps alter | |
254 | `fixed_regs' and `call_used_regs', convert them to HARD_REG_SETs. */ | |
fef511b5 SL |
255 | static void |
256 | init_reg_sets_1 (void) | |
257 | { | |
258 | unsigned int i, j; | |
ef4bddc2 | 259 | unsigned int /* machine_mode */ m; |
fef511b5 SL |
260 | |
261 | restore_register_info (); | |
b5deb7b6 SL |
262 | |
263 | #ifdef REG_ALLOC_ORDER | |
264 | for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) | |
265 | inv_reg_alloc_order[reg_alloc_order[i]] = i; | |
266 | #endif | |
267 | ||
5efd84c5 | 268 | /* Let the target tweak things if necessary. */ |
910bc42d | 269 | |
5efd84c5 | 270 | targetm.conditional_register_usage (); |
910bc42d | 271 | |
54dac99e RK |
272 | /* Compute number of hard regs in each class. */ |
273 | ||
703ad42b | 274 | memset (reg_class_size, 0, sizeof reg_class_size); |
54dac99e | 275 | for (i = 0; i < N_REG_CLASSES; i++) |
c033690d BS |
276 | { |
277 | bool any_nonfixed = false; | |
278 | for (j = 0; j < FIRST_PSEUDO_REGISTER; j++) | |
279 | if (TEST_HARD_REG_BIT (reg_class_contents[i], j)) | |
280 | { | |
281 | reg_class_size[i]++; | |
282 | if (!fixed_regs[j]) | |
283 | any_nonfixed = true; | |
284 | } | |
285 | class_only_fixed_regs[i] = !any_nonfixed; | |
286 | } | |
54dac99e RK |
287 | |
288 | /* Initialize the table of subunions. | |
289 | reg_class_subunion[I][J] gets the largest-numbered reg-class | |
290 | that is contained in the union of classes I and J. */ | |
291 | ||
b5deb7b6 | 292 | memset (reg_class_subunion, 0, sizeof reg_class_subunion); |
54dac99e RK |
293 | for (i = 0; i < N_REG_CLASSES; i++) |
294 | { | |
295 | for (j = 0; j < N_REG_CLASSES; j++) | |
296 | { | |
49a27995 | 297 | HARD_REG_SET c; |
b3694847 | 298 | int k; |
54dac99e RK |
299 | |
300 | COPY_HARD_REG_SET (c, reg_class_contents[i]); | |
301 | IOR_HARD_REG_SET (c, reg_class_contents[j]); | |
302 | for (k = 0; k < N_REG_CLASSES; k++) | |
56b138ae RS |
303 | if (hard_reg_set_subset_p (reg_class_contents[k], c) |
304 | && !hard_reg_set_subset_p (reg_class_contents[k], | |
305 | reg_class_contents | |
306 | [(int) reg_class_subunion[i][j]])) | |
54dac99e | 307 | reg_class_subunion[i][j] = (enum reg_class) k; |
54dac99e RK |
308 | } |
309 | } | |
310 | ||
311 | /* Initialize the table of superunions. | |
312 | reg_class_superunion[I][J] gets the smallest-numbered reg-class | |
313 | containing the union of classes I and J. */ | |
314 | ||
b5deb7b6 | 315 | memset (reg_class_superunion, 0, sizeof reg_class_superunion); |
54dac99e RK |
316 | for (i = 0; i < N_REG_CLASSES; i++) |
317 | { | |
318 | for (j = 0; j < N_REG_CLASSES; j++) | |
319 | { | |
49a27995 | 320 | HARD_REG_SET c; |
b3694847 | 321 | int k; |
54dac99e RK |
322 | |
323 | COPY_HARD_REG_SET (c, reg_class_contents[i]); | |
324 | IOR_HARD_REG_SET (c, reg_class_contents[j]); | |
325 | for (k = 0; k < N_REG_CLASSES; k++) | |
56b138ae RS |
326 | if (hard_reg_set_subset_p (c, reg_class_contents[k])) |
327 | break; | |
54dac99e | 328 | |
54dac99e RK |
329 | reg_class_superunion[i][j] = (enum reg_class) k; |
330 | } | |
331 | } | |
332 | ||
333 | /* Initialize the tables of subclasses and superclasses of each reg class. | |
334 | First clear the whole table, then add the elements as they are found. */ | |
335 | ||
336 | for (i = 0; i < N_REG_CLASSES; i++) | |
337 | { | |
338 | for (j = 0; j < N_REG_CLASSES; j++) | |
2af2dbdc | 339 | reg_class_subclasses[i][j] = LIM_REG_CLASSES; |
54dac99e RK |
340 | } |
341 | ||
342 | for (i = 0; i < N_REG_CLASSES; i++) | |
343 | { | |
344 | if (i == (int) NO_REGS) | |
345 | continue; | |
346 | ||
347 | for (j = i + 1; j < N_REG_CLASSES; j++) | |
56b138ae RS |
348 | if (hard_reg_set_subset_p (reg_class_contents[i], |
349 | reg_class_contents[j])) | |
350 | { | |
351 | /* Reg class I is a subclass of J. | |
352 | Add J to the table of superclasses of I. */ | |
353 | enum reg_class *p; | |
354 | ||
56b138ae RS |
355 | /* Add I to the table of superclasses of J. */ |
356 | p = ®_class_subclasses[j][0]; | |
357 | while (*p != LIM_REG_CLASSES) p++; | |
358 | *p = (enum reg_class) i; | |
359 | } | |
54dac99e | 360 | } |
e4600702 | 361 | |
54dac99e RK |
362 | /* Initialize "constant" tables. */ |
363 | ||
364 | CLEAR_HARD_REG_SET (fixed_reg_set); | |
365 | CLEAR_HARD_REG_SET (call_used_reg_set); | |
366 | CLEAR_HARD_REG_SET (call_fixed_reg_set); | |
4e2db584 | 367 | CLEAR_HARD_REG_SET (regs_invalidated_by_call); |
f2ecb626 JH |
368 | if (!regs_invalidated_by_call_regset) |
369 | { | |
370 | bitmap_obstack_initialize (&persistent_obstack); | |
371 | regs_invalidated_by_call_regset = ALLOC_REG_SET (&persistent_obstack); | |
372 | } | |
373 | else | |
374 | CLEAR_REG_SET (regs_invalidated_by_call_regset); | |
9e582b1d JR |
375 | if (!fixed_reg_set_regset) |
376 | fixed_reg_set_regset = ALLOC_REG_SET (&persistent_obstack); | |
377 | else | |
378 | CLEAR_REG_SET (fixed_reg_set_regset); | |
54dac99e | 379 | |
006b72bf | 380 | AND_HARD_REG_SET (operand_reg_set, accessible_reg_set); |
54dac99e RK |
381 | for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) |
382 | { | |
006b72bf RS |
383 | /* As a special exception, registers whose class is NO_REGS are |
384 | not accepted by `register_operand'. The reason for this change | |
385 | is to allow the representation of special architecture artifacts | |
386 | (such as a condition code register) without extending the rtl | |
387 | definitions. Since registers of class NO_REGS cannot be used | |
388 | as registers in any case where register classes are examined, | |
389 | it is better to apply this exception in a target-independent way. */ | |
390 | if (REGNO_REG_CLASS (i) == NO_REGS) | |
391 | CLEAR_HARD_REG_BIT (operand_reg_set, i); | |
392 | ||
393 | /* If a register is too limited to be treated as a register operand, | |
394 | then it should never be allocated to a pseudo. */ | |
395 | if (!TEST_HARD_REG_BIT (operand_reg_set, i)) | |
396 | { | |
397 | fixed_regs[i] = 1; | |
398 | call_used_regs[i] = 1; | |
399 | } | |
400 | ||
e3cadb61 | 401 | /* call_used_regs must include fixed_regs. */ |
41374e13 | 402 | gcc_assert (!fixed_regs[i] || call_used_regs[i]); |
e3cadb61 RS |
403 | #ifdef CALL_REALLY_USED_REGISTERS |
404 | /* call_used_regs must include call_really_used_regs. */ | |
41374e13 | 405 | gcc_assert (!call_really_used_regs[i] || call_used_regs[i]); |
e3cadb61 RS |
406 | #endif |
407 | ||
54dac99e | 408 | if (fixed_regs[i]) |
9e582b1d JR |
409 | { |
410 | SET_HARD_REG_BIT (fixed_reg_set, i); | |
411 | SET_REGNO_REG_SET (fixed_reg_set_regset, i); | |
412 | } | |
54dac99e RK |
413 | |
414 | if (call_used_regs[i]) | |
415 | SET_HARD_REG_BIT (call_used_reg_set, i); | |
4e2db584 RH |
416 | |
417 | /* There are a couple of fixed registers that we know are safe to | |
418 | exclude from being clobbered by calls: | |
419 | ||
079e7538 NF |
420 | The frame pointer is always preserved across calls. The arg |
421 | pointer is if it is fixed. The stack pointer usually is, | |
422 | unless TARGET_RETURN_POPS_ARGS, in which case an explicit | |
423 | CLOBBER will be present. If we are generating PIC code, the | |
424 | PIC offset table register is preserved across calls, though the | |
425 | target can override that. */ | |
a6a2274a | 426 | |
f6ae6c51 RS |
427 | if (i == STACK_POINTER_REGNUM) |
428 | ; | |
429 | else if (global_regs[i]) | |
f2ecb626 JH |
430 | { |
431 | SET_HARD_REG_BIT (regs_invalidated_by_call, i); | |
432 | SET_REGNO_REG_SET (regs_invalidated_by_call_regset, i); | |
433 | } | |
f6ae6c51 | 434 | else if (i == FRAME_POINTER_REGNUM) |
4e2db584 | 435 | ; |
c3e08036 TS |
436 | else if (!HARD_FRAME_POINTER_IS_FRAME_POINTER |
437 | && i == HARD_FRAME_POINTER_REGNUM) | |
4e2db584 | 438 | ; |
3f393fc6 TS |
439 | else if (FRAME_POINTER_REGNUM != ARG_POINTER_REGNUM |
440 | && i == ARG_POINTER_REGNUM && fixed_regs[i]) | |
4e2db584 | 441 | ; |
f8fe0a4a JM |
442 | else if (!PIC_OFFSET_TABLE_REG_CALL_CLOBBERED |
443 | && i == (unsigned) PIC_OFFSET_TABLE_REGNUM && fixed_regs[i]) | |
4e2db584 | 444 | ; |
f6ae6c51 | 445 | else if (CALL_REALLY_USED_REGNO_P (i)) |
f2ecb626 JH |
446 | { |
447 | SET_HARD_REG_BIT (regs_invalidated_by_call, i); | |
448 | SET_REGNO_REG_SET (regs_invalidated_by_call_regset, i); | |
449 | } | |
54dac99e | 450 | } |
4e2db584 | 451 | |
c3284718 | 452 | COPY_HARD_REG_SET (call_fixed_reg_set, fixed_reg_set); |
f80041ef | 453 | COPY_HARD_REG_SET (fixed_nonglobal_reg_set, fixed_reg_set); |
adee59ae | 454 | |
b5deb7b6 SL |
455 | /* Preserve global registers if called more than once. */ |
456 | for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) | |
457 | { | |
458 | if (global_regs[i]) | |
459 | { | |
adee59ae | 460 | fixed_regs[i] = call_used_regs[i] = 1; |
b5deb7b6 SL |
461 | SET_HARD_REG_BIT (fixed_reg_set, i); |
462 | SET_HARD_REG_BIT (call_used_reg_set, i); | |
463 | SET_HARD_REG_BIT (call_fixed_reg_set, i); | |
464 | } | |
465 | } | |
466 | ||
26277d41 | 467 | memset (have_regs_of_mode, 0, sizeof (have_regs_of_mode)); |
6836e024 | 468 | memset (contains_reg_of_mode, 0, sizeof (contains_reg_of_mode)); |
dbbbbf3b | 469 | for (m = 0; m < (unsigned int) MAX_MACHINE_MODE; m++) |
779d7a1a | 470 | { |
4692943d | 471 | HARD_REG_SET ok_regs, ok_regs2; |
779d7a1a | 472 | CLEAR_HARD_REG_SET (ok_regs); |
4692943d | 473 | CLEAR_HARD_REG_SET (ok_regs2); |
779d7a1a | 474 | for (j = 0; j < FIRST_PSEUDO_REGISTER; j++) |
4692943d | 475 | if (!TEST_HARD_REG_BIT (fixed_nonglobal_reg_set, j) |
f939c3e6 | 476 | && targetm.hard_regno_mode_ok (j, (machine_mode) m)) |
4692943d BS |
477 | { |
478 | SET_HARD_REG_BIT (ok_regs, j); | |
479 | if (!fixed_regs[j]) | |
480 | SET_HARD_REG_BIT (ok_regs2, j); | |
481 | } | |
bbbbb16a | 482 | |
779d7a1a | 483 | for (i = 0; i < N_REG_CLASSES; i++) |
ef4bddc2 | 484 | if ((targetm.class_max_nregs ((reg_class_t) i, (machine_mode) m) |
bbbbb16a | 485 | <= reg_class_size[i]) |
779d7a1a JH |
486 | && hard_reg_set_intersect_p (ok_regs, reg_class_contents[i])) |
487 | { | |
4692943d BS |
488 | contains_reg_of_mode[i][m] = 1; |
489 | if (hard_reg_set_intersect_p (ok_regs2, reg_class_contents[i])) | |
490 | { | |
491 | have_regs_of_mode[m] = 1; | |
492 | contains_allocatable_reg_of_mode[i][m] = 1; | |
493 | } | |
779d7a1a JH |
494 | } |
495 | } | |
c27c5281 DE |
496 | } |
497 | ||
498 | /* Compute the table of register modes. | |
499 | These values are used to record death information for individual registers | |
b5deb7b6 SL |
500 | (as opposed to a multi-register mode). |
501 | This function might be invoked more than once, if the target has support | |
502 | for changing register usage conventions on a per-function basis. | |
503 | */ | |
28420116 | 504 | void |
b5deb7b6 | 505 | init_reg_modes_target (void) |
c27c5281 | 506 | { |
66fd46b6 JH |
507 | int i, j; |
508 | ||
509 | for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) | |
510 | for (j = 0; j < MAX_MACHINE_MODE; j++) | |
ef4bddc2 | 511 | hard_regno_nregs[i][j] = HARD_REGNO_NREGS (i, (machine_mode)j); |
ca4aac00 DE |
512 | |
513 | for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) | |
7f21d440 | 514 | { |
fee226d2 | 515 | reg_raw_mode[i] = choose_hard_reg_mode (i, 1, false); |
7f21d440 | 516 | |
35aebd56 RS |
517 | /* If we couldn't find a valid mode, just use the previous mode |
518 | if it is suitable, otherwise fall back on word_mode. */ | |
7f21d440 | 519 | if (reg_raw_mode[i] == VOIDmode) |
35aebd56 RS |
520 | { |
521 | if (i > 0 && hard_regno_nregs[i][reg_raw_mode[i - 1]] == 1) | |
522 | reg_raw_mode[i] = reg_raw_mode[i - 1]; | |
523 | else | |
524 | reg_raw_mode[i] = word_mode; | |
525 | } | |
7f21d440 | 526 | } |
ca4aac00 DE |
527 | } |
528 | ||
b5deb7b6 SL |
529 | /* Finish initializing the register sets and initialize the register modes. |
530 | This function might be invoked more than once, if the target has support | |
531 | for changing register usage conventions on a per-function basis. | |
532 | */ | |
c27c5281 | 533 | void |
0c20a65f | 534 | init_regs (void) |
c27c5281 DE |
535 | { |
536 | /* This finishes what was started by init_reg_sets, but couldn't be done | |
537 | until after register usage was specified. */ | |
b93a436e | 538 | init_reg_sets_1 (); |
6cde4876 JL |
539 | } |
540 | ||
2af2dbdc | 541 | /* The same as previous function plus initializing IRA. */ |
f68211cd VM |
542 | void |
543 | reinit_regs (void) | |
544 | { | |
545 | init_regs (); | |
8d9b7be5 JZ |
546 | /* caller_save needs to be re-initialized. */ |
547 | caller_save_initialized_p = false; | |
2175bf49 RS |
548 | if (this_target_rtl->target_specific_initialized) |
549 | { | |
550 | ira_init (); | |
551 | recog_init (); | |
552 | } | |
f68211cd VM |
553 | } |
554 | ||
6cde4876 JL |
555 | /* Initialize some fake stack-frame MEM references for use in |
556 | memory_move_secondary_cost. */ | |
6cde4876 | 557 | void |
0c20a65f | 558 | init_fake_stack_mems (void) |
6cde4876 | 559 | { |
2af2dbdc | 560 | int i; |
bbbbb16a | 561 | |
2af2dbdc | 562 | for (i = 0; i < MAX_MACHINE_MODE; i++) |
ef4bddc2 | 563 | top_of_stack[i] = gen_rtx_MEM ((machine_mode) i, stack_pointer_rtx); |
c27c5281 DE |
564 | } |
565 | ||
de8f4b07 AS |
566 | |
567 | /* Compute cost of moving data from a register of class FROM to one of | |
568 | TO, using MODE. */ | |
569 | ||
570 | int | |
ef4bddc2 | 571 | register_move_cost (machine_mode mode, reg_class_t from, reg_class_t to) |
de8f4b07 AS |
572 | { |
573 | return targetm.register_move_cost (mode, from, to); | |
574 | } | |
575 | ||
f5c21ef3 | 576 | /* Compute cost of moving registers to/from memory. */ |
6f76a878 | 577 | |
f5c21ef3 | 578 | int |
ef4bddc2 | 579 | memory_move_cost (machine_mode mode, reg_class_t rclass, bool in) |
f5c21ef3 AS |
580 | { |
581 | return targetm.memory_move_cost (mode, rclass, in); | |
582 | } | |
473fe49b | 583 | |
cbd5b9a2 KR |
584 | /* Compute extra cost of moving registers to/from memory due to reloads. |
585 | Only needed if secondary reloads are required for memory moves. */ | |
586 | int | |
ef4bddc2 | 587 | memory_move_secondary_cost (machine_mode mode, reg_class_t rclass, |
f5c21ef3 | 588 | bool in) |
cbd5b9a2 | 589 | { |
faa832a7 | 590 | reg_class_t altclass; |
cbd5b9a2 | 591 | int partial_cost = 0; |
cbd5b9a2 | 592 | /* We need a memory reference to feed to SECONDARY... macros. */ |
dc297297 | 593 | /* mem may be unused even if the SECONDARY_ macros are defined. */ |
272df862 KG |
594 | rtx mem ATTRIBUTE_UNUSED = top_of_stack[(int) mode]; |
595 | ||
d858f359 | 596 | altclass = secondary_reload_class (in ? 1 : 0, rclass, mode, mem); |
473fe49b | 597 | |
cbd5b9a2 KR |
598 | if (altclass == NO_REGS) |
599 | return 0; | |
600 | ||
601 | if (in) | |
de8f4b07 | 602 | partial_cost = register_move_cost (mode, altclass, rclass); |
cbd5b9a2 | 603 | else |
de8f4b07 | 604 | partial_cost = register_move_cost (mode, rclass, altclass); |
cbd5b9a2 | 605 | |
d858f359 | 606 | if (rclass == altclass) |
cbd5b9a2 | 607 | /* This isn't simply a copy-to-temporary situation. Can't guess |
f5c21ef3 AS |
608 | what it is, so TARGET_MEMORY_MOVE_COST really ought not to be |
609 | calling here in that case. | |
cbd5b9a2 | 610 | |
41374e13 | 611 | I'm tempted to put in an assert here, but returning this will |
cbd5b9a2 KR |
612 | probably only give poor estimates, which is what we would've |
613 | had before this code anyways. */ | |
614 | return partial_cost; | |
615 | ||
616 | /* Check if the secondary reload register will also need a | |
617 | secondary reload. */ | |
618 | return memory_move_secondary_cost (mode, altclass, in) + partial_cost; | |
619 | } | |
cbd5b9a2 | 620 | |
ca4aac00 | 621 | /* Return a machine mode that is legitimate for hard reg REGNO and large |
fee226d2 R |
622 | enough to save nregs. If we can't find one, return VOIDmode. |
623 | If CALL_SAVED is true, only consider modes that are call saved. */ | |
ef4bddc2 | 624 | machine_mode |
0c20a65f | 625 | choose_hard_reg_mode (unsigned int regno ATTRIBUTE_UNUSED, |
fee226d2 | 626 | unsigned int nregs, bool call_saved) |
ca4aac00 | 627 | { |
ef4bddc2 RS |
628 | unsigned int /* machine_mode */ m; |
629 | machine_mode found_mode = VOIDmode, mode; | |
ca4aac00 DE |
630 | |
631 | /* We first look for the largest integer mode that can be validly | |
632 | held in REGNO. If none, we look for the largest floating-point mode. | |
633 | If we still didn't find a valid mode, try CCmode. */ | |
634 | ||
c94843d2 | 635 | FOR_EACH_MODE_IN_CLASS (mode, MODE_INT) |
66fd46b6 | 636 | if ((unsigned) hard_regno_nregs[regno][mode] == nregs |
f939c3e6 | 637 | && targetm.hard_regno_mode_ok (regno, mode) |
80ec73f4 RS |
638 | && (!call_saved |
639 | || !targetm.hard_regno_call_part_clobbered (regno, mode)) | |
80a18161 | 640 | && GET_MODE_SIZE (mode) > GET_MODE_SIZE (found_mode)) |
ca4aac00 DE |
641 | found_mode = mode; |
642 | ||
c94843d2 | 643 | FOR_EACH_MODE_IN_CLASS (mode, MODE_FLOAT) |
66fd46b6 | 644 | if ((unsigned) hard_regno_nregs[regno][mode] == nregs |
f939c3e6 | 645 | && targetm.hard_regno_mode_ok (regno, mode) |
80ec73f4 RS |
646 | && (!call_saved |
647 | || !targetm.hard_regno_call_part_clobbered (regno, mode)) | |
80a18161 | 648 | && GET_MODE_SIZE (mode) > GET_MODE_SIZE (found_mode)) |
ca4aac00 DE |
649 | found_mode = mode; |
650 | ||
c94843d2 | 651 | FOR_EACH_MODE_IN_CLASS (mode, MODE_VECTOR_FLOAT) |
66fd46b6 | 652 | if ((unsigned) hard_regno_nregs[regno][mode] == nregs |
f939c3e6 | 653 | && targetm.hard_regno_mode_ok (regno, mode) |
80ec73f4 RS |
654 | && (!call_saved |
655 | || !targetm.hard_regno_call_part_clobbered (regno, mode)) | |
80a18161 | 656 | && GET_MODE_SIZE (mode) > GET_MODE_SIZE (found_mode)) |
78b583fe AH |
657 | found_mode = mode; |
658 | ||
c94843d2 | 659 | FOR_EACH_MODE_IN_CLASS (mode, MODE_VECTOR_INT) |
66fd46b6 | 660 | if ((unsigned) hard_regno_nregs[regno][mode] == nregs |
f939c3e6 | 661 | && targetm.hard_regno_mode_ok (regno, mode) |
80ec73f4 RS |
662 | && (!call_saved |
663 | || !targetm.hard_regno_call_part_clobbered (regno, mode)) | |
80a18161 | 664 | && GET_MODE_SIZE (mode) > GET_MODE_SIZE (found_mode)) |
78b583fe AH |
665 | found_mode = mode; |
666 | ||
667 | if (found_mode != VOIDmode) | |
668 | return found_mode; | |
669 | ||
0548a9df | 670 | /* Iterate over all of the CCmodes. */ |
dbbbbf3b JDA |
671 | for (m = (unsigned int) CCmode; m < (unsigned int) NUM_MACHINE_MODES; ++m) |
672 | { | |
ef4bddc2 | 673 | mode = (machine_mode) m; |
66fd46b6 | 674 | if ((unsigned) hard_regno_nregs[regno][mode] == nregs |
f939c3e6 | 675 | && targetm.hard_regno_mode_ok (regno, mode) |
80ec73f4 RS |
676 | && (!call_saved |
677 | || !targetm.hard_regno_call_part_clobbered (regno, mode))) | |
dbbbbf3b JDA |
678 | return mode; |
679 | } | |
ca4aac00 DE |
680 | |
681 | /* We can't find a mode valid for this register. */ | |
682 | return VOIDmode; | |
54dac99e RK |
683 | } |
684 | ||
685 | /* Specify the usage characteristics of the register named NAME. | |
686 | It should be a fixed register if FIXED and a | |
687 | call-used register if CALL_USED. */ | |
54dac99e | 688 | void |
0c20a65f | 689 | fix_register (const char *name, int fixed, int call_used) |
54dac99e RK |
690 | { |
691 | int i; | |
0c6d290e | 692 | int reg, nregs; |
54dac99e RK |
693 | |
694 | /* Decode the name and update the primary form of | |
695 | the register info. */ | |
696 | ||
0c6d290e | 697 | if ((reg = decode_reg_name_and_count (name, &nregs)) >= 0) |
e5c90c23 | 698 | { |
0c6d290e RE |
699 | gcc_assert (nregs >= 1); |
700 | for (i = reg; i < reg + nregs; i++) | |
701 | { | |
702 | if ((i == STACK_POINTER_REGNUM | |
cb2fdc84 | 703 | #ifdef HARD_FRAME_POINTER_REGNUM |
0c6d290e | 704 | || i == HARD_FRAME_POINTER_REGNUM |
cb2fdc84 | 705 | #else |
0c6d290e | 706 | || i == FRAME_POINTER_REGNUM |
cb2fdc84 | 707 | #endif |
0c6d290e RE |
708 | ) |
709 | && (fixed == 0 || call_used == 0)) | |
658bd5ca | 710 | { |
0c6d290e | 711 | switch (fixed) |
658bd5ca JM |
712 | { |
713 | case 0: | |
0c6d290e RE |
714 | switch (call_used) |
715 | { | |
716 | case 0: | |
717 | error ("can%'t use %qs as a call-saved register", name); | |
718 | break; | |
719 | ||
720 | case 1: | |
721 | error ("can%'t use %qs as a call-used register", name); | |
722 | break; | |
723 | ||
724 | default: | |
725 | gcc_unreachable (); | |
726 | } | |
658bd5ca JM |
727 | break; |
728 | ||
729 | case 1: | |
0c6d290e RE |
730 | switch (call_used) |
731 | { | |
732 | case 1: | |
733 | error ("can%'t use %qs as a fixed register", name); | |
734 | break; | |
735 | ||
736 | case 0: | |
737 | default: | |
738 | gcc_unreachable (); | |
739 | } | |
658bd5ca JM |
740 | break; |
741 | ||
742 | default: | |
743 | gcc_unreachable (); | |
744 | } | |
658bd5ca | 745 | } |
0c6d290e RE |
746 | else |
747 | { | |
748 | fixed_regs[i] = fixed; | |
749 | call_used_regs[i] = call_used; | |
ec523c2f | 750 | #ifdef CALL_REALLY_USED_REGISTERS |
0c6d290e RE |
751 | if (fixed == 0) |
752 | call_really_used_regs[i] = call_used; | |
d3259baa | 753 | #endif |
0c6d290e | 754 | } |
cb2fdc84 | 755 | } |
e5c90c23 TW |
756 | } |
757 | else | |
54dac99e | 758 | { |
d4ee4d25 | 759 | warning (0, "unknown register name: %s", name); |
54dac99e RK |
760 | } |
761 | } | |
614f68e2 RK |
762 | |
763 | /* Mark register number I as global. */ | |
614f68e2 | 764 | void |
1460ec5c | 765 | globalize_reg (tree decl, int i) |
614f68e2 | 766 | { |
1460ec5c AK |
767 | location_t loc = DECL_SOURCE_LOCATION (decl); |
768 | ||
2c65142a UB |
769 | #ifdef STACK_REGS |
770 | if (IN_RANGE (i, FIRST_STACK_REG, LAST_STACK_REG)) | |
771 | { | |
772 | error ("stack register used for global register variable"); | |
773 | return; | |
774 | } | |
775 | #endif | |
776 | ||
c07c7c9d | 777 | if (fixed_regs[i] == 0 && no_global_reg_vars) |
1460ec5c | 778 | error_at (loc, "global register variable follows a function definition"); |
6c85df69 | 779 | |
614f68e2 RK |
780 | if (global_regs[i]) |
781 | { | |
1460ec5c AK |
782 | warning_at (loc, 0, |
783 | "register of %qD used for multiple global register variables", | |
784 | decl); | |
785 | inform (DECL_SOURCE_LOCATION (global_regs_decl[i]), | |
786 | "conflicts with %qD", global_regs_decl[i]); | |
614f68e2 RK |
787 | return; |
788 | } | |
789 | ||
790 | if (call_used_regs[i] && ! fixed_regs[i]) | |
1460ec5c | 791 | warning_at (loc, 0, "call-clobbered register used for global register variable"); |
614f68e2 RK |
792 | |
793 | global_regs[i] = 1; | |
1460ec5c | 794 | global_regs_decl[i] = decl; |
614f68e2 | 795 | |
f6ae6c51 RS |
796 | /* If we're globalizing the frame pointer, we need to set the |
797 | appropriate regs_invalidated_by_call bit, even if it's already | |
798 | set in fixed_regs. */ | |
799 | if (i != STACK_POINTER_REGNUM) | |
f2ecb626 JH |
800 | { |
801 | SET_HARD_REG_BIT (regs_invalidated_by_call, i); | |
802 | SET_REGNO_REG_SET (regs_invalidated_by_call_regset, i); | |
2af2dbdc | 803 | } |
f6ae6c51 | 804 | |
614f68e2 RK |
805 | /* If already fixed, nothing else to do. */ |
806 | if (fixed_regs[i]) | |
807 | return; | |
808 | ||
adee59ae | 809 | fixed_regs[i] = call_used_regs[i] = 1; |
74ae207d R |
810 | #ifdef CALL_REALLY_USED_REGISTERS |
811 | call_really_used_regs[i] = 1; | |
812 | #endif | |
614f68e2 RK |
813 | |
814 | SET_HARD_REG_BIT (fixed_reg_set, i); | |
815 | SET_HARD_REG_BIT (call_used_reg_set, i); | |
816 | SET_HARD_REG_BIT (call_fixed_reg_set, i); | |
58929c10 AO |
817 | |
818 | reinit_regs (); | |
614f68e2 | 819 | } |
54dac99e | 820 | \f |
54dac99e | 821 | |
d55d8fc7 | 822 | /* Structure used to record preferences of given pseudo. */ |
9ffc5a70 JH |
823 | struct reg_pref |
824 | { | |
8b649f3f PB |
825 | /* (enum reg_class) prefclass is the preferred class. May be |
826 | NO_REGS if no class is better than memory. */ | |
9ffc5a70 JH |
827 | char prefclass; |
828 | ||
829 | /* altclass is a register class that we should use for allocating | |
830 | pseudo if no register in the preferred class is available. | |
831 | If no register in this class is available, memory is preferred. | |
832 | ||
833 | It might appear to be more general to have a bitmask of classes here, | |
834 | but since it is recommended that there be a class corresponding to the | |
835 | union of most major pair of classes, that generality is not required. */ | |
836 | char altclass; | |
ce18efcb | 837 | |
1756cb66 | 838 | /* allocnoclass is a register class that IRA uses for allocating |
ce18efcb | 839 | the pseudo. */ |
1756cb66 | 840 | char allocnoclass; |
9ffc5a70 JH |
841 | }; |
842 | ||
2af2dbdc VM |
843 | /* Record preferences of each pseudo. This is available after RA is |
844 | run. */ | |
9ffc5a70 | 845 | static struct reg_pref *reg_pref; |
54d23420 | 846 | |
1833192f VM |
847 | /* Current size of reg_info. */ |
848 | static int reg_info_size; | |
dfc0f53a VM |
849 | /* Max_reg_num still last resize_reg_info call. */ |
850 | static int max_regno_since_last_resize; | |
1833192f | 851 | |
54dac99e RK |
852 | /* Return the reg_class in which pseudo reg number REGNO is best allocated. |
853 | This function is sometimes called before the info has been computed. | |
854 | When that happens, just return GENERAL_REGS, which is innocuous. */ | |
54dac99e | 855 | enum reg_class |
0c20a65f | 856 | reg_preferred_class (int regno) |
54dac99e | 857 | { |
9ffc5a70 | 858 | if (reg_pref == 0) |
54dac99e | 859 | return GENERAL_REGS; |
058e97ec | 860 | |
dfc0f53a | 861 | gcc_assert (regno < reg_info_size); |
9ffc5a70 | 862 | return (enum reg_class) reg_pref[regno].prefclass; |
54dac99e RK |
863 | } |
864 | ||
e4600702 | 865 | enum reg_class |
0c20a65f | 866 | reg_alternate_class (int regno) |
54dac99e | 867 | { |
9ffc5a70 | 868 | if (reg_pref == 0) |
e4600702 RK |
869 | return ALL_REGS; |
870 | ||
dfc0f53a | 871 | gcc_assert (regno < reg_info_size); |
9ffc5a70 | 872 | return (enum reg_class) reg_pref[regno].altclass; |
54dac99e RK |
873 | } |
874 | ||
ce18efcb VM |
875 | /* Return the reg_class which is used by IRA for its allocation. */ |
876 | enum reg_class | |
1756cb66 | 877 | reg_allocno_class (int regno) |
54dac99e | 878 | { |
ce18efcb VM |
879 | if (reg_pref == 0) |
880 | return NO_REGS; | |
6c85df69 | 881 | |
dfc0f53a | 882 | gcc_assert (regno < reg_info_size); |
1756cb66 | 883 | return (enum reg_class) reg_pref[regno].allocnoclass; |
54dac99e | 884 | } |
6fb5fa3c | 885 | |
b1f21e0a | 886 | \f |
058e97ec | 887 | |
dfc0f53a | 888 | /* Allocate space for reg info and initilize it. */ |
ce18efcb | 889 | static void |
058e97ec VM |
890 | allocate_reg_info (void) |
891 | { | |
dfc0f53a VM |
892 | int i; |
893 | ||
894 | max_regno_since_last_resize = max_reg_num (); | |
895 | reg_info_size = max_regno_since_last_resize * 3 / 2 + 1; | |
058e97ec | 896 | gcc_assert (! reg_pref && ! reg_renumber); |
ce18efcb VM |
897 | reg_renumber = XNEWVEC (short, reg_info_size); |
898 | reg_pref = XCNEWVEC (struct reg_pref, reg_info_size); | |
899 | memset (reg_renumber, -1, reg_info_size * sizeof (short)); | |
dfc0f53a VM |
900 | for (i = 0; i < reg_info_size; i++) |
901 | { | |
902 | reg_pref[i].prefclass = GENERAL_REGS; | |
903 | reg_pref[i].altclass = ALL_REGS; | |
904 | reg_pref[i].allocnoclass = GENERAL_REGS; | |
905 | } | |
058e97ec VM |
906 | } |
907 | ||
908 | ||
dfc0f53a VM |
909 | /* Resize reg info. The new elements will be initialized. Return TRUE |
910 | if new pseudos were added since the last call. */ | |
ce18efcb | 911 | bool |
058e97ec VM |
912 | resize_reg_info (void) |
913 | { | |
dfc0f53a VM |
914 | int old, i; |
915 | bool change_p; | |
058e97ec | 916 | |
1fe28116 VM |
917 | if (reg_pref == NULL) |
918 | { | |
919 | allocate_reg_info (); | |
920 | return true; | |
921 | } | |
dfc0f53a VM |
922 | change_p = max_regno_since_last_resize != max_reg_num (); |
923 | max_regno_since_last_resize = max_reg_num (); | |
924 | if (reg_info_size >= max_reg_num ()) | |
925 | return change_p; | |
ce18efcb | 926 | old = reg_info_size; |
dfc0f53a | 927 | reg_info_size = max_reg_num () * 3 / 2 + 1; |
058e97ec | 928 | gcc_assert (reg_pref && reg_renumber); |
ce18efcb VM |
929 | reg_renumber = XRESIZEVEC (short, reg_renumber, reg_info_size); |
930 | reg_pref = XRESIZEVEC (struct reg_pref, reg_pref, reg_info_size); | |
931 | memset (reg_pref + old, -1, | |
932 | (reg_info_size - old) * sizeof (struct reg_pref)); | |
933 | memset (reg_renumber + old, -1, (reg_info_size - old) * sizeof (short)); | |
dfc0f53a VM |
934 | for (i = old; i < reg_info_size; i++) |
935 | { | |
936 | reg_pref[i].prefclass = GENERAL_REGS; | |
937 | reg_pref[i].altclass = ALL_REGS; | |
938 | reg_pref[i].allocnoclass = GENERAL_REGS; | |
939 | } | |
ce18efcb | 940 | return true; |
058e97ec VM |
941 | } |
942 | ||
943 | ||
ed396e68 BS |
944 | /* Free up the space allocated by allocate_reg_info. */ |
945 | void | |
0c20a65f | 946 | free_reg_info (void) |
ed396e68 | 947 | { |
6fb5fa3c | 948 | if (reg_pref) |
ed396e68 | 949 | { |
6fb5fa3c DB |
950 | free (reg_pref); |
951 | reg_pref = NULL; | |
952 | } | |
ed396e68 | 953 | |
6fb5fa3c DB |
954 | if (reg_renumber) |
955 | { | |
956 | free (reg_renumber); | |
957 | reg_renumber = NULL; | |
ed396e68 | 958 | } |
ed396e68 | 959 | } |
e53a16e7 | 960 | |
ce18efcb | 961 | /* Initialize some global data for this pass. */ |
b8698a0f | 962 | static unsigned int |
ce18efcb VM |
963 | reginfo_init (void) |
964 | { | |
965 | if (df) | |
966 | df_compute_regs_ever_live (true); | |
967 | ||
532aafad | 968 | /* This prevents dump_reg_info from losing if called |
ce18efcb VM |
969 | before reginfo is run. */ |
970 | reg_pref = NULL; | |
dfc0f53a | 971 | reg_info_size = max_regno_since_last_resize = 0; |
ce18efcb VM |
972 | /* No more global register variables may be declared. */ |
973 | no_global_reg_vars = 1; | |
974 | return 1; | |
975 | } | |
976 | ||
27a4cd48 DM |
977 | namespace { |
978 | ||
979 | const pass_data pass_data_reginfo_init = | |
ce18efcb | 980 | { |
27a4cd48 DM |
981 | RTL_PASS, /* type */ |
982 | "reginfo", /* name */ | |
983 | OPTGROUP_NONE, /* optinfo_flags */ | |
27a4cd48 DM |
984 | TV_NONE, /* tv_id */ |
985 | 0, /* properties_required */ | |
986 | 0, /* properties_provided */ | |
987 | 0, /* properties_destroyed */ | |
988 | 0, /* todo_flags_start */ | |
989 | 0, /* todo_flags_finish */ | |
ce18efcb | 990 | }; |
058e97ec | 991 | |
27a4cd48 DM |
992 | class pass_reginfo_init : public rtl_opt_pass |
993 | { | |
994 | public: | |
c3284718 RS |
995 | pass_reginfo_init (gcc::context *ctxt) |
996 | : rtl_opt_pass (pass_data_reginfo_init, ctxt) | |
27a4cd48 DM |
997 | {} |
998 | ||
999 | /* opt_pass methods: */ | |
be55bfe6 | 1000 | virtual unsigned int execute (function *) { return reginfo_init (); } |
27a4cd48 DM |
1001 | |
1002 | }; // class pass_reginfo_init | |
1003 | ||
1004 | } // anon namespace | |
1005 | ||
1006 | rtl_opt_pass * | |
1007 | make_pass_reginfo_init (gcc::context *ctxt) | |
1008 | { | |
1009 | return new pass_reginfo_init (ctxt); | |
1010 | } | |
1011 | ||
058e97ec VM |
1012 | \f |
1013 | ||
dfc0f53a | 1014 | /* Set up preferred, alternate, and allocno classes for REGNO as |
1756cb66 | 1015 | PREFCLASS, ALTCLASS, and ALLOCNOCLASS. */ |
058e97ec VM |
1016 | void |
1017 | setup_reg_classes (int regno, | |
ce18efcb | 1018 | enum reg_class prefclass, enum reg_class altclass, |
1756cb66 | 1019 | enum reg_class allocnoclass) |
058e97ec VM |
1020 | { |
1021 | if (reg_pref == NULL) | |
1022 | return; | |
dfc0f53a | 1023 | gcc_assert (reg_info_size >= max_reg_num ()); |
058e97ec VM |
1024 | reg_pref[regno].prefclass = prefclass; |
1025 | reg_pref[regno].altclass = altclass; | |
1756cb66 | 1026 | reg_pref[regno].allocnoclass = allocnoclass; |
058e97ec VM |
1027 | } |
1028 | ||
54dac99e | 1029 | \f |
6fb5fa3c DB |
1030 | /* This is the `regscan' pass of the compiler, run just before cse and |
1031 | again just before loop. It finds the first and last use of each | |
1032 | pseudo-register. */ | |
79b9ec0d | 1033 | |
f6956569 | 1034 | static void reg_scan_mark_refs (rtx, rtx_insn *); |
2af2dbdc | 1035 | |
54dac99e | 1036 | void |
f6956569 | 1037 | reg_scan (rtx_insn *f, unsigned int nregs ATTRIBUTE_UNUSED) |
54dac99e | 1038 | { |
f6956569 | 1039 | rtx_insn *insn; |
54dac99e | 1040 | |
28cb2b14 RS |
1041 | timevar_push (TV_REG_SCAN); |
1042 | ||
54dac99e | 1043 | for (insn = f; insn; insn = NEXT_INSN (insn)) |
28cb2b14 | 1044 | if (INSN_P (insn)) |
54dac99e | 1045 | { |
6fb5fa3c | 1046 | reg_scan_mark_refs (PATTERN (insn), insn); |
01565a55 | 1047 | if (REG_NOTES (insn)) |
6fb5fa3c | 1048 | reg_scan_mark_refs (REG_NOTES (insn), insn); |
f903b91f | 1049 | } |
79b9ec0d | 1050 | |
0d446150 | 1051 | timevar_pop (TV_REG_SCAN); |
f903b91f DM |
1052 | } |
1053 | ||
e53a16e7 | 1054 | |
1ebecb64 | 1055 | /* X is the expression to scan. INSN is the insn it appears in. |
e53a16e7 ILT |
1056 | NOTE_FLAG is nonzero if X is from INSN's notes rather than its body. |
1057 | We should only record information for REGs with numbers | |
1058 | greater than or equal to MIN_REGNO. */ | |
08d95f91 | 1059 | static void |
f6956569 | 1060 | reg_scan_mark_refs (rtx x, rtx_insn *insn) |
54dac99e | 1061 | { |
b3694847 SS |
1062 | enum rtx_code code; |
1063 | rtx dest; | |
1064 | rtx note; | |
54dac99e | 1065 | |
ed8d2920 MM |
1066 | if (!x) |
1067 | return; | |
fa23c636 | 1068 | code = GET_CODE (x); |
54dac99e RK |
1069 | switch (code) |
1070 | { | |
54dac99e | 1071 | case CONST: |
d8116890 | 1072 | CASE_CONST_ANY: |
54dac99e RK |
1073 | case CC0: |
1074 | case PC: | |
1075 | case SYMBOL_REF: | |
1076 | case LABEL_REF: | |
1077 | case ADDR_VEC: | |
1078 | case ADDR_DIFF_VEC: | |
54dac99e | 1079 | case REG: |
6fb5fa3c | 1080 | return; |
54dac99e | 1081 | |
01565a55 | 1082 | case EXPR_LIST: |
7b18c3db | 1083 | if (XEXP (x, 0)) |
6fb5fa3c | 1084 | reg_scan_mark_refs (XEXP (x, 0), insn); |
01565a55 | 1085 | if (XEXP (x, 1)) |
6fb5fa3c | 1086 | reg_scan_mark_refs (XEXP (x, 1), insn); |
01565a55 RK |
1087 | break; |
1088 | ||
1089 | case INSN_LIST: | |
f91aec98 | 1090 | case INT_LIST: |
01565a55 | 1091 | if (XEXP (x, 1)) |
6fb5fa3c | 1092 | reg_scan_mark_refs (XEXP (x, 1), insn); |
01565a55 RK |
1093 | break; |
1094 | ||
ed8d2920 | 1095 | case CLOBBER: |
6fb5fa3c DB |
1096 | if (MEM_P (XEXP (x, 0))) |
1097 | reg_scan_mark_refs (XEXP (XEXP (x, 0), 0), insn); | |
ed8d2920 MM |
1098 | break; |
1099 | ||
54dac99e RK |
1100 | case SET: |
1101 | /* Count a set of the destination if it is a register. */ | |
1102 | for (dest = SET_DEST (x); | |
1103 | GET_CODE (dest) == SUBREG || GET_CODE (dest) == STRICT_LOW_PART | |
bd5fb71c | 1104 | || GET_CODE (dest) == ZERO_EXTRACT; |
54dac99e RK |
1105 | dest = XEXP (dest, 0)) |
1106 | ; | |
1107 | ||
be8dcd74 RK |
1108 | /* If this is setting a pseudo from another pseudo or the sum of a |
1109 | pseudo and a constant integer and the other pseudo is known to be | |
1110 | a pointer, set the destination to be a pointer as well. | |
1111 | ||
1112 | Likewise if it is setting the destination from an address or from a | |
1113 | value equivalent to an address or to the sum of an address and | |
1114 | something else. | |
a6a2274a | 1115 | |
be8dcd74 RK |
1116 | But don't do any of this if the pseudo corresponds to a user |
1117 | variable since it should have already been set as a pointer based | |
1118 | on the type. */ | |
1119 | ||
f8cfc6aa | 1120 | if (REG_P (SET_DEST (x)) |
be8dcd74 | 1121 | && REGNO (SET_DEST (x)) >= FIRST_PSEUDO_REGISTER |
64d3b4ca JL |
1122 | /* If the destination pseudo is set more than once, then other |
1123 | sets might not be to a pointer value (consider access to a | |
d55d8fc7 | 1124 | union in two threads of control in the presence of global |
3502dc9c | 1125 | optimizations). So only set REG_POINTER on the destination |
64d3b4ca | 1126 | pseudo if this is the only set of that pseudo. */ |
6fb5fa3c | 1127 | && DF_REG_DEF_COUNT (REGNO (SET_DEST (x))) == 1 |
be8dcd74 | 1128 | && ! REG_USERVAR_P (SET_DEST (x)) |
3502dc9c | 1129 | && ! REG_POINTER (SET_DEST (x)) |
f8cfc6aa | 1130 | && ((REG_P (SET_SRC (x)) |
3502dc9c | 1131 | && REG_POINTER (SET_SRC (x))) |
be8dcd74 RK |
1132 | || ((GET_CODE (SET_SRC (x)) == PLUS |
1133 | || GET_CODE (SET_SRC (x)) == LO_SUM) | |
481683e1 | 1134 | && CONST_INT_P (XEXP (SET_SRC (x), 1)) |
f8cfc6aa | 1135 | && REG_P (XEXP (SET_SRC (x), 0)) |
3502dc9c | 1136 | && REG_POINTER (XEXP (SET_SRC (x), 0))) |
be8dcd74 RK |
1137 | || GET_CODE (SET_SRC (x)) == CONST |
1138 | || GET_CODE (SET_SRC (x)) == SYMBOL_REF | |
1139 | || GET_CODE (SET_SRC (x)) == LABEL_REF | |
1140 | || (GET_CODE (SET_SRC (x)) == HIGH | |
1141 | && (GET_CODE (XEXP (SET_SRC (x), 0)) == CONST | |
1142 | || GET_CODE (XEXP (SET_SRC (x), 0)) == SYMBOL_REF | |
1143 | || GET_CODE (XEXP (SET_SRC (x), 0)) == LABEL_REF)) | |
1144 | || ((GET_CODE (SET_SRC (x)) == PLUS | |
1145 | || GET_CODE (SET_SRC (x)) == LO_SUM) | |
1146 | && (GET_CODE (XEXP (SET_SRC (x), 1)) == CONST | |
1147 | || GET_CODE (XEXP (SET_SRC (x), 1)) == SYMBOL_REF | |
1148 | || GET_CODE (XEXP (SET_SRC (x), 1)) == LABEL_REF)) | |
1149 | || ((note = find_reg_note (insn, REG_EQUAL, 0)) != 0 | |
1150 | && (GET_CODE (XEXP (note, 0)) == CONST | |
1151 | || GET_CODE (XEXP (note, 0)) == SYMBOL_REF | |
1152 | || GET_CODE (XEXP (note, 0)) == LABEL_REF)))) | |
3502dc9c | 1153 | REG_POINTER (SET_DEST (x)) = 1; |
be8dcd74 | 1154 | |
0d4903b8 | 1155 | /* If this is setting a register from a register or from a simple |
a560d4d4 | 1156 | conversion of a register, propagate REG_EXPR. */ |
6fb5fa3c | 1157 | if (REG_P (dest) && !REG_ATTRS (dest)) |
de6f3f7a | 1158 | set_reg_attrs_from_value (dest, SET_SRC (x)); |
0d4903b8 | 1159 | |
191816a3 | 1160 | /* fall through */ |
54dac99e RK |
1161 | |
1162 | default: | |
1163 | { | |
b3694847 SS |
1164 | const char *fmt = GET_RTX_FORMAT (code); |
1165 | int i; | |
54dac99e RK |
1166 | for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--) |
1167 | { | |
1168 | if (fmt[i] == 'e') | |
6fb5fa3c | 1169 | reg_scan_mark_refs (XEXP (x, i), insn); |
54dac99e RK |
1170 | else if (fmt[i] == 'E' && XVEC (x, i) != 0) |
1171 | { | |
b3694847 | 1172 | int j; |
54dac99e | 1173 | for (j = XVECLEN (x, i) - 1; j >= 0; j--) |
6fb5fa3c | 1174 | reg_scan_mark_refs (XVECEXP (x, i, j), insn); |
54dac99e RK |
1175 | } |
1176 | } | |
1177 | } | |
1178 | } | |
1179 | } | |
1180 | \f | |
2af2dbdc | 1181 | |
54dac99e RK |
1182 | /* Return nonzero if C1 is a subset of C2, i.e., if every register in C1 |
1183 | is also in C2. */ | |
54dac99e | 1184 | int |
faa832a7 | 1185 | reg_class_subset_p (reg_class_t c1, reg_class_t c2) |
54dac99e | 1186 | { |
56b138ae RS |
1187 | return (c1 == c2 |
1188 | || c2 == ALL_REGS | |
1189 | || hard_reg_set_subset_p (reg_class_contents[(int) c1], | |
1190 | reg_class_contents[(int) c2])); | |
54dac99e RK |
1191 | } |
1192 | ||
1193 | /* Return nonzero if there is a register that is in both C1 and C2. */ | |
54dac99e | 1194 | int |
a56b31ca | 1195 | reg_classes_intersect_p (reg_class_t c1, reg_class_t c2) |
54dac99e | 1196 | { |
56b138ae RS |
1197 | return (c1 == c2 |
1198 | || c1 == ALL_REGS | |
1199 | || c2 == ALL_REGS | |
1200 | || hard_reg_set_intersect_p (reg_class_contents[(int) c1], | |
1201 | reg_class_contents[(int) c2])); | |
54dac99e RK |
1202 | } |
1203 | ||
2af2dbdc | 1204 | \f |
6969eb0d | 1205 | inline hashval_t |
67f58944 | 1206 | simplifiable_subregs_hasher::hash (const simplifiable_subreg *value) |
6969eb0d RS |
1207 | { |
1208 | return value->shape.unique_id (); | |
1209 | } | |
1210 | ||
1211 | inline bool | |
67f58944 TS |
1212 | simplifiable_subregs_hasher::equal (const simplifiable_subreg *value, |
1213 | const subreg_shape *compare) | |
6969eb0d RS |
1214 | { |
1215 | return value->shape == *compare; | |
1216 | } | |
1217 | ||
1218 | inline simplifiable_subreg::simplifiable_subreg (const subreg_shape &shape_in) | |
1219 | : shape (shape_in) | |
1220 | { | |
1221 | CLEAR_HARD_REG_SET (simplifiable_regs); | |
1222 | } | |
1223 | ||
1224 | /* Return the set of hard registers that are able to form the subreg | |
1225 | described by SHAPE. */ | |
1226 | ||
1227 | const HARD_REG_SET & | |
1228 | simplifiable_subregs (const subreg_shape &shape) | |
1229 | { | |
1230 | if (!this_target_hard_regs->x_simplifiable_subregs) | |
1231 | this_target_hard_regs->x_simplifiable_subregs | |
1232 | = new hash_table <simplifiable_subregs_hasher> (30); | |
1233 | simplifiable_subreg **slot | |
1234 | = (this_target_hard_regs->x_simplifiable_subregs | |
1235 | ->find_slot_with_hash (&shape, shape.unique_id (), INSERT)); | |
1236 | ||
1237 | if (!*slot) | |
1238 | { | |
1239 | simplifiable_subreg *info = new simplifiable_subreg (shape); | |
1240 | for (unsigned int i = 0; i < FIRST_PSEUDO_REGISTER; ++i) | |
f939c3e6 | 1241 | if (targetm.hard_regno_mode_ok (i, shape.inner_mode) |
6969eb0d RS |
1242 | && simplify_subreg_regno (i, shape.inner_mode, shape.offset, |
1243 | shape.outer_mode) >= 0) | |
1244 | SET_HARD_REG_BIT (info->simplifiable_regs, i); | |
1245 | *slot = info; | |
1246 | } | |
1247 | return (*slot)->simplifiable_regs; | |
1248 | } | |
2af2dbdc VM |
1249 | |
1250 | /* Passes for keeping and updating info about modes of registers | |
1251 | inside subregisters. */ | |
1252 | ||
6969eb0d RS |
1253 | static HARD_REG_SET **valid_mode_changes; |
1254 | static obstack valid_mode_changes_obstack; | |
41bf2a8b | 1255 | |
2692b5c8 RS |
1256 | /* Restrict the choice of register for SUBREG_REG (SUBREG) based |
1257 | on information about SUBREG. | |
1258 | ||
1259 | If PARTIAL_DEF, SUBREG is a partial definition of a multipart inner | |
1260 | register and we want to ensure that the other parts of the inner | |
1261 | register are correctly preserved. If !PARTIAL_DEF we need to | |
1262 | ensure that SUBREG itself can be formed. */ | |
1263 | ||
6fb5fa3c | 1264 | static void |
2692b5c8 | 1265 | record_subregs_of_mode (rtx subreg, bool partial_def) |
41bf2a8b | 1266 | { |
41bf2a8b | 1267 | unsigned int regno; |
41bf2a8b RH |
1268 | |
1269 | if (!REG_P (SUBREG_REG (subreg))) | |
1270 | return; | |
1271 | ||
1272 | regno = REGNO (SUBREG_REG (subreg)); | |
41bf2a8b RH |
1273 | if (regno < FIRST_PSEUDO_REGISTER) |
1274 | return; | |
1275 | ||
2692b5c8 RS |
1276 | subreg_shape shape (shape_of_subreg (subreg)); |
1277 | if (partial_def) | |
1278 | { | |
1279 | /* The number of independently-accessible SHAPE.outer_mode values | |
1280 | in SHAPE.inner_mode is GET_MODE_SIZE (SHAPE.inner_mode) / SIZE. | |
1281 | We need to check that the assignment will preserve all the other | |
1282 | SIZE-byte chunks in the inner register besides the one that | |
1283 | includes SUBREG. | |
1284 | ||
1285 | In practice it is enough to check whether an equivalent | |
1286 | SHAPE.inner_mode value in an adjacent SIZE-byte chunk can be formed. | |
1287 | If the underlying registers are small enough, both subregs will | |
1288 | be valid. If the underlying registers are too large, one of the | |
1289 | subregs will be invalid. | |
1290 | ||
1291 | This relies on the fact that we've already been passed | |
1292 | SUBREG with PARTIAL_DEF set to false. */ | |
1293 | unsigned int size = MAX (REGMODE_NATURAL_SIZE (shape.inner_mode), | |
1294 | GET_MODE_SIZE (shape.outer_mode)); | |
1295 | gcc_checking_assert (size < GET_MODE_SIZE (shape.inner_mode)); | |
1296 | if (shape.offset >= size) | |
1297 | shape.offset -= size; | |
1298 | else | |
1299 | shape.offset += size; | |
1300 | } | |
1301 | ||
6969eb0d RS |
1302 | if (valid_mode_changes[regno]) |
1303 | AND_HARD_REG_SET (*valid_mode_changes[regno], | |
2692b5c8 | 1304 | simplifiable_subregs (shape)); |
6969eb0d | 1305 | else |
41bf2a8b | 1306 | { |
6969eb0d RS |
1307 | valid_mode_changes[regno] |
1308 | = XOBNEW (&valid_mode_changes_obstack, HARD_REG_SET); | |
1309 | COPY_HARD_REG_SET (*valid_mode_changes[regno], | |
2692b5c8 | 1310 | simplifiable_subregs (shape)); |
41bf2a8b | 1311 | } |
41bf2a8b RH |
1312 | } |
1313 | ||
6fb5fa3c | 1314 | /* Call record_subregs_of_mode for all the subregs in X. */ |
b8698a0f | 1315 | static void |
6969eb0d | 1316 | find_subregs_of_mode (rtx x) |
6fb5fa3c DB |
1317 | { |
1318 | enum rtx_code code = GET_CODE (x); | |
1319 | const char * const fmt = GET_RTX_FORMAT (code); | |
1320 | int i; | |
1321 | ||
1322 | if (code == SUBREG) | |
2692b5c8 | 1323 | record_subregs_of_mode (x, false); |
b8698a0f | 1324 | |
6fb5fa3c DB |
1325 | /* Time for some deep diving. */ |
1326 | for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--) | |
1327 | { | |
1328 | if (fmt[i] == 'e') | |
6969eb0d | 1329 | find_subregs_of_mode (XEXP (x, i)); |
6fb5fa3c DB |
1330 | else if (fmt[i] == 'E') |
1331 | { | |
1332 | int j; | |
1333 | for (j = XVECLEN (x, i) - 1; j >= 0; j--) | |
6969eb0d | 1334 | find_subregs_of_mode (XVECEXP (x, i, j)); |
6fb5fa3c DB |
1335 | } |
1336 | } | |
1337 | } | |
1338 | ||
1833192f | 1339 | void |
6fb5fa3c DB |
1340 | init_subregs_of_mode (void) |
1341 | { | |
1342 | basic_block bb; | |
f6956569 | 1343 | rtx_insn *insn; |
6fb5fa3c | 1344 | |
6969eb0d RS |
1345 | gcc_obstack_init (&valid_mode_changes_obstack); |
1346 | valid_mode_changes = XCNEWVEC (HARD_REG_SET *, max_reg_num ()); | |
6fb5fa3c | 1347 | |
11cd3bed | 1348 | FOR_EACH_BB_FN (bb, cfun) |
6fb5fa3c | 1349 | FOR_BB_INSNS (bb, insn) |
a6d1cd85 | 1350 | if (NONDEBUG_INSN_P (insn)) |
2692b5c8 RS |
1351 | { |
1352 | find_subregs_of_mode (PATTERN (insn)); | |
1353 | df_ref def; | |
1354 | FOR_EACH_INSN_DEF (def, insn) | |
1355 | if (DF_REF_FLAGS_IS_SET (def, DF_REF_PARTIAL) | |
33845ca9 | 1356 | && read_modify_subreg_p (DF_REF_REG (def))) |
2692b5c8 RS |
1357 | record_subregs_of_mode (DF_REF_REG (def), true); |
1358 | } | |
6fb5fa3c DB |
1359 | } |
1360 | ||
dab67d2c RS |
1361 | const HARD_REG_SET * |
1362 | valid_mode_changes_for_regno (unsigned int regno) | |
cff9f8d5 | 1363 | { |
dab67d2c | 1364 | return valid_mode_changes[regno]; |
cff9f8d5 | 1365 | } |
6fb5fa3c | 1366 | |
1833192f | 1367 | void |
6fb5fa3c DB |
1368 | finish_subregs_of_mode (void) |
1369 | { | |
6969eb0d | 1370 | XDELETEVEC (valid_mode_changes); |
a4fe9e99 | 1371 | obstack_free (&valid_mode_changes_obstack, NULL); |
6fb5fa3c | 1372 | } |
6969eb0d RS |
1373 | |
1374 | /* Free all data attached to the structure. This isn't a destructor because | |
1375 | we don't want to run on exit. */ | |
1376 | ||
1833192f | 1377 | void |
6969eb0d | 1378 | target_hard_regs::finalize () |
6fb5fa3c | 1379 | { |
6969eb0d | 1380 | delete x_simplifiable_subregs; |
6fb5fa3c | 1381 | } |