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