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