]>
Commit | Line | Data |
---|---|---|
47dd2e78 | 1 | /* IRA conflict builder. |
7cf0dbf3 | 2 | Copyright (C) 2006, 2007, 2008, 2009, 2010 |
47dd2e78 | 3 | Free Software Foundation, Inc. |
4 | Contributed by Vladimir Makarov <vmakarov@redhat.com>. | |
5 | ||
6 | This file is part of GCC. | |
7 | ||
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 | |
10 | Software Foundation; either version 3, or (at your option) any later | |
11 | version. | |
12 | ||
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. | |
17 | ||
18 | You should have received a copy of the GNU General Public License | |
19 | along with GCC; see the file COPYING3. If not see | |
20 | <http://www.gnu.org/licenses/>. */ | |
21 | ||
22 | #include "config.h" | |
23 | #include "system.h" | |
24 | #include "coretypes.h" | |
25 | #include "tm.h" | |
26 | #include "regs.h" | |
27 | #include "rtl.h" | |
28 | #include "tm_p.h" | |
29 | #include "target.h" | |
30 | #include "flags.h" | |
31 | #include "hard-reg-set.h" | |
32 | #include "basic-block.h" | |
33 | #include "insn-config.h" | |
34 | #include "recog.h" | |
0b205f4c | 35 | #include "diagnostic-core.h" |
47dd2e78 | 36 | #include "params.h" |
37 | #include "df.h" | |
38 | #include "sparseset.h" | |
39 | #include "ira-int.h" | |
bef7b1de | 40 | #include "addresses.h" |
47dd2e78 | 41 | |
42 | /* This file contains code responsible for allocno conflict creation, | |
43 | allocno copy creation and allocno info accumulation on upper level | |
44 | regions. */ | |
45 | ||
46 | /* ira_allocnos_num array of arrays of bits, recording whether two | |
47 | allocno's conflict (can't go in the same hardware register). | |
48 | ||
49 | Some arrays will be used as conflict bit vector of the | |
be18556f | 50 | corresponding allocnos see function build_object_conflicts. */ |
47dd2e78 | 51 | static IRA_INT_TYPE **conflicts; |
52 | ||
ae9587ed | 53 | /* Macro to test a conflict of C1 and C2 in `conflicts'. */ |
be18556f | 54 | #define OBJECTS_CONFLICT_P(C1, C2) \ |
ae9587ed | 55 | (OBJECT_MIN (C1) <= OBJECT_CONFLICT_ID (C2) \ |
56 | && OBJECT_CONFLICT_ID (C2) <= OBJECT_MAX (C1) \ | |
57 | && TEST_MINMAX_SET_BIT (conflicts[OBJECT_CONFLICT_ID (C1)], \ | |
58 | OBJECT_CONFLICT_ID (C2), \ | |
59 | OBJECT_MIN (C1), OBJECT_MAX (C1))) | |
47dd2e78 | 60 | |
61 | \f | |
be18556f | 62 | /* Record a conflict between objects OBJ1 and OBJ2. If necessary, |
63 | canonicalize the conflict by recording it for lower-order subobjects | |
64 | of the corresponding allocnos. */ | |
65 | static void | |
66 | record_object_conflict (ira_object_t obj1, ira_object_t obj2) | |
67 | { | |
68 | ira_allocno_t a1 = OBJECT_ALLOCNO (obj1); | |
69 | ira_allocno_t a2 = OBJECT_ALLOCNO (obj2); | |
70 | int w1 = OBJECT_SUBWORD (obj1); | |
71 | int w2 = OBJECT_SUBWORD (obj2); | |
72 | int id1, id2; | |
73 | ||
74 | /* Canonicalize the conflict. If two identically-numbered words | |
75 | conflict, always record this as a conflict between words 0. That | |
76 | is the only information we need, and it is easier to test for if | |
77 | it is collected in each allocno's lowest-order object. */ | |
78 | if (w1 == w2 && w1 > 0) | |
79 | { | |
80 | obj1 = ALLOCNO_OBJECT (a1, 0); | |
81 | obj2 = ALLOCNO_OBJECT (a2, 0); | |
82 | } | |
83 | id1 = OBJECT_CONFLICT_ID (obj1); | |
84 | id2 = OBJECT_CONFLICT_ID (obj2); | |
85 | ||
86 | SET_MINMAX_SET_BIT (conflicts[id1], id2, OBJECT_MIN (obj1), | |
87 | OBJECT_MAX (obj1)); | |
88 | SET_MINMAX_SET_BIT (conflicts[id2], id1, OBJECT_MIN (obj2), | |
89 | OBJECT_MAX (obj2)); | |
90 | } | |
91 | ||
95c83f01 | 92 | /* Build allocno conflict table by processing allocno live ranges. |
93 | Return true if the table was built. The table is not built if it | |
94 | is too big. */ | |
95 | static bool | |
47dd2e78 | 96 | build_conflict_bit_table (void) |
97 | { | |
ae9587ed | 98 | int i; |
47dd2e78 | 99 | unsigned int j; |
66d9a7b9 | 100 | enum reg_class aclass; |
ae9587ed | 101 | int object_set_words, allocated_words_num, conflict_bit_vec_words_num; |
fbff82f4 | 102 | live_range_t r; |
ae9587ed | 103 | ira_allocno_t allocno; |
47dd2e78 | 104 | ira_allocno_iterator ai; |
ae9587ed | 105 | sparseset objects_live; |
be18556f | 106 | ira_object_t obj; |
107 | ira_allocno_object_iterator aoi; | |
47dd2e78 | 108 | |
95c83f01 | 109 | allocated_words_num = 0; |
110 | FOR_EACH_ALLOCNO (allocno, ai) | |
be18556f | 111 | FOR_EACH_ALLOCNO_OBJECT (allocno, obj, aoi) |
112 | { | |
113 | if (OBJECT_MAX (obj) < OBJECT_MIN (obj)) | |
95c83f01 | 114 | continue; |
be18556f | 115 | conflict_bit_vec_words_num |
116 | = ((OBJECT_MAX (obj) - OBJECT_MIN (obj) + IRA_INT_BITS) | |
117 | / IRA_INT_BITS); | |
118 | allocated_words_num += conflict_bit_vec_words_num; | |
7867279a | 119 | if ((unsigned HOST_WIDEST_INT) allocated_words_num * sizeof (IRA_INT_TYPE) |
120 | > (unsigned HOST_WIDEST_INT) IRA_MAX_CONFLICT_TABLE_SIZE * 1024 * 1024) | |
be18556f | 121 | { |
122 | if (internal_flag_ira_verbose > 0 && ira_dump_file != NULL) | |
123 | fprintf | |
124 | (ira_dump_file, | |
125 | "+++Conflict table will be too big(>%dMB) -- don't use it\n", | |
126 | IRA_MAX_CONFLICT_TABLE_SIZE); | |
127 | return false; | |
128 | } | |
129 | } | |
ae9587ed | 130 | |
47dd2e78 | 131 | conflicts = (IRA_INT_TYPE **) ira_allocate (sizeof (IRA_INT_TYPE *) |
ae9587ed | 132 | * ira_objects_num); |
47dd2e78 | 133 | allocated_words_num = 0; |
134 | FOR_EACH_ALLOCNO (allocno, ai) | |
be18556f | 135 | FOR_EACH_ALLOCNO_OBJECT (allocno, obj, aoi) |
136 | { | |
137 | int id = OBJECT_CONFLICT_ID (obj); | |
138 | if (OBJECT_MAX (obj) < OBJECT_MIN (obj)) | |
139 | { | |
140 | conflicts[id] = NULL; | |
141 | continue; | |
142 | } | |
143 | conflict_bit_vec_words_num | |
144 | = ((OBJECT_MAX (obj) - OBJECT_MIN (obj) + IRA_INT_BITS) | |
145 | / IRA_INT_BITS); | |
146 | allocated_words_num += conflict_bit_vec_words_num; | |
147 | conflicts[id] | |
148 | = (IRA_INT_TYPE *) ira_allocate (sizeof (IRA_INT_TYPE) | |
149 | * conflict_bit_vec_words_num); | |
150 | memset (conflicts[id], 0, | |
151 | sizeof (IRA_INT_TYPE) * conflict_bit_vec_words_num); | |
152 | } | |
ae9587ed | 153 | |
154 | object_set_words = (ira_objects_num + IRA_INT_BITS - 1) / IRA_INT_BITS; | |
47dd2e78 | 155 | if (internal_flag_ira_verbose > 0 && ira_dump_file != NULL) |
156 | fprintf | |
157 | (ira_dump_file, | |
158 | "+++Allocating %ld bytes for conflict table (uncompressed size %ld)\n", | |
159 | (long) allocated_words_num * sizeof (IRA_INT_TYPE), | |
ae9587ed | 160 | (long) object_set_words * ira_objects_num * sizeof (IRA_INT_TYPE)); |
161 | ||
162 | objects_live = sparseset_alloc (ira_objects_num); | |
47dd2e78 | 163 | for (i = 0; i < ira_max_point; i++) |
164 | { | |
165 | for (r = ira_start_point_ranges[i]; r != NULL; r = r->start_next) | |
166 | { | |
9d53e372 | 167 | ira_object_t obj = r->object; |
168 | ira_allocno_t allocno = OBJECT_ALLOCNO (obj); | |
ae9587ed | 169 | int id = OBJECT_CONFLICT_ID (obj); |
170 | ||
be18556f | 171 | gcc_assert (id < ira_objects_num); |
172 | ||
66d9a7b9 | 173 | aclass = ALLOCNO_CLASS (allocno); |
ae9587ed | 174 | sparseset_set_bit (objects_live, id); |
175 | EXECUTE_IF_SET_IN_SPARSESET (objects_live, j) | |
47dd2e78 | 176 | { |
be18556f | 177 | ira_object_t live_obj = ira_object_id_map[j]; |
178 | ira_allocno_t live_a = OBJECT_ALLOCNO (live_obj); | |
66d9a7b9 | 179 | enum reg_class live_aclass = ALLOCNO_CLASS (live_a); |
ae9587ed | 180 | |
66d9a7b9 | 181 | if (ira_reg_classes_intersect_p[aclass][live_aclass] |
47dd2e78 | 182 | /* Don't set up conflict for the allocno with itself. */ |
be18556f | 183 | && live_a != allocno) |
47dd2e78 | 184 | { |
be18556f | 185 | record_object_conflict (obj, live_obj); |
47dd2e78 | 186 | } |
187 | } | |
188 | } | |
48e1416a | 189 | |
47dd2e78 | 190 | for (r = ira_finish_point_ranges[i]; r != NULL; r = r->finish_next) |
be18556f | 191 | sparseset_clear_bit (objects_live, OBJECT_CONFLICT_ID (r->object)); |
47dd2e78 | 192 | } |
ae9587ed | 193 | sparseset_free (objects_live); |
95c83f01 | 194 | return true; |
47dd2e78 | 195 | } |
47dd2e78 | 196 | \f |
ae9587ed | 197 | /* Return true iff allocnos A1 and A2 cannot be allocated to the same |
198 | register due to conflicts. */ | |
199 | ||
200 | static bool | |
be18556f | 201 | allocnos_conflict_for_copy_p (ira_allocno_t a1, ira_allocno_t a2) |
ae9587ed | 202 | { |
be18556f | 203 | /* Due to the fact that we canonicalize conflicts (see |
204 | record_object_conflict), we only need to test for conflicts of | |
205 | the lowest order words. */ | |
206 | ira_object_t obj1 = ALLOCNO_OBJECT (a1, 0); | |
207 | ira_object_t obj2 = ALLOCNO_OBJECT (a2, 0); | |
66d9a7b9 | 208 | |
ae9587ed | 209 | return OBJECTS_CONFLICT_P (obj1, obj2); |
210 | } | |
47dd2e78 | 211 | |
212 | /* Return TRUE if the operand constraint STR is commutative. */ | |
213 | static bool | |
214 | commutative_constraint_p (const char *str) | |
215 | { | |
34347cd4 | 216 | int curr_alt, c; |
47dd2e78 | 217 | bool ignore_p; |
47dd2e78 | 218 | |
34347cd4 | 219 | for (ignore_p = false, curr_alt = 0;;) |
47dd2e78 | 220 | { |
221 | c = *str; | |
222 | if (c == '\0') | |
223 | break; | |
224 | str += CONSTRAINT_LEN (c, str); | |
34347cd4 | 225 | if (c == '#' || !recog_data.alternative_enabled_p[curr_alt]) |
47dd2e78 | 226 | ignore_p = true; |
227 | else if (c == ',') | |
34347cd4 | 228 | { |
229 | curr_alt++; | |
230 | ignore_p = false; | |
231 | } | |
47dd2e78 | 232 | else if (! ignore_p) |
233 | { | |
234 | /* Usually `%' is the first constraint character but the | |
235 | documentation does not require this. */ | |
236 | if (c == '%') | |
237 | return true; | |
238 | } | |
239 | } | |
240 | return false; | |
241 | } | |
242 | ||
243 | /* Return the number of the operand which should be the same in any | |
244 | case as operand with number OP_NUM (or negative value if there is | |
245 | no such operand). If USE_COMMUT_OP_P is TRUE, the function makes | |
246 | temporarily commutative operand exchange before this. The function | |
247 | takes only really possible alternatives into consideration. */ | |
248 | static int | |
249 | get_dup_num (int op_num, bool use_commut_op_p) | |
250 | { | |
251 | int curr_alt, c, original, dup; | |
252 | bool ignore_p, commut_op_used_p; | |
253 | const char *str; | |
254 | rtx op; | |
255 | ||
256 | if (op_num < 0 || recog_data.n_alternatives == 0) | |
257 | return -1; | |
258 | op = recog_data.operand[op_num]; | |
47dd2e78 | 259 | commut_op_used_p = true; |
260 | if (use_commut_op_p) | |
261 | { | |
262 | if (commutative_constraint_p (recog_data.constraints[op_num])) | |
263 | op_num++; | |
264 | else if (op_num > 0 && commutative_constraint_p (recog_data.constraints | |
265 | [op_num - 1])) | |
266 | op_num--; | |
267 | else | |
268 | commut_op_used_p = false; | |
269 | } | |
270 | str = recog_data.constraints[op_num]; | |
271 | for (ignore_p = false, original = -1, curr_alt = 0;;) | |
272 | { | |
273 | c = *str; | |
274 | if (c == '\0') | |
275 | break; | |
34347cd4 | 276 | if (c == '#' || !recog_data.alternative_enabled_p[curr_alt]) |
47dd2e78 | 277 | ignore_p = true; |
278 | else if (c == ',') | |
279 | { | |
280 | curr_alt++; | |
281 | ignore_p = false; | |
282 | } | |
283 | else if (! ignore_p) | |
284 | switch (c) | |
285 | { | |
286 | case 'X': | |
287 | return -1; | |
48e1416a | 288 | |
47dd2e78 | 289 | case 'm': |
290 | case 'o': | |
291 | /* Accept a register which might be placed in memory. */ | |
292 | return -1; | |
293 | break; | |
294 | ||
295 | case 'V': | |
296 | case '<': | |
297 | case '>': | |
298 | break; | |
299 | ||
300 | case 'p': | |
fd50b071 | 301 | if (address_operand (op, VOIDmode)) |
302 | return -1; | |
47dd2e78 | 303 | break; |
fd50b071 | 304 | |
47dd2e78 | 305 | case 'g': |
306 | return -1; | |
48e1416a | 307 | |
47dd2e78 | 308 | case 'r': |
309 | case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': | |
310 | case 'h': case 'j': case 'k': case 'l': | |
311 | case 'q': case 't': case 'u': | |
312 | case 'v': case 'w': case 'x': case 'y': case 'z': | |
313 | case 'A': case 'B': case 'C': case 'D': | |
314 | case 'Q': case 'R': case 'S': case 'T': case 'U': | |
315 | case 'W': case 'Y': case 'Z': | |
316 | { | |
317 | enum reg_class cl; | |
318 | ||
319 | cl = (c == 'r' | |
320 | ? GENERAL_REGS : REG_CLASS_FROM_CONSTRAINT (c, str)); | |
321 | if (cl != NO_REGS) | |
322 | return -1; | |
323 | #ifdef EXTRA_CONSTRAINT_STR | |
324 | else if (EXTRA_CONSTRAINT_STR (op, c, str)) | |
325 | return -1; | |
326 | #endif | |
327 | break; | |
328 | } | |
48e1416a | 329 | |
47dd2e78 | 330 | case '0': case '1': case '2': case '3': case '4': |
331 | case '5': case '6': case '7': case '8': case '9': | |
332 | if (original != -1 && original != c) | |
333 | return -1; | |
334 | original = c; | |
335 | break; | |
336 | } | |
337 | str += CONSTRAINT_LEN (c, str); | |
338 | } | |
339 | if (original == -1) | |
340 | return -1; | |
341 | dup = original - '0'; | |
342 | if (use_commut_op_p) | |
343 | { | |
344 | if (commutative_constraint_p (recog_data.constraints[dup])) | |
345 | dup++; | |
346 | else if (dup > 0 | |
347 | && commutative_constraint_p (recog_data.constraints[dup -1])) | |
348 | dup--; | |
349 | else if (! commut_op_used_p) | |
350 | return -1; | |
351 | } | |
352 | return dup; | |
353 | } | |
354 | ||
f0a46d83 | 355 | /* Check that X is REG or SUBREG of REG. */ |
356 | #define REG_SUBREG_P(x) \ | |
357 | (REG_P (x) || (GET_CODE (x) == SUBREG && REG_P (SUBREG_REG (x)))) | |
358 | ||
359 | /* Return X if X is a REG, otherwise it should be SUBREG of REG and | |
360 | the function returns the reg in this case. *OFFSET will be set to | |
361 | 0 in the first case or the regno offset in the first case. */ | |
362 | static rtx | |
363 | go_through_subreg (rtx x, int *offset) | |
364 | { | |
365 | rtx reg; | |
366 | ||
367 | *offset = 0; | |
368 | if (REG_P (x)) | |
369 | return x; | |
370 | ira_assert (GET_CODE (x) == SUBREG); | |
371 | reg = SUBREG_REG (x); | |
372 | ira_assert (REG_P (reg)); | |
373 | if (REGNO (reg) < FIRST_PSEUDO_REGISTER) | |
374 | *offset = subreg_regno_offset (REGNO (reg), GET_MODE (reg), | |
375 | SUBREG_BYTE (x), GET_MODE (x)); | |
376 | else | |
377 | *offset = (SUBREG_BYTE (x) / REGMODE_NATURAL_SIZE (GET_MODE (x))); | |
378 | return reg; | |
379 | } | |
380 | ||
47dd2e78 | 381 | /* Process registers REG1 and REG2 in move INSN with execution |
382 | frequency FREQ. The function also processes the registers in a | |
383 | potential move insn (INSN == NULL in this case) with frequency | |
384 | FREQ. The function can modify hard register costs of the | |
385 | corresponding allocnos or create a copy involving the corresponding | |
386 | allocnos. The function does nothing if the both registers are hard | |
387 | registers. When nothing is changed, the function returns | |
388 | FALSE. */ | |
389 | static bool | |
b7c06809 | 390 | process_regs_for_copy (rtx reg1, rtx reg2, bool constraint_p, |
391 | rtx insn, int freq) | |
47dd2e78 | 392 | { |
296a743c | 393 | int allocno_preferenced_hard_regno, cost, index, offset1, offset2; |
f0a46d83 | 394 | bool only_regs_p; |
47dd2e78 | 395 | ira_allocno_t a; |
d3ba22dc | 396 | reg_class_t rclass, aclass; |
47dd2e78 | 397 | enum machine_mode mode; |
398 | ira_copy_t cp; | |
399 | ||
f0a46d83 | 400 | gcc_assert (REG_SUBREG_P (reg1) && REG_SUBREG_P (reg2)); |
401 | only_regs_p = REG_P (reg1) && REG_P (reg2); | |
402 | reg1 = go_through_subreg (reg1, &offset1); | |
403 | reg2 = go_through_subreg (reg2, &offset2); | |
296a743c | 404 | /* Set up hard regno preferenced by allocno. If allocno gets the |
405 | hard regno the copy (or potential move) insn will be removed. */ | |
47dd2e78 | 406 | if (HARD_REGISTER_P (reg1)) |
407 | { | |
408 | if (HARD_REGISTER_P (reg2)) | |
409 | return false; | |
296a743c | 410 | allocno_preferenced_hard_regno = REGNO (reg1) + offset1 - offset2; |
47dd2e78 | 411 | a = ira_curr_regno_allocno_map[REGNO (reg2)]; |
412 | } | |
413 | else if (HARD_REGISTER_P (reg2)) | |
414 | { | |
296a743c | 415 | allocno_preferenced_hard_regno = REGNO (reg2) + offset2 - offset1; |
47dd2e78 | 416 | a = ira_curr_regno_allocno_map[REGNO (reg1)]; |
417 | } | |
ae9587ed | 418 | else |
47dd2e78 | 419 | { |
ae9587ed | 420 | ira_allocno_t a1 = ira_curr_regno_allocno_map[REGNO (reg1)]; |
421 | ira_allocno_t a2 = ira_curr_regno_allocno_map[REGNO (reg2)]; | |
9f8ac546 | 422 | |
be18556f | 423 | if (!allocnos_conflict_for_copy_p (a1, a2) && offset1 == offset2) |
ae9587ed | 424 | { |
425 | cp = ira_add_allocno_copy (a1, a2, freq, constraint_p, insn, | |
426 | ira_curr_loop_tree_node); | |
427 | bitmap_set_bit (ira_curr_loop_tree_node->local_copies, cp->num); | |
428 | return true; | |
429 | } | |
430 | else | |
431 | return false; | |
47dd2e78 | 432 | } |
ae9587ed | 433 | |
66d9a7b9 | 434 | if (! IN_RANGE (allocno_preferenced_hard_regno, |
435 | 0, FIRST_PSEUDO_REGISTER - 1)) | |
296a743c | 436 | /* Can not be tied. */ |
437 | return false; | |
438 | rclass = REGNO_REG_CLASS (allocno_preferenced_hard_regno); | |
47dd2e78 | 439 | mode = ALLOCNO_MODE (a); |
66d9a7b9 | 440 | aclass = ALLOCNO_CLASS (a); |
55c858c5 | 441 | if (only_regs_p && insn != NULL_RTX |
d3ba22dc | 442 | && reg_class_size[rclass] <= ira_reg_class_max_nregs [rclass][mode]) |
47dd2e78 | 443 | /* It is already taken into account in ira-costs.c. */ |
444 | return false; | |
66d9a7b9 | 445 | index = ira_class_hard_reg_index[aclass][allocno_preferenced_hard_regno]; |
47dd2e78 | 446 | if (index < 0) |
66d9a7b9 | 447 | /* Can not be tied. It is not in the allocno class. */ |
47dd2e78 | 448 | return false; |
66d9a7b9 | 449 | ira_init_register_move_cost_if_necessary (mode); |
47dd2e78 | 450 | if (HARD_REGISTER_P (reg1)) |
66d9a7b9 | 451 | cost = ira_register_move_cost[mode][aclass][rclass] * freq; |
47dd2e78 | 452 | else |
66d9a7b9 | 453 | cost = ira_register_move_cost[mode][rclass][aclass] * freq; |
c58db480 | 454 | do |
df07a54c | 455 | { |
456 | ira_allocate_and_set_costs | |
66d9a7b9 | 457 | (&ALLOCNO_HARD_REG_COSTS (a), aclass, |
458 | ALLOCNO_CLASS_COST (a)); | |
df07a54c | 459 | ira_allocate_and_set_costs |
66d9a7b9 | 460 | (&ALLOCNO_CONFLICT_HARD_REG_COSTS (a), aclass, 0); |
df07a54c | 461 | ALLOCNO_HARD_REG_COSTS (a)[index] -= cost; |
462 | ALLOCNO_CONFLICT_HARD_REG_COSTS (a)[index] -= cost; | |
66d9a7b9 | 463 | if (ALLOCNO_HARD_REG_COSTS (a)[index] < ALLOCNO_CLASS_COST (a)) |
464 | ALLOCNO_CLASS_COST (a) = ALLOCNO_HARD_REG_COSTS (a)[index]; | |
c58db480 | 465 | a = ira_parent_or_cap_allocno (a); |
df07a54c | 466 | } |
c58db480 | 467 | while (a != NULL); |
47dd2e78 | 468 | return true; |
469 | } | |
470 | ||
106453cc | 471 | /* Process all of the output registers of the current insn which are |
472 | not bound (BOUND_P) and the input register REG (its operand number | |
473 | OP_NUM) which dies in the insn as if there were a move insn between | |
474 | them with frequency FREQ. */ | |
47dd2e78 | 475 | static void |
106453cc | 476 | process_reg_shuffles (rtx reg, int op_num, int freq, bool *bound_p) |
47dd2e78 | 477 | { |
478 | int i; | |
479 | rtx another_reg; | |
480 | ||
f0a46d83 | 481 | gcc_assert (REG_SUBREG_P (reg)); |
47dd2e78 | 482 | for (i = 0; i < recog_data.n_operands; i++) |
483 | { | |
484 | another_reg = recog_data.operand[i]; | |
48e1416a | 485 | |
f0a46d83 | 486 | if (!REG_SUBREG_P (another_reg) || op_num == i |
106453cc | 487 | || recog_data.operand_type[i] != OP_OUT |
488 | || bound_p[i]) | |
47dd2e78 | 489 | continue; |
48e1416a | 490 | |
b7c06809 | 491 | process_regs_for_copy (reg, another_reg, false, NULL_RTX, freq); |
47dd2e78 | 492 | } |
493 | } | |
494 | ||
495 | /* Process INSN and create allocno copies if necessary. For example, | |
496 | it might be because INSN is a pseudo-register move or INSN is two | |
497 | operand insn. */ | |
498 | static void | |
499 | add_insn_allocno_copies (rtx insn) | |
500 | { | |
4e51a669 | 501 | rtx set, operand, dup; |
47dd2e78 | 502 | const char *str; |
106453cc | 503 | bool commut_p, bound_p[MAX_RECOG_OPERANDS]; |
504 | int i, j, n, freq; | |
ae9587ed | 505 | |
47dd2e78 | 506 | freq = REG_FREQ_FROM_BB (BLOCK_FOR_INSN (insn)); |
507 | if (freq == 0) | |
508 | freq = 1; | |
509 | if ((set = single_set (insn)) != NULL_RTX | |
f0a46d83 | 510 | && REG_SUBREG_P (SET_DEST (set)) && REG_SUBREG_P (SET_SRC (set)) |
47dd2e78 | 511 | && ! side_effects_p (set) |
f0a46d83 | 512 | && find_reg_note (insn, REG_DEAD, |
513 | REG_P (SET_SRC (set)) | |
514 | ? SET_SRC (set) | |
515 | : SUBREG_REG (SET_SRC (set))) != NULL_RTX) | |
47dd2e78 | 516 | { |
66d9a7b9 | 517 | process_regs_for_copy (SET_DEST (set), SET_SRC (set), |
518 | false, insn, freq); | |
106453cc | 519 | return; |
520 | } | |
4e51a669 | 521 | /* Fast check of possibility of constraint or shuffle copies. If |
522 | there are no dead registers, there will be no such copies. */ | |
523 | if (! find_reg_note (insn, REG_DEAD, NULL_RTX)) | |
106453cc | 524 | return; |
525 | extract_insn (insn); | |
526 | for (i = 0; i < recog_data.n_operands; i++) | |
527 | bound_p[i] = false; | |
528 | for (i = 0; i < recog_data.n_operands; i++) | |
529 | { | |
530 | operand = recog_data.operand[i]; | |
531 | if (! REG_SUBREG_P (operand)) | |
532 | continue; | |
533 | str = recog_data.constraints[i]; | |
534 | while (*str == ' ' || *str == '\t') | |
535 | str++; | |
536 | for (j = 0, commut_p = false; j < 2; j++, commut_p = true) | |
537 | if ((n = get_dup_num (i, commut_p)) >= 0) | |
538 | { | |
539 | bound_p[n] = true; | |
540 | dup = recog_data.operand[n]; | |
541 | if (REG_SUBREG_P (dup) | |
542 | && find_reg_note (insn, REG_DEAD, | |
543 | REG_P (operand) | |
544 | ? operand | |
545 | : SUBREG_REG (operand)) != NULL_RTX) | |
546 | process_regs_for_copy (operand, dup, true, NULL_RTX, freq); | |
547 | } | |
548 | } | |
549 | for (i = 0; i < recog_data.n_operands; i++) | |
550 | { | |
551 | operand = recog_data.operand[i]; | |
552 | if (REG_SUBREG_P (operand) | |
553 | && find_reg_note (insn, REG_DEAD, | |
554 | REG_P (operand) | |
555 | ? operand : SUBREG_REG (operand)) != NULL_RTX) | |
556 | /* If an operand dies, prefer its hard register for the output | |
557 | operands by decreasing the hard register cost or creating | |
558 | the corresponding allocno copies. The cost will not | |
559 | correspond to a real move insn cost, so make the frequency | |
560 | smaller. */ | |
561 | process_reg_shuffles (operand, i, freq < 8 ? 1 : freq / 8, bound_p); | |
47dd2e78 | 562 | } |
563 | } | |
564 | ||
565 | /* Add copies originated from BB given by LOOP_TREE_NODE. */ | |
566 | static void | |
567 | add_copies (ira_loop_tree_node_t loop_tree_node) | |
568 | { | |
569 | basic_block bb; | |
570 | rtx insn; | |
571 | ||
572 | bb = loop_tree_node->bb; | |
573 | if (bb == NULL) | |
574 | return; | |
575 | FOR_BB_INSNS (bb, insn) | |
9845d120 | 576 | if (NONDEBUG_INSN_P (insn)) |
47dd2e78 | 577 | add_insn_allocno_copies (insn); |
578 | } | |
579 | ||
580 | /* Propagate copies the corresponding allocnos on upper loop tree | |
581 | level. */ | |
582 | static void | |
583 | propagate_copies (void) | |
584 | { | |
585 | ira_copy_t cp; | |
586 | ira_copy_iterator ci; | |
587 | ira_allocno_t a1, a2, parent_a1, parent_a2; | |
47dd2e78 | 588 | |
589 | FOR_EACH_COPY (cp, ci) | |
590 | { | |
591 | a1 = cp->first; | |
592 | a2 = cp->second; | |
593 | if (ALLOCNO_LOOP_TREE_NODE (a1) == ira_loop_tree_root) | |
594 | continue; | |
595 | ira_assert ((ALLOCNO_LOOP_TREE_NODE (a2) != ira_loop_tree_root)); | |
c58db480 | 596 | parent_a1 = ira_parent_or_cap_allocno (a1); |
597 | parent_a2 = ira_parent_or_cap_allocno (a2); | |
47dd2e78 | 598 | ira_assert (parent_a1 != NULL && parent_a2 != NULL); |
be18556f | 599 | if (! allocnos_conflict_for_copy_p (parent_a1, parent_a2)) |
b7c06809 | 600 | ira_add_allocno_copy (parent_a1, parent_a2, cp->freq, |
601 | cp->constraint_p, cp->insn, cp->loop_tree_node); | |
47dd2e78 | 602 | } |
603 | } | |
604 | ||
47dd2e78 | 605 | /* Array used to collect all conflict allocnos for given allocno. */ |
ae9587ed | 606 | static ira_object_t *collected_conflict_objects; |
47dd2e78 | 607 | |
608 | /* Build conflict vectors or bit conflict vectors (whatever is more | |
be18556f | 609 | profitable) for object OBJ from the conflict table. */ |
47dd2e78 | 610 | static void |
be18556f | 611 | build_object_conflicts (ira_object_t obj) |
47dd2e78 | 612 | { |
613 | int i, px, parent_num; | |
ae9587ed | 614 | ira_allocno_t parent_a, another_parent_a; |
be18556f | 615 | ira_object_t parent_obj; |
616 | ira_allocno_t a = OBJECT_ALLOCNO (obj); | |
617 | IRA_INT_TYPE *object_conflicts; | |
01eb3997 | 618 | minmax_set_iterator asi; |
71a39acf | 619 | int parent_min, parent_max ATTRIBUTE_UNUSED; |
47dd2e78 | 620 | |
be18556f | 621 | object_conflicts = conflicts[OBJECT_CONFLICT_ID (obj)]; |
47dd2e78 | 622 | px = 0; |
be18556f | 623 | FOR_EACH_BIT_IN_MINMAX_SET (object_conflicts, |
ae9587ed | 624 | OBJECT_MIN (obj), OBJECT_MAX (obj), i, asi) |
47dd2e78 | 625 | { |
ae9587ed | 626 | ira_object_t another_obj = ira_object_id_map[i]; |
627 | ira_allocno_t another_a = OBJECT_ALLOCNO (obj); | |
66d9a7b9 | 628 | |
14792f4e | 629 | ira_assert (ira_reg_classes_intersect_p |
66d9a7b9 | 630 | [ALLOCNO_CLASS (a)][ALLOCNO_CLASS (another_a)]); |
ae9587ed | 631 | collected_conflict_objects[px++] = another_obj; |
47dd2e78 | 632 | } |
ae9587ed | 633 | if (ira_conflict_vector_profitable_p (obj, px)) |
47dd2e78 | 634 | { |
be18556f | 635 | ira_object_t *vec; |
ae9587ed | 636 | ira_allocate_conflict_vec (obj, px); |
637 | vec = OBJECT_CONFLICT_VEC (obj); | |
638 | memcpy (vec, collected_conflict_objects, sizeof (ira_object_t) * px); | |
47dd2e78 | 639 | vec[px] = NULL; |
ae9587ed | 640 | OBJECT_NUM_CONFLICTS (obj) = px; |
47dd2e78 | 641 | } |
642 | else | |
643 | { | |
be18556f | 644 | int conflict_bit_vec_words_num; |
66d9a7b9 | 645 | |
be18556f | 646 | OBJECT_CONFLICT_ARRAY (obj) = object_conflicts; |
ae9587ed | 647 | if (OBJECT_MAX (obj) < OBJECT_MIN (obj)) |
47dd2e78 | 648 | conflict_bit_vec_words_num = 0; |
649 | else | |
650 | conflict_bit_vec_words_num | |
ae9587ed | 651 | = ((OBJECT_MAX (obj) - OBJECT_MIN (obj) + IRA_INT_BITS) |
47dd2e78 | 652 | / IRA_INT_BITS); |
ae9587ed | 653 | OBJECT_CONFLICT_ARRAY_SIZE (obj) |
47dd2e78 | 654 | = conflict_bit_vec_words_num * sizeof (IRA_INT_TYPE); |
655 | } | |
be18556f | 656 | |
c58db480 | 657 | parent_a = ira_parent_or_cap_allocno (a); |
658 | if (parent_a == NULL) | |
47dd2e78 | 659 | return; |
66d9a7b9 | 660 | ira_assert (ALLOCNO_CLASS (a) == ALLOCNO_CLASS (parent_a)); |
be18556f | 661 | ira_assert (ALLOCNO_NUM_OBJECTS (a) == ALLOCNO_NUM_OBJECTS (parent_a)); |
662 | parent_obj = ALLOCNO_OBJECT (parent_a, OBJECT_SUBWORD (obj)); | |
ae9587ed | 663 | parent_num = OBJECT_CONFLICT_ID (parent_obj); |
66d9a7b9 | 664 | parent_min = OBJECT_MIN (parent_obj); |
665 | parent_max = OBJECT_MAX (parent_obj); | |
be18556f | 666 | FOR_EACH_BIT_IN_MINMAX_SET (object_conflicts, |
ae9587ed | 667 | OBJECT_MIN (obj), OBJECT_MAX (obj), i, asi) |
47dd2e78 | 668 | { |
ae9587ed | 669 | ira_object_t another_obj = ira_object_id_map[i]; |
670 | ira_allocno_t another_a = OBJECT_ALLOCNO (another_obj); | |
be18556f | 671 | int another_word = OBJECT_SUBWORD (another_obj); |
ae9587ed | 672 | |
14792f4e | 673 | ira_assert (ira_reg_classes_intersect_p |
66d9a7b9 | 674 | [ALLOCNO_CLASS (a)][ALLOCNO_CLASS (another_a)]); |
be18556f | 675 | |
c58db480 | 676 | another_parent_a = ira_parent_or_cap_allocno (another_a); |
677 | if (another_parent_a == NULL) | |
47dd2e78 | 678 | continue; |
679 | ira_assert (ALLOCNO_NUM (another_parent_a) >= 0); | |
66d9a7b9 | 680 | ira_assert (ALLOCNO_CLASS (another_a) |
681 | == ALLOCNO_CLASS (another_parent_a)); | |
be18556f | 682 | ira_assert (ALLOCNO_NUM_OBJECTS (another_a) |
683 | == ALLOCNO_NUM_OBJECTS (another_parent_a)); | |
01eb3997 | 684 | SET_MINMAX_SET_BIT (conflicts[parent_num], |
be18556f | 685 | OBJECT_CONFLICT_ID (ALLOCNO_OBJECT (another_parent_a, |
66d9a7b9 | 686 | another_word)), |
687 | parent_min, parent_max); | |
47dd2e78 | 688 | } |
689 | } | |
690 | ||
691 | /* Build conflict vectors or bit conflict vectors (whatever is more | |
692 | profitable) of all allocnos from the conflict table. */ | |
693 | static void | |
694 | build_conflicts (void) | |
695 | { | |
696 | int i; | |
697 | ira_allocno_t a, cap; | |
698 | ||
ae9587ed | 699 | collected_conflict_objects |
700 | = (ira_object_t *) ira_allocate (sizeof (ira_object_t) | |
701 | * ira_objects_num); | |
47dd2e78 | 702 | for (i = max_reg_num () - 1; i >= FIRST_PSEUDO_REGISTER; i--) |
703 | for (a = ira_regno_allocno_map[i]; | |
704 | a != NULL; | |
705 | a = ALLOCNO_NEXT_REGNO_ALLOCNO (a)) | |
706 | { | |
be18556f | 707 | int j, nregs = ALLOCNO_NUM_OBJECTS (a); |
708 | for (j = 0; j < nregs; j++) | |
709 | { | |
710 | ira_object_t obj = ALLOCNO_OBJECT (a, j); | |
711 | build_object_conflicts (obj); | |
712 | for (cap = ALLOCNO_CAP (a); cap != NULL; cap = ALLOCNO_CAP (cap)) | |
713 | { | |
714 | ira_object_t cap_obj = ALLOCNO_OBJECT (cap, j); | |
715 | gcc_assert (ALLOCNO_NUM_OBJECTS (cap) == ALLOCNO_NUM_OBJECTS (a)); | |
716 | build_object_conflicts (cap_obj); | |
717 | } | |
718 | } | |
47dd2e78 | 719 | } |
ae9587ed | 720 | ira_free (collected_conflict_objects); |
47dd2e78 | 721 | } |
722 | ||
723 | \f | |
724 | ||
725 | /* Print hard reg set SET with TITLE to FILE. */ | |
726 | static void | |
727 | print_hard_reg_set (FILE *file, const char *title, HARD_REG_SET set) | |
728 | { | |
729 | int i, start; | |
730 | ||
609e7ca1 | 731 | fputs (title, file); |
47dd2e78 | 732 | for (start = -1, i = 0; i < FIRST_PSEUDO_REGISTER; i++) |
733 | { | |
734 | if (TEST_HARD_REG_BIT (set, i)) | |
735 | { | |
736 | if (i == 0 || ! TEST_HARD_REG_BIT (set, i - 1)) | |
737 | start = i; | |
738 | } | |
739 | if (start >= 0 | |
740 | && (i == FIRST_PSEUDO_REGISTER - 1 || ! TEST_HARD_REG_BIT (set, i))) | |
741 | { | |
742 | if (start == i - 1) | |
743 | fprintf (file, " %d", start); | |
744 | else if (start == i - 2) | |
745 | fprintf (file, " %d %d", start, start + 1); | |
746 | else | |
747 | fprintf (file, " %d-%d", start, i - 1); | |
748 | start = -1; | |
749 | } | |
750 | } | |
609e7ca1 | 751 | putc ('\n', file); |
47dd2e78 | 752 | } |
753 | ||
47dd2e78 | 754 | static void |
c32f7a5a | 755 | print_allocno_conflicts (FILE * file, bool reg_p, ira_allocno_t a) |
47dd2e78 | 756 | { |
47dd2e78 | 757 | HARD_REG_SET conflicting_hard_regs; |
c32f7a5a | 758 | basic_block bb; |
be18556f | 759 | int n, i; |
47dd2e78 | 760 | |
c32f7a5a | 761 | if (reg_p) |
762 | fprintf (file, ";; r%d", ALLOCNO_REGNO (a)); | |
763 | else | |
47dd2e78 | 764 | { |
c32f7a5a | 765 | fprintf (file, ";; a%d(r%d,", ALLOCNO_NUM (a), ALLOCNO_REGNO (a)); |
766 | if ((bb = ALLOCNO_LOOP_TREE_NODE (a)->bb) != NULL) | |
767 | fprintf (file, "b%d", bb->index); | |
47dd2e78 | 768 | else |
9f8ac546 | 769 | fprintf (file, "l%d", ALLOCNO_LOOP_TREE_NODE (a)->loop_num); |
c32f7a5a | 770 | putc (')', file); |
771 | } | |
ae9587ed | 772 | |
c32f7a5a | 773 | fputs (" conflicts:", file); |
be18556f | 774 | n = ALLOCNO_NUM_OBJECTS (a); |
775 | for (i = 0; i < n; i++) | |
776 | { | |
777 | ira_object_t obj = ALLOCNO_OBJECT (a, i); | |
778 | ira_object_t conflict_obj; | |
779 | ira_object_conflict_iterator oci; | |
780 | ||
781 | if (OBJECT_CONFLICT_ARRAY (obj) == NULL) | |
782 | continue; | |
783 | if (n > 1) | |
784 | fprintf (file, "\n;; subobject %d:", i); | |
785 | FOR_EACH_OBJECT_CONFLICT (obj, conflict_obj, oci) | |
786 | { | |
787 | ira_allocno_t conflict_a = OBJECT_ALLOCNO (conflict_obj); | |
788 | if (reg_p) | |
789 | fprintf (file, " r%d,", ALLOCNO_REGNO (conflict_a)); | |
790 | else | |
791 | { | |
792 | fprintf (file, " a%d(r%d", ALLOCNO_NUM (conflict_a), | |
793 | ALLOCNO_REGNO (conflict_a)); | |
794 | if (ALLOCNO_NUM_OBJECTS (conflict_a) > 1) | |
795 | fprintf (file, ",w%d", OBJECT_SUBWORD (conflict_obj)); | |
796 | if ((bb = ALLOCNO_LOOP_TREE_NODE (conflict_a)->bb) != NULL) | |
797 | fprintf (file, ",b%d", bb->index); | |
798 | else | |
799 | fprintf (file, ",l%d", | |
9f8ac546 | 800 | ALLOCNO_LOOP_TREE_NODE (conflict_a)->loop_num); |
be18556f | 801 | putc (')', file); |
802 | } | |
803 | } | |
804 | COPY_HARD_REG_SET (conflicting_hard_regs, OBJECT_TOTAL_CONFLICT_HARD_REGS (obj)); | |
805 | AND_COMPL_HARD_REG_SET (conflicting_hard_regs, ira_no_alloc_regs); | |
806 | AND_HARD_REG_SET (conflicting_hard_regs, | |
66d9a7b9 | 807 | reg_class_contents[ALLOCNO_CLASS (a)]); |
be18556f | 808 | print_hard_reg_set (file, "\n;; total conflict hard regs:", |
809 | conflicting_hard_regs); | |
810 | ||
811 | COPY_HARD_REG_SET (conflicting_hard_regs, OBJECT_CONFLICT_HARD_REGS (obj)); | |
812 | AND_COMPL_HARD_REG_SET (conflicting_hard_regs, ira_no_alloc_regs); | |
813 | AND_HARD_REG_SET (conflicting_hard_regs, | |
66d9a7b9 | 814 | reg_class_contents[ALLOCNO_CLASS (a)]); |
be18556f | 815 | print_hard_reg_set (file, ";; conflict hard regs:", |
816 | conflicting_hard_regs); | |
817 | putc ('\n', file); | |
818 | } | |
ae9587ed | 819 | |
47dd2e78 | 820 | } |
821 | ||
c32f7a5a | 822 | /* Print information about allocno or only regno (if REG_P) conflicts |
823 | to FILE. */ | |
824 | static void | |
825 | print_conflicts (FILE *file, bool reg_p) | |
826 | { | |
827 | ira_allocno_t a; | |
828 | ira_allocno_iterator ai; | |
829 | ||
830 | FOR_EACH_ALLOCNO (a, ai) | |
831 | print_allocno_conflicts (file, reg_p, a); | |
832 | } | |
833 | ||
47dd2e78 | 834 | /* Print information about allocno or only regno (if REG_P) conflicts |
835 | to stderr. */ | |
836 | void | |
837 | ira_debug_conflicts (bool reg_p) | |
838 | { | |
839 | print_conflicts (stderr, reg_p); | |
840 | } | |
841 | ||
842 | \f | |
843 | ||
844 | /* Entry function which builds allocno conflicts and allocno copies | |
845 | and accumulate some allocno info on upper level regions. */ | |
846 | void | |
847 | ira_build_conflicts (void) | |
848 | { | |
f8a8fc7b | 849 | enum reg_class base; |
47dd2e78 | 850 | ira_allocno_t a; |
851 | ira_allocno_iterator ai; | |
14792f4e | 852 | HARD_REG_SET temp_hard_reg_set; |
47dd2e78 | 853 | |
95c83f01 | 854 | if (ira_conflicts_p) |
47dd2e78 | 855 | { |
95c83f01 | 856 | ira_conflicts_p = build_conflict_bit_table (); |
857 | if (ira_conflicts_p) | |
47dd2e78 | 858 | { |
ae9587ed | 859 | ira_object_t obj; |
860 | ira_object_iterator oi; | |
861 | ||
95c83f01 | 862 | build_conflicts (); |
863 | ira_traverse_loop_tree (true, ira_loop_tree_root, NULL, add_copies); | |
864 | /* We need finished conflict table for the subsequent call. */ | |
865 | if (flag_ira_region == IRA_REGION_ALL | |
866 | || flag_ira_region == IRA_REGION_MIXED) | |
867 | propagate_copies (); | |
ae9587ed | 868 | |
95c83f01 | 869 | /* Now we can free memory for the conflict table (see function |
be18556f | 870 | build_object_conflicts for details). */ |
ae9587ed | 871 | FOR_EACH_OBJECT (obj, oi) |
95c83f01 | 872 | { |
ae9587ed | 873 | if (OBJECT_CONFLICT_ARRAY (obj) != conflicts[OBJECT_CONFLICT_ID (obj)]) |
874 | ira_free (conflicts[OBJECT_CONFLICT_ID (obj)]); | |
95c83f01 | 875 | } |
876 | ira_free (conflicts); | |
47dd2e78 | 877 | } |
47dd2e78 | 878 | } |
f8a8fc7b | 879 | base = base_reg_class (VOIDmode, ADDR_SPACE_GENERIC, ADDRESS, SCRATCH); |
880 | if (! targetm.class_likely_spilled_p (base)) | |
14792f4e | 881 | CLEAR_HARD_REG_SET (temp_hard_reg_set); |
882 | else | |
883 | { | |
f8a8fc7b | 884 | COPY_HARD_REG_SET (temp_hard_reg_set, reg_class_contents[base]); |
14792f4e | 885 | AND_COMPL_HARD_REG_SET (temp_hard_reg_set, ira_no_alloc_regs); |
886 | AND_HARD_REG_SET (temp_hard_reg_set, call_used_reg_set); | |
887 | } | |
47dd2e78 | 888 | FOR_EACH_ALLOCNO (a, ai) |
889 | { | |
be18556f | 890 | int i, n = ALLOCNO_NUM_OBJECTS (a); |
66d9a7b9 | 891 | |
be18556f | 892 | for (i = 0; i < n; i++) |
47dd2e78 | 893 | { |
be18556f | 894 | ira_object_t obj = ALLOCNO_OBJECT (a, i); |
62f13add | 895 | rtx allocno_reg = regno_reg_rtx [ALLOCNO_REGNO (a)]; |
be18556f | 896 | |
897 | if ((! flag_caller_saves && ALLOCNO_CALLS_CROSSED_NUM (a) != 0) | |
898 | /* For debugging purposes don't put user defined variables in | |
899 | callee-clobbered registers. */ | |
62f13add | 900 | || (optimize == 0 && REG_USERVAR_P (allocno_reg))) |
be18556f | 901 | { |
902 | IOR_HARD_REG_SET (OBJECT_TOTAL_CONFLICT_HARD_REGS (obj), | |
903 | call_used_reg_set); | |
904 | IOR_HARD_REG_SET (OBJECT_CONFLICT_HARD_REGS (obj), | |
905 | call_used_reg_set); | |
906 | } | |
907 | else if (ALLOCNO_CALLS_CROSSED_NUM (a) != 0) | |
908 | { | |
909 | IOR_HARD_REG_SET (OBJECT_TOTAL_CONFLICT_HARD_REGS (obj), | |
910 | no_caller_save_reg_set); | |
911 | IOR_HARD_REG_SET (OBJECT_TOTAL_CONFLICT_HARD_REGS (obj), | |
912 | temp_hard_reg_set); | |
913 | IOR_HARD_REG_SET (OBJECT_CONFLICT_HARD_REGS (obj), | |
914 | no_caller_save_reg_set); | |
915 | IOR_HARD_REG_SET (OBJECT_CONFLICT_HARD_REGS (obj), | |
916 | temp_hard_reg_set); | |
917 | } | |
6b71fb7f | 918 | |
919 | if (ALLOCNO_CALLS_CROSSED_NUM (a) != 0) | |
920 | { | |
921 | int regno; | |
922 | ||
923 | /* Allocnos bigger than the saved part of call saved | |
924 | regs must conflict with them. */ | |
925 | for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++) | |
926 | if (!TEST_HARD_REG_BIT (call_used_reg_set, regno) | |
927 | && HARD_REGNO_CALL_PART_CLOBBERED (regno, | |
928 | obj->allocno->mode)) | |
929 | { | |
930 | SET_HARD_REG_BIT (OBJECT_CONFLICT_HARD_REGS (obj), regno); | |
931 | SET_HARD_REG_BIT (OBJECT_TOTAL_CONFLICT_HARD_REGS (obj), | |
932 | regno); | |
933 | } | |
934 | } | |
47dd2e78 | 935 | } |
936 | } | |
95c83f01 | 937 | if (optimize && ira_conflicts_p |
938 | && internal_flag_ira_verbose > 2 && ira_dump_file != NULL) | |
47dd2e78 | 939 | print_conflicts (ira_dump_file, false); |
940 | } |