]>
Commit | Line | Data |
---|---|---|
47dd2e78 | 1 | /* IRA processing allocno lives to build allocno live ranges. |
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" | |
cab55469 | 31 | #include "except.h" |
47dd2e78 | 32 | #include "hard-reg-set.h" |
33 | #include "basic-block.h" | |
34 | #include "insn-config.h" | |
35 | #include "recog.h" | |
0b205f4c | 36 | #include "diagnostic-core.h" |
47dd2e78 | 37 | #include "params.h" |
38 | #include "df.h" | |
82cc92bf | 39 | #include "sbitmap.h" |
47dd2e78 | 40 | #include "sparseset.h" |
41 | #include "ira-int.h" | |
42 | ||
43 | /* The code in this file is similar to one in global but the code | |
44 | works on the allocno basis and creates live ranges instead of | |
45 | pseudo-register conflicts. */ | |
46 | ||
47 | /* Program points are enumerated by numbers from range | |
48 | 0..IRA_MAX_POINT-1. There are approximately two times more program | |
49 | points than insns. Program points are places in the program where | |
50 | liveness info can be changed. In most general case (there are more | |
51 | complicated cases too) some program points correspond to places | |
52 | where input operand dies and other ones correspond to places where | |
53 | output operands are born. */ | |
54 | int ira_max_point; | |
55 | ||
56 | /* Arrays of size IRA_MAX_POINT mapping a program point to the allocno | |
57 | live ranges with given start/finish point. */ | |
fbff82f4 | 58 | live_range_t *ira_start_point_ranges, *ira_finish_point_ranges; |
47dd2e78 | 59 | |
60 | /* Number of the current program point. */ | |
61 | static int curr_point; | |
62 | ||
63 | /* Point where register pressure excess started or -1 if there is no | |
64 | register pressure excess. Excess pressure for a register class at | |
65 | some point means that there are more allocnos of given register | |
66 | class living at the point than number of hard-registers of the | |
67 | class available for the allocation. It is defined only for cover | |
68 | classes. */ | |
69 | static int high_pressure_start_point[N_REG_CLASSES]; | |
70 | ||
be18556f | 71 | /* Objects live at current point in the scan. */ |
72 | static sparseset objects_live; | |
73 | ||
74 | /* A temporary bitmap used in functions that wish to avoid visiting an allocno | |
75 | multiple times. */ | |
76 | static sparseset allocnos_processed; | |
47dd2e78 | 77 | |
78 | /* Set of hard regs (except eliminable ones) currently live. */ | |
79 | static HARD_REG_SET hard_regs_live; | |
80 | ||
81 | /* The loop tree node corresponding to the current basic block. */ | |
82 | static ira_loop_tree_node_t curr_bb_node; | |
83 | ||
df07a54c | 84 | /* The number of the last processed call. */ |
85 | static int last_call_num; | |
86 | /* The number of last call at which given allocno was saved. */ | |
87 | static int *allocno_saved_at_call; | |
88 | ||
be18556f | 89 | /* Record the birth of hard register REGNO, updating hard_regs_live and |
90 | hard reg conflict information for living allocnos. */ | |
47dd2e78 | 91 | static void |
b4f5e198 | 92 | make_hard_regno_born (int regno) |
47dd2e78 | 93 | { |
94 | unsigned int i; | |
47dd2e78 | 95 | |
b4f5e198 | 96 | SET_HARD_REG_BIT (hard_regs_live, regno); |
be18556f | 97 | EXECUTE_IF_SET_IN_SPARSESET (objects_live, i) |
47dd2e78 | 98 | { |
be18556f | 99 | ira_object_t obj = ira_object_id_map[i]; |
ae9587ed | 100 | SET_HARD_REG_BIT (OBJECT_CONFLICT_HARD_REGS (obj), regno); |
101 | SET_HARD_REG_BIT (OBJECT_TOTAL_CONFLICT_HARD_REGS (obj), regno); | |
47dd2e78 | 102 | } |
b4f5e198 | 103 | } |
104 | ||
105 | /* Process the death of hard register REGNO. This updates | |
106 | hard_regs_live. */ | |
107 | static void | |
108 | make_hard_regno_dead (int regno) | |
109 | { | |
110 | CLEAR_HARD_REG_BIT (hard_regs_live, regno); | |
111 | } | |
112 | ||
be18556f | 113 | /* Record the birth of object OBJ. Set a bit for it in objects_live, |
114 | start a new live range for it if necessary and update hard register | |
115 | conflicts. */ | |
b4f5e198 | 116 | static void |
be18556f | 117 | make_object_born (ira_object_t obj) |
b4f5e198 | 118 | { |
be18556f | 119 | live_range_t lr = OBJECT_LIVE_RANGES (obj); |
b4f5e198 | 120 | |
be18556f | 121 | sparseset_set_bit (objects_live, OBJECT_CONFLICT_ID (obj)); |
ae9587ed | 122 | IOR_HARD_REG_SET (OBJECT_CONFLICT_HARD_REGS (obj), hard_regs_live); |
123 | IOR_HARD_REG_SET (OBJECT_TOTAL_CONFLICT_HARD_REGS (obj), hard_regs_live); | |
b4f5e198 | 124 | |
be18556f | 125 | if (lr == NULL |
126 | || (lr->finish != curr_point && lr->finish + 1 != curr_point)) | |
127 | ira_add_live_range_to_object (obj, curr_point, -1); | |
47dd2e78 | 128 | } |
129 | ||
be18556f | 130 | /* Update ALLOCNO_EXCESS_PRESSURE_POINTS_NUM for the allocno |
131 | associated with object OBJ. */ | |
47dd2e78 | 132 | static void |
be18556f | 133 | update_allocno_pressure_excess_length (ira_object_t obj) |
47dd2e78 | 134 | { |
be18556f | 135 | ira_allocno_t a = OBJECT_ALLOCNO (obj); |
14792f4e | 136 | int start, i; |
137 | enum reg_class cover_class, cl; | |
fbff82f4 | 138 | live_range_t p; |
47dd2e78 | 139 | |
140 | cover_class = ALLOCNO_COVER_CLASS (a); | |
14792f4e | 141 | for (i = 0; |
142 | (cl = ira_reg_class_super_classes[cover_class][i]) != LIM_REG_CLASSES; | |
143 | i++) | |
144 | { | |
145 | if (high_pressure_start_point[cl] < 0) | |
146 | continue; | |
9d53e372 | 147 | p = OBJECT_LIVE_RANGES (obj); |
14792f4e | 148 | ira_assert (p != NULL); |
149 | start = (high_pressure_start_point[cl] > p->start | |
150 | ? high_pressure_start_point[cl] : p->start); | |
151 | ALLOCNO_EXCESS_PRESSURE_POINTS_NUM (a) += curr_point - start + 1; | |
152 | } | |
47dd2e78 | 153 | } |
154 | ||
be18556f | 155 | /* Process the death of object OBJ, which is associated with allocno |
156 | A. This finishes the current live range for it. */ | |
47dd2e78 | 157 | static void |
be18556f | 158 | make_object_dead (ira_object_t obj) |
47dd2e78 | 159 | { |
be18556f | 160 | live_range_t lr; |
47dd2e78 | 161 | |
be18556f | 162 | sparseset_clear_bit (objects_live, OBJECT_CONFLICT_ID (obj)); |
163 | lr = OBJECT_LIVE_RANGES (obj); | |
164 | ira_assert (lr != NULL); | |
165 | lr->finish = curr_point; | |
166 | update_allocno_pressure_excess_length (obj); | |
47dd2e78 | 167 | } |
168 | ||
47dd2e78 | 169 | /* The current register pressures for each cover class for the current |
170 | basic block. */ | |
171 | static int curr_reg_pressure[N_REG_CLASSES]; | |
172 | ||
b4f5e198 | 173 | /* Record that register pressure for COVER_CLASS increased by N |
174 | registers. Update the current register pressure, maximal register | |
175 | pressure for the current BB and the start point of the register | |
176 | pressure excess. */ | |
47dd2e78 | 177 | static void |
b4f5e198 | 178 | inc_register_pressure (enum reg_class cover_class, int n) |
47dd2e78 | 179 | { |
14792f4e | 180 | int i; |
b4f5e198 | 181 | enum reg_class cl; |
47dd2e78 | 182 | |
14792f4e | 183 | for (i = 0; |
184 | (cl = ira_reg_class_super_classes[cover_class][i]) != LIM_REG_CLASSES; | |
185 | i++) | |
186 | { | |
b4f5e198 | 187 | curr_reg_pressure[cl] += n; |
14792f4e | 188 | if (high_pressure_start_point[cl] < 0 |
189 | && (curr_reg_pressure[cl] > ira_available_class_regs[cl])) | |
190 | high_pressure_start_point[cl] = curr_point; | |
191 | if (curr_bb_node->reg_pressure[cl] < curr_reg_pressure[cl]) | |
192 | curr_bb_node->reg_pressure[cl] = curr_reg_pressure[cl]; | |
193 | } | |
47dd2e78 | 194 | } |
195 | ||
b4f5e198 | 196 | /* Record that register pressure for COVER_CLASS has decreased by |
197 | NREGS registers; update current register pressure, start point of | |
198 | the register pressure excess, and register pressure excess length | |
199 | for living allocnos. */ | |
200 | ||
47dd2e78 | 201 | static void |
b4f5e198 | 202 | dec_register_pressure (enum reg_class cover_class, int nregs) |
47dd2e78 | 203 | { |
14792f4e | 204 | int i; |
205 | unsigned int j; | |
b4f5e198 | 206 | enum reg_class cl; |
207 | bool set_p = false; | |
47dd2e78 | 208 | |
b4f5e198 | 209 | for (i = 0; |
210 | (cl = ira_reg_class_super_classes[cover_class][i]) != LIM_REG_CLASSES; | |
211 | i++) | |
47dd2e78 | 212 | { |
b4f5e198 | 213 | curr_reg_pressure[cl] -= nregs; |
214 | ira_assert (curr_reg_pressure[cl] >= 0); | |
215 | if (high_pressure_start_point[cl] >= 0 | |
216 | && curr_reg_pressure[cl] <= ira_available_class_regs[cl]) | |
217 | set_p = true; | |
218 | } | |
219 | if (set_p) | |
220 | { | |
be18556f | 221 | EXECUTE_IF_SET_IN_SPARSESET (objects_live, j) |
222 | update_allocno_pressure_excess_length (ira_object_id_map[j]); | |
14792f4e | 223 | for (i = 0; |
224 | (cl = ira_reg_class_super_classes[cover_class][i]) | |
225 | != LIM_REG_CLASSES; | |
226 | i++) | |
b4f5e198 | 227 | if (high_pressure_start_point[cl] >= 0 |
228 | && curr_reg_pressure[cl] <= ira_available_class_regs[cl]) | |
229 | high_pressure_start_point[cl] = -1; | |
47dd2e78 | 230 | } |
47dd2e78 | 231 | } |
232 | ||
b4f5e198 | 233 | /* Mark the pseudo register REGNO as live. Update all information about |
234 | live ranges and register pressure. */ | |
47dd2e78 | 235 | static void |
b4f5e198 | 236 | mark_pseudo_regno_live (int regno) |
47dd2e78 | 237 | { |
b4f5e198 | 238 | ira_allocno_t a = ira_curr_regno_allocno_map[regno]; |
be18556f | 239 | int i, n, nregs; |
b4f5e198 | 240 | enum reg_class cl; |
47dd2e78 | 241 | |
b4f5e198 | 242 | if (a == NULL) |
243 | return; | |
47dd2e78 | 244 | |
b4f5e198 | 245 | /* Invalidate because it is referenced. */ |
246 | allocno_saved_at_call[ALLOCNO_NUM (a)] = 0; | |
47dd2e78 | 247 | |
be18556f | 248 | n = ALLOCNO_NUM_OBJECTS (a); |
249 | cl = ALLOCNO_COVER_CLASS (a); | |
250 | nregs = ira_reg_class_nregs[cl][ALLOCNO_MODE (a)]; | |
251 | if (n > 1) | |
252 | { | |
253 | /* We track every subobject separately. */ | |
254 | gcc_assert (nregs == n); | |
255 | nregs = 1; | |
256 | } | |
257 | ||
258 | for (i = 0; i < n; i++) | |
259 | { | |
260 | ira_object_t obj = ALLOCNO_OBJECT (a, i); | |
261 | if (sparseset_bit_p (objects_live, OBJECT_CONFLICT_ID (obj))) | |
262 | continue; | |
263 | ||
264 | inc_register_pressure (cl, nregs); | |
265 | make_object_born (obj); | |
266 | } | |
267 | } | |
268 | ||
269 | /* Like mark_pseudo_regno_live, but try to only mark one subword of | |
270 | the pseudo as live. SUBWORD indicates which; a value of 0 | |
271 | indicates the low part. */ | |
272 | static void | |
273 | mark_pseudo_regno_subword_live (int regno, int subword) | |
274 | { | |
275 | ira_allocno_t a = ira_curr_regno_allocno_map[regno]; | |
276 | int n, nregs; | |
277 | enum reg_class cl; | |
278 | ira_object_t obj; | |
279 | ||
280 | if (a == NULL) | |
b4f5e198 | 281 | return; |
282 | ||
be18556f | 283 | /* Invalidate because it is referenced. */ |
284 | allocno_saved_at_call[ALLOCNO_NUM (a)] = 0; | |
285 | ||
286 | n = ALLOCNO_NUM_OBJECTS (a); | |
287 | if (n == 1) | |
288 | { | |
289 | mark_pseudo_regno_live (regno); | |
290 | return; | |
291 | } | |
292 | ||
b4f5e198 | 293 | cl = ALLOCNO_COVER_CLASS (a); |
294 | nregs = ira_reg_class_nregs[cl][ALLOCNO_MODE (a)]; | |
be18556f | 295 | gcc_assert (nregs == n); |
296 | obj = ALLOCNO_OBJECT (a, subword); | |
297 | ||
298 | if (sparseset_bit_p (objects_live, OBJECT_CONFLICT_ID (obj))) | |
299 | return; | |
300 | ||
b4f5e198 | 301 | inc_register_pressure (cl, nregs); |
be18556f | 302 | make_object_born (obj); |
b4f5e198 | 303 | } |
304 | ||
be18556f | 305 | /* Mark the register REG as live. Store a 1 in hard_regs_live for |
306 | this register, record how many consecutive hardware registers it | |
307 | actually needs. */ | |
b4f5e198 | 308 | static void |
309 | mark_hard_reg_live (rtx reg) | |
310 | { | |
311 | int regno = REGNO (reg); | |
312 | ||
313 | if (! TEST_HARD_REG_BIT (ira_no_alloc_regs, regno)) | |
47dd2e78 | 314 | { |
315 | int last = regno + hard_regno_nregs[regno][GET_MODE (reg)]; | |
47dd2e78 | 316 | |
317 | while (regno < last) | |
318 | { | |
319 | if (! TEST_HARD_REG_BIT (hard_regs_live, regno) | |
320 | && ! TEST_HARD_REG_BIT (eliminable_regset, regno)) | |
321 | { | |
b4f5e198 | 322 | enum reg_class cover_class = ira_hard_regno_cover_class[regno]; |
323 | inc_register_pressure (cover_class, 1); | |
324 | make_hard_regno_born (regno); | |
47dd2e78 | 325 | } |
326 | regno++; | |
327 | } | |
328 | } | |
329 | } | |
330 | ||
044621b2 | 331 | /* Mark a pseudo, or one of its subwords, as live. REGNO is the pseudo's |
332 | register number; ORIG_REG is the access in the insn, which may be a | |
333 | subreg. */ | |
334 | static void | |
335 | mark_pseudo_reg_live (rtx orig_reg, unsigned regno) | |
336 | { | |
337 | if (df_read_modify_subreg_p (orig_reg)) | |
338 | { | |
339 | mark_pseudo_regno_subword_live (regno, | |
340 | subreg_lowpart_p (orig_reg) ? 0 : 1); | |
341 | } | |
342 | else | |
343 | mark_pseudo_regno_live (regno); | |
344 | } | |
345 | ||
793e7497 | 346 | /* Mark the register referenced by use or def REF as live. */ |
347 | static void | |
ed6e85ae | 348 | mark_ref_live (df_ref ref) |
47dd2e78 | 349 | { |
be18556f | 350 | rtx reg = DF_REF_REG (ref); |
351 | rtx orig_reg = reg; | |
793e7497 | 352 | |
793e7497 | 353 | if (GET_CODE (reg) == SUBREG) |
354 | reg = SUBREG_REG (reg); | |
be18556f | 355 | |
b4f5e198 | 356 | if (REGNO (reg) >= FIRST_PSEUDO_REGISTER) |
044621b2 | 357 | mark_pseudo_reg_live (orig_reg, REGNO (reg)); |
b4f5e198 | 358 | else |
359 | mark_hard_reg_live (reg); | |
47dd2e78 | 360 | } |
361 | ||
b4f5e198 | 362 | /* Mark the pseudo register REGNO as dead. Update all information about |
363 | live ranges and register pressure. */ | |
47dd2e78 | 364 | static void |
b4f5e198 | 365 | mark_pseudo_regno_dead (int regno) |
47dd2e78 | 366 | { |
b4f5e198 | 367 | ira_allocno_t a = ira_curr_regno_allocno_map[regno]; |
be18556f | 368 | int n, i, nregs; |
b4f5e198 | 369 | enum reg_class cl; |
47dd2e78 | 370 | |
b4f5e198 | 371 | if (a == NULL) |
372 | return; | |
47dd2e78 | 373 | |
b4f5e198 | 374 | /* Invalidate because it is referenced. */ |
375 | allocno_saved_at_call[ALLOCNO_NUM (a)] = 0; | |
47dd2e78 | 376 | |
be18556f | 377 | n = ALLOCNO_NUM_OBJECTS (a); |
378 | cl = ALLOCNO_COVER_CLASS (a); | |
379 | nregs = ira_reg_class_nregs[cl][ALLOCNO_MODE (a)]; | |
380 | if (n > 1) | |
381 | { | |
382 | /* We track every subobject separately. */ | |
383 | gcc_assert (nregs == n); | |
384 | nregs = 1; | |
385 | } | |
386 | for (i = 0; i < n; i++) | |
387 | { | |
388 | ira_object_t obj = ALLOCNO_OBJECT (a, i); | |
389 | if (!sparseset_bit_p (objects_live, OBJECT_CONFLICT_ID (obj))) | |
390 | continue; | |
391 | ||
392 | dec_register_pressure (cl, nregs); | |
393 | make_object_dead (obj); | |
394 | } | |
395 | } | |
396 | ||
397 | /* Like mark_pseudo_regno_dead, but called when we know that only part of the | |
398 | register dies. SUBWORD indicates which; a value of 0 indicates the low part. */ | |
399 | static void | |
400 | mark_pseudo_regno_subword_dead (int regno, int subword) | |
401 | { | |
402 | ira_allocno_t a = ira_curr_regno_allocno_map[regno]; | |
403 | int n, nregs; | |
404 | enum reg_class cl; | |
405 | ira_object_t obj; | |
406 | ||
407 | if (a == NULL) | |
408 | return; | |
409 | ||
410 | /* Invalidate because it is referenced. */ | |
411 | allocno_saved_at_call[ALLOCNO_NUM (a)] = 0; | |
412 | ||
413 | n = ALLOCNO_NUM_OBJECTS (a); | |
414 | if (n == 1) | |
415 | /* The allocno as a whole doesn't die in this case. */ | |
b4f5e198 | 416 | return; |
417 | ||
418 | cl = ALLOCNO_COVER_CLASS (a); | |
419 | nregs = ira_reg_class_nregs[cl][ALLOCNO_MODE (a)]; | |
be18556f | 420 | gcc_assert (nregs == n); |
421 | ||
422 | obj = ALLOCNO_OBJECT (a, subword); | |
423 | if (!sparseset_bit_p (objects_live, OBJECT_CONFLICT_ID (obj))) | |
424 | return; | |
b4f5e198 | 425 | |
be18556f | 426 | dec_register_pressure (cl, 1); |
427 | make_object_dead (obj); | |
b4f5e198 | 428 | } |
429 | ||
be18556f | 430 | /* Mark the hard register REG as dead. Store a 0 in hard_regs_live for the |
431 | register. */ | |
b4f5e198 | 432 | static void |
433 | mark_hard_reg_dead (rtx reg) | |
434 | { | |
435 | int regno = REGNO (reg); | |
436 | ||
437 | if (! TEST_HARD_REG_BIT (ira_no_alloc_regs, regno)) | |
47dd2e78 | 438 | { |
439 | int last = regno + hard_regno_nregs[regno][GET_MODE (reg)]; | |
47dd2e78 | 440 | |
441 | while (regno < last) | |
442 | { | |
443 | if (TEST_HARD_REG_BIT (hard_regs_live, regno)) | |
444 | { | |
b4f5e198 | 445 | enum reg_class cover_class = ira_hard_regno_cover_class[regno]; |
446 | dec_register_pressure (cover_class, 1); | |
447 | make_hard_regno_dead (regno); | |
47dd2e78 | 448 | } |
449 | regno++; | |
450 | } | |
451 | } | |
452 | } | |
453 | ||
044621b2 | 454 | /* Mark a pseudo, or one of its subwords, as dead. REGNO is the pseudo's |
455 | register number; ORIG_REG is the access in the insn, which may be a | |
456 | subreg. */ | |
457 | static void | |
458 | mark_pseudo_reg_dead (rtx orig_reg, unsigned regno) | |
459 | { | |
460 | if (df_read_modify_subreg_p (orig_reg)) | |
461 | { | |
462 | mark_pseudo_regno_subword_dead (regno, | |
463 | subreg_lowpart_p (orig_reg) ? 0 : 1); | |
464 | } | |
465 | else | |
466 | mark_pseudo_regno_dead (regno); | |
467 | } | |
468 | ||
793e7497 | 469 | /* Mark the register referenced by definition DEF as dead, if the |
470 | definition is a total one. */ | |
471 | static void | |
ed6e85ae | 472 | mark_ref_dead (df_ref def) |
793e7497 | 473 | { |
be18556f | 474 | rtx reg = DF_REF_REG (def); |
475 | rtx orig_reg = reg; | |
793e7497 | 476 | |
be18556f | 477 | if (DF_REF_FLAGS_IS_SET (def, DF_REF_CONDITIONAL)) |
793e7497 | 478 | return; |
479 | ||
793e7497 | 480 | if (GET_CODE (reg) == SUBREG) |
481 | reg = SUBREG_REG (reg); | |
be18556f | 482 | |
483 | if (DF_REF_FLAGS_IS_SET (def, DF_REF_PARTIAL) | |
484 | && (GET_CODE (orig_reg) != SUBREG | |
485 | || REGNO (reg) < FIRST_PSEUDO_REGISTER | |
486 | || !df_read_modify_subreg_p (orig_reg))) | |
487 | return; | |
488 | ||
b4f5e198 | 489 | if (REGNO (reg) >= FIRST_PSEUDO_REGISTER) |
044621b2 | 490 | mark_pseudo_reg_dead (orig_reg, REGNO (reg)); |
b4f5e198 | 491 | else |
492 | mark_hard_reg_dead (reg); | |
793e7497 | 493 | } |
494 | ||
044621b2 | 495 | /* If REG is a pseudo or a subreg of it, and the class of its allocno |
496 | intersects CL, make a conflict with pseudo DREG. ORIG_DREG is the | |
497 | rtx actually accessed, it may be indentical to DREG or a subreg of it. | |
498 | Advance the current program point before making the conflict if | |
499 | ADVANCE_P. Return TRUE if we will need to advance the current | |
500 | program point. */ | |
793e7497 | 501 | static bool |
044621b2 | 502 | make_pseudo_conflict (rtx reg, enum reg_class cl, rtx dreg, rtx orig_dreg, |
503 | bool advance_p) | |
793e7497 | 504 | { |
044621b2 | 505 | rtx orig_reg = reg; |
7173d4d0 | 506 | ira_allocno_t a; |
793e7497 | 507 | |
7173d4d0 | 508 | if (GET_CODE (reg) == SUBREG) |
509 | reg = SUBREG_REG (reg); | |
48e1416a | 510 | |
7173d4d0 | 511 | if (! REG_P (reg) || REGNO (reg) < FIRST_PSEUDO_REGISTER) |
512 | return advance_p; | |
48e1416a | 513 | |
7173d4d0 | 514 | a = ira_curr_regno_allocno_map[REGNO (reg)]; |
515 | if (! reg_classes_intersect_p (cl, ALLOCNO_COVER_CLASS (a))) | |
516 | return advance_p; | |
793e7497 | 517 | |
7173d4d0 | 518 | if (advance_p) |
519 | curr_point++; | |
793e7497 | 520 | |
044621b2 | 521 | mark_pseudo_reg_live (orig_reg, REGNO (reg)); |
522 | mark_pseudo_reg_live (orig_dreg, REGNO (dreg)); | |
523 | mark_pseudo_reg_dead (orig_reg, REGNO (reg)); | |
524 | mark_pseudo_reg_dead (orig_dreg, REGNO (dreg)); | |
7173d4d0 | 525 | |
526 | return false; | |
527 | } | |
793e7497 | 528 | |
7173d4d0 | 529 | /* Check and make if necessary conflicts for pseudo DREG of class |
530 | DEF_CL of the current insn with input operand USE of class USE_CL. | |
044621b2 | 531 | ORIG_DREG is the rtx actually accessed, it may be indentical to |
532 | DREG or a subreg of it. Advance the current program point before | |
533 | making the conflict if ADVANCE_P. Return TRUE if we will need to | |
534 | advance the current program point. */ | |
7173d4d0 | 535 | static bool |
044621b2 | 536 | check_and_make_def_use_conflict (rtx dreg, rtx orig_dreg, |
537 | enum reg_class def_cl, int use, | |
538 | enum reg_class use_cl, bool advance_p) | |
7173d4d0 | 539 | { |
540 | if (! reg_classes_intersect_p (def_cl, use_cl)) | |
541 | return advance_p; | |
48e1416a | 542 | |
7173d4d0 | 543 | advance_p = make_pseudo_conflict (recog_data.operand[use], |
044621b2 | 544 | use_cl, dreg, orig_dreg, advance_p); |
545 | ||
7173d4d0 | 546 | /* Reload may end up swapping commutative operands, so you |
547 | have to take both orderings into account. The | |
548 | constraints for the two operands can be completely | |
549 | different. (Indeed, if the constraints for the two | |
550 | operands are the same for all alternatives, there's no | |
551 | point marking them as commutative.) */ | |
e91a9c3f | 552 | if (use < recog_data.n_operands - 1 |
7173d4d0 | 553 | && recog_data.constraints[use][0] == '%') |
554 | advance_p | |
555 | = make_pseudo_conflict (recog_data.operand[use + 1], | |
044621b2 | 556 | use_cl, dreg, orig_dreg, advance_p); |
7173d4d0 | 557 | if (use >= 1 |
558 | && recog_data.constraints[use - 1][0] == '%') | |
559 | advance_p | |
560 | = make_pseudo_conflict (recog_data.operand[use - 1], | |
044621b2 | 561 | use_cl, dreg, orig_dreg, advance_p); |
7173d4d0 | 562 | return advance_p; |
563 | } | |
564 | ||
565 | /* Check and make if necessary conflicts for definition DEF of class | |
566 | DEF_CL of the current insn with input operands. Process only | |
567 | constraints of alternative ALT. */ | |
568 | static void | |
569 | check_and_make_def_conflict (int alt, int def, enum reg_class def_cl) | |
570 | { | |
571 | int use, use_match; | |
572 | ira_allocno_t a; | |
573 | enum reg_class use_cl, acl; | |
574 | bool advance_p; | |
575 | rtx dreg = recog_data.operand[def]; | |
044621b2 | 576 | rtx orig_dreg = dreg; |
48e1416a | 577 | |
7173d4d0 | 578 | if (def_cl == NO_REGS) |
579 | return; | |
48e1416a | 580 | |
7173d4d0 | 581 | if (GET_CODE (dreg) == SUBREG) |
582 | dreg = SUBREG_REG (dreg); | |
48e1416a | 583 | |
7173d4d0 | 584 | if (! REG_P (dreg) || REGNO (dreg) < FIRST_PSEUDO_REGISTER) |
585 | return; | |
48e1416a | 586 | |
7173d4d0 | 587 | a = ira_curr_regno_allocno_map[REGNO (dreg)]; |
588 | acl = ALLOCNO_COVER_CLASS (a); | |
589 | if (! reg_classes_intersect_p (acl, def_cl)) | |
590 | return; | |
48e1416a | 591 | |
7173d4d0 | 592 | advance_p = true; |
48e1416a | 593 | |
7173d4d0 | 594 | for (use = 0; use < recog_data.n_operands; use++) |
595 | { | |
d09294c0 | 596 | int alt1; |
597 | ||
7173d4d0 | 598 | if (use == def || recog_data.operand_type[use] == OP_OUT) |
c2b66149 | 599 | continue; |
48e1416a | 600 | |
7173d4d0 | 601 | if (recog_op_alt[use][alt].anything_ok) |
602 | use_cl = ALL_REGS; | |
793e7497 | 603 | else |
7173d4d0 | 604 | use_cl = recog_op_alt[use][alt].cl; |
48e1416a | 605 | |
d09294c0 | 606 | /* If there's any alternative that allows USE to match DEF, do not |
607 | record a conflict. If that causes us to create an invalid | |
be18556f | 608 | instruction due to the earlyclobber, reload must fix it up. */ |
d09294c0 | 609 | for (alt1 = 0; alt1 < recog_data.n_alternatives; alt1++) |
610 | if (recog_op_alt[use][alt1].matches == def | |
611 | || (use < recog_data.n_operands - 1 | |
612 | && recog_data.constraints[use][0] == '%' | |
613 | && recog_op_alt[use + 1][alt1].matches == def) | |
614 | || (use >= 1 | |
615 | && recog_data.constraints[use - 1][0] == '%' | |
616 | && recog_op_alt[use - 1][alt1].matches == def)) | |
617 | break; | |
618 | ||
619 | if (alt1 < recog_data.n_alternatives) | |
620 | continue; | |
621 | ||
044621b2 | 622 | advance_p = check_and_make_def_use_conflict (dreg, orig_dreg, def_cl, |
623 | use, use_cl, advance_p); | |
48e1416a | 624 | |
7173d4d0 | 625 | if ((use_match = recog_op_alt[use][alt].matches) >= 0) |
626 | { | |
627 | if (use_match == def) | |
c2b66149 | 628 | continue; |
48e1416a | 629 | |
7173d4d0 | 630 | if (recog_op_alt[use_match][alt].anything_ok) |
631 | use_cl = ALL_REGS; | |
632 | else | |
633 | use_cl = recog_op_alt[use_match][alt].cl; | |
044621b2 | 634 | advance_p = check_and_make_def_use_conflict (dreg, orig_dreg, def_cl, |
635 | use, use_cl, advance_p); | |
7173d4d0 | 636 | } |
793e7497 | 637 | } |
7173d4d0 | 638 | } |
639 | ||
640 | /* Make conflicts of early clobber pseudo registers of the current | |
641 | insn with its inputs. Avoid introducing unnecessary conflicts by | |
642 | checking classes of the constraints and pseudos because otherwise | |
643 | significant code degradation is possible for some targets. */ | |
644 | static void | |
645 | make_early_clobber_and_input_conflicts (void) | |
646 | { | |
647 | int alt; | |
648 | int def, def_match; | |
649 | enum reg_class def_cl; | |
650 | ||
651 | for (alt = 0; alt < recog_data.n_alternatives; alt++) | |
652 | for (def = 0; def < recog_data.n_operands; def++) | |
653 | { | |
654 | def_cl = NO_REGS; | |
655 | if (recog_op_alt[def][alt].earlyclobber) | |
656 | { | |
657 | if (recog_op_alt[def][alt].anything_ok) | |
658 | def_cl = ALL_REGS; | |
659 | else | |
660 | def_cl = recog_op_alt[def][alt].cl; | |
661 | check_and_make_def_conflict (alt, def, def_cl); | |
662 | } | |
663 | if ((def_match = recog_op_alt[def][alt].matches) >= 0 | |
664 | && (recog_op_alt[def_match][alt].earlyclobber | |
665 | || recog_op_alt[def][alt].earlyclobber)) | |
666 | { | |
667 | if (recog_op_alt[def_match][alt].anything_ok) | |
668 | def_cl = ALL_REGS; | |
669 | else | |
670 | def_cl = recog_op_alt[def_match][alt].cl; | |
671 | check_and_make_def_conflict (alt, def, def_cl); | |
672 | } | |
673 | } | |
674 | } | |
675 | ||
676 | /* Mark early clobber hard registers of the current INSN as live (if | |
677 | LIVE_P) or dead. Return true if there are such registers. */ | |
678 | static bool | |
679 | mark_hard_reg_early_clobbers (rtx insn, bool live_p) | |
680 | { | |
681 | df_ref *def_rec; | |
682 | bool set_p = false; | |
793e7497 | 683 | |
684 | for (def_rec = DF_INSN_DEFS (insn); *def_rec; def_rec++) | |
685 | if (DF_REF_FLAGS_IS_SET (*def_rec, DF_REF_MUST_CLOBBER)) | |
686 | { | |
687 | rtx dreg = DF_REF_REG (*def_rec); | |
48e1416a | 688 | |
793e7497 | 689 | if (GET_CODE (dreg) == SUBREG) |
690 | dreg = SUBREG_REG (dreg); | |
691 | if (! REG_P (dreg) || REGNO (dreg) >= FIRST_PSEUDO_REGISTER) | |
692 | continue; | |
693 | ||
694 | /* Hard register clobbers are believed to be early clobber | |
695 | because there is no way to say that non-operand hard | |
48e1416a | 696 | register clobbers are not early ones. */ |
793e7497 | 697 | if (live_p) |
698 | mark_ref_live (*def_rec); | |
699 | else | |
700 | mark_ref_dead (*def_rec); | |
701 | set_p = true; | |
702 | } | |
703 | ||
704 | return set_p; | |
705 | } | |
706 | ||
47dd2e78 | 707 | /* Checks that CONSTRAINTS permits to use only one hard register. If |
708 | it is so, the function returns the class of the hard register. | |
709 | Otherwise it returns NO_REGS. */ | |
710 | static enum reg_class | |
711 | single_reg_class (const char *constraints, rtx op, rtx equiv_const) | |
712 | { | |
713 | int ignore_p; | |
714 | enum reg_class cl, next_cl; | |
715 | int c; | |
716 | ||
717 | cl = NO_REGS; | |
718 | for (ignore_p = false; | |
719 | (c = *constraints); | |
720 | constraints += CONSTRAINT_LEN (c, constraints)) | |
721 | if (c == '#') | |
722 | ignore_p = true; | |
723 | else if (c == ',') | |
724 | ignore_p = false; | |
725 | else if (! ignore_p) | |
726 | switch (c) | |
727 | { | |
728 | case ' ': | |
729 | case '\t': | |
730 | case '=': | |
731 | case '+': | |
732 | case '*': | |
733 | case '&': | |
734 | case '%': | |
735 | case '!': | |
736 | case '?': | |
737 | break; | |
738 | case 'i': | |
739 | if (CONSTANT_P (op) | |
740 | || (equiv_const != NULL_RTX && CONSTANT_P (equiv_const))) | |
741 | return NO_REGS; | |
742 | break; | |
743 | ||
744 | case 'n': | |
971ba038 | 745 | if (CONST_INT_P (op) |
47dd2e78 | 746 | || (GET_CODE (op) == CONST_DOUBLE && GET_MODE (op) == VOIDmode) |
747 | || (equiv_const != NULL_RTX | |
971ba038 | 748 | && (CONST_INT_P (equiv_const) |
47dd2e78 | 749 | || (GET_CODE (equiv_const) == CONST_DOUBLE |
750 | && GET_MODE (equiv_const) == VOIDmode)))) | |
751 | return NO_REGS; | |
752 | break; | |
48e1416a | 753 | |
47dd2e78 | 754 | case 's': |
971ba038 | 755 | if ((CONSTANT_P (op) && !CONST_INT_P (op) |
47dd2e78 | 756 | && (GET_CODE (op) != CONST_DOUBLE || GET_MODE (op) != VOIDmode)) |
757 | || (equiv_const != NULL_RTX | |
758 | && CONSTANT_P (equiv_const) | |
971ba038 | 759 | && !CONST_INT_P (equiv_const) |
47dd2e78 | 760 | && (GET_CODE (equiv_const) != CONST_DOUBLE |
761 | || GET_MODE (equiv_const) != VOIDmode))) | |
762 | return NO_REGS; | |
763 | break; | |
48e1416a | 764 | |
47dd2e78 | 765 | case 'I': |
766 | case 'J': | |
767 | case 'K': | |
768 | case 'L': | |
769 | case 'M': | |
770 | case 'N': | |
771 | case 'O': | |
772 | case 'P': | |
971ba038 | 773 | if ((CONST_INT_P (op) |
47dd2e78 | 774 | && CONST_OK_FOR_CONSTRAINT_P (INTVAL (op), c, constraints)) |
775 | || (equiv_const != NULL_RTX | |
971ba038 | 776 | && CONST_INT_P (equiv_const) |
47dd2e78 | 777 | && CONST_OK_FOR_CONSTRAINT_P (INTVAL (equiv_const), |
778 | c, constraints))) | |
779 | return NO_REGS; | |
780 | break; | |
48e1416a | 781 | |
47dd2e78 | 782 | case 'E': |
783 | case 'F': | |
784 | if (GET_CODE (op) == CONST_DOUBLE | |
785 | || (GET_CODE (op) == CONST_VECTOR | |
786 | && GET_MODE_CLASS (GET_MODE (op)) == MODE_VECTOR_FLOAT) | |
787 | || (equiv_const != NULL_RTX | |
788 | && (GET_CODE (equiv_const) == CONST_DOUBLE | |
789 | || (GET_CODE (equiv_const) == CONST_VECTOR | |
790 | && (GET_MODE_CLASS (GET_MODE (equiv_const)) | |
791 | == MODE_VECTOR_FLOAT))))) | |
792 | return NO_REGS; | |
793 | break; | |
48e1416a | 794 | |
47dd2e78 | 795 | case 'G': |
796 | case 'H': | |
797 | if ((GET_CODE (op) == CONST_DOUBLE | |
798 | && CONST_DOUBLE_OK_FOR_CONSTRAINT_P (op, c, constraints)) | |
799 | || (equiv_const != NULL_RTX | |
800 | && GET_CODE (equiv_const) == CONST_DOUBLE | |
801 | && CONST_DOUBLE_OK_FOR_CONSTRAINT_P (equiv_const, | |
802 | c, constraints))) | |
803 | return NO_REGS; | |
804 | /* ??? what about memory */ | |
805 | case 'r': | |
806 | case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': | |
807 | case 'h': case 'j': case 'k': case 'l': | |
808 | case 'q': case 't': case 'u': | |
809 | case 'v': case 'w': case 'x': case 'y': case 'z': | |
810 | case 'A': case 'B': case 'C': case 'D': | |
811 | case 'Q': case 'R': case 'S': case 'T': case 'U': | |
812 | case 'W': case 'Y': case 'Z': | |
813 | next_cl = (c == 'r' | |
814 | ? GENERAL_REGS | |
815 | : REG_CLASS_FROM_CONSTRAINT (c, constraints)); | |
816 | if ((cl != NO_REGS && next_cl != cl) | |
a7dcf969 | 817 | || (ira_available_class_regs[next_cl] |
818 | > ira_reg_class_nregs[next_cl][GET_MODE (op)])) | |
47dd2e78 | 819 | return NO_REGS; |
820 | cl = next_cl; | |
821 | break; | |
48e1416a | 822 | |
47dd2e78 | 823 | case '0': case '1': case '2': case '3': case '4': |
824 | case '5': case '6': case '7': case '8': case '9': | |
825 | next_cl | |
826 | = single_reg_class (recog_data.constraints[c - '0'], | |
827 | recog_data.operand[c - '0'], NULL_RTX); | |
a7dcf969 | 828 | if ((cl != NO_REGS && next_cl != cl) |
829 | || next_cl == NO_REGS | |
830 | || (ira_available_class_regs[next_cl] | |
831 | > ira_reg_class_nregs[next_cl][GET_MODE (op)])) | |
47dd2e78 | 832 | return NO_REGS; |
833 | cl = next_cl; | |
834 | break; | |
48e1416a | 835 | |
47dd2e78 | 836 | default: |
837 | return NO_REGS; | |
838 | } | |
839 | return cl; | |
840 | } | |
841 | ||
842 | /* The function checks that operand OP_NUM of the current insn can use | |
843 | only one hard register. If it is so, the function returns the | |
844 | class of the hard register. Otherwise it returns NO_REGS. */ | |
845 | static enum reg_class | |
846 | single_reg_operand_class (int op_num) | |
847 | { | |
848 | if (op_num < 0 || recog_data.n_alternatives == 0) | |
849 | return NO_REGS; | |
850 | return single_reg_class (recog_data.constraints[op_num], | |
851 | recog_data.operand[op_num], NULL_RTX); | |
852 | } | |
853 | ||
a7dcf969 | 854 | /* The function sets up hard register set *SET to hard registers which |
855 | might be used by insn reloads because the constraints are too | |
856 | strict. */ | |
857 | void | |
858 | ira_implicitly_set_insn_hard_regs (HARD_REG_SET *set) | |
859 | { | |
5fce5299 | 860 | int i, c, regno = 0; |
a7dcf969 | 861 | bool ignore_p; |
862 | enum reg_class cl; | |
863 | rtx op; | |
864 | enum machine_mode mode; | |
865 | ||
866 | CLEAR_HARD_REG_SET (*set); | |
867 | for (i = 0; i < recog_data.n_operands; i++) | |
868 | { | |
869 | op = recog_data.operand[i]; | |
870 | ||
871 | if (GET_CODE (op) == SUBREG) | |
872 | op = SUBREG_REG (op); | |
48e1416a | 873 | |
a7dcf969 | 874 | if (GET_CODE (op) == SCRATCH |
875 | || (REG_P (op) && (regno = REGNO (op)) >= FIRST_PSEUDO_REGISTER)) | |
876 | { | |
877 | const char *p = recog_data.constraints[i]; | |
878 | ||
879 | mode = (GET_CODE (op) == SCRATCH | |
880 | ? GET_MODE (op) : PSEUDO_REGNO_MODE (regno)); | |
881 | cl = NO_REGS; | |
882 | for (ignore_p = false; (c = *p); p += CONSTRAINT_LEN (c, p)) | |
883 | if (c == '#') | |
884 | ignore_p = true; | |
885 | else if (c == ',') | |
886 | ignore_p = false; | |
887 | else if (! ignore_p) | |
888 | switch (c) | |
889 | { | |
890 | case 'r': | |
891 | case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': | |
892 | case 'h': case 'j': case 'k': case 'l': | |
893 | case 'q': case 't': case 'u': | |
894 | case 'v': case 'w': case 'x': case 'y': case 'z': | |
895 | case 'A': case 'B': case 'C': case 'D': | |
896 | case 'Q': case 'R': case 'S': case 'T': case 'U': | |
897 | case 'W': case 'Y': case 'Z': | |
898 | cl = (c == 'r' | |
899 | ? GENERAL_REGS | |
900 | : REG_CLASS_FROM_CONSTRAINT (c, p)); | |
901 | if (cl != NO_REGS | |
0cc9609c | 902 | /* There is no register pressure problem if all of the |
903 | regs in this class are fixed. */ | |
904 | && ira_available_class_regs[cl] != 0 | |
a7dcf969 | 905 | && (ira_available_class_regs[cl] |
906 | <= ira_reg_class_nregs[cl][mode])) | |
907 | IOR_HARD_REG_SET (*set, reg_class_contents[cl]); | |
908 | break; | |
909 | } | |
910 | } | |
911 | } | |
912 | } | |
47dd2e78 | 913 | /* Processes input operands, if IN_P, or output operands otherwise of |
914 | the current insn with FREQ to find allocno which can use only one | |
915 | hard register and makes other currently living allocnos conflicting | |
916 | with the hard register. */ | |
917 | static void | |
918 | process_single_reg_class_operands (bool in_p, int freq) | |
919 | { | |
744d7848 | 920 | int i, regno; |
47dd2e78 | 921 | unsigned int px; |
da7a04f1 | 922 | enum reg_class cl; |
47dd2e78 | 923 | rtx operand; |
924 | ira_allocno_t operand_a, a; | |
925 | ||
926 | for (i = 0; i < recog_data.n_operands; i++) | |
927 | { | |
928 | operand = recog_data.operand[i]; | |
929 | if (in_p && recog_data.operand_type[i] != OP_IN | |
930 | && recog_data.operand_type[i] != OP_INOUT) | |
931 | continue; | |
932 | if (! in_p && recog_data.operand_type[i] != OP_OUT | |
933 | && recog_data.operand_type[i] != OP_INOUT) | |
934 | continue; | |
935 | cl = single_reg_operand_class (i); | |
936 | if (cl == NO_REGS) | |
937 | continue; | |
938 | ||
939 | operand_a = NULL; | |
940 | ||
941 | if (GET_CODE (operand) == SUBREG) | |
942 | operand = SUBREG_REG (operand); | |
48e1416a | 943 | |
47dd2e78 | 944 | if (REG_P (operand) |
945 | && (regno = REGNO (operand)) >= FIRST_PSEUDO_REGISTER) | |
946 | { | |
47dd2e78 | 947 | enum reg_class cover_class; |
948 | ||
949 | operand_a = ira_curr_regno_allocno_map[regno]; | |
47dd2e78 | 950 | cover_class = ALLOCNO_COVER_CLASS (operand_a); |
951 | if (ira_class_subset_p[cl][cover_class] | |
744d7848 | 952 | && ira_class_hard_regs_num[cl] != 0) |
47dd2e78 | 953 | { |
744d7848 | 954 | /* View the desired allocation of OPERAND as: |
955 | ||
956 | (REG:YMODE YREGNO), | |
957 | ||
958 | a simplification of: | |
959 | ||
960 | (subreg:YMODE (reg:XMODE XREGNO) OFFSET). */ | |
961 | enum machine_mode ymode, xmode; | |
962 | int xregno, yregno; | |
963 | HOST_WIDE_INT offset; | |
964 | ||
965 | xmode = recog_data.operand_mode[i]; | |
966 | xregno = ira_class_hard_regs[cl][0]; | |
967 | ymode = ALLOCNO_MODE (operand_a); | |
968 | offset = subreg_lowpart_offset (ymode, xmode); | |
969 | yregno = simplify_subreg_regno (xregno, xmode, offset, ymode); | |
970 | if (yregno >= 0 | |
971 | && ira_class_hard_reg_index[cover_class][yregno] >= 0) | |
972 | { | |
973 | int cost; | |
974 | ||
975 | ira_allocate_and_set_costs | |
976 | (&ALLOCNO_CONFLICT_HARD_REG_COSTS (operand_a), | |
977 | cover_class, 0); | |
978 | cost | |
979 | = (freq | |
980 | * (in_p | |
981 | ? ira_get_register_move_cost (xmode, cover_class, cl) | |
982 | : ira_get_register_move_cost (xmode, cl, | |
983 | cover_class))); | |
984 | ALLOCNO_CONFLICT_HARD_REG_COSTS (operand_a) | |
985 | [ira_class_hard_reg_index[cover_class][yregno]] -= cost; | |
986 | } | |
47dd2e78 | 987 | } |
988 | } | |
989 | ||
be18556f | 990 | EXECUTE_IF_SET_IN_SPARSESET (objects_live, px) |
47dd2e78 | 991 | { |
be18556f | 992 | ira_object_t obj = ira_object_id_map[px]; |
993 | a = OBJECT_ALLOCNO (obj); | |
47dd2e78 | 994 | if (a != operand_a) |
995 | { | |
996 | /* We could increase costs of A instead of making it | |
997 | conflicting with the hard register. But it works worse | |
998 | because it will be spilled in reload in anyway. */ | |
ae9587ed | 999 | IOR_HARD_REG_SET (OBJECT_CONFLICT_HARD_REGS (obj), |
47dd2e78 | 1000 | reg_class_contents[cl]); |
ae9587ed | 1001 | IOR_HARD_REG_SET (OBJECT_TOTAL_CONFLICT_HARD_REGS (obj), |
47dd2e78 | 1002 | reg_class_contents[cl]); |
1003 | } | |
1004 | } | |
1005 | } | |
1006 | } | |
1007 | ||
9f724a58 | 1008 | /* Return true when one of the predecessor edges of BB is marked with |
1009 | EDGE_ABNORMAL_CALL or EDGE_EH. */ | |
1010 | static bool | |
1011 | bb_has_abnormal_call_pred (basic_block bb) | |
1012 | { | |
1013 | edge e; | |
1014 | edge_iterator ei; | |
48e1416a | 1015 | |
9f724a58 | 1016 | FOR_EACH_EDGE (e, ei, bb->preds) |
1017 | { | |
1018 | if (e->flags & (EDGE_ABNORMAL_CALL | EDGE_EH)) | |
1019 | return true; | |
1020 | } | |
1021 | return false; | |
1022 | } | |
1023 | ||
47dd2e78 | 1024 | /* Process insns of the basic block given by its LOOP_TREE_NODE to |
1025 | update allocno live ranges, allocno hard register conflicts, | |
1026 | intersected calls, and register pressure info for allocnos for the | |
1027 | basic block for and regions containing the basic block. */ | |
1028 | static void | |
1029 | process_bb_node_lives (ira_loop_tree_node_t loop_tree_node) | |
1030 | { | |
7e03a244 | 1031 | int i, freq; |
47dd2e78 | 1032 | unsigned int j; |
1033 | basic_block bb; | |
1034 | rtx insn; | |
47dd2e78 | 1035 | bitmap_iterator bi; |
7e03a244 | 1036 | bitmap reg_live_out; |
47dd2e78 | 1037 | unsigned int px; |
793e7497 | 1038 | bool set_p; |
47dd2e78 | 1039 | |
1040 | bb = loop_tree_node->bb; | |
1041 | if (bb != NULL) | |
1042 | { | |
1043 | for (i = 0; i < ira_reg_class_cover_size; i++) | |
1044 | { | |
1045 | curr_reg_pressure[ira_reg_class_cover[i]] = 0; | |
1046 | high_pressure_start_point[ira_reg_class_cover[i]] = -1; | |
1047 | } | |
1048 | curr_bb_node = loop_tree_node; | |
2dd81ece | 1049 | reg_live_out = DF_LR_OUT (bb); |
be18556f | 1050 | sparseset_clear (objects_live); |
7e03a244 | 1051 | REG_SET_TO_HARD_REG_SET (hard_regs_live, reg_live_out); |
47dd2e78 | 1052 | AND_COMPL_HARD_REG_SET (hard_regs_live, eliminable_regset); |
1053 | AND_COMPL_HARD_REG_SET (hard_regs_live, ira_no_alloc_regs); | |
1054 | for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) | |
1055 | if (TEST_HARD_REG_BIT (hard_regs_live, i)) | |
1056 | { | |
14792f4e | 1057 | enum reg_class cover_class, cl; |
48e1416a | 1058 | |
14792f4e | 1059 | cover_class = ira_class_translate[REGNO_REG_CLASS (i)]; |
1060 | for (j = 0; | |
1061 | (cl = ira_reg_class_super_classes[cover_class][j]) | |
1062 | != LIM_REG_CLASSES; | |
1063 | j++) | |
1064 | { | |
1065 | curr_reg_pressure[cl]++; | |
1066 | if (curr_bb_node->reg_pressure[cl] < curr_reg_pressure[cl]) | |
1067 | curr_bb_node->reg_pressure[cl] = curr_reg_pressure[cl]; | |
1068 | ira_assert (curr_reg_pressure[cl] | |
1069 | <= ira_available_class_regs[cl]); | |
1070 | } | |
47dd2e78 | 1071 | } |
7e03a244 | 1072 | EXECUTE_IF_SET_IN_BITMAP (reg_live_out, FIRST_PSEUDO_REGISTER, j, bi) |
b4f5e198 | 1073 | mark_pseudo_regno_live (j); |
48e1416a | 1074 | |
7e03a244 | 1075 | freq = REG_FREQ_FROM_BB (bb); |
1076 | if (freq == 0) | |
1077 | freq = 1; | |
1078 | ||
df07a54c | 1079 | /* Invalidate all allocno_saved_at_call entries. */ |
1080 | last_call_num++; | |
1081 | ||
47dd2e78 | 1082 | /* Scan the code of this basic block, noting which allocnos and |
7e03a244 | 1083 | hard regs are born or die. |
1084 | ||
1085 | Note that this loop treats uninitialized values as live until | |
1086 | the beginning of the block. For example, if an instruction | |
1087 | uses (reg:DI foo), and only (subreg:SI (reg:DI foo) 0) is ever | |
1088 | set, FOO will remain live until the beginning of the block. | |
1089 | Likewise if FOO is not set at all. This is unnecessarily | |
1090 | pessimistic, but it probably doesn't matter much in practice. */ | |
1091 | FOR_BB_INSNS_REVERSE (bb, insn) | |
47dd2e78 | 1092 | { |
ed6e85ae | 1093 | df_ref *def_rec, *use_rec; |
7e03a244 | 1094 | bool call_p; |
48e1416a | 1095 | |
9845d120 | 1096 | if (!NONDEBUG_INSN_P (insn)) |
47dd2e78 | 1097 | continue; |
48e1416a | 1098 | |
47dd2e78 | 1099 | if (internal_flag_ira_verbose > 2 && ira_dump_file != NULL) |
1100 | fprintf (ira_dump_file, " Insn %u(l%d): point = %d\n", | |
1101 | INSN_UID (insn), loop_tree_node->parent->loop->num, | |
1102 | curr_point); | |
1103 | ||
7e03a244 | 1104 | /* Mark each defined value as live. We need to do this for |
1105 | unused values because they still conflict with quantities | |
1106 | that are live at the time of the definition. | |
1107 | ||
1108 | Ignore DF_REF_MAY_CLOBBERs on a call instruction. Such | |
1109 | references represent the effect of the called function | |
1110 | on a call-clobbered register. Marking the register as | |
1111 | live would stop us from allocating it to a call-crossing | |
1112 | allocno. */ | |
1113 | call_p = CALL_P (insn); | |
1114 | for (def_rec = DF_INSN_DEFS (insn); *def_rec; def_rec++) | |
1115 | if (!call_p || !DF_REF_FLAGS_IS_SET (*def_rec, DF_REF_MAY_CLOBBER)) | |
1116 | mark_ref_live (*def_rec); | |
1117 | ||
1118 | /* If INSN has multiple outputs, then any value used in one | |
1119 | of the outputs conflicts with the other outputs. Model this | |
1120 | by making the used value live during the output phase. | |
1121 | ||
1122 | It is unsafe to use !single_set here since it will ignore | |
1123 | an unused output. Just because an output is unused does | |
1124 | not mean the compiler can assume the side effect will not | |
1125 | occur. Consider if ALLOCNO appears in the address of an | |
1126 | output and we reload the output. If we allocate ALLOCNO | |
1127 | to the same hard register as an unused output we could | |
1128 | set the hard register before the output reload insn. */ | |
1129 | if (GET_CODE (PATTERN (insn)) == PARALLEL && multiple_sets (insn)) | |
1130 | for (use_rec = DF_INSN_USES (insn); *use_rec; use_rec++) | |
1131 | { | |
1132 | int i; | |
1133 | rtx reg; | |
1134 | ||
1135 | reg = DF_REF_REG (*use_rec); | |
1136 | for (i = XVECLEN (PATTERN (insn), 0) - 1; i >= 0; i--) | |
1137 | { | |
1138 | rtx set; | |
1139 | ||
1140 | set = XVECEXP (PATTERN (insn), 0, i); | |
1141 | if (GET_CODE (set) == SET | |
1142 | && reg_overlap_mentioned_p (reg, SET_DEST (set))) | |
1143 | { | |
1144 | /* After the previous loop, this is a no-op if | |
1145 | REG is contained within SET_DEST (SET). */ | |
1146 | mark_ref_live (*use_rec); | |
1147 | break; | |
1148 | } | |
1149 | } | |
1150 | } | |
48e1416a | 1151 | |
47dd2e78 | 1152 | extract_insn (insn); |
793e7497 | 1153 | preprocess_constraints (); |
7e03a244 | 1154 | process_single_reg_class_operands (false, freq); |
48e1416a | 1155 | |
7e03a244 | 1156 | /* See which defined values die here. */ |
1157 | for (def_rec = DF_INSN_DEFS (insn); *def_rec; def_rec++) | |
1158 | if (!call_p || !DF_REF_FLAGS_IS_SET (*def_rec, DF_REF_MAY_CLOBBER)) | |
1159 | mark_ref_dead (*def_rec); | |
47dd2e78 | 1160 | |
7e03a244 | 1161 | if (call_p) |
47dd2e78 | 1162 | { |
df07a54c | 1163 | last_call_num++; |
be18556f | 1164 | sparseset_clear (allocnos_processed); |
7e03a244 | 1165 | /* The current set of live allocnos are live across the call. */ |
be18556f | 1166 | EXECUTE_IF_SET_IN_SPARSESET (objects_live, i) |
47dd2e78 | 1167 | { |
be18556f | 1168 | ira_object_t obj = ira_object_id_map[i]; |
1169 | ira_allocno_t a = OBJECT_ALLOCNO (obj); | |
1170 | int num = ALLOCNO_NUM (a); | |
48e1416a | 1171 | |
d6a421d5 | 1172 | /* Don't allocate allocnos that cross setjmps or any |
1173 | call, if this function receives a nonlocal | |
1174 | goto. */ | |
1175 | if (cfun->has_nonlocal_label | |
1176 | || find_reg_note (insn, REG_SETJMP, | |
1177 | NULL_RTX) != NULL_RTX) | |
47dd2e78 | 1178 | { |
ae9587ed | 1179 | SET_HARD_REG_SET (OBJECT_CONFLICT_HARD_REGS (obj)); |
1180 | SET_HARD_REG_SET (OBJECT_TOTAL_CONFLICT_HARD_REGS (obj)); | |
47dd2e78 | 1181 | } |
cab55469 | 1182 | if (can_throw_internal (insn)) |
1183 | { | |
ae9587ed | 1184 | IOR_HARD_REG_SET (OBJECT_CONFLICT_HARD_REGS (obj), |
cab55469 | 1185 | call_used_reg_set); |
be18556f | 1186 | IOR_HARD_REG_SET (OBJECT_TOTAL_CONFLICT_HARD_REGS (obj), |
1187 | call_used_reg_set); | |
cab55469 | 1188 | } |
be18556f | 1189 | |
1190 | if (sparseset_bit_p (allocnos_processed, num)) | |
1191 | continue; | |
1192 | sparseset_set_bit (allocnos_processed, num); | |
1193 | ||
1194 | if (allocno_saved_at_call[num] != last_call_num) | |
1195 | /* Here we are mimicking caller-save.c behaviour | |
1196 | which does not save hard register at a call if | |
1197 | it was saved on previous call in the same basic | |
1198 | block and the hard register was not mentioned | |
1199 | between the two calls. */ | |
1200 | ALLOCNO_CALL_FREQ (a) += freq; | |
1201 | /* Mark it as saved at the next call. */ | |
1202 | allocno_saved_at_call[num] = last_call_num + 1; | |
1203 | ALLOCNO_CALLS_CROSSED_NUM (a)++; | |
47dd2e78 | 1204 | } |
1205 | } | |
48e1416a | 1206 | |
7173d4d0 | 1207 | make_early_clobber_and_input_conflicts (); |
1208 | ||
7e03a244 | 1209 | curr_point++; |
1210 | ||
1211 | /* Mark each used value as live. */ | |
1212 | for (use_rec = DF_INSN_USES (insn); *use_rec; use_rec++) | |
1213 | mark_ref_live (*use_rec); | |
1214 | ||
7e03a244 | 1215 | process_single_reg_class_operands (true, freq); |
48e1416a | 1216 | |
7173d4d0 | 1217 | set_p = mark_hard_reg_early_clobbers (insn, true); |
1218 | ||
793e7497 | 1219 | if (set_p) |
1220 | { | |
7173d4d0 | 1221 | mark_hard_reg_early_clobbers (insn, false); |
793e7497 | 1222 | |
7173d4d0 | 1223 | /* Mark each hard reg as live again. For example, a |
793e7497 | 1224 | hard register can be in clobber and in an insn |
1225 | input. */ | |
1226 | for (use_rec = DF_INSN_USES (insn); *use_rec; use_rec++) | |
7173d4d0 | 1227 | { |
1228 | rtx ureg = DF_REF_REG (*use_rec); | |
48e1416a | 1229 | |
7173d4d0 | 1230 | if (GET_CODE (ureg) == SUBREG) |
1231 | ureg = SUBREG_REG (ureg); | |
1232 | if (! REG_P (ureg) || REGNO (ureg) >= FIRST_PSEUDO_REGISTER) | |
1233 | continue; | |
48e1416a | 1234 | |
7173d4d0 | 1235 | mark_ref_live (*use_rec); |
1236 | } | |
793e7497 | 1237 | } |
47dd2e78 | 1238 | |
47dd2e78 | 1239 | curr_point++; |
1240 | } | |
7e03a244 | 1241 | |
fee75d9b | 1242 | #ifdef EH_RETURN_DATA_REGNO |
1243 | if (bb_has_eh_pred (bb)) | |
1244 | for (j = 0; ; ++j) | |
1245 | { | |
1246 | unsigned int regno = EH_RETURN_DATA_REGNO (j); | |
1247 | if (regno == INVALID_REGNUM) | |
1248 | break; | |
b4f5e198 | 1249 | make_hard_regno_born (regno); |
fee75d9b | 1250 | } |
1251 | #endif | |
1252 | ||
7e03a244 | 1253 | /* Allocnos can't go in stack regs at the start of a basic block |
1254 | that is reached by an abnormal edge. Likewise for call | |
1255 | clobbered regs, because caller-save, fixup_abnormal_edges and | |
1256 | possibly the table driven EH machinery are not quite ready to | |
1257 | handle such allocnos live across such edges. */ | |
fee75d9b | 1258 | if (bb_has_abnormal_pred (bb)) |
7e03a244 | 1259 | { |
1260 | #ifdef STACK_REGS | |
be18556f | 1261 | EXECUTE_IF_SET_IN_SPARSESET (objects_live, px) |
7e03a244 | 1262 | { |
be18556f | 1263 | ira_allocno_t a = OBJECT_ALLOCNO (ira_object_id_map[px]); |
1264 | ALLOCNO_NO_STACK_REG_P (a) = true; | |
1265 | ALLOCNO_TOTAL_NO_STACK_REG_P (a) = true; | |
7e03a244 | 1266 | } |
1267 | for (px = FIRST_STACK_REG; px <= LAST_STACK_REG; px++) | |
b4f5e198 | 1268 | make_hard_regno_born (px); |
7e03a244 | 1269 | #endif |
1270 | /* No need to record conflicts for call clobbered regs if we | |
1271 | have nonlocal labels around, as we don't ever try to | |
1272 | allocate such regs in this case. */ | |
9f724a58 | 1273 | if (!cfun->has_nonlocal_label && bb_has_abnormal_call_pred (bb)) |
7e03a244 | 1274 | for (px = 0; px < FIRST_PSEUDO_REGISTER; px++) |
1275 | if (call_used_regs[px]) | |
b4f5e198 | 1276 | make_hard_regno_born (px); |
7e03a244 | 1277 | } |
1278 | ||
be18556f | 1279 | EXECUTE_IF_SET_IN_SPARSESET (objects_live, i) |
1280 | make_object_dead (ira_object_id_map[i]); | |
47dd2e78 | 1281 | |
1282 | curr_point++; | |
1283 | ||
1284 | } | |
1285 | /* Propagate register pressure to upper loop tree nodes: */ | |
1286 | if (loop_tree_node != ira_loop_tree_root) | |
1287 | for (i = 0; i < ira_reg_class_cover_size; i++) | |
1288 | { | |
1289 | enum reg_class cover_class; | |
1290 | ||
1291 | cover_class = ira_reg_class_cover[i]; | |
1292 | if (loop_tree_node->reg_pressure[cover_class] | |
1293 | > loop_tree_node->parent->reg_pressure[cover_class]) | |
1294 | loop_tree_node->parent->reg_pressure[cover_class] | |
1295 | = loop_tree_node->reg_pressure[cover_class]; | |
1296 | } | |
1297 | } | |
1298 | ||
1299 | /* Create and set up IRA_START_POINT_RANGES and | |
1300 | IRA_FINISH_POINT_RANGES. */ | |
1301 | static void | |
1302 | create_start_finish_chains (void) | |
1303 | { | |
be18556f | 1304 | ira_object_t obj; |
1305 | ira_object_iterator oi; | |
fbff82f4 | 1306 | live_range_t r; |
47dd2e78 | 1307 | |
1308 | ira_start_point_ranges | |
be18556f | 1309 | = (live_range_t *) ira_allocate (ira_max_point * sizeof (live_range_t)); |
1310 | memset (ira_start_point_ranges, 0, ira_max_point * sizeof (live_range_t)); | |
47dd2e78 | 1311 | ira_finish_point_ranges |
be18556f | 1312 | = (live_range_t *) ira_allocate (ira_max_point * sizeof (live_range_t)); |
1313 | memset (ira_finish_point_ranges, 0, ira_max_point * sizeof (live_range_t)); | |
1314 | FOR_EACH_OBJECT (obj, oi) | |
1315 | for (r = OBJECT_LIVE_RANGES (obj); r != NULL; r = r->next) | |
1316 | { | |
1317 | r->start_next = ira_start_point_ranges[r->start]; | |
1318 | ira_start_point_ranges[r->start] = r; | |
1319 | r->finish_next = ira_finish_point_ranges[r->finish]; | |
47dd2e78 | 1320 | ira_finish_point_ranges[r->finish] = r; |
be18556f | 1321 | } |
47dd2e78 | 1322 | } |
1323 | ||
1324 | /* Rebuild IRA_START_POINT_RANGES and IRA_FINISH_POINT_RANGES after | |
1325 | new live ranges and program points were added as a result if new | |
1326 | insn generation. */ | |
1327 | void | |
1328 | ira_rebuild_start_finish_chains (void) | |
1329 | { | |
1330 | ira_free (ira_finish_point_ranges); | |
1331 | ira_free (ira_start_point_ranges); | |
1332 | create_start_finish_chains (); | |
1333 | } | |
1334 | ||
7f36fbdf | 1335 | /* Compress allocno live ranges by removing program points where |
1336 | nothing happens. */ | |
1337 | static void | |
1338 | remove_some_program_points_and_update_live_ranges (void) | |
1339 | { | |
1340 | unsigned i; | |
1341 | int n; | |
1342 | int *map; | |
9d53e372 | 1343 | ira_object_t obj; |
1344 | ira_object_iterator oi; | |
fbff82f4 | 1345 | live_range_t r; |
82cc92bf | 1346 | sbitmap born_or_dead, born, dead; |
1347 | sbitmap_iterator sbi; | |
1348 | bool born_p, dead_p, prev_born_p, prev_dead_p; | |
1349 | ||
1350 | born = sbitmap_alloc (ira_max_point); | |
1351 | dead = sbitmap_alloc (ira_max_point); | |
1352 | sbitmap_zero (born); | |
1353 | sbitmap_zero (dead); | |
9d53e372 | 1354 | FOR_EACH_OBJECT (obj, oi) |
1355 | for (r = OBJECT_LIVE_RANGES (obj); r != NULL; r = r->next) | |
1356 | { | |
1357 | ira_assert (r->start <= r->finish); | |
82cc92bf | 1358 | SET_BIT (born, r->start); |
1359 | SET_BIT (dead, r->finish); | |
9d53e372 | 1360 | } |
1361 | ||
82cc92bf | 1362 | born_or_dead = sbitmap_alloc (ira_max_point); |
1363 | sbitmap_a_or_b (born_or_dead, born, dead); | |
7f36fbdf | 1364 | map = (int *) ira_allocate (sizeof (int) * ira_max_point); |
82cc92bf | 1365 | n = -1; |
1366 | prev_born_p = prev_dead_p = false; | |
1367 | EXECUTE_IF_SET_IN_SBITMAP (born_or_dead, 0, i, sbi) | |
7f36fbdf | 1368 | { |
82cc92bf | 1369 | born_p = TEST_BIT (born, i); |
1370 | dead_p = TEST_BIT (dead, i); | |
1371 | if ((prev_born_p && ! prev_dead_p && born_p && ! dead_p) | |
1372 | || (prev_dead_p && ! prev_born_p && dead_p && ! born_p)) | |
1373 | map[i] = n; | |
1374 | else | |
1375 | map[i] = ++n; | |
1376 | prev_born_p = born_p; | |
1377 | prev_dead_p = dead_p; | |
7f36fbdf | 1378 | } |
82cc92bf | 1379 | sbitmap_free (born_or_dead); |
1380 | sbitmap_free (born); | |
1381 | sbitmap_free (dead); | |
1382 | n++; | |
7f36fbdf | 1383 | if (internal_flag_ira_verbose > 1 && ira_dump_file != NULL) |
1384 | fprintf (ira_dump_file, "Compressing live ranges: from %d to %d - %d%%\n", | |
1385 | ira_max_point, n, 100 * n / ira_max_point); | |
1386 | ira_max_point = n; | |
9d53e372 | 1387 | |
1388 | FOR_EACH_OBJECT (obj, oi) | |
1389 | for (r = OBJECT_LIVE_RANGES (obj); r != NULL; r = r->next) | |
1390 | { | |
1391 | r->start = map[r->start]; | |
1392 | r->finish = map[r->finish]; | |
1393 | } | |
be18556f | 1394 | |
7f36fbdf | 1395 | ira_free (map); |
1396 | } | |
1397 | ||
47dd2e78 | 1398 | /* Print live ranges R to file F. */ |
1399 | void | |
fbff82f4 | 1400 | ira_print_live_range_list (FILE *f, live_range_t r) |
47dd2e78 | 1401 | { |
1402 | for (; r != NULL; r = r->next) | |
1403 | fprintf (f, " [%d..%d]", r->start, r->finish); | |
1404 | fprintf (f, "\n"); | |
1405 | } | |
1406 | ||
1407 | /* Print live ranges R to stderr. */ | |
1408 | void | |
fbff82f4 | 1409 | ira_debug_live_range_list (live_range_t r) |
47dd2e78 | 1410 | { |
1411 | ira_print_live_range_list (stderr, r); | |
1412 | } | |
1413 | ||
be18556f | 1414 | /* Print live ranges of object OBJ to file F. */ |
1415 | static void | |
1416 | print_object_live_ranges (FILE *f, ira_object_t obj) | |
1417 | { | |
1418 | ira_print_live_range_list (f, OBJECT_LIVE_RANGES (obj)); | |
1419 | } | |
1420 | ||
47dd2e78 | 1421 | /* Print live ranges of allocno A to file F. */ |
1422 | static void | |
1423 | print_allocno_live_ranges (FILE *f, ira_allocno_t a) | |
1424 | { | |
be18556f | 1425 | int n = ALLOCNO_NUM_OBJECTS (a); |
1426 | int i; | |
1427 | for (i = 0; i < n; i++) | |
1428 | { | |
1429 | fprintf (f, " a%d(r%d", ALLOCNO_NUM (a), ALLOCNO_REGNO (a)); | |
1430 | if (n > 1) | |
1431 | fprintf (f, " [%d]", i); | |
1432 | fprintf (f, "):"); | |
1433 | print_object_live_ranges (f, ALLOCNO_OBJECT (a, i)); | |
1434 | } | |
47dd2e78 | 1435 | } |
1436 | ||
1437 | /* Print live ranges of allocno A to stderr. */ | |
1438 | void | |
1439 | ira_debug_allocno_live_ranges (ira_allocno_t a) | |
1440 | { | |
1441 | print_allocno_live_ranges (stderr, a); | |
1442 | } | |
1443 | ||
1444 | /* Print live ranges of all allocnos to file F. */ | |
1445 | static void | |
1446 | print_live_ranges (FILE *f) | |
1447 | { | |
1448 | ira_allocno_t a; | |
1449 | ira_allocno_iterator ai; | |
1450 | ||
1451 | FOR_EACH_ALLOCNO (a, ai) | |
1452 | print_allocno_live_ranges (f, a); | |
1453 | } | |
1454 | ||
1455 | /* Print live ranges of all allocnos to stderr. */ | |
1456 | void | |
1457 | ira_debug_live_ranges (void) | |
1458 | { | |
1459 | print_live_ranges (stderr); | |
1460 | } | |
1461 | ||
1462 | /* The main entry function creates live ranges, set up | |
be18556f | 1463 | CONFLICT_HARD_REGS and TOTAL_CONFLICT_HARD_REGS for objects, and |
47dd2e78 | 1464 | calculate register pressure info. */ |
1465 | void | |
1466 | ira_create_allocno_live_ranges (void) | |
1467 | { | |
be18556f | 1468 | objects_live = sparseset_alloc (ira_objects_num); |
1469 | allocnos_processed = sparseset_alloc (ira_allocnos_num); | |
47dd2e78 | 1470 | curr_point = 0; |
df07a54c | 1471 | last_call_num = 0; |
1472 | allocno_saved_at_call | |
1473 | = (int *) ira_allocate (ira_allocnos_num * sizeof (int)); | |
1474 | memset (allocno_saved_at_call, 0, ira_allocnos_num * sizeof (int)); | |
47dd2e78 | 1475 | ira_traverse_loop_tree (true, ira_loop_tree_root, NULL, |
1476 | process_bb_node_lives); | |
1477 | ira_max_point = curr_point; | |
1478 | create_start_finish_chains (); | |
1479 | if (internal_flag_ira_verbose > 2 && ira_dump_file != NULL) | |
1480 | print_live_ranges (ira_dump_file); | |
1481 | /* Clean up. */ | |
df07a54c | 1482 | ira_free (allocno_saved_at_call); |
be18556f | 1483 | sparseset_free (objects_live); |
1484 | sparseset_free (allocnos_processed); | |
47dd2e78 | 1485 | } |
1486 | ||
7f36fbdf | 1487 | /* Compress allocno live ranges. */ |
1488 | void | |
1489 | ira_compress_allocno_live_ranges (void) | |
1490 | { | |
1491 | remove_some_program_points_and_update_live_ranges (); | |
1492 | ira_rebuild_start_finish_chains (); | |
1493 | if (internal_flag_ira_verbose > 2 && ira_dump_file != NULL) | |
1494 | { | |
1495 | fprintf (ira_dump_file, "Ranges after the compression:\n"); | |
1496 | print_live_ranges (ira_dump_file); | |
1497 | } | |
1498 | } | |
1499 | ||
47dd2e78 | 1500 | /* Free arrays IRA_START_POINT_RANGES and IRA_FINISH_POINT_RANGES. */ |
1501 | void | |
1502 | ira_finish_allocno_live_ranges (void) | |
1503 | { | |
1504 | ira_free (ira_finish_point_ranges); | |
1505 | ira_free (ira_start_point_ranges); | |
1506 | } |