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