]>
Commit | Line | Data |
---|---|---|
6207bd2c | 1 | /* Sets (bit vectors) of hard registers, and operations on them. |
d91f7526 | 2 | Copyright (C) 1987, 1992, 1994, 2000, 2003, 2004, 2005, 2007, 2008, 2009, |
71e45bc2 | 3 | 2010, 2011, 2012 Free Software Foundation, Inc. |
6207bd2c | 4 | |
f12b58b3 | 5 | This file is part of GCC |
6207bd2c | 6 | |
f12b58b3 | 7 | GCC is free software; you can redistribute it and/or modify it under |
8 | the terms of the GNU General Public License as published by the Free | |
8c4c00c1 | 9 | Software Foundation; either version 3, or (at your option) any later |
f12b58b3 | 10 | version. |
6207bd2c | 11 | |
f12b58b3 | 12 | GCC is distributed in the hope that it will be useful, but WITHOUT ANY |
13 | WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
14 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
15 | for more details. | |
6207bd2c | 16 | |
17 | You should have received a copy of the GNU General Public License | |
8c4c00c1 | 18 | along with GCC; see the file COPYING3. If not see |
19 | <http://www.gnu.org/licenses/>. */ | |
6207bd2c | 20 | |
2a281353 | 21 | #ifndef GCC_HARD_REG_SET_H |
48e1416a | 22 | #define GCC_HARD_REG_SET_H |
6207bd2c | 23 | |
24 | /* Define the type of a set of hard registers. */ | |
25 | ||
c7a2b3e5 | 26 | /* HARD_REG_ELT_TYPE is a typedef of the unsigned integral type which |
27 | will be used for hard reg sets, either alone or in an array. | |
28 | ||
29 | If HARD_REG_SET is a macro, its definition is HARD_REG_ELT_TYPE, | |
30 | and it has enough bits to represent all the target machine's hard | |
31 | registers. Otherwise, it is a typedef for a suitably sized array | |
32 | of HARD_REG_ELT_TYPEs. HARD_REG_SET_LONGS is defined as how many. | |
6207bd2c | 33 | |
34 | Note that lots of code assumes that the first part of a regset is | |
35 | the same format as a HARD_REG_SET. To help make sure this is true, | |
3f28a032 | 36 | we only try the widest fast integer mode (HOST_WIDEST_FAST_INT) |
37 | instead of all the smaller types. This approach loses only if | |
91275768 | 38 | there are very few registers and then only in the few cases where |
3f28a032 | 39 | we have an array of HARD_REG_SETs, so it needn't be as complex as |
40 | it used to be. */ | |
c7a2b3e5 | 41 | |
3f28a032 | 42 | typedef unsigned HOST_WIDEST_FAST_INT HARD_REG_ELT_TYPE; |
6207bd2c | 43 | |
3f28a032 | 44 | #if FIRST_PSEUDO_REGISTER <= HOST_BITS_PER_WIDEST_FAST_INT |
c7a2b3e5 | 45 | |
46 | #define HARD_REG_SET HARD_REG_ELT_TYPE | |
6207bd2c | 47 | |
48 | #else | |
49 | ||
50 | #define HARD_REG_SET_LONGS \ | |
3f28a032 | 51 | ((FIRST_PSEUDO_REGISTER + HOST_BITS_PER_WIDEST_FAST_INT - 1) \ |
52 | / HOST_BITS_PER_WIDEST_FAST_INT) | |
c7a2b3e5 | 53 | typedef HARD_REG_ELT_TYPE HARD_REG_SET[HARD_REG_SET_LONGS]; |
6207bd2c | 54 | |
55 | #endif | |
56 | ||
2e851bb8 | 57 | /* HARD_REG_SET wrapped into a structure, to make it possible to |
58 | use HARD_REG_SET even in APIs that should not include | |
59 | hard-reg-set.h. */ | |
60 | struct hard_reg_set_container | |
61 | { | |
62 | HARD_REG_SET set; | |
63 | }; | |
64 | ||
c7a2b3e5 | 65 | /* HARD_CONST is used to cast a constant to the appropriate type |
66 | for use with a HARD_REG_SET. */ | |
6207bd2c | 67 | |
c7a2b3e5 | 68 | #define HARD_CONST(X) ((HARD_REG_ELT_TYPE) (X)) |
6207bd2c | 69 | |
70 | /* Define macros SET_HARD_REG_BIT, CLEAR_HARD_REG_BIT and TEST_HARD_REG_BIT | |
71 | to set, clear or test one bit in a hard reg set of type HARD_REG_SET. | |
72 | All three take two arguments: the set and the register number. | |
73 | ||
74 | In the case where sets are arrays of longs, the first argument | |
75 | is actually a pointer to a long. | |
76 | ||
77 | Define two macros for initializing a set: | |
78 | CLEAR_HARD_REG_SET and SET_HARD_REG_SET. | |
79 | These take just one argument. | |
80 | ||
81 | Also define macros for copying hard reg sets: | |
82 | COPY_HARD_REG_SET and COMPL_HARD_REG_SET. | |
83 | These take two arguments TO and FROM; they read from FROM | |
84 | and store into TO. COMPL_HARD_REG_SET complements each bit. | |
85 | ||
86 | Also define macros for combining hard reg sets: | |
87 | IOR_HARD_REG_SET and AND_HARD_REG_SET. | |
88 | These take two arguments TO and FROM; they read from FROM | |
89 | and combine bitwise into TO. Define also two variants | |
90 | IOR_COMPL_HARD_REG_SET and AND_COMPL_HARD_REG_SET | |
91 | which use the complement of the set FROM. | |
92 | ||
ddc556d1 | 93 | Also define: |
94 | ||
95 | hard_reg_set_subset_p (X, Y), which returns true if X is a subset of Y. | |
96 | hard_reg_set_equal_p (X, Y), which returns true if X and Y are equal. | |
97 | hard_reg_set_intersect_p (X, Y), which returns true if X and Y intersect. | |
98 | hard_reg_set_empty_p (X), which returns true if X is empty. */ | |
6207bd2c | 99 | |
e1ab7874 | 100 | #define UHOST_BITS_PER_WIDE_INT ((unsigned) HOST_BITS_PER_WIDEST_FAST_INT) |
101 | ||
6207bd2c | 102 | #ifdef HARD_REG_SET |
103 | ||
104 | #define SET_HARD_REG_BIT(SET, BIT) \ | |
105 | ((SET) |= HARD_CONST (1) << (BIT)) | |
106 | #define CLEAR_HARD_REG_BIT(SET, BIT) \ | |
107 | ((SET) &= ~(HARD_CONST (1) << (BIT))) | |
108 | #define TEST_HARD_REG_BIT(SET, BIT) \ | |
42339e9b | 109 | (!!((SET) & (HARD_CONST (1) << (BIT)))) |
6207bd2c | 110 | |
111 | #define CLEAR_HARD_REG_SET(TO) ((TO) = HARD_CONST (0)) | |
c7a2b3e5 | 112 | #define SET_HARD_REG_SET(TO) ((TO) = ~ HARD_CONST (0)) |
6207bd2c | 113 | |
114 | #define COPY_HARD_REG_SET(TO, FROM) ((TO) = (FROM)) | |
115 | #define COMPL_HARD_REG_SET(TO, FROM) ((TO) = ~(FROM)) | |
116 | ||
117 | #define IOR_HARD_REG_SET(TO, FROM) ((TO) |= (FROM)) | |
118 | #define IOR_COMPL_HARD_REG_SET(TO, FROM) ((TO) |= ~ (FROM)) | |
119 | #define AND_HARD_REG_SET(TO, FROM) ((TO) &= (FROM)) | |
120 | #define AND_COMPL_HARD_REG_SET(TO, FROM) ((TO) &= ~ (FROM)) | |
121 | ||
ddc556d1 | 122 | static inline bool |
123 | hard_reg_set_subset_p (const HARD_REG_SET x, const HARD_REG_SET y) | |
124 | { | |
125 | return (x & ~y) == HARD_CONST (0); | |
126 | } | |
127 | ||
128 | static inline bool | |
129 | hard_reg_set_equal_p (const HARD_REG_SET x, const HARD_REG_SET y) | |
130 | { | |
131 | return x == y; | |
132 | } | |
133 | ||
134 | static inline bool | |
135 | hard_reg_set_intersect_p (const HARD_REG_SET x, const HARD_REG_SET y) | |
136 | { | |
137 | return (x & y) != HARD_CONST (0); | |
138 | } | |
139 | ||
140 | static inline bool | |
141 | hard_reg_set_empty_p (const HARD_REG_SET x) | |
142 | { | |
143 | return x == HARD_CONST (0); | |
144 | } | |
c7a2b3e5 | 145 | |
6207bd2c | 146 | #else |
147 | ||
6207bd2c | 148 | #define SET_HARD_REG_BIT(SET, BIT) \ |
149 | ((SET)[(BIT) / UHOST_BITS_PER_WIDE_INT] \ | |
c7a2b3e5 | 150 | |= HARD_CONST (1) << ((BIT) % UHOST_BITS_PER_WIDE_INT)) |
6207bd2c | 151 | |
152 | #define CLEAR_HARD_REG_BIT(SET, BIT) \ | |
153 | ((SET)[(BIT) / UHOST_BITS_PER_WIDE_INT] \ | |
c7a2b3e5 | 154 | &= ~(HARD_CONST (1) << ((BIT) % UHOST_BITS_PER_WIDE_INT))) |
6207bd2c | 155 | |
156 | #define TEST_HARD_REG_BIT(SET, BIT) \ | |
42339e9b | 157 | (!!((SET)[(BIT) / UHOST_BITS_PER_WIDE_INT] \ |
158 | & (HARD_CONST (1) << ((BIT) % UHOST_BITS_PER_WIDE_INT)))) | |
6207bd2c | 159 | |
3f28a032 | 160 | #if FIRST_PSEUDO_REGISTER <= 2*HOST_BITS_PER_WIDEST_FAST_INT |
f9bc9bee | 161 | #define CLEAR_HARD_REG_SET(TO) \ |
19cb6b50 | 162 | do { HARD_REG_ELT_TYPE *scan_tp_ = (TO); \ |
f9bc9bee | 163 | scan_tp_[0] = 0; \ |
164 | scan_tp_[1] = 0; } while (0) | |
165 | ||
166 | #define SET_HARD_REG_SET(TO) \ | |
19cb6b50 | 167 | do { HARD_REG_ELT_TYPE *scan_tp_ = (TO); \ |
f9bc9bee | 168 | scan_tp_[0] = -1; \ |
169 | scan_tp_[1] = -1; } while (0) | |
170 | ||
171 | #define COPY_HARD_REG_SET(TO, FROM) \ | |
19cb6b50 | 172 | do { HARD_REG_ELT_TYPE *scan_tp_ = (TO), *scan_fp_ = (FROM); \ |
f9bc9bee | 173 | scan_tp_[0] = scan_fp_[0]; \ |
174 | scan_tp_[1] = scan_fp_[1]; } while (0) | |
175 | ||
176 | #define COMPL_HARD_REG_SET(TO, FROM) \ | |
19cb6b50 | 177 | do { HARD_REG_ELT_TYPE *scan_tp_ = (TO), *scan_fp_ = (FROM); \ |
f9bc9bee | 178 | scan_tp_[0] = ~ scan_fp_[0]; \ |
179 | scan_tp_[1] = ~ scan_fp_[1]; } while (0) | |
180 | ||
181 | #define AND_HARD_REG_SET(TO, FROM) \ | |
19cb6b50 | 182 | do { HARD_REG_ELT_TYPE *scan_tp_ = (TO), *scan_fp_ = (FROM); \ |
183 | scan_tp_[0] &= scan_fp_[0]; \ | |
f9bc9bee | 184 | scan_tp_[1] &= scan_fp_[1]; } while (0) |
185 | ||
186 | #define AND_COMPL_HARD_REG_SET(TO, FROM) \ | |
19cb6b50 | 187 | do { HARD_REG_ELT_TYPE *scan_tp_ = (TO), *scan_fp_ = (FROM); \ |
f9bc9bee | 188 | scan_tp_[0] &= ~ scan_fp_[0]; \ |
189 | scan_tp_[1] &= ~ scan_fp_[1]; } while (0) | |
190 | ||
191 | #define IOR_HARD_REG_SET(TO, FROM) \ | |
19cb6b50 | 192 | do { HARD_REG_ELT_TYPE *scan_tp_ = (TO), *scan_fp_ = (FROM); \ |
f9bc9bee | 193 | scan_tp_[0] |= scan_fp_[0]; \ |
194 | scan_tp_[1] |= scan_fp_[1]; } while (0) | |
195 | ||
196 | #define IOR_COMPL_HARD_REG_SET(TO, FROM) \ | |
19cb6b50 | 197 | do { HARD_REG_ELT_TYPE *scan_tp_ = (TO), *scan_fp_ = (FROM); \ |
f9bc9bee | 198 | scan_tp_[0] |= ~ scan_fp_[0]; \ |
199 | scan_tp_[1] |= ~ scan_fp_[1]; } while (0) | |
200 | ||
ddc556d1 | 201 | static inline bool |
202 | hard_reg_set_subset_p (const HARD_REG_SET x, const HARD_REG_SET y) | |
203 | { | |
204 | return (x[0] & ~y[0]) == 0 && (x[1] & ~y[1]) == 0; | |
205 | } | |
206 | ||
207 | static inline bool | |
208 | hard_reg_set_equal_p (const HARD_REG_SET x, const HARD_REG_SET y) | |
209 | { | |
210 | return x[0] == y[0] && x[1] == y[1]; | |
211 | } | |
212 | ||
213 | static inline bool | |
214 | hard_reg_set_intersect_p (const HARD_REG_SET x, const HARD_REG_SET y) | |
215 | { | |
216 | return (x[0] & y[0]) != 0 || (x[1] & y[1]) != 0; | |
217 | } | |
218 | ||
219 | static inline bool | |
220 | hard_reg_set_empty_p (const HARD_REG_SET x) | |
221 | { | |
222 | return x[0] == 0 && x[1] == 0; | |
223 | } | |
f9bc9bee | 224 | |
225 | #else | |
6a5b7d12 | 226 | #if FIRST_PSEUDO_REGISTER <= 3*HOST_BITS_PER_WIDEST_FAST_INT |
f9bc9bee | 227 | #define CLEAR_HARD_REG_SET(TO) \ |
19cb6b50 | 228 | do { HARD_REG_ELT_TYPE *scan_tp_ = (TO); \ |
f9bc9bee | 229 | scan_tp_[0] = 0; \ |
230 | scan_tp_[1] = 0; \ | |
231 | scan_tp_[2] = 0; } while (0) | |
232 | ||
233 | #define SET_HARD_REG_SET(TO) \ | |
19cb6b50 | 234 | do { HARD_REG_ELT_TYPE *scan_tp_ = (TO); \ |
f9bc9bee | 235 | scan_tp_[0] = -1; \ |
236 | scan_tp_[1] = -1; \ | |
237 | scan_tp_[2] = -1; } while (0) | |
238 | ||
239 | #define COPY_HARD_REG_SET(TO, FROM) \ | |
19cb6b50 | 240 | do { HARD_REG_ELT_TYPE *scan_tp_ = (TO), *scan_fp_ = (FROM); \ |
f9bc9bee | 241 | scan_tp_[0] = scan_fp_[0]; \ |
242 | scan_tp_[1] = scan_fp_[1]; \ | |
243 | scan_tp_[2] = scan_fp_[2]; } while (0) | |
244 | ||
245 | #define COMPL_HARD_REG_SET(TO, FROM) \ | |
19cb6b50 | 246 | do { HARD_REG_ELT_TYPE *scan_tp_ = (TO), *scan_fp_ = (FROM); \ |
f9bc9bee | 247 | scan_tp_[0] = ~ scan_fp_[0]; \ |
248 | scan_tp_[1] = ~ scan_fp_[1]; \ | |
249 | scan_tp_[2] = ~ scan_fp_[2]; } while (0) | |
250 | ||
251 | #define AND_HARD_REG_SET(TO, FROM) \ | |
19cb6b50 | 252 | do { HARD_REG_ELT_TYPE *scan_tp_ = (TO), *scan_fp_ = (FROM); \ |
253 | scan_tp_[0] &= scan_fp_[0]; \ | |
254 | scan_tp_[1] &= scan_fp_[1]; \ | |
f9bc9bee | 255 | scan_tp_[2] &= scan_fp_[2]; } while (0) |
256 | ||
257 | #define AND_COMPL_HARD_REG_SET(TO, FROM) \ | |
19cb6b50 | 258 | do { HARD_REG_ELT_TYPE *scan_tp_ = (TO), *scan_fp_ = (FROM); \ |
f9bc9bee | 259 | scan_tp_[0] &= ~ scan_fp_[0]; \ |
260 | scan_tp_[1] &= ~ scan_fp_[1]; \ | |
261 | scan_tp_[2] &= ~ scan_fp_[2]; } while (0) | |
262 | ||
263 | #define IOR_HARD_REG_SET(TO, FROM) \ | |
19cb6b50 | 264 | do { HARD_REG_ELT_TYPE *scan_tp_ = (TO), *scan_fp_ = (FROM); \ |
f9bc9bee | 265 | scan_tp_[0] |= scan_fp_[0]; \ |
266 | scan_tp_[1] |= scan_fp_[1]; \ | |
267 | scan_tp_[2] |= scan_fp_[2]; } while (0) | |
268 | ||
269 | #define IOR_COMPL_HARD_REG_SET(TO, FROM) \ | |
19cb6b50 | 270 | do { HARD_REG_ELT_TYPE *scan_tp_ = (TO), *scan_fp_ = (FROM); \ |
f9bc9bee | 271 | scan_tp_[0] |= ~ scan_fp_[0]; \ |
272 | scan_tp_[1] |= ~ scan_fp_[1]; \ | |
273 | scan_tp_[2] |= ~ scan_fp_[2]; } while (0) | |
274 | ||
ddc556d1 | 275 | static inline bool |
276 | hard_reg_set_subset_p (const HARD_REG_SET x, const HARD_REG_SET y) | |
277 | { | |
278 | return ((x[0] & ~y[0]) == 0 | |
279 | && (x[1] & ~y[1]) == 0 | |
280 | && (x[2] & ~y[2]) == 0); | |
281 | } | |
282 | ||
283 | static inline bool | |
284 | hard_reg_set_equal_p (const HARD_REG_SET x, const HARD_REG_SET y) | |
285 | { | |
286 | return x[0] == y[0] && x[1] == y[1] && x[2] == y[2]; | |
287 | } | |
288 | ||
289 | static inline bool | |
290 | hard_reg_set_intersect_p (const HARD_REG_SET x, const HARD_REG_SET y) | |
291 | { | |
292 | return ((x[0] & y[0]) != 0 | |
293 | || (x[1] & y[1]) != 0 | |
294 | || (x[2] & y[2]) != 0); | |
295 | } | |
296 | ||
297 | static inline bool | |
298 | hard_reg_set_empty_p (const HARD_REG_SET x) | |
299 | { | |
300 | return x[0] == 0 && x[1] == 0 && x[2] == 0; | |
301 | } | |
f9bc9bee | 302 | |
303 | #else | |
3f28a032 | 304 | #if FIRST_PSEUDO_REGISTER <= 4*HOST_BITS_PER_WIDEST_FAST_INT |
f9bc9bee | 305 | #define CLEAR_HARD_REG_SET(TO) \ |
19cb6b50 | 306 | do { HARD_REG_ELT_TYPE *scan_tp_ = (TO); \ |
f9bc9bee | 307 | scan_tp_[0] = 0; \ |
308 | scan_tp_[1] = 0; \ | |
309 | scan_tp_[2] = 0; \ | |
310 | scan_tp_[3] = 0; } while (0) | |
311 | ||
312 | #define SET_HARD_REG_SET(TO) \ | |
19cb6b50 | 313 | do { HARD_REG_ELT_TYPE *scan_tp_ = (TO); \ |
f9bc9bee | 314 | scan_tp_[0] = -1; \ |
315 | scan_tp_[1] = -1; \ | |
316 | scan_tp_[2] = -1; \ | |
317 | scan_tp_[3] = -1; } while (0) | |
318 | ||
319 | #define COPY_HARD_REG_SET(TO, FROM) \ | |
19cb6b50 | 320 | do { HARD_REG_ELT_TYPE *scan_tp_ = (TO), *scan_fp_ = (FROM); \ |
f9bc9bee | 321 | scan_tp_[0] = scan_fp_[0]; \ |
322 | scan_tp_[1] = scan_fp_[1]; \ | |
323 | scan_tp_[2] = scan_fp_[2]; \ | |
324 | scan_tp_[3] = scan_fp_[3]; } while (0) | |
325 | ||
326 | #define COMPL_HARD_REG_SET(TO, FROM) \ | |
19cb6b50 | 327 | do { HARD_REG_ELT_TYPE *scan_tp_ = (TO), *scan_fp_ = (FROM); \ |
f9bc9bee | 328 | scan_tp_[0] = ~ scan_fp_[0]; \ |
329 | scan_tp_[1] = ~ scan_fp_[1]; \ | |
330 | scan_tp_[2] = ~ scan_fp_[2]; \ | |
331 | scan_tp_[3] = ~ scan_fp_[3]; } while (0) | |
332 | ||
333 | #define AND_HARD_REG_SET(TO, FROM) \ | |
19cb6b50 | 334 | do { HARD_REG_ELT_TYPE *scan_tp_ = (TO), *scan_fp_ = (FROM); \ |
335 | scan_tp_[0] &= scan_fp_[0]; \ | |
336 | scan_tp_[1] &= scan_fp_[1]; \ | |
337 | scan_tp_[2] &= scan_fp_[2]; \ | |
f9bc9bee | 338 | scan_tp_[3] &= scan_fp_[3]; } while (0) |
339 | ||
340 | #define AND_COMPL_HARD_REG_SET(TO, FROM) \ | |
19cb6b50 | 341 | do { HARD_REG_ELT_TYPE *scan_tp_ = (TO), *scan_fp_ = (FROM); \ |
f9bc9bee | 342 | scan_tp_[0] &= ~ scan_fp_[0]; \ |
343 | scan_tp_[1] &= ~ scan_fp_[1]; \ | |
344 | scan_tp_[2] &= ~ scan_fp_[2]; \ | |
345 | scan_tp_[3] &= ~ scan_fp_[3]; } while (0) | |
346 | ||
347 | #define IOR_HARD_REG_SET(TO, FROM) \ | |
19cb6b50 | 348 | do { HARD_REG_ELT_TYPE *scan_tp_ = (TO), *scan_fp_ = (FROM); \ |
f9bc9bee | 349 | scan_tp_[0] |= scan_fp_[0]; \ |
350 | scan_tp_[1] |= scan_fp_[1]; \ | |
351 | scan_tp_[2] |= scan_fp_[2]; \ | |
352 | scan_tp_[3] |= scan_fp_[3]; } while (0) | |
353 | ||
354 | #define IOR_COMPL_HARD_REG_SET(TO, FROM) \ | |
19cb6b50 | 355 | do { HARD_REG_ELT_TYPE *scan_tp_ = (TO), *scan_fp_ = (FROM); \ |
f9bc9bee | 356 | scan_tp_[0] |= ~ scan_fp_[0]; \ |
357 | scan_tp_[1] |= ~ scan_fp_[1]; \ | |
358 | scan_tp_[2] |= ~ scan_fp_[2]; \ | |
359 | scan_tp_[3] |= ~ scan_fp_[3]; } while (0) | |
360 | ||
ddc556d1 | 361 | static inline bool |
362 | hard_reg_set_subset_p (const HARD_REG_SET x, const HARD_REG_SET y) | |
363 | { | |
364 | return ((x[0] & ~y[0]) == 0 | |
365 | && (x[1] & ~y[1]) == 0 | |
366 | && (x[2] & ~y[2]) == 0 | |
367 | && (x[3] & ~y[3]) == 0); | |
368 | } | |
369 | ||
370 | static inline bool | |
371 | hard_reg_set_equal_p (const HARD_REG_SET x, const HARD_REG_SET y) | |
372 | { | |
373 | return x[0] == y[0] && x[1] == y[1] && x[2] == y[2] && x[3] == y[3]; | |
374 | } | |
375 | ||
376 | static inline bool | |
377 | hard_reg_set_intersect_p (const HARD_REG_SET x, const HARD_REG_SET y) | |
378 | { | |
379 | return ((x[0] & y[0]) != 0 | |
380 | || (x[1] & y[1]) != 0 | |
381 | || (x[2] & y[2]) != 0 | |
382 | || (x[3] & y[3]) != 0); | |
383 | } | |
384 | ||
385 | static inline bool | |
386 | hard_reg_set_empty_p (const HARD_REG_SET x) | |
387 | { | |
388 | return x[0] == 0 && x[1] == 0 && x[2] == 0 && x[3] == 0; | |
389 | } | |
f9bc9bee | 390 | |
dea7b504 | 391 | #else /* FIRST_PSEUDO_REGISTER > 4*HOST_BITS_PER_WIDEST_FAST_INT */ |
f9bc9bee | 392 | |
6207bd2c | 393 | #define CLEAR_HARD_REG_SET(TO) \ |
19cb6b50 | 394 | do { HARD_REG_ELT_TYPE *scan_tp_ = (TO); \ |
395 | int i; \ | |
6207bd2c | 396 | for (i = 0; i < HARD_REG_SET_LONGS; i++) \ |
397 | *scan_tp_++ = 0; } while (0) | |
398 | ||
399 | #define SET_HARD_REG_SET(TO) \ | |
19cb6b50 | 400 | do { HARD_REG_ELT_TYPE *scan_tp_ = (TO); \ |
401 | int i; \ | |
6207bd2c | 402 | for (i = 0; i < HARD_REG_SET_LONGS; i++) \ |
403 | *scan_tp_++ = -1; } while (0) | |
404 | ||
405 | #define COPY_HARD_REG_SET(TO, FROM) \ | |
19cb6b50 | 406 | do { HARD_REG_ELT_TYPE *scan_tp_ = (TO), *scan_fp_ = (FROM); \ |
407 | int i; \ | |
6207bd2c | 408 | for (i = 0; i < HARD_REG_SET_LONGS; i++) \ |
409 | *scan_tp_++ = *scan_fp_++; } while (0) | |
410 | ||
411 | #define COMPL_HARD_REG_SET(TO, FROM) \ | |
19cb6b50 | 412 | do { HARD_REG_ELT_TYPE *scan_tp_ = (TO), *scan_fp_ = (FROM); \ |
413 | int i; \ | |
6207bd2c | 414 | for (i = 0; i < HARD_REG_SET_LONGS; i++) \ |
415 | *scan_tp_++ = ~ *scan_fp_++; } while (0) | |
416 | ||
417 | #define AND_HARD_REG_SET(TO, FROM) \ | |
19cb6b50 | 418 | do { HARD_REG_ELT_TYPE *scan_tp_ = (TO), *scan_fp_ = (FROM); \ |
419 | int i; \ | |
6207bd2c | 420 | for (i = 0; i < HARD_REG_SET_LONGS; i++) \ |
421 | *scan_tp_++ &= *scan_fp_++; } while (0) | |
422 | ||
423 | #define AND_COMPL_HARD_REG_SET(TO, FROM) \ | |
19cb6b50 | 424 | do { HARD_REG_ELT_TYPE *scan_tp_ = (TO), *scan_fp_ = (FROM); \ |
425 | int i; \ | |
6207bd2c | 426 | for (i = 0; i < HARD_REG_SET_LONGS; i++) \ |
427 | *scan_tp_++ &= ~ *scan_fp_++; } while (0) | |
428 | ||
429 | #define IOR_HARD_REG_SET(TO, FROM) \ | |
19cb6b50 | 430 | do { HARD_REG_ELT_TYPE *scan_tp_ = (TO), *scan_fp_ = (FROM); \ |
431 | int i; \ | |
6207bd2c | 432 | for (i = 0; i < HARD_REG_SET_LONGS; i++) \ |
433 | *scan_tp_++ |= *scan_fp_++; } while (0) | |
434 | ||
435 | #define IOR_COMPL_HARD_REG_SET(TO, FROM) \ | |
19cb6b50 | 436 | do { HARD_REG_ELT_TYPE *scan_tp_ = (TO), *scan_fp_ = (FROM); \ |
437 | int i; \ | |
6207bd2c | 438 | for (i = 0; i < HARD_REG_SET_LONGS; i++) \ |
439 | *scan_tp_++ |= ~ *scan_fp_++; } while (0) | |
440 | ||
ddc556d1 | 441 | static inline bool |
442 | hard_reg_set_subset_p (const HARD_REG_SET x, const HARD_REG_SET y) | |
443 | { | |
444 | int i; | |
445 | ||
446 | for (i = 0; i < HARD_REG_SET_LONGS; i++) | |
447 | if ((x[i] & ~y[i]) != 0) | |
448 | return false; | |
449 | return true; | |
450 | } | |
451 | ||
452 | static inline bool | |
453 | hard_reg_set_equal_p (const HARD_REG_SET x, const HARD_REG_SET y) | |
454 | { | |
455 | int i; | |
456 | ||
457 | for (i = 0; i < HARD_REG_SET_LONGS; i++) | |
458 | if (x[i] != y[i]) | |
459 | return false; | |
460 | return true; | |
461 | } | |
462 | ||
463 | static inline bool | |
464 | hard_reg_set_intersect_p (const HARD_REG_SET x, const HARD_REG_SET y) | |
465 | { | |
466 | int i; | |
467 | ||
468 | for (i = 0; i < HARD_REG_SET_LONGS; i++) | |
469 | if ((x[i] & y[i]) != 0) | |
470 | return true; | |
471 | return false; | |
472 | } | |
473 | ||
474 | static inline bool | |
475 | hard_reg_set_empty_p (const HARD_REG_SET x) | |
476 | { | |
477 | int i; | |
478 | ||
479 | for (i = 0; i < HARD_REG_SET_LONGS; i++) | |
480 | if (x[i] != 0) | |
481 | return false; | |
482 | return true; | |
483 | } | |
6207bd2c | 484 | |
485 | #endif | |
f9bc9bee | 486 | #endif |
487 | #endif | |
488 | #endif | |
6207bd2c | 489 | |
e1ab7874 | 490 | /* Iterator for hard register sets. */ |
491 | ||
492 | typedef struct | |
493 | { | |
494 | /* Pointer to the current element. */ | |
495 | HARD_REG_ELT_TYPE *pelt; | |
496 | ||
497 | /* The length of the set. */ | |
498 | unsigned short length; | |
499 | ||
500 | /* Word within the current element. */ | |
501 | unsigned short word_no; | |
502 | ||
503 | /* Contents of the actually processed word. When finding next bit | |
504 | it is shifted right, so that the actual bit is always the least | |
505 | significant bit of ACTUAL. */ | |
506 | HARD_REG_ELT_TYPE bits; | |
507 | } hard_reg_set_iterator; | |
508 | ||
509 | #define HARD_REG_ELT_BITS UHOST_BITS_PER_WIDE_INT | |
510 | ||
48e1416a | 511 | /* The implementation of the iterator functions is fully analogous to |
e1ab7874 | 512 | the bitmap iterators. */ |
513 | static inline void | |
48e1416a | 514 | hard_reg_set_iter_init (hard_reg_set_iterator *iter, HARD_REG_SET set, |
e1ab7874 | 515 | unsigned min, unsigned *regno) |
516 | { | |
517 | #ifdef HARD_REG_SET_LONGS | |
518 | iter->pelt = set; | |
519 | iter->length = HARD_REG_SET_LONGS; | |
520 | #else | |
521 | iter->pelt = &set; | |
522 | iter->length = 1; | |
523 | #endif | |
524 | iter->word_no = min / HARD_REG_ELT_BITS; | |
525 | if (iter->word_no < iter->length) | |
526 | { | |
527 | iter->bits = iter->pelt[iter->word_no]; | |
528 | iter->bits >>= min % HARD_REG_ELT_BITS; | |
529 | ||
530 | /* This is required for correct search of the next bit. */ | |
531 | min += !iter->bits; | |
532 | } | |
533 | *regno = min; | |
534 | } | |
535 | ||
48e1416a | 536 | static inline bool |
e1ab7874 | 537 | hard_reg_set_iter_set (hard_reg_set_iterator *iter, unsigned *regno) |
538 | { | |
539 | while (1) | |
540 | { | |
541 | /* Return false when we're advanced past the end of the set. */ | |
542 | if (iter->word_no >= iter->length) | |
543 | return false; | |
544 | ||
545 | if (iter->bits) | |
546 | { | |
547 | /* Find the correct bit and return it. */ | |
548 | while (!(iter->bits & 1)) | |
549 | { | |
550 | iter->bits >>= 1; | |
551 | *regno += 1; | |
552 | } | |
553 | return (*regno < FIRST_PSEUDO_REGISTER); | |
554 | } | |
48e1416a | 555 | |
e1ab7874 | 556 | /* Round to the beginning of the next word. */ |
557 | *regno = (*regno + HARD_REG_ELT_BITS - 1); | |
558 | *regno -= *regno % HARD_REG_ELT_BITS; | |
559 | ||
560 | /* Find the next non-zero word. */ | |
561 | while (++iter->word_no < iter->length) | |
562 | { | |
563 | iter->bits = iter->pelt[iter->word_no]; | |
564 | if (iter->bits) | |
565 | break; | |
566 | *regno += HARD_REG_ELT_BITS; | |
567 | } | |
568 | } | |
569 | } | |
570 | ||
571 | static inline void | |
572 | hard_reg_set_iter_next (hard_reg_set_iterator *iter, unsigned *regno) | |
573 | { | |
574 | iter->bits >>= 1; | |
575 | *regno += 1; | |
576 | } | |
577 | ||
578 | #define EXECUTE_IF_SET_IN_HARD_REG_SET(SET, MIN, REGNUM, ITER) \ | |
579 | for (hard_reg_set_iter_init (&(ITER), (SET), (MIN), &(REGNUM)); \ | |
580 | hard_reg_set_iter_set (&(ITER), &(REGNUM)); \ | |
581 | hard_reg_set_iter_next (&(ITER), &(REGNUM))) | |
582 | ||
583 | ||
6207bd2c | 584 | /* Define some standard sets of registers. */ |
585 | ||
6207bd2c | 586 | /* Indexed by hard register number, contains 1 for registers |
587 | that are being used for global register decls. | |
588 | These must be exempt from ordinary flow analysis | |
589 | and are also considered fixed. */ | |
590 | ||
591 | extern char global_regs[FIRST_PSEUDO_REGISTER]; | |
592 | ||
6d0eb0c4 | 593 | struct target_hard_regs { |
9fbe2159 | 594 | /* The set of registers that actually exist on the current target. */ |
595 | HARD_REG_SET x_accessible_reg_set; | |
596 | ||
597 | /* The set of registers that should be considered to be register | |
598 | operands. It is a subset of x_accessible_reg_set. */ | |
599 | HARD_REG_SET x_operand_reg_set; | |
600 | ||
6d0eb0c4 | 601 | /* Indexed by hard register number, contains 1 for registers |
602 | that are fixed use (stack pointer, pc, frame pointer, etc.;. | |
603 | These are the registers that cannot be used to allocate | |
604 | a pseudo reg whose life does not cross calls. */ | |
605 | char x_fixed_regs[FIRST_PSEUDO_REGISTER]; | |
6207bd2c | 606 | |
6d0eb0c4 | 607 | /* The same info as a HARD_REG_SET. */ |
608 | HARD_REG_SET x_fixed_reg_set; | |
fbf51e51 | 609 | |
6d0eb0c4 | 610 | /* Indexed by hard register number, contains 1 for registers |
611 | that are fixed use or are clobbered by function calls. | |
612 | These are the registers that cannot be used to allocate | |
613 | a pseudo reg whose life crosses calls. */ | |
614 | char x_call_used_regs[FIRST_PSEUDO_REGISTER]; | |
fbf51e51 | 615 | |
6d0eb0c4 | 616 | char x_call_really_used_regs[FIRST_PSEUDO_REGISTER]; |
617 | ||
618 | /* The same info as a HARD_REG_SET. */ | |
619 | HARD_REG_SET x_call_used_reg_set; | |
6207bd2c | 620 | |
6d0eb0c4 | 621 | /* Contains registers that are fixed use -- i.e. in fixed_reg_set -- or |
622 | a function value return register or TARGET_STRUCT_VALUE_RTX or | |
623 | STATIC_CHAIN_REGNUM. These are the registers that cannot hold quantities | |
624 | across calls even if we are willing to save and restore them. */ | |
625 | HARD_REG_SET x_call_fixed_reg_set; | |
6207bd2c | 626 | |
6d0eb0c4 | 627 | /* Contains 1 for registers that are set or clobbered by calls. */ |
628 | /* ??? Ideally, this would be just call_used_regs plus global_regs, but | |
629 | for someone's bright idea to have call_used_regs strictly include | |
630 | fixed_regs. Which leaves us guessing as to the set of fixed_regs | |
631 | that are actually preserved. We know for sure that those associated | |
632 | with the local stack frame are safe, but scant others. */ | |
633 | HARD_REG_SET x_regs_invalidated_by_call; | |
6207bd2c | 634 | |
c3997e3d | 635 | /* Call used hard registers which can not be saved because there is no |
636 | insn for this. */ | |
637 | HARD_REG_SET x_no_caller_save_reg_set; | |
638 | ||
6d0eb0c4 | 639 | /* Table of register numbers in the order in which to try to use them. */ |
640 | int x_reg_alloc_order[FIRST_PSEUDO_REGISTER]; | |
bccb5444 | 641 | |
6d0eb0c4 | 642 | /* The inverse of reg_alloc_order. */ |
643 | int x_inv_reg_alloc_order[FIRST_PSEUDO_REGISTER]; | |
6207bd2c | 644 | |
6d0eb0c4 | 645 | /* For each reg class, a HARD_REG_SET saying which registers are in it. */ |
646 | HARD_REG_SET x_reg_class_contents[N_REG_CLASSES]; | |
6207bd2c | 647 | |
6d0eb0c4 | 648 | /* For each reg class, a boolean saying whether the class contains only |
649 | fixed registers. */ | |
650 | bool x_class_only_fixed_regs[N_REG_CLASSES]; | |
47dd2e78 | 651 | |
6d0eb0c4 | 652 | /* For each reg class, number of regs it contains. */ |
653 | unsigned int x_reg_class_size[N_REG_CLASSES]; | |
47dd2e78 | 654 | |
6d0eb0c4 | 655 | /* For each reg class, table listing all the classes contained in it. */ |
656 | enum reg_class x_reg_class_subclasses[N_REG_CLASSES][N_REG_CLASSES]; | |
6207bd2c | 657 | |
6d0eb0c4 | 658 | /* For each pair of reg classes, |
659 | a largest reg class contained in their union. */ | |
660 | enum reg_class x_reg_class_subunion[N_REG_CLASSES][N_REG_CLASSES]; | |
6207bd2c | 661 | |
6d0eb0c4 | 662 | /* For each pair of reg classes, |
663 | the smallest reg class that contains their union. */ | |
664 | enum reg_class x_reg_class_superunion[N_REG_CLASSES][N_REG_CLASSES]; | |
6207bd2c | 665 | |
6d0eb0c4 | 666 | /* Vector indexed by hardware reg giving its name. */ |
667 | const char *x_reg_names[FIRST_PSEUDO_REGISTER]; | |
668 | }; | |
6207bd2c | 669 | |
6d0eb0c4 | 670 | extern struct target_hard_regs default_target_hard_regs; |
671 | #if SWITCHABLE_TARGET | |
672 | extern struct target_hard_regs *this_target_hard_regs; | |
673 | #else | |
674 | #define this_target_hard_regs (&default_target_hard_regs) | |
675 | #endif | |
6207bd2c | 676 | |
9fbe2159 | 677 | #define accessible_reg_set \ |
678 | (this_target_hard_regs->x_accessible_reg_set) | |
679 | #define operand_reg_set \ | |
680 | (this_target_hard_regs->x_operand_reg_set) | |
6d0eb0c4 | 681 | #define fixed_regs \ |
682 | (this_target_hard_regs->x_fixed_regs) | |
683 | #define fixed_reg_set \ | |
684 | (this_target_hard_regs->x_fixed_reg_set) | |
685 | #define call_used_regs \ | |
686 | (this_target_hard_regs->x_call_used_regs) | |
687 | #define call_really_used_regs \ | |
688 | (this_target_hard_regs->x_call_really_used_regs) | |
689 | #define call_used_reg_set \ | |
690 | (this_target_hard_regs->x_call_used_reg_set) | |
691 | #define call_fixed_reg_set \ | |
692 | (this_target_hard_regs->x_call_fixed_reg_set) | |
693 | #define regs_invalidated_by_call \ | |
694 | (this_target_hard_regs->x_regs_invalidated_by_call) | |
c3997e3d | 695 | #define no_caller_save_reg_set \ |
696 | (this_target_hard_regs->x_no_caller_save_reg_set) | |
6d0eb0c4 | 697 | #define reg_alloc_order \ |
698 | (this_target_hard_regs->x_reg_alloc_order) | |
699 | #define inv_reg_alloc_order \ | |
700 | (this_target_hard_regs->x_inv_reg_alloc_order) | |
701 | #define reg_class_contents \ | |
702 | (this_target_hard_regs->x_reg_class_contents) | |
703 | #define class_only_fixed_regs \ | |
704 | (this_target_hard_regs->x_class_only_fixed_regs) | |
705 | #define reg_class_size \ | |
706 | (this_target_hard_regs->x_reg_class_size) | |
707 | #define reg_class_subclasses \ | |
708 | (this_target_hard_regs->x_reg_class_subclasses) | |
709 | #define reg_class_subunion \ | |
710 | (this_target_hard_regs->x_reg_class_subunion) | |
711 | #define reg_class_superunion \ | |
712 | (this_target_hard_regs->x_reg_class_superunion) | |
713 | #define reg_names \ | |
714 | (this_target_hard_regs->x_reg_names) | |
89e8d34f | 715 | |
ada8adad | 716 | /* Vector indexed by reg class giving its name. */ |
717 | ||
718 | extern const char * reg_class_names[]; | |
719 | ||
6e7fc474 | 720 | /* Given a hard REGN a FROM mode and a TO mode, return nonzero if |
897118e8 | 721 | REGN cannot change modes between the specified modes. */ |
722 | #define REG_CANNOT_CHANGE_MODE_P(REGN, FROM, TO) \ | |
22aae821 | 723 | CANNOT_CHANGE_MODE_CLASS (FROM, TO, REGNO_REG_CLASS (REGN)) |
897118e8 | 724 | |
2a281353 | 725 | #endif /* ! GCC_HARD_REG_SET_H */ |