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