]>
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++) | |
ad474626 | 511 | this_target_regs->x_hard_regno_nregs[i][j] |
c43f4279 | 512 | = targetm.hard_regno_nregs (i, (machine_mode) j); |
ca4aac00 DE |
513 | |
514 | for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) | |
7f21d440 | 515 | { |
fee226d2 | 516 | reg_raw_mode[i] = choose_hard_reg_mode (i, 1, false); |
7f21d440 | 517 | |
35aebd56 RS |
518 | /* If we couldn't find a valid mode, just use the previous mode |
519 | if it is suitable, otherwise fall back on word_mode. */ | |
7f21d440 | 520 | if (reg_raw_mode[i] == VOIDmode) |
35aebd56 | 521 | { |
ad474626 | 522 | if (i > 0 && hard_regno_nregs (i, reg_raw_mode[i - 1]) == 1) |
35aebd56 RS |
523 | reg_raw_mode[i] = reg_raw_mode[i - 1]; |
524 | else | |
525 | reg_raw_mode[i] = word_mode; | |
526 | } | |
7f21d440 | 527 | } |
ca4aac00 DE |
528 | } |
529 | ||
b5deb7b6 SL |
530 | /* Finish initializing the register sets and initialize the register modes. |
531 | This function might be invoked more than once, if the target has support | |
532 | for changing register usage conventions on a per-function basis. | |
533 | */ | |
c27c5281 | 534 | void |
0c20a65f | 535 | init_regs (void) |
c27c5281 DE |
536 | { |
537 | /* This finishes what was started by init_reg_sets, but couldn't be done | |
538 | until after register usage was specified. */ | |
b93a436e | 539 | init_reg_sets_1 (); |
6cde4876 JL |
540 | } |
541 | ||
2af2dbdc | 542 | /* The same as previous function plus initializing IRA. */ |
f68211cd VM |
543 | void |
544 | reinit_regs (void) | |
545 | { | |
546 | init_regs (); | |
8d9b7be5 JZ |
547 | /* caller_save needs to be re-initialized. */ |
548 | caller_save_initialized_p = false; | |
2175bf49 RS |
549 | if (this_target_rtl->target_specific_initialized) |
550 | { | |
551 | ira_init (); | |
552 | recog_init (); | |
553 | } | |
f68211cd VM |
554 | } |
555 | ||
6cde4876 JL |
556 | /* Initialize some fake stack-frame MEM references for use in |
557 | memory_move_secondary_cost. */ | |
6cde4876 | 558 | void |
0c20a65f | 559 | init_fake_stack_mems (void) |
6cde4876 | 560 | { |
2af2dbdc | 561 | int i; |
bbbbb16a | 562 | |
2af2dbdc | 563 | for (i = 0; i < MAX_MACHINE_MODE; i++) |
ef4bddc2 | 564 | top_of_stack[i] = gen_rtx_MEM ((machine_mode) i, stack_pointer_rtx); |
c27c5281 DE |
565 | } |
566 | ||
de8f4b07 AS |
567 | |
568 | /* Compute cost of moving data from a register of class FROM to one of | |
569 | TO, using MODE. */ | |
570 | ||
571 | int | |
ef4bddc2 | 572 | register_move_cost (machine_mode mode, reg_class_t from, reg_class_t to) |
de8f4b07 AS |
573 | { |
574 | return targetm.register_move_cost (mode, from, to); | |
575 | } | |
576 | ||
f5c21ef3 | 577 | /* Compute cost of moving registers to/from memory. */ |
6f76a878 | 578 | |
f5c21ef3 | 579 | int |
ef4bddc2 | 580 | memory_move_cost (machine_mode mode, reg_class_t rclass, bool in) |
f5c21ef3 AS |
581 | { |
582 | return targetm.memory_move_cost (mode, rclass, in); | |
583 | } | |
473fe49b | 584 | |
cbd5b9a2 KR |
585 | /* Compute extra cost of moving registers to/from memory due to reloads. |
586 | Only needed if secondary reloads are required for memory moves. */ | |
587 | int | |
ef4bddc2 | 588 | memory_move_secondary_cost (machine_mode mode, reg_class_t rclass, |
f5c21ef3 | 589 | bool in) |
cbd5b9a2 | 590 | { |
faa832a7 | 591 | reg_class_t altclass; |
cbd5b9a2 | 592 | int partial_cost = 0; |
cbd5b9a2 | 593 | /* We need a memory reference to feed to SECONDARY... macros. */ |
dc297297 | 594 | /* mem may be unused even if the SECONDARY_ macros are defined. */ |
272df862 KG |
595 | rtx mem ATTRIBUTE_UNUSED = top_of_stack[(int) mode]; |
596 | ||
d858f359 | 597 | altclass = secondary_reload_class (in ? 1 : 0, rclass, mode, mem); |
473fe49b | 598 | |
cbd5b9a2 KR |
599 | if (altclass == NO_REGS) |
600 | return 0; | |
601 | ||
602 | if (in) | |
de8f4b07 | 603 | partial_cost = register_move_cost (mode, altclass, rclass); |
cbd5b9a2 | 604 | else |
de8f4b07 | 605 | partial_cost = register_move_cost (mode, rclass, altclass); |
cbd5b9a2 | 606 | |
d858f359 | 607 | if (rclass == altclass) |
cbd5b9a2 | 608 | /* This isn't simply a copy-to-temporary situation. Can't guess |
f5c21ef3 AS |
609 | what it is, so TARGET_MEMORY_MOVE_COST really ought not to be |
610 | calling here in that case. | |
cbd5b9a2 | 611 | |
41374e13 | 612 | I'm tempted to put in an assert here, but returning this will |
cbd5b9a2 KR |
613 | probably only give poor estimates, which is what we would've |
614 | had before this code anyways. */ | |
615 | return partial_cost; | |
616 | ||
617 | /* Check if the secondary reload register will also need a | |
618 | secondary reload. */ | |
619 | return memory_move_secondary_cost (mode, altclass, in) + partial_cost; | |
620 | } | |
cbd5b9a2 | 621 | |
ca4aac00 | 622 | /* Return a machine mode that is legitimate for hard reg REGNO and large |
fee226d2 R |
623 | enough to save nregs. If we can't find one, return VOIDmode. |
624 | If CALL_SAVED is true, only consider modes that are call saved. */ | |
ef4bddc2 | 625 | machine_mode |
0c20a65f | 626 | choose_hard_reg_mode (unsigned int regno ATTRIBUTE_UNUSED, |
fee226d2 | 627 | unsigned int nregs, bool call_saved) |
ca4aac00 | 628 | { |
ef4bddc2 RS |
629 | unsigned int /* machine_mode */ m; |
630 | machine_mode found_mode = VOIDmode, mode; | |
ca4aac00 DE |
631 | |
632 | /* We first look for the largest integer mode that can be validly | |
633 | held in REGNO. If none, we look for the largest floating-point mode. | |
634 | If we still didn't find a valid mode, try CCmode. */ | |
635 | ||
c94843d2 | 636 | FOR_EACH_MODE_IN_CLASS (mode, MODE_INT) |
ad474626 | 637 | if (hard_regno_nregs (regno, mode) == nregs |
f939c3e6 | 638 | && targetm.hard_regno_mode_ok (regno, mode) |
80ec73f4 RS |
639 | && (!call_saved |
640 | || !targetm.hard_regno_call_part_clobbered (regno, mode)) | |
80a18161 | 641 | && GET_MODE_SIZE (mode) > GET_MODE_SIZE (found_mode)) |
ca4aac00 DE |
642 | found_mode = mode; |
643 | ||
c94843d2 | 644 | FOR_EACH_MODE_IN_CLASS (mode, MODE_FLOAT) |
ad474626 | 645 | if (hard_regno_nregs (regno, mode) == nregs |
f939c3e6 | 646 | && targetm.hard_regno_mode_ok (regno, mode) |
80ec73f4 RS |
647 | && (!call_saved |
648 | || !targetm.hard_regno_call_part_clobbered (regno, mode)) | |
80a18161 | 649 | && GET_MODE_SIZE (mode) > GET_MODE_SIZE (found_mode)) |
ca4aac00 DE |
650 | found_mode = mode; |
651 | ||
c94843d2 | 652 | FOR_EACH_MODE_IN_CLASS (mode, MODE_VECTOR_FLOAT) |
ad474626 | 653 | if (hard_regno_nregs (regno, mode) == nregs |
f939c3e6 | 654 | && targetm.hard_regno_mode_ok (regno, mode) |
80ec73f4 RS |
655 | && (!call_saved |
656 | || !targetm.hard_regno_call_part_clobbered (regno, mode)) | |
80a18161 | 657 | && GET_MODE_SIZE (mode) > GET_MODE_SIZE (found_mode)) |
78b583fe AH |
658 | found_mode = mode; |
659 | ||
c94843d2 | 660 | FOR_EACH_MODE_IN_CLASS (mode, MODE_VECTOR_INT) |
ad474626 | 661 | if (hard_regno_nregs (regno, mode) == nregs |
f939c3e6 | 662 | && targetm.hard_regno_mode_ok (regno, mode) |
80ec73f4 RS |
663 | && (!call_saved |
664 | || !targetm.hard_regno_call_part_clobbered (regno, mode)) | |
80a18161 | 665 | && GET_MODE_SIZE (mode) > GET_MODE_SIZE (found_mode)) |
78b583fe AH |
666 | found_mode = mode; |
667 | ||
668 | if (found_mode != VOIDmode) | |
669 | return found_mode; | |
670 | ||
0548a9df | 671 | /* Iterate over all of the CCmodes. */ |
dbbbbf3b JDA |
672 | for (m = (unsigned int) CCmode; m < (unsigned int) NUM_MACHINE_MODES; ++m) |
673 | { | |
ef4bddc2 | 674 | mode = (machine_mode) m; |
ad474626 | 675 | if (hard_regno_nregs (regno, mode) == nregs |
f939c3e6 | 676 | && targetm.hard_regno_mode_ok (regno, mode) |
80ec73f4 RS |
677 | && (!call_saved |
678 | || !targetm.hard_regno_call_part_clobbered (regno, mode))) | |
dbbbbf3b JDA |
679 | return mode; |
680 | } | |
ca4aac00 DE |
681 | |
682 | /* We can't find a mode valid for this register. */ | |
683 | return VOIDmode; | |
54dac99e RK |
684 | } |
685 | ||
686 | /* Specify the usage characteristics of the register named NAME. | |
687 | It should be a fixed register if FIXED and a | |
688 | call-used register if CALL_USED. */ | |
54dac99e | 689 | void |
0c20a65f | 690 | fix_register (const char *name, int fixed, int call_used) |
54dac99e RK |
691 | { |
692 | int i; | |
0c6d290e | 693 | int reg, nregs; |
54dac99e RK |
694 | |
695 | /* Decode the name and update the primary form of | |
696 | the register info. */ | |
697 | ||
0c6d290e | 698 | if ((reg = decode_reg_name_and_count (name, &nregs)) >= 0) |
e5c90c23 | 699 | { |
0c6d290e RE |
700 | gcc_assert (nregs >= 1); |
701 | for (i = reg; i < reg + nregs; i++) | |
702 | { | |
703 | if ((i == STACK_POINTER_REGNUM | |
cb2fdc84 | 704 | #ifdef HARD_FRAME_POINTER_REGNUM |
0c6d290e | 705 | || i == HARD_FRAME_POINTER_REGNUM |
cb2fdc84 | 706 | #else |
0c6d290e | 707 | || i == FRAME_POINTER_REGNUM |
cb2fdc84 | 708 | #endif |
0c6d290e RE |
709 | ) |
710 | && (fixed == 0 || call_used == 0)) | |
658bd5ca | 711 | { |
0c6d290e | 712 | switch (fixed) |
658bd5ca JM |
713 | { |
714 | case 0: | |
0c6d290e RE |
715 | switch (call_used) |
716 | { | |
717 | case 0: | |
718 | error ("can%'t use %qs as a call-saved register", name); | |
719 | break; | |
720 | ||
721 | case 1: | |
722 | error ("can%'t use %qs as a call-used register", name); | |
723 | break; | |
724 | ||
725 | default: | |
726 | gcc_unreachable (); | |
727 | } | |
658bd5ca JM |
728 | break; |
729 | ||
730 | case 1: | |
0c6d290e RE |
731 | switch (call_used) |
732 | { | |
733 | case 1: | |
734 | error ("can%'t use %qs as a fixed register", name); | |
735 | break; | |
736 | ||
737 | case 0: | |
738 | default: | |
739 | gcc_unreachable (); | |
740 | } | |
658bd5ca JM |
741 | break; |
742 | ||
743 | default: | |
744 | gcc_unreachable (); | |
745 | } | |
658bd5ca | 746 | } |
0c6d290e RE |
747 | else |
748 | { | |
749 | fixed_regs[i] = fixed; | |
750 | call_used_regs[i] = call_used; | |
ec523c2f | 751 | #ifdef CALL_REALLY_USED_REGISTERS |
0c6d290e RE |
752 | if (fixed == 0) |
753 | call_really_used_regs[i] = call_used; | |
d3259baa | 754 | #endif |
0c6d290e | 755 | } |
cb2fdc84 | 756 | } |
e5c90c23 TW |
757 | } |
758 | else | |
54dac99e | 759 | { |
d4ee4d25 | 760 | warning (0, "unknown register name: %s", name); |
54dac99e RK |
761 | } |
762 | } | |
614f68e2 RK |
763 | |
764 | /* Mark register number I as global. */ | |
614f68e2 | 765 | void |
1460ec5c | 766 | globalize_reg (tree decl, int i) |
614f68e2 | 767 | { |
1460ec5c AK |
768 | location_t loc = DECL_SOURCE_LOCATION (decl); |
769 | ||
2c65142a UB |
770 | #ifdef STACK_REGS |
771 | if (IN_RANGE (i, FIRST_STACK_REG, LAST_STACK_REG)) | |
772 | { | |
773 | error ("stack register used for global register variable"); | |
774 | return; | |
775 | } | |
776 | #endif | |
777 | ||
c07c7c9d | 778 | if (fixed_regs[i] == 0 && no_global_reg_vars) |
1460ec5c | 779 | error_at (loc, "global register variable follows a function definition"); |
6c85df69 | 780 | |
614f68e2 RK |
781 | if (global_regs[i]) |
782 | { | |
1460ec5c AK |
783 | warning_at (loc, 0, |
784 | "register of %qD used for multiple global register variables", | |
785 | decl); | |
786 | inform (DECL_SOURCE_LOCATION (global_regs_decl[i]), | |
787 | "conflicts with %qD", global_regs_decl[i]); | |
614f68e2 RK |
788 | return; |
789 | } | |
790 | ||
791 | if (call_used_regs[i] && ! fixed_regs[i]) | |
1460ec5c | 792 | warning_at (loc, 0, "call-clobbered register used for global register variable"); |
614f68e2 RK |
793 | |
794 | global_regs[i] = 1; | |
1460ec5c | 795 | global_regs_decl[i] = decl; |
614f68e2 | 796 | |
f6ae6c51 RS |
797 | /* If we're globalizing the frame pointer, we need to set the |
798 | appropriate regs_invalidated_by_call bit, even if it's already | |
799 | set in fixed_regs. */ | |
800 | if (i != STACK_POINTER_REGNUM) | |
f2ecb626 JH |
801 | { |
802 | SET_HARD_REG_BIT (regs_invalidated_by_call, i); | |
803 | SET_REGNO_REG_SET (regs_invalidated_by_call_regset, i); | |
2af2dbdc | 804 | } |
f6ae6c51 | 805 | |
614f68e2 RK |
806 | /* If already fixed, nothing else to do. */ |
807 | if (fixed_regs[i]) | |
808 | return; | |
809 | ||
adee59ae | 810 | fixed_regs[i] = call_used_regs[i] = 1; |
74ae207d R |
811 | #ifdef CALL_REALLY_USED_REGISTERS |
812 | call_really_used_regs[i] = 1; | |
813 | #endif | |
614f68e2 RK |
814 | |
815 | SET_HARD_REG_BIT (fixed_reg_set, i); | |
816 | SET_HARD_REG_BIT (call_used_reg_set, i); | |
817 | SET_HARD_REG_BIT (call_fixed_reg_set, i); | |
58929c10 AO |
818 | |
819 | reinit_regs (); | |
614f68e2 | 820 | } |
54dac99e | 821 | \f |
54dac99e | 822 | |
d55d8fc7 | 823 | /* Structure used to record preferences of given pseudo. */ |
9ffc5a70 JH |
824 | struct reg_pref |
825 | { | |
8b649f3f PB |
826 | /* (enum reg_class) prefclass is the preferred class. May be |
827 | NO_REGS if no class is better than memory. */ | |
9ffc5a70 JH |
828 | char prefclass; |
829 | ||
830 | /* altclass is a register class that we should use for allocating | |
831 | pseudo if no register in the preferred class is available. | |
832 | If no register in this class is available, memory is preferred. | |
833 | ||
834 | It might appear to be more general to have a bitmask of classes here, | |
835 | but since it is recommended that there be a class corresponding to the | |
836 | union of most major pair of classes, that generality is not required. */ | |
837 | char altclass; | |
ce18efcb | 838 | |
1756cb66 | 839 | /* allocnoclass is a register class that IRA uses for allocating |
ce18efcb | 840 | the pseudo. */ |
1756cb66 | 841 | char allocnoclass; |
9ffc5a70 JH |
842 | }; |
843 | ||
2af2dbdc VM |
844 | /* Record preferences of each pseudo. This is available after RA is |
845 | run. */ | |
9ffc5a70 | 846 | static struct reg_pref *reg_pref; |
54d23420 | 847 | |
1833192f VM |
848 | /* Current size of reg_info. */ |
849 | static int reg_info_size; | |
dfc0f53a VM |
850 | /* Max_reg_num still last resize_reg_info call. */ |
851 | static int max_regno_since_last_resize; | |
1833192f | 852 | |
54dac99e RK |
853 | /* Return the reg_class in which pseudo reg number REGNO is best allocated. |
854 | This function is sometimes called before the info has been computed. | |
855 | When that happens, just return GENERAL_REGS, which is innocuous. */ | |
54dac99e | 856 | enum reg_class |
0c20a65f | 857 | reg_preferred_class (int regno) |
54dac99e | 858 | { |
9ffc5a70 | 859 | if (reg_pref == 0) |
54dac99e | 860 | return GENERAL_REGS; |
058e97ec | 861 | |
dfc0f53a | 862 | gcc_assert (regno < reg_info_size); |
9ffc5a70 | 863 | return (enum reg_class) reg_pref[regno].prefclass; |
54dac99e RK |
864 | } |
865 | ||
e4600702 | 866 | enum reg_class |
0c20a65f | 867 | reg_alternate_class (int regno) |
54dac99e | 868 | { |
9ffc5a70 | 869 | if (reg_pref == 0) |
e4600702 RK |
870 | return ALL_REGS; |
871 | ||
dfc0f53a | 872 | gcc_assert (regno < reg_info_size); |
9ffc5a70 | 873 | return (enum reg_class) reg_pref[regno].altclass; |
54dac99e RK |
874 | } |
875 | ||
ce18efcb VM |
876 | /* Return the reg_class which is used by IRA for its allocation. */ |
877 | enum reg_class | |
1756cb66 | 878 | reg_allocno_class (int regno) |
54dac99e | 879 | { |
ce18efcb VM |
880 | if (reg_pref == 0) |
881 | return NO_REGS; | |
6c85df69 | 882 | |
dfc0f53a | 883 | gcc_assert (regno < reg_info_size); |
1756cb66 | 884 | return (enum reg_class) reg_pref[regno].allocnoclass; |
54dac99e | 885 | } |
6fb5fa3c | 886 | |
b1f21e0a | 887 | \f |
058e97ec | 888 | |
dfc0f53a | 889 | /* Allocate space for reg info and initilize it. */ |
ce18efcb | 890 | static void |
058e97ec VM |
891 | allocate_reg_info (void) |
892 | { | |
dfc0f53a VM |
893 | int i; |
894 | ||
895 | max_regno_since_last_resize = max_reg_num (); | |
896 | reg_info_size = max_regno_since_last_resize * 3 / 2 + 1; | |
058e97ec | 897 | gcc_assert (! reg_pref && ! reg_renumber); |
ce18efcb VM |
898 | reg_renumber = XNEWVEC (short, reg_info_size); |
899 | reg_pref = XCNEWVEC (struct reg_pref, reg_info_size); | |
900 | memset (reg_renumber, -1, reg_info_size * sizeof (short)); | |
dfc0f53a VM |
901 | for (i = 0; i < reg_info_size; i++) |
902 | { | |
903 | reg_pref[i].prefclass = GENERAL_REGS; | |
904 | reg_pref[i].altclass = ALL_REGS; | |
905 | reg_pref[i].allocnoclass = GENERAL_REGS; | |
906 | } | |
058e97ec VM |
907 | } |
908 | ||
909 | ||
dfc0f53a VM |
910 | /* Resize reg info. The new elements will be initialized. Return TRUE |
911 | if new pseudos were added since the last call. */ | |
ce18efcb | 912 | bool |
058e97ec VM |
913 | resize_reg_info (void) |
914 | { | |
dfc0f53a VM |
915 | int old, i; |
916 | bool change_p; | |
058e97ec | 917 | |
1fe28116 VM |
918 | if (reg_pref == NULL) |
919 | { | |
920 | allocate_reg_info (); | |
921 | return true; | |
922 | } | |
dfc0f53a VM |
923 | change_p = max_regno_since_last_resize != max_reg_num (); |
924 | max_regno_since_last_resize = max_reg_num (); | |
925 | if (reg_info_size >= max_reg_num ()) | |
926 | return change_p; | |
ce18efcb | 927 | old = reg_info_size; |
dfc0f53a | 928 | reg_info_size = max_reg_num () * 3 / 2 + 1; |
058e97ec | 929 | gcc_assert (reg_pref && reg_renumber); |
ce18efcb VM |
930 | reg_renumber = XRESIZEVEC (short, reg_renumber, reg_info_size); |
931 | reg_pref = XRESIZEVEC (struct reg_pref, reg_pref, reg_info_size); | |
932 | memset (reg_pref + old, -1, | |
933 | (reg_info_size - old) * sizeof (struct reg_pref)); | |
934 | memset (reg_renumber + old, -1, (reg_info_size - old) * sizeof (short)); | |
dfc0f53a VM |
935 | for (i = old; i < reg_info_size; i++) |
936 | { | |
937 | reg_pref[i].prefclass = GENERAL_REGS; | |
938 | reg_pref[i].altclass = ALL_REGS; | |
939 | reg_pref[i].allocnoclass = GENERAL_REGS; | |
940 | } | |
ce18efcb | 941 | return true; |
058e97ec VM |
942 | } |
943 | ||
944 | ||
ed396e68 BS |
945 | /* Free up the space allocated by allocate_reg_info. */ |
946 | void | |
0c20a65f | 947 | free_reg_info (void) |
ed396e68 | 948 | { |
6fb5fa3c | 949 | if (reg_pref) |
ed396e68 | 950 | { |
6fb5fa3c DB |
951 | free (reg_pref); |
952 | reg_pref = NULL; | |
953 | } | |
ed396e68 | 954 | |
6fb5fa3c DB |
955 | if (reg_renumber) |
956 | { | |
957 | free (reg_renumber); | |
958 | reg_renumber = NULL; | |
ed396e68 | 959 | } |
ed396e68 | 960 | } |
e53a16e7 | 961 | |
ce18efcb | 962 | /* Initialize some global data for this pass. */ |
b8698a0f | 963 | static unsigned int |
ce18efcb VM |
964 | reginfo_init (void) |
965 | { | |
966 | if (df) | |
967 | df_compute_regs_ever_live (true); | |
968 | ||
532aafad | 969 | /* This prevents dump_reg_info from losing if called |
ce18efcb VM |
970 | before reginfo is run. */ |
971 | reg_pref = NULL; | |
dfc0f53a | 972 | reg_info_size = max_regno_since_last_resize = 0; |
ce18efcb VM |
973 | /* No more global register variables may be declared. */ |
974 | no_global_reg_vars = 1; | |
975 | return 1; | |
976 | } | |
977 | ||
27a4cd48 DM |
978 | namespace { |
979 | ||
980 | const pass_data pass_data_reginfo_init = | |
ce18efcb | 981 | { |
27a4cd48 DM |
982 | RTL_PASS, /* type */ |
983 | "reginfo", /* name */ | |
984 | OPTGROUP_NONE, /* optinfo_flags */ | |
27a4cd48 DM |
985 | TV_NONE, /* tv_id */ |
986 | 0, /* properties_required */ | |
987 | 0, /* properties_provided */ | |
988 | 0, /* properties_destroyed */ | |
989 | 0, /* todo_flags_start */ | |
990 | 0, /* todo_flags_finish */ | |
ce18efcb | 991 | }; |
058e97ec | 992 | |
27a4cd48 DM |
993 | class pass_reginfo_init : public rtl_opt_pass |
994 | { | |
995 | public: | |
c3284718 RS |
996 | pass_reginfo_init (gcc::context *ctxt) |
997 | : rtl_opt_pass (pass_data_reginfo_init, ctxt) | |
27a4cd48 DM |
998 | {} |
999 | ||
1000 | /* opt_pass methods: */ | |
be55bfe6 | 1001 | virtual unsigned int execute (function *) { return reginfo_init (); } |
27a4cd48 DM |
1002 | |
1003 | }; // class pass_reginfo_init | |
1004 | ||
1005 | } // anon namespace | |
1006 | ||
1007 | rtl_opt_pass * | |
1008 | make_pass_reginfo_init (gcc::context *ctxt) | |
1009 | { | |
1010 | return new pass_reginfo_init (ctxt); | |
1011 | } | |
1012 | ||
058e97ec VM |
1013 | \f |
1014 | ||
dfc0f53a | 1015 | /* Set up preferred, alternate, and allocno classes for REGNO as |
1756cb66 | 1016 | PREFCLASS, ALTCLASS, and ALLOCNOCLASS. */ |
058e97ec VM |
1017 | void |
1018 | setup_reg_classes (int regno, | |
ce18efcb | 1019 | enum reg_class prefclass, enum reg_class altclass, |
1756cb66 | 1020 | enum reg_class allocnoclass) |
058e97ec VM |
1021 | { |
1022 | if (reg_pref == NULL) | |
1023 | return; | |
dfc0f53a | 1024 | gcc_assert (reg_info_size >= max_reg_num ()); |
058e97ec VM |
1025 | reg_pref[regno].prefclass = prefclass; |
1026 | reg_pref[regno].altclass = altclass; | |
1756cb66 | 1027 | reg_pref[regno].allocnoclass = allocnoclass; |
058e97ec VM |
1028 | } |
1029 | ||
54dac99e | 1030 | \f |
6fb5fa3c DB |
1031 | /* This is the `regscan' pass of the compiler, run just before cse and |
1032 | again just before loop. It finds the first and last use of each | |
1033 | pseudo-register. */ | |
79b9ec0d | 1034 | |
f6956569 | 1035 | static void reg_scan_mark_refs (rtx, rtx_insn *); |
2af2dbdc | 1036 | |
54dac99e | 1037 | void |
f6956569 | 1038 | reg_scan (rtx_insn *f, unsigned int nregs ATTRIBUTE_UNUSED) |
54dac99e | 1039 | { |
f6956569 | 1040 | rtx_insn *insn; |
54dac99e | 1041 | |
28cb2b14 RS |
1042 | timevar_push (TV_REG_SCAN); |
1043 | ||
54dac99e | 1044 | for (insn = f; insn; insn = NEXT_INSN (insn)) |
28cb2b14 | 1045 | if (INSN_P (insn)) |
54dac99e | 1046 | { |
6fb5fa3c | 1047 | reg_scan_mark_refs (PATTERN (insn), insn); |
01565a55 | 1048 | if (REG_NOTES (insn)) |
6fb5fa3c | 1049 | reg_scan_mark_refs (REG_NOTES (insn), insn); |
f903b91f | 1050 | } |
79b9ec0d | 1051 | |
0d446150 | 1052 | timevar_pop (TV_REG_SCAN); |
f903b91f DM |
1053 | } |
1054 | ||
e53a16e7 | 1055 | |
1ebecb64 | 1056 | /* X is the expression to scan. INSN is the insn it appears in. |
e53a16e7 ILT |
1057 | NOTE_FLAG is nonzero if X is from INSN's notes rather than its body. |
1058 | We should only record information for REGs with numbers | |
1059 | greater than or equal to MIN_REGNO. */ | |
08d95f91 | 1060 | static void |
f6956569 | 1061 | reg_scan_mark_refs (rtx x, rtx_insn *insn) |
54dac99e | 1062 | { |
b3694847 SS |
1063 | enum rtx_code code; |
1064 | rtx dest; | |
1065 | rtx note; | |
54dac99e | 1066 | |
ed8d2920 MM |
1067 | if (!x) |
1068 | return; | |
fa23c636 | 1069 | code = GET_CODE (x); |
54dac99e RK |
1070 | switch (code) |
1071 | { | |
54dac99e | 1072 | case CONST: |
d8116890 | 1073 | CASE_CONST_ANY: |
54dac99e RK |
1074 | case CC0: |
1075 | case PC: | |
1076 | case SYMBOL_REF: | |
1077 | case LABEL_REF: | |
1078 | case ADDR_VEC: | |
1079 | case ADDR_DIFF_VEC: | |
54dac99e | 1080 | case REG: |
6fb5fa3c | 1081 | return; |
54dac99e | 1082 | |
01565a55 | 1083 | case EXPR_LIST: |
7b18c3db | 1084 | if (XEXP (x, 0)) |
6fb5fa3c | 1085 | reg_scan_mark_refs (XEXP (x, 0), insn); |
01565a55 | 1086 | if (XEXP (x, 1)) |
6fb5fa3c | 1087 | reg_scan_mark_refs (XEXP (x, 1), insn); |
01565a55 RK |
1088 | break; |
1089 | ||
1090 | case INSN_LIST: | |
f91aec98 | 1091 | case INT_LIST: |
01565a55 | 1092 | if (XEXP (x, 1)) |
6fb5fa3c | 1093 | reg_scan_mark_refs (XEXP (x, 1), insn); |
01565a55 RK |
1094 | break; |
1095 | ||
ed8d2920 | 1096 | case CLOBBER: |
6fb5fa3c DB |
1097 | if (MEM_P (XEXP (x, 0))) |
1098 | reg_scan_mark_refs (XEXP (XEXP (x, 0), 0), insn); | |
ed8d2920 MM |
1099 | break; |
1100 | ||
54dac99e RK |
1101 | case SET: |
1102 | /* Count a set of the destination if it is a register. */ | |
1103 | for (dest = SET_DEST (x); | |
1104 | GET_CODE (dest) == SUBREG || GET_CODE (dest) == STRICT_LOW_PART | |
bd5fb71c | 1105 | || GET_CODE (dest) == ZERO_EXTRACT; |
54dac99e RK |
1106 | dest = XEXP (dest, 0)) |
1107 | ; | |
1108 | ||
be8dcd74 RK |
1109 | /* If this is setting a pseudo from another pseudo or the sum of a |
1110 | pseudo and a constant integer and the other pseudo is known to be | |
1111 | a pointer, set the destination to be a pointer as well. | |
1112 | ||
1113 | Likewise if it is setting the destination from an address or from a | |
1114 | value equivalent to an address or to the sum of an address and | |
1115 | something else. | |
a6a2274a | 1116 | |
be8dcd74 RK |
1117 | But don't do any of this if the pseudo corresponds to a user |
1118 | variable since it should have already been set as a pointer based | |
1119 | on the type. */ | |
1120 | ||
f8cfc6aa | 1121 | if (REG_P (SET_DEST (x)) |
be8dcd74 | 1122 | && REGNO (SET_DEST (x)) >= FIRST_PSEUDO_REGISTER |
64d3b4ca JL |
1123 | /* If the destination pseudo is set more than once, then other |
1124 | sets might not be to a pointer value (consider access to a | |
d55d8fc7 | 1125 | union in two threads of control in the presence of global |
3502dc9c | 1126 | optimizations). So only set REG_POINTER on the destination |
64d3b4ca | 1127 | pseudo if this is the only set of that pseudo. */ |
6fb5fa3c | 1128 | && DF_REG_DEF_COUNT (REGNO (SET_DEST (x))) == 1 |
be8dcd74 | 1129 | && ! REG_USERVAR_P (SET_DEST (x)) |
3502dc9c | 1130 | && ! REG_POINTER (SET_DEST (x)) |
f8cfc6aa | 1131 | && ((REG_P (SET_SRC (x)) |
3502dc9c | 1132 | && REG_POINTER (SET_SRC (x))) |
be8dcd74 RK |
1133 | || ((GET_CODE (SET_SRC (x)) == PLUS |
1134 | || GET_CODE (SET_SRC (x)) == LO_SUM) | |
481683e1 | 1135 | && CONST_INT_P (XEXP (SET_SRC (x), 1)) |
f8cfc6aa | 1136 | && REG_P (XEXP (SET_SRC (x), 0)) |
3502dc9c | 1137 | && REG_POINTER (XEXP (SET_SRC (x), 0))) |
be8dcd74 RK |
1138 | || GET_CODE (SET_SRC (x)) == CONST |
1139 | || GET_CODE (SET_SRC (x)) == SYMBOL_REF | |
1140 | || GET_CODE (SET_SRC (x)) == LABEL_REF | |
1141 | || (GET_CODE (SET_SRC (x)) == HIGH | |
1142 | && (GET_CODE (XEXP (SET_SRC (x), 0)) == CONST | |
1143 | || GET_CODE (XEXP (SET_SRC (x), 0)) == SYMBOL_REF | |
1144 | || GET_CODE (XEXP (SET_SRC (x), 0)) == LABEL_REF)) | |
1145 | || ((GET_CODE (SET_SRC (x)) == PLUS | |
1146 | || GET_CODE (SET_SRC (x)) == LO_SUM) | |
1147 | && (GET_CODE (XEXP (SET_SRC (x), 1)) == CONST | |
1148 | || GET_CODE (XEXP (SET_SRC (x), 1)) == SYMBOL_REF | |
1149 | || GET_CODE (XEXP (SET_SRC (x), 1)) == LABEL_REF)) | |
1150 | || ((note = find_reg_note (insn, REG_EQUAL, 0)) != 0 | |
1151 | && (GET_CODE (XEXP (note, 0)) == CONST | |
1152 | || GET_CODE (XEXP (note, 0)) == SYMBOL_REF | |
1153 | || GET_CODE (XEXP (note, 0)) == LABEL_REF)))) | |
3502dc9c | 1154 | REG_POINTER (SET_DEST (x)) = 1; |
be8dcd74 | 1155 | |
0d4903b8 | 1156 | /* If this is setting a register from a register or from a simple |
a560d4d4 | 1157 | conversion of a register, propagate REG_EXPR. */ |
6fb5fa3c | 1158 | if (REG_P (dest) && !REG_ATTRS (dest)) |
de6f3f7a | 1159 | set_reg_attrs_from_value (dest, SET_SRC (x)); |
0d4903b8 | 1160 | |
191816a3 | 1161 | /* fall through */ |
54dac99e RK |
1162 | |
1163 | default: | |
1164 | { | |
b3694847 SS |
1165 | const char *fmt = GET_RTX_FORMAT (code); |
1166 | int i; | |
54dac99e RK |
1167 | for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--) |
1168 | { | |
1169 | if (fmt[i] == 'e') | |
6fb5fa3c | 1170 | reg_scan_mark_refs (XEXP (x, i), insn); |
54dac99e RK |
1171 | else if (fmt[i] == 'E' && XVEC (x, i) != 0) |
1172 | { | |
b3694847 | 1173 | int j; |
54dac99e | 1174 | for (j = XVECLEN (x, i) - 1; j >= 0; j--) |
6fb5fa3c | 1175 | reg_scan_mark_refs (XVECEXP (x, i, j), insn); |
54dac99e RK |
1176 | } |
1177 | } | |
1178 | } | |
1179 | } | |
1180 | } | |
1181 | \f | |
2af2dbdc | 1182 | |
54dac99e RK |
1183 | /* Return nonzero if C1 is a subset of C2, i.e., if every register in C1 |
1184 | is also in C2. */ | |
54dac99e | 1185 | int |
faa832a7 | 1186 | reg_class_subset_p (reg_class_t c1, reg_class_t c2) |
54dac99e | 1187 | { |
56b138ae RS |
1188 | return (c1 == c2 |
1189 | || c2 == ALL_REGS | |
1190 | || hard_reg_set_subset_p (reg_class_contents[(int) c1], | |
1191 | reg_class_contents[(int) c2])); | |
54dac99e RK |
1192 | } |
1193 | ||
1194 | /* Return nonzero if there is a register that is in both C1 and C2. */ | |
54dac99e | 1195 | int |
a56b31ca | 1196 | reg_classes_intersect_p (reg_class_t c1, reg_class_t c2) |
54dac99e | 1197 | { |
56b138ae RS |
1198 | return (c1 == c2 |
1199 | || c1 == ALL_REGS | |
1200 | || c2 == ALL_REGS | |
1201 | || hard_reg_set_intersect_p (reg_class_contents[(int) c1], | |
1202 | reg_class_contents[(int) c2])); | |
54dac99e RK |
1203 | } |
1204 | ||
2af2dbdc | 1205 | \f |
6969eb0d | 1206 | inline hashval_t |
67f58944 | 1207 | simplifiable_subregs_hasher::hash (const simplifiable_subreg *value) |
6969eb0d RS |
1208 | { |
1209 | return value->shape.unique_id (); | |
1210 | } | |
1211 | ||
1212 | inline bool | |
67f58944 TS |
1213 | simplifiable_subregs_hasher::equal (const simplifiable_subreg *value, |
1214 | const subreg_shape *compare) | |
6969eb0d RS |
1215 | { |
1216 | return value->shape == *compare; | |
1217 | } | |
1218 | ||
1219 | inline simplifiable_subreg::simplifiable_subreg (const subreg_shape &shape_in) | |
1220 | : shape (shape_in) | |
1221 | { | |
1222 | CLEAR_HARD_REG_SET (simplifiable_regs); | |
1223 | } | |
1224 | ||
1225 | /* Return the set of hard registers that are able to form the subreg | |
1226 | described by SHAPE. */ | |
1227 | ||
1228 | const HARD_REG_SET & | |
1229 | simplifiable_subregs (const subreg_shape &shape) | |
1230 | { | |
1231 | if (!this_target_hard_regs->x_simplifiable_subregs) | |
1232 | this_target_hard_regs->x_simplifiable_subregs | |
1233 | = new hash_table <simplifiable_subregs_hasher> (30); | |
1234 | simplifiable_subreg **slot | |
1235 | = (this_target_hard_regs->x_simplifiable_subregs | |
1236 | ->find_slot_with_hash (&shape, shape.unique_id (), INSERT)); | |
1237 | ||
1238 | if (!*slot) | |
1239 | { | |
1240 | simplifiable_subreg *info = new simplifiable_subreg (shape); | |
1241 | for (unsigned int i = 0; i < FIRST_PSEUDO_REGISTER; ++i) | |
f939c3e6 | 1242 | if (targetm.hard_regno_mode_ok (i, shape.inner_mode) |
6969eb0d RS |
1243 | && simplify_subreg_regno (i, shape.inner_mode, shape.offset, |
1244 | shape.outer_mode) >= 0) | |
1245 | SET_HARD_REG_BIT (info->simplifiable_regs, i); | |
1246 | *slot = info; | |
1247 | } | |
1248 | return (*slot)->simplifiable_regs; | |
1249 | } | |
2af2dbdc VM |
1250 | |
1251 | /* Passes for keeping and updating info about modes of registers | |
1252 | inside subregisters. */ | |
1253 | ||
6969eb0d RS |
1254 | static HARD_REG_SET **valid_mode_changes; |
1255 | static obstack valid_mode_changes_obstack; | |
41bf2a8b | 1256 | |
2692b5c8 RS |
1257 | /* Restrict the choice of register for SUBREG_REG (SUBREG) based |
1258 | on information about SUBREG. | |
1259 | ||
1260 | If PARTIAL_DEF, SUBREG is a partial definition of a multipart inner | |
1261 | register and we want to ensure that the other parts of the inner | |
1262 | register are correctly preserved. If !PARTIAL_DEF we need to | |
1263 | ensure that SUBREG itself can be formed. */ | |
1264 | ||
6fb5fa3c | 1265 | static void |
2692b5c8 | 1266 | record_subregs_of_mode (rtx subreg, bool partial_def) |
41bf2a8b | 1267 | { |
41bf2a8b | 1268 | unsigned int regno; |
41bf2a8b RH |
1269 | |
1270 | if (!REG_P (SUBREG_REG (subreg))) | |
1271 | return; | |
1272 | ||
1273 | regno = REGNO (SUBREG_REG (subreg)); | |
41bf2a8b RH |
1274 | if (regno < FIRST_PSEUDO_REGISTER) |
1275 | return; | |
1276 | ||
2692b5c8 RS |
1277 | subreg_shape shape (shape_of_subreg (subreg)); |
1278 | if (partial_def) | |
1279 | { | |
1280 | /* The number of independently-accessible SHAPE.outer_mode values | |
1281 | in SHAPE.inner_mode is GET_MODE_SIZE (SHAPE.inner_mode) / SIZE. | |
1282 | We need to check that the assignment will preserve all the other | |
1283 | SIZE-byte chunks in the inner register besides the one that | |
1284 | includes SUBREG. | |
1285 | ||
1286 | In practice it is enough to check whether an equivalent | |
1287 | SHAPE.inner_mode value in an adjacent SIZE-byte chunk can be formed. | |
1288 | If the underlying registers are small enough, both subregs will | |
1289 | be valid. If the underlying registers are too large, one of the | |
1290 | subregs will be invalid. | |
1291 | ||
1292 | This relies on the fact that we've already been passed | |
1293 | SUBREG with PARTIAL_DEF set to false. */ | |
1294 | unsigned int size = MAX (REGMODE_NATURAL_SIZE (shape.inner_mode), | |
1295 | GET_MODE_SIZE (shape.outer_mode)); | |
1296 | gcc_checking_assert (size < GET_MODE_SIZE (shape.inner_mode)); | |
1297 | if (shape.offset >= size) | |
1298 | shape.offset -= size; | |
1299 | else | |
1300 | shape.offset += size; | |
1301 | } | |
1302 | ||
6969eb0d RS |
1303 | if (valid_mode_changes[regno]) |
1304 | AND_HARD_REG_SET (*valid_mode_changes[regno], | |
2692b5c8 | 1305 | simplifiable_subregs (shape)); |
6969eb0d | 1306 | else |
41bf2a8b | 1307 | { |
6969eb0d RS |
1308 | valid_mode_changes[regno] |
1309 | = XOBNEW (&valid_mode_changes_obstack, HARD_REG_SET); | |
1310 | COPY_HARD_REG_SET (*valid_mode_changes[regno], | |
2692b5c8 | 1311 | simplifiable_subregs (shape)); |
41bf2a8b | 1312 | } |
41bf2a8b RH |
1313 | } |
1314 | ||
6fb5fa3c | 1315 | /* Call record_subregs_of_mode for all the subregs in X. */ |
b8698a0f | 1316 | static void |
6969eb0d | 1317 | find_subregs_of_mode (rtx x) |
6fb5fa3c DB |
1318 | { |
1319 | enum rtx_code code = GET_CODE (x); | |
1320 | const char * const fmt = GET_RTX_FORMAT (code); | |
1321 | int i; | |
1322 | ||
1323 | if (code == SUBREG) | |
2692b5c8 | 1324 | record_subregs_of_mode (x, false); |
b8698a0f | 1325 | |
6fb5fa3c DB |
1326 | /* Time for some deep diving. */ |
1327 | for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--) | |
1328 | { | |
1329 | if (fmt[i] == 'e') | |
6969eb0d | 1330 | find_subregs_of_mode (XEXP (x, i)); |
6fb5fa3c DB |
1331 | else if (fmt[i] == 'E') |
1332 | { | |
1333 | int j; | |
1334 | for (j = XVECLEN (x, i) - 1; j >= 0; j--) | |
6969eb0d | 1335 | find_subregs_of_mode (XVECEXP (x, i, j)); |
6fb5fa3c DB |
1336 | } |
1337 | } | |
1338 | } | |
1339 | ||
1833192f | 1340 | void |
6fb5fa3c DB |
1341 | init_subregs_of_mode (void) |
1342 | { | |
1343 | basic_block bb; | |
f6956569 | 1344 | rtx_insn *insn; |
6fb5fa3c | 1345 | |
6969eb0d RS |
1346 | gcc_obstack_init (&valid_mode_changes_obstack); |
1347 | valid_mode_changes = XCNEWVEC (HARD_REG_SET *, max_reg_num ()); | |
6fb5fa3c | 1348 | |
11cd3bed | 1349 | FOR_EACH_BB_FN (bb, cfun) |
6fb5fa3c | 1350 | FOR_BB_INSNS (bb, insn) |
a6d1cd85 | 1351 | if (NONDEBUG_INSN_P (insn)) |
2692b5c8 RS |
1352 | { |
1353 | find_subregs_of_mode (PATTERN (insn)); | |
1354 | df_ref def; | |
1355 | FOR_EACH_INSN_DEF (def, insn) | |
1356 | if (DF_REF_FLAGS_IS_SET (def, DF_REF_PARTIAL) | |
33845ca9 | 1357 | && read_modify_subreg_p (DF_REF_REG (def))) |
2692b5c8 RS |
1358 | record_subregs_of_mode (DF_REF_REG (def), true); |
1359 | } | |
6fb5fa3c DB |
1360 | } |
1361 | ||
dab67d2c RS |
1362 | const HARD_REG_SET * |
1363 | valid_mode_changes_for_regno (unsigned int regno) | |
cff9f8d5 | 1364 | { |
dab67d2c | 1365 | return valid_mode_changes[regno]; |
cff9f8d5 | 1366 | } |
6fb5fa3c | 1367 | |
1833192f | 1368 | void |
6fb5fa3c DB |
1369 | finish_subregs_of_mode (void) |
1370 | { | |
6969eb0d | 1371 | XDELETEVEC (valid_mode_changes); |
a4fe9e99 | 1372 | obstack_free (&valid_mode_changes_obstack, NULL); |
6fb5fa3c | 1373 | } |
6969eb0d RS |
1374 | |
1375 | /* Free all data attached to the structure. This isn't a destructor because | |
1376 | we don't want to run on exit. */ | |
1377 | ||
1833192f | 1378 | void |
6969eb0d | 1379 | target_hard_regs::finalize () |
6fb5fa3c | 1380 | { |
6969eb0d | 1381 | delete x_simplifiable_subregs; |
6fb5fa3c | 1382 | } |