Mercurial > hg > CbC > CbC_gcc
comparison gcc/resource.c @ 0:a06113de4d67
first commit
author | kent <kent@cr.ie.u-ryukyu.ac.jp> |
---|---|
date | Fri, 17 Jul 2009 14:47:48 +0900 |
parents | |
children | 58ad6c70ea60 |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:a06113de4d67 |
---|---|
1 /* Definitions for computing resource usage of specific insns. | |
2 Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 | |
3 Free Software Foundation, Inc. | |
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 "toplev.h" | |
26 #include "rtl.h" | |
27 #include "tm_p.h" | |
28 #include "hard-reg-set.h" | |
29 #include "function.h" | |
30 #include "regs.h" | |
31 #include "flags.h" | |
32 #include "output.h" | |
33 #include "resource.h" | |
34 #include "except.h" | |
35 #include "insn-attr.h" | |
36 #include "params.h" | |
37 #include "df.h" | |
38 | |
39 /* This structure is used to record liveness information at the targets or | |
40 fallthrough insns of branches. We will most likely need the information | |
41 at targets again, so save them in a hash table rather than recomputing them | |
42 each time. */ | |
43 | |
44 struct target_info | |
45 { | |
46 int uid; /* INSN_UID of target. */ | |
47 struct target_info *next; /* Next info for same hash bucket. */ | |
48 HARD_REG_SET live_regs; /* Registers live at target. */ | |
49 int block; /* Basic block number containing target. */ | |
50 int bb_tick; /* Generation count of basic block info. */ | |
51 }; | |
52 | |
53 #define TARGET_HASH_PRIME 257 | |
54 | |
55 /* Indicates what resources are required at the beginning of the epilogue. */ | |
56 static struct resources start_of_epilogue_needs; | |
57 | |
58 /* Indicates what resources are required at function end. */ | |
59 static struct resources end_of_function_needs; | |
60 | |
61 /* Define the hash table itself. */ | |
62 static struct target_info **target_hash_table = NULL; | |
63 | |
64 /* For each basic block, we maintain a generation number of its basic | |
65 block info, which is updated each time we move an insn from the | |
66 target of a jump. This is the generation number indexed by block | |
67 number. */ | |
68 | |
69 static int *bb_ticks; | |
70 | |
71 /* Marks registers possibly live at the current place being scanned by | |
72 mark_target_live_regs. Also used by update_live_status. */ | |
73 | |
74 static HARD_REG_SET current_live_regs; | |
75 | |
76 /* Marks registers for which we have seen a REG_DEAD note but no assignment. | |
77 Also only used by the next two functions. */ | |
78 | |
79 static HARD_REG_SET pending_dead_regs; | |
80 | |
81 static void update_live_status (rtx, const_rtx, void *); | |
82 static int find_basic_block (rtx, int); | |
83 static rtx next_insn_no_annul (rtx); | |
84 static rtx find_dead_or_set_registers (rtx, struct resources*, | |
85 rtx*, int, struct resources, | |
86 struct resources); | |
87 | |
88 /* Utility function called from mark_target_live_regs via note_stores. | |
89 It deadens any CLOBBERed registers and livens any SET registers. */ | |
90 | |
91 static void | |
92 update_live_status (rtx dest, const_rtx x, void *data ATTRIBUTE_UNUSED) | |
93 { | |
94 int first_regno, last_regno; | |
95 int i; | |
96 | |
97 if (!REG_P (dest) | |
98 && (GET_CODE (dest) != SUBREG || !REG_P (SUBREG_REG (dest)))) | |
99 return; | |
100 | |
101 if (GET_CODE (dest) == SUBREG) | |
102 { | |
103 first_regno = subreg_regno (dest); | |
104 last_regno = first_regno + subreg_nregs (dest); | |
105 | |
106 } | |
107 else | |
108 { | |
109 first_regno = REGNO (dest); | |
110 last_regno = END_HARD_REGNO (dest); | |
111 } | |
112 | |
113 if (GET_CODE (x) == CLOBBER) | |
114 for (i = first_regno; i < last_regno; i++) | |
115 CLEAR_HARD_REG_BIT (current_live_regs, i); | |
116 else | |
117 for (i = first_regno; i < last_regno; i++) | |
118 { | |
119 SET_HARD_REG_BIT (current_live_regs, i); | |
120 CLEAR_HARD_REG_BIT (pending_dead_regs, i); | |
121 } | |
122 } | |
123 | |
124 /* Find the number of the basic block with correct live register | |
125 information that starts closest to INSN. Return -1 if we couldn't | |
126 find such a basic block or the beginning is more than | |
127 SEARCH_LIMIT instructions before INSN. Use SEARCH_LIMIT = -1 for | |
128 an unlimited search. | |
129 | |
130 The delay slot filling code destroys the control-flow graph so, | |
131 instead of finding the basic block containing INSN, we search | |
132 backwards toward a BARRIER where the live register information is | |
133 correct. */ | |
134 | |
135 static int | |
136 find_basic_block (rtx insn, int search_limit) | |
137 { | |
138 basic_block bb; | |
139 | |
140 /* Scan backwards to the previous BARRIER. Then see if we can find a | |
141 label that starts a basic block. Return the basic block number. */ | |
142 for (insn = prev_nonnote_insn (insn); | |
143 insn && !BARRIER_P (insn) && search_limit != 0; | |
144 insn = prev_nonnote_insn (insn), --search_limit) | |
145 ; | |
146 | |
147 /* The closest BARRIER is too far away. */ | |
148 if (search_limit == 0) | |
149 return -1; | |
150 | |
151 /* The start of the function. */ | |
152 else if (insn == 0) | |
153 return ENTRY_BLOCK_PTR->next_bb->index; | |
154 | |
155 /* See if any of the upcoming CODE_LABELs start a basic block. If we reach | |
156 anything other than a CODE_LABEL or note, we can't find this code. */ | |
157 for (insn = next_nonnote_insn (insn); | |
158 insn && LABEL_P (insn); | |
159 insn = next_nonnote_insn (insn)) | |
160 { | |
161 FOR_EACH_BB (bb) | |
162 if (insn == BB_HEAD (bb)) | |
163 return bb->index; | |
164 } | |
165 | |
166 return -1; | |
167 } | |
168 | |
169 /* Similar to next_insn, but ignores insns in the delay slots of | |
170 an annulled branch. */ | |
171 | |
172 static rtx | |
173 next_insn_no_annul (rtx insn) | |
174 { | |
175 if (insn) | |
176 { | |
177 /* If INSN is an annulled branch, skip any insns from the target | |
178 of the branch. */ | |
179 if (INSN_P (insn) | |
180 && INSN_ANNULLED_BRANCH_P (insn) | |
181 && NEXT_INSN (PREV_INSN (insn)) != insn) | |
182 { | |
183 rtx next = NEXT_INSN (insn); | |
184 enum rtx_code code = GET_CODE (next); | |
185 | |
186 while ((code == INSN || code == JUMP_INSN || code == CALL_INSN) | |
187 && INSN_FROM_TARGET_P (next)) | |
188 { | |
189 insn = next; | |
190 next = NEXT_INSN (insn); | |
191 code = GET_CODE (next); | |
192 } | |
193 } | |
194 | |
195 insn = NEXT_INSN (insn); | |
196 if (insn && NONJUMP_INSN_P (insn) | |
197 && GET_CODE (PATTERN (insn)) == SEQUENCE) | |
198 insn = XVECEXP (PATTERN (insn), 0, 0); | |
199 } | |
200 | |
201 return insn; | |
202 } | |
203 | |
204 /* Given X, some rtl, and RES, a pointer to a `struct resource', mark | |
205 which resources are referenced by the insn. If INCLUDE_DELAYED_EFFECTS | |
206 is TRUE, resources used by the called routine will be included for | |
207 CALL_INSNs. */ | |
208 | |
209 void | |
210 mark_referenced_resources (rtx x, struct resources *res, | |
211 int include_delayed_effects) | |
212 { | |
213 enum rtx_code code = GET_CODE (x); | |
214 int i, j; | |
215 unsigned int r; | |
216 const char *format_ptr; | |
217 | |
218 /* Handle leaf items for which we set resource flags. Also, special-case | |
219 CALL, SET and CLOBBER operators. */ | |
220 switch (code) | |
221 { | |
222 case CONST: | |
223 case CONST_INT: | |
224 case CONST_DOUBLE: | |
225 case CONST_FIXED: | |
226 case CONST_VECTOR: | |
227 case PC: | |
228 case SYMBOL_REF: | |
229 case LABEL_REF: | |
230 return; | |
231 | |
232 case SUBREG: | |
233 if (!REG_P (SUBREG_REG (x))) | |
234 mark_referenced_resources (SUBREG_REG (x), res, 0); | |
235 else | |
236 { | |
237 unsigned int regno = subreg_regno (x); | |
238 unsigned int last_regno = regno + subreg_nregs (x); | |
239 | |
240 gcc_assert (last_regno <= FIRST_PSEUDO_REGISTER); | |
241 for (r = regno; r < last_regno; r++) | |
242 SET_HARD_REG_BIT (res->regs, r); | |
243 } | |
244 return; | |
245 | |
246 case REG: | |
247 gcc_assert (HARD_REGISTER_P (x)); | |
248 add_to_hard_reg_set (&res->regs, GET_MODE (x), REGNO (x)); | |
249 return; | |
250 | |
251 case MEM: | |
252 /* If this memory shouldn't change, it really isn't referencing | |
253 memory. */ | |
254 if (MEM_READONLY_P (x)) | |
255 res->unch_memory = 1; | |
256 else | |
257 res->memory = 1; | |
258 res->volatil |= MEM_VOLATILE_P (x); | |
259 | |
260 /* Mark registers used to access memory. */ | |
261 mark_referenced_resources (XEXP (x, 0), res, 0); | |
262 return; | |
263 | |
264 case CC0: | |
265 res->cc = 1; | |
266 return; | |
267 | |
268 case UNSPEC_VOLATILE: | |
269 case TRAP_IF: | |
270 case ASM_INPUT: | |
271 /* Traditional asm's are always volatile. */ | |
272 res->volatil = 1; | |
273 break; | |
274 | |
275 case ASM_OPERANDS: | |
276 res->volatil |= MEM_VOLATILE_P (x); | |
277 | |
278 /* For all ASM_OPERANDS, we must traverse the vector of input operands. | |
279 We can not just fall through here since then we would be confused | |
280 by the ASM_INPUT rtx inside ASM_OPERANDS, which do not indicate | |
281 traditional asms unlike their normal usage. */ | |
282 | |
283 for (i = 0; i < ASM_OPERANDS_INPUT_LENGTH (x); i++) | |
284 mark_referenced_resources (ASM_OPERANDS_INPUT (x, i), res, 0); | |
285 return; | |
286 | |
287 case CALL: | |
288 /* The first operand will be a (MEM (xxx)) but doesn't really reference | |
289 memory. The second operand may be referenced, though. */ | |
290 mark_referenced_resources (XEXP (XEXP (x, 0), 0), res, 0); | |
291 mark_referenced_resources (XEXP (x, 1), res, 0); | |
292 return; | |
293 | |
294 case SET: | |
295 /* Usually, the first operand of SET is set, not referenced. But | |
296 registers used to access memory are referenced. SET_DEST is | |
297 also referenced if it is a ZERO_EXTRACT. */ | |
298 | |
299 mark_referenced_resources (SET_SRC (x), res, 0); | |
300 | |
301 x = SET_DEST (x); | |
302 if (GET_CODE (x) == ZERO_EXTRACT | |
303 || GET_CODE (x) == STRICT_LOW_PART) | |
304 mark_referenced_resources (x, res, 0); | |
305 else if (GET_CODE (x) == SUBREG) | |
306 x = SUBREG_REG (x); | |
307 if (MEM_P (x)) | |
308 mark_referenced_resources (XEXP (x, 0), res, 0); | |
309 return; | |
310 | |
311 case CLOBBER: | |
312 return; | |
313 | |
314 case CALL_INSN: | |
315 if (include_delayed_effects) | |
316 { | |
317 /* A CALL references memory, the frame pointer if it exists, the | |
318 stack pointer, any global registers and any registers given in | |
319 USE insns immediately in front of the CALL. | |
320 | |
321 However, we may have moved some of the parameter loading insns | |
322 into the delay slot of this CALL. If so, the USE's for them | |
323 don't count and should be skipped. */ | |
324 rtx insn = PREV_INSN (x); | |
325 rtx sequence = 0; | |
326 int seq_size = 0; | |
327 int i; | |
328 | |
329 /* If we are part of a delay slot sequence, point at the SEQUENCE. */ | |
330 if (NEXT_INSN (insn) != x) | |
331 { | |
332 sequence = PATTERN (NEXT_INSN (insn)); | |
333 seq_size = XVECLEN (sequence, 0); | |
334 gcc_assert (GET_CODE (sequence) == SEQUENCE); | |
335 } | |
336 | |
337 res->memory = 1; | |
338 SET_HARD_REG_BIT (res->regs, STACK_POINTER_REGNUM); | |
339 if (frame_pointer_needed) | |
340 { | |
341 SET_HARD_REG_BIT (res->regs, FRAME_POINTER_REGNUM); | |
342 #if FRAME_POINTER_REGNUM != HARD_FRAME_POINTER_REGNUM | |
343 SET_HARD_REG_BIT (res->regs, HARD_FRAME_POINTER_REGNUM); | |
344 #endif | |
345 } | |
346 | |
347 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) | |
348 if (global_regs[i]) | |
349 SET_HARD_REG_BIT (res->regs, i); | |
350 | |
351 /* Check for a REG_SETJMP. If it exists, then we must | |
352 assume that this call can need any register. | |
353 | |
354 This is done to be more conservative about how we handle setjmp. | |
355 We assume that they both use and set all registers. Using all | |
356 registers ensures that a register will not be considered dead | |
357 just because it crosses a setjmp call. A register should be | |
358 considered dead only if the setjmp call returns nonzero. */ | |
359 if (find_reg_note (x, REG_SETJMP, NULL)) | |
360 SET_HARD_REG_SET (res->regs); | |
361 | |
362 { | |
363 rtx link; | |
364 | |
365 for (link = CALL_INSN_FUNCTION_USAGE (x); | |
366 link; | |
367 link = XEXP (link, 1)) | |
368 if (GET_CODE (XEXP (link, 0)) == USE) | |
369 { | |
370 for (i = 1; i < seq_size; i++) | |
371 { | |
372 rtx slot_pat = PATTERN (XVECEXP (sequence, 0, i)); | |
373 if (GET_CODE (slot_pat) == SET | |
374 && rtx_equal_p (SET_DEST (slot_pat), | |
375 XEXP (XEXP (link, 0), 0))) | |
376 break; | |
377 } | |
378 if (i >= seq_size) | |
379 mark_referenced_resources (XEXP (XEXP (link, 0), 0), | |
380 res, 0); | |
381 } | |
382 } | |
383 } | |
384 | |
385 /* ... fall through to other INSN processing ... */ | |
386 | |
387 case INSN: | |
388 case JUMP_INSN: | |
389 | |
390 #ifdef INSN_REFERENCES_ARE_DELAYED | |
391 if (! include_delayed_effects | |
392 && INSN_REFERENCES_ARE_DELAYED (x)) | |
393 return; | |
394 #endif | |
395 | |
396 /* No special processing, just speed up. */ | |
397 mark_referenced_resources (PATTERN (x), res, include_delayed_effects); | |
398 return; | |
399 | |
400 default: | |
401 break; | |
402 } | |
403 | |
404 /* Process each sub-expression and flag what it needs. */ | |
405 format_ptr = GET_RTX_FORMAT (code); | |
406 for (i = 0; i < GET_RTX_LENGTH (code); i++) | |
407 switch (*format_ptr++) | |
408 { | |
409 case 'e': | |
410 mark_referenced_resources (XEXP (x, i), res, include_delayed_effects); | |
411 break; | |
412 | |
413 case 'E': | |
414 for (j = 0; j < XVECLEN (x, i); j++) | |
415 mark_referenced_resources (XVECEXP (x, i, j), res, | |
416 include_delayed_effects); | |
417 break; | |
418 } | |
419 } | |
420 | |
421 /* A subroutine of mark_target_live_regs. Search forward from TARGET | |
422 looking for registers that are set before they are used. These are dead. | |
423 Stop after passing a few conditional jumps, and/or a small | |
424 number of unconditional branches. */ | |
425 | |
426 static rtx | |
427 find_dead_or_set_registers (rtx target, struct resources *res, | |
428 rtx *jump_target, int jump_count, | |
429 struct resources set, struct resources needed) | |
430 { | |
431 HARD_REG_SET scratch; | |
432 rtx insn, next; | |
433 rtx jump_insn = 0; | |
434 int i; | |
435 | |
436 for (insn = target; insn; insn = next) | |
437 { | |
438 rtx this_jump_insn = insn; | |
439 | |
440 next = NEXT_INSN (insn); | |
441 | |
442 /* If this instruction can throw an exception, then we don't | |
443 know where we might end up next. That means that we have to | |
444 assume that whatever we have already marked as live really is | |
445 live. */ | |
446 if (can_throw_internal (insn)) | |
447 break; | |
448 | |
449 switch (GET_CODE (insn)) | |
450 { | |
451 case CODE_LABEL: | |
452 /* After a label, any pending dead registers that weren't yet | |
453 used can be made dead. */ | |
454 AND_COMPL_HARD_REG_SET (pending_dead_regs, needed.regs); | |
455 AND_COMPL_HARD_REG_SET (res->regs, pending_dead_regs); | |
456 CLEAR_HARD_REG_SET (pending_dead_regs); | |
457 | |
458 continue; | |
459 | |
460 case BARRIER: | |
461 case NOTE: | |
462 continue; | |
463 | |
464 case INSN: | |
465 if (GET_CODE (PATTERN (insn)) == USE) | |
466 { | |
467 /* If INSN is a USE made by update_block, we care about the | |
468 underlying insn. Any registers set by the underlying insn | |
469 are live since the insn is being done somewhere else. */ | |
470 if (INSN_P (XEXP (PATTERN (insn), 0))) | |
471 mark_set_resources (XEXP (PATTERN (insn), 0), res, 0, | |
472 MARK_SRC_DEST_CALL); | |
473 | |
474 /* All other USE insns are to be ignored. */ | |
475 continue; | |
476 } | |
477 else if (GET_CODE (PATTERN (insn)) == CLOBBER) | |
478 continue; | |
479 else if (GET_CODE (PATTERN (insn)) == SEQUENCE) | |
480 { | |
481 /* An unconditional jump can be used to fill the delay slot | |
482 of a call, so search for a JUMP_INSN in any position. */ | |
483 for (i = 0; i < XVECLEN (PATTERN (insn), 0); i++) | |
484 { | |
485 this_jump_insn = XVECEXP (PATTERN (insn), 0, i); | |
486 if (JUMP_P (this_jump_insn)) | |
487 break; | |
488 } | |
489 } | |
490 | |
491 default: | |
492 break; | |
493 } | |
494 | |
495 if (JUMP_P (this_jump_insn)) | |
496 { | |
497 if (jump_count++ < 10) | |
498 { | |
499 if (any_uncondjump_p (this_jump_insn) | |
500 || GET_CODE (PATTERN (this_jump_insn)) == RETURN) | |
501 { | |
502 next = JUMP_LABEL (this_jump_insn); | |
503 if (jump_insn == 0) | |
504 { | |
505 jump_insn = insn; | |
506 if (jump_target) | |
507 *jump_target = JUMP_LABEL (this_jump_insn); | |
508 } | |
509 } | |
510 else if (any_condjump_p (this_jump_insn)) | |
511 { | |
512 struct resources target_set, target_res; | |
513 struct resources fallthrough_res; | |
514 | |
515 /* We can handle conditional branches here by following | |
516 both paths, and then IOR the results of the two paths | |
517 together, which will give us registers that are dead | |
518 on both paths. Since this is expensive, we give it | |
519 a much higher cost than unconditional branches. The | |
520 cost was chosen so that we will follow at most 1 | |
521 conditional branch. */ | |
522 | |
523 jump_count += 4; | |
524 if (jump_count >= 10) | |
525 break; | |
526 | |
527 mark_referenced_resources (insn, &needed, 1); | |
528 | |
529 /* For an annulled branch, mark_set_resources ignores slots | |
530 filled by instructions from the target. This is correct | |
531 if the branch is not taken. Since we are following both | |
532 paths from the branch, we must also compute correct info | |
533 if the branch is taken. We do this by inverting all of | |
534 the INSN_FROM_TARGET_P bits, calling mark_set_resources, | |
535 and then inverting the INSN_FROM_TARGET_P bits again. */ | |
536 | |
537 if (GET_CODE (PATTERN (insn)) == SEQUENCE | |
538 && INSN_ANNULLED_BRANCH_P (this_jump_insn)) | |
539 { | |
540 for (i = 1; i < XVECLEN (PATTERN (insn), 0); i++) | |
541 INSN_FROM_TARGET_P (XVECEXP (PATTERN (insn), 0, i)) | |
542 = ! INSN_FROM_TARGET_P (XVECEXP (PATTERN (insn), 0, i)); | |
543 | |
544 target_set = set; | |
545 mark_set_resources (insn, &target_set, 0, | |
546 MARK_SRC_DEST_CALL); | |
547 | |
548 for (i = 1; i < XVECLEN (PATTERN (insn), 0); i++) | |
549 INSN_FROM_TARGET_P (XVECEXP (PATTERN (insn), 0, i)) | |
550 = ! INSN_FROM_TARGET_P (XVECEXP (PATTERN (insn), 0, i)); | |
551 | |
552 mark_set_resources (insn, &set, 0, MARK_SRC_DEST_CALL); | |
553 } | |
554 else | |
555 { | |
556 mark_set_resources (insn, &set, 0, MARK_SRC_DEST_CALL); | |
557 target_set = set; | |
558 } | |
559 | |
560 target_res = *res; | |
561 COPY_HARD_REG_SET (scratch, target_set.regs); | |
562 AND_COMPL_HARD_REG_SET (scratch, needed.regs); | |
563 AND_COMPL_HARD_REG_SET (target_res.regs, scratch); | |
564 | |
565 fallthrough_res = *res; | |
566 COPY_HARD_REG_SET (scratch, set.regs); | |
567 AND_COMPL_HARD_REG_SET (scratch, needed.regs); | |
568 AND_COMPL_HARD_REG_SET (fallthrough_res.regs, scratch); | |
569 | |
570 find_dead_or_set_registers (JUMP_LABEL (this_jump_insn), | |
571 &target_res, 0, jump_count, | |
572 target_set, needed); | |
573 find_dead_or_set_registers (next, | |
574 &fallthrough_res, 0, jump_count, | |
575 set, needed); | |
576 IOR_HARD_REG_SET (fallthrough_res.regs, target_res.regs); | |
577 AND_HARD_REG_SET (res->regs, fallthrough_res.regs); | |
578 break; | |
579 } | |
580 else | |
581 break; | |
582 } | |
583 else | |
584 { | |
585 /* Don't try this optimization if we expired our jump count | |
586 above, since that would mean there may be an infinite loop | |
587 in the function being compiled. */ | |
588 jump_insn = 0; | |
589 break; | |
590 } | |
591 } | |
592 | |
593 mark_referenced_resources (insn, &needed, 1); | |
594 mark_set_resources (insn, &set, 0, MARK_SRC_DEST_CALL); | |
595 | |
596 COPY_HARD_REG_SET (scratch, set.regs); | |
597 AND_COMPL_HARD_REG_SET (scratch, needed.regs); | |
598 AND_COMPL_HARD_REG_SET (res->regs, scratch); | |
599 } | |
600 | |
601 return jump_insn; | |
602 } | |
603 | |
604 /* Given X, a part of an insn, and a pointer to a `struct resource', | |
605 RES, indicate which resources are modified by the insn. If | |
606 MARK_TYPE is MARK_SRC_DEST_CALL, also mark resources potentially | |
607 set by the called routine. | |
608 | |
609 If IN_DEST is nonzero, it means we are inside a SET. Otherwise, | |
610 objects are being referenced instead of set. | |
611 | |
612 We never mark the insn as modifying the condition code unless it explicitly | |
613 SETs CC0 even though this is not totally correct. The reason for this is | |
614 that we require a SET of CC0 to immediately precede the reference to CC0. | |
615 So if some other insn sets CC0 as a side-effect, we know it cannot affect | |
616 our computation and thus may be placed in a delay slot. */ | |
617 | |
618 void | |
619 mark_set_resources (rtx x, struct resources *res, int in_dest, | |
620 enum mark_resource_type mark_type) | |
621 { | |
622 enum rtx_code code; | |
623 int i, j; | |
624 unsigned int r; | |
625 const char *format_ptr; | |
626 | |
627 restart: | |
628 | |
629 code = GET_CODE (x); | |
630 | |
631 switch (code) | |
632 { | |
633 case NOTE: | |
634 case BARRIER: | |
635 case CODE_LABEL: | |
636 case USE: | |
637 case CONST_INT: | |
638 case CONST_DOUBLE: | |
639 case CONST_FIXED: | |
640 case CONST_VECTOR: | |
641 case LABEL_REF: | |
642 case SYMBOL_REF: | |
643 case CONST: | |
644 case PC: | |
645 /* These don't set any resources. */ | |
646 return; | |
647 | |
648 case CC0: | |
649 if (in_dest) | |
650 res->cc = 1; | |
651 return; | |
652 | |
653 case CALL_INSN: | |
654 /* Called routine modifies the condition code, memory, any registers | |
655 that aren't saved across calls, global registers and anything | |
656 explicitly CLOBBERed immediately after the CALL_INSN. */ | |
657 | |
658 if (mark_type == MARK_SRC_DEST_CALL) | |
659 { | |
660 rtx link; | |
661 | |
662 res->cc = res->memory = 1; | |
663 | |
664 IOR_HARD_REG_SET (res->regs, regs_invalidated_by_call); | |
665 | |
666 for (link = CALL_INSN_FUNCTION_USAGE (x); | |
667 link; link = XEXP (link, 1)) | |
668 if (GET_CODE (XEXP (link, 0)) == CLOBBER) | |
669 mark_set_resources (SET_DEST (XEXP (link, 0)), res, 1, | |
670 MARK_SRC_DEST); | |
671 | |
672 /* Check for a REG_SETJMP. If it exists, then we must | |
673 assume that this call can clobber any register. */ | |
674 if (find_reg_note (x, REG_SETJMP, NULL)) | |
675 SET_HARD_REG_SET (res->regs); | |
676 } | |
677 | |
678 /* ... and also what its RTL says it modifies, if anything. */ | |
679 | |
680 case JUMP_INSN: | |
681 case INSN: | |
682 | |
683 /* An insn consisting of just a CLOBBER (or USE) is just for flow | |
684 and doesn't actually do anything, so we ignore it. */ | |
685 | |
686 #ifdef INSN_SETS_ARE_DELAYED | |
687 if (mark_type != MARK_SRC_DEST_CALL | |
688 && INSN_SETS_ARE_DELAYED (x)) | |
689 return; | |
690 #endif | |
691 | |
692 x = PATTERN (x); | |
693 if (GET_CODE (x) != USE && GET_CODE (x) != CLOBBER) | |
694 goto restart; | |
695 return; | |
696 | |
697 case SET: | |
698 /* If the source of a SET is a CALL, this is actually done by | |
699 the called routine. So only include it if we are to include the | |
700 effects of the calling routine. */ | |
701 | |
702 mark_set_resources (SET_DEST (x), res, | |
703 (mark_type == MARK_SRC_DEST_CALL | |
704 || GET_CODE (SET_SRC (x)) != CALL), | |
705 mark_type); | |
706 | |
707 mark_set_resources (SET_SRC (x), res, 0, MARK_SRC_DEST); | |
708 return; | |
709 | |
710 case CLOBBER: | |
711 mark_set_resources (XEXP (x, 0), res, 1, MARK_SRC_DEST); | |
712 return; | |
713 | |
714 case SEQUENCE: | |
715 for (i = 0; i < XVECLEN (x, 0); i++) | |
716 if (! (INSN_ANNULLED_BRANCH_P (XVECEXP (x, 0, 0)) | |
717 && INSN_FROM_TARGET_P (XVECEXP (x, 0, i)))) | |
718 mark_set_resources (XVECEXP (x, 0, i), res, 0, mark_type); | |
719 return; | |
720 | |
721 case POST_INC: | |
722 case PRE_INC: | |
723 case POST_DEC: | |
724 case PRE_DEC: | |
725 mark_set_resources (XEXP (x, 0), res, 1, MARK_SRC_DEST); | |
726 return; | |
727 | |
728 case PRE_MODIFY: | |
729 case POST_MODIFY: | |
730 mark_set_resources (XEXP (x, 0), res, 1, MARK_SRC_DEST); | |
731 mark_set_resources (XEXP (XEXP (x, 1), 0), res, 0, MARK_SRC_DEST); | |
732 mark_set_resources (XEXP (XEXP (x, 1), 1), res, 0, MARK_SRC_DEST); | |
733 return; | |
734 | |
735 case SIGN_EXTRACT: | |
736 case ZERO_EXTRACT: | |
737 mark_set_resources (XEXP (x, 0), res, in_dest, MARK_SRC_DEST); | |
738 mark_set_resources (XEXP (x, 1), res, 0, MARK_SRC_DEST); | |
739 mark_set_resources (XEXP (x, 2), res, 0, MARK_SRC_DEST); | |
740 return; | |
741 | |
742 case MEM: | |
743 if (in_dest) | |
744 { | |
745 res->memory = 1; | |
746 res->unch_memory |= MEM_READONLY_P (x); | |
747 res->volatil |= MEM_VOLATILE_P (x); | |
748 } | |
749 | |
750 mark_set_resources (XEXP (x, 0), res, 0, MARK_SRC_DEST); | |
751 return; | |
752 | |
753 case SUBREG: | |
754 if (in_dest) | |
755 { | |
756 if (!REG_P (SUBREG_REG (x))) | |
757 mark_set_resources (SUBREG_REG (x), res, in_dest, mark_type); | |
758 else | |
759 { | |
760 unsigned int regno = subreg_regno (x); | |
761 unsigned int last_regno = regno + subreg_nregs (x); | |
762 | |
763 gcc_assert (last_regno <= FIRST_PSEUDO_REGISTER); | |
764 for (r = regno; r < last_regno; r++) | |
765 SET_HARD_REG_BIT (res->regs, r); | |
766 } | |
767 } | |
768 return; | |
769 | |
770 case REG: | |
771 if (in_dest) | |
772 { | |
773 gcc_assert (HARD_REGISTER_P (x)); | |
774 add_to_hard_reg_set (&res->regs, GET_MODE (x), REGNO (x)); | |
775 } | |
776 return; | |
777 | |
778 case UNSPEC_VOLATILE: | |
779 case ASM_INPUT: | |
780 /* Traditional asm's are always volatile. */ | |
781 res->volatil = 1; | |
782 return; | |
783 | |
784 case TRAP_IF: | |
785 res->volatil = 1; | |
786 break; | |
787 | |
788 case ASM_OPERANDS: | |
789 res->volatil |= MEM_VOLATILE_P (x); | |
790 | |
791 /* For all ASM_OPERANDS, we must traverse the vector of input operands. | |
792 We can not just fall through here since then we would be confused | |
793 by the ASM_INPUT rtx inside ASM_OPERANDS, which do not indicate | |
794 traditional asms unlike their normal usage. */ | |
795 | |
796 for (i = 0; i < ASM_OPERANDS_INPUT_LENGTH (x); i++) | |
797 mark_set_resources (ASM_OPERANDS_INPUT (x, i), res, in_dest, | |
798 MARK_SRC_DEST); | |
799 return; | |
800 | |
801 default: | |
802 break; | |
803 } | |
804 | |
805 /* Process each sub-expression and flag what it needs. */ | |
806 format_ptr = GET_RTX_FORMAT (code); | |
807 for (i = 0; i < GET_RTX_LENGTH (code); i++) | |
808 switch (*format_ptr++) | |
809 { | |
810 case 'e': | |
811 mark_set_resources (XEXP (x, i), res, in_dest, mark_type); | |
812 break; | |
813 | |
814 case 'E': | |
815 for (j = 0; j < XVECLEN (x, i); j++) | |
816 mark_set_resources (XVECEXP (x, i, j), res, in_dest, mark_type); | |
817 break; | |
818 } | |
819 } | |
820 | |
821 /* Return TRUE if INSN is a return, possibly with a filled delay slot. */ | |
822 | |
823 static bool | |
824 return_insn_p (const_rtx insn) | |
825 { | |
826 if (JUMP_P (insn) && GET_CODE (PATTERN (insn)) == RETURN) | |
827 return true; | |
828 | |
829 if (NONJUMP_INSN_P (insn) && GET_CODE (PATTERN (insn)) == SEQUENCE) | |
830 return return_insn_p (XVECEXP (PATTERN (insn), 0, 0)); | |
831 | |
832 return false; | |
833 } | |
834 | |
835 /* Set the resources that are live at TARGET. | |
836 | |
837 If TARGET is zero, we refer to the end of the current function and can | |
838 return our precomputed value. | |
839 | |
840 Otherwise, we try to find out what is live by consulting the basic block | |
841 information. This is tricky, because we must consider the actions of | |
842 reload and jump optimization, which occur after the basic block information | |
843 has been computed. | |
844 | |
845 Accordingly, we proceed as follows:: | |
846 | |
847 We find the previous BARRIER and look at all immediately following labels | |
848 (with no intervening active insns) to see if any of them start a basic | |
849 block. If we hit the start of the function first, we use block 0. | |
850 | |
851 Once we have found a basic block and a corresponding first insns, we can | |
852 accurately compute the live status from basic_block_live_regs and | |
853 reg_renumber. (By starting at a label following a BARRIER, we are immune | |
854 to actions taken by reload and jump.) Then we scan all insns between | |
855 that point and our target. For each CLOBBER (or for call-clobbered regs | |
856 when we pass a CALL_INSN), mark the appropriate registers are dead. For | |
857 a SET, mark them as live. | |
858 | |
859 We have to be careful when using REG_DEAD notes because they are not | |
860 updated by such things as find_equiv_reg. So keep track of registers | |
861 marked as dead that haven't been assigned to, and mark them dead at the | |
862 next CODE_LABEL since reload and jump won't propagate values across labels. | |
863 | |
864 If we cannot find the start of a basic block (should be a very rare | |
865 case, if it can happen at all), mark everything as potentially live. | |
866 | |
867 Next, scan forward from TARGET looking for things set or clobbered | |
868 before they are used. These are not live. | |
869 | |
870 Because we can be called many times on the same target, save our results | |
871 in a hash table indexed by INSN_UID. This is only done if the function | |
872 init_resource_info () was invoked before we are called. */ | |
873 | |
874 void | |
875 mark_target_live_regs (rtx insns, rtx target, struct resources *res) | |
876 { | |
877 int b = -1; | |
878 unsigned int i; | |
879 struct target_info *tinfo = NULL; | |
880 rtx insn; | |
881 rtx jump_insn = 0; | |
882 rtx jump_target; | |
883 HARD_REG_SET scratch; | |
884 struct resources set, needed; | |
885 | |
886 /* Handle end of function. */ | |
887 if (target == 0) | |
888 { | |
889 *res = end_of_function_needs; | |
890 return; | |
891 } | |
892 | |
893 /* Handle return insn. */ | |
894 else if (return_insn_p (target)) | |
895 { | |
896 *res = end_of_function_needs; | |
897 mark_referenced_resources (target, res, 0); | |
898 return; | |
899 } | |
900 | |
901 /* We have to assume memory is needed, but the CC isn't. */ | |
902 res->memory = 1; | |
903 res->volatil = res->unch_memory = 0; | |
904 res->cc = 0; | |
905 | |
906 /* See if we have computed this value already. */ | |
907 if (target_hash_table != NULL) | |
908 { | |
909 for (tinfo = target_hash_table[INSN_UID (target) % TARGET_HASH_PRIME]; | |
910 tinfo; tinfo = tinfo->next) | |
911 if (tinfo->uid == INSN_UID (target)) | |
912 break; | |
913 | |
914 /* Start by getting the basic block number. If we have saved | |
915 information, we can get it from there unless the insn at the | |
916 start of the basic block has been deleted. */ | |
917 if (tinfo && tinfo->block != -1 | |
918 && ! INSN_DELETED_P (BB_HEAD (BASIC_BLOCK (tinfo->block)))) | |
919 b = tinfo->block; | |
920 } | |
921 | |
922 if (b == -1) | |
923 b = find_basic_block (target, MAX_DELAY_SLOT_LIVE_SEARCH); | |
924 | |
925 if (target_hash_table != NULL) | |
926 { | |
927 if (tinfo) | |
928 { | |
929 /* If the information is up-to-date, use it. Otherwise, we will | |
930 update it below. */ | |
931 if (b == tinfo->block && b != -1 && tinfo->bb_tick == bb_ticks[b]) | |
932 { | |
933 COPY_HARD_REG_SET (res->regs, tinfo->live_regs); | |
934 return; | |
935 } | |
936 } | |
937 else | |
938 { | |
939 /* Allocate a place to put our results and chain it into the | |
940 hash table. */ | |
941 tinfo = XNEW (struct target_info); | |
942 tinfo->uid = INSN_UID (target); | |
943 tinfo->block = b; | |
944 tinfo->next | |
945 = target_hash_table[INSN_UID (target) % TARGET_HASH_PRIME]; | |
946 target_hash_table[INSN_UID (target) % TARGET_HASH_PRIME] = tinfo; | |
947 } | |
948 } | |
949 | |
950 CLEAR_HARD_REG_SET (pending_dead_regs); | |
951 | |
952 /* If we found a basic block, get the live registers from it and update | |
953 them with anything set or killed between its start and the insn before | |
954 TARGET. Otherwise, we must assume everything is live. */ | |
955 if (b != -1) | |
956 { | |
957 regset regs_live = DF_LR_IN (BASIC_BLOCK (b)); | |
958 rtx start_insn, stop_insn; | |
959 | |
960 /* Compute hard regs live at start of block -- this is the real hard regs | |
961 marked live, plus live pseudo regs that have been renumbered to | |
962 hard regs. */ | |
963 | |
964 REG_SET_TO_HARD_REG_SET (current_live_regs, regs_live); | |
965 | |
966 /* Get starting and ending insn, handling the case where each might | |
967 be a SEQUENCE. */ | |
968 start_insn = (b == ENTRY_BLOCK_PTR->next_bb->index ? | |
969 insns : BB_HEAD (BASIC_BLOCK (b))); | |
970 stop_insn = target; | |
971 | |
972 if (NONJUMP_INSN_P (start_insn) | |
973 && GET_CODE (PATTERN (start_insn)) == SEQUENCE) | |
974 start_insn = XVECEXP (PATTERN (start_insn), 0, 0); | |
975 | |
976 if (NONJUMP_INSN_P (stop_insn) | |
977 && GET_CODE (PATTERN (stop_insn)) == SEQUENCE) | |
978 stop_insn = next_insn (PREV_INSN (stop_insn)); | |
979 | |
980 for (insn = start_insn; insn != stop_insn; | |
981 insn = next_insn_no_annul (insn)) | |
982 { | |
983 rtx link; | |
984 rtx real_insn = insn; | |
985 enum rtx_code code = GET_CODE (insn); | |
986 | |
987 /* If this insn is from the target of a branch, it isn't going to | |
988 be used in the sequel. If it is used in both cases, this | |
989 test will not be true. */ | |
990 if ((code == INSN || code == JUMP_INSN || code == CALL_INSN) | |
991 && INSN_FROM_TARGET_P (insn)) | |
992 continue; | |
993 | |
994 /* If this insn is a USE made by update_block, we care about the | |
995 underlying insn. */ | |
996 if (code == INSN && GET_CODE (PATTERN (insn)) == USE | |
997 && INSN_P (XEXP (PATTERN (insn), 0))) | |
998 real_insn = XEXP (PATTERN (insn), 0); | |
999 | |
1000 if (CALL_P (real_insn)) | |
1001 { | |
1002 /* CALL clobbers all call-used regs that aren't fixed except | |
1003 sp, ap, and fp. Do this before setting the result of the | |
1004 call live. */ | |
1005 AND_COMPL_HARD_REG_SET (current_live_regs, | |
1006 regs_invalidated_by_call); | |
1007 | |
1008 /* A CALL_INSN sets any global register live, since it may | |
1009 have been modified by the call. */ | |
1010 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) | |
1011 if (global_regs[i]) | |
1012 SET_HARD_REG_BIT (current_live_regs, i); | |
1013 } | |
1014 | |
1015 /* Mark anything killed in an insn to be deadened at the next | |
1016 label. Ignore USE insns; the only REG_DEAD notes will be for | |
1017 parameters. But they might be early. A CALL_INSN will usually | |
1018 clobber registers used for parameters. It isn't worth bothering | |
1019 with the unlikely case when it won't. */ | |
1020 if ((NONJUMP_INSN_P (real_insn) | |
1021 && GET_CODE (PATTERN (real_insn)) != USE | |
1022 && GET_CODE (PATTERN (real_insn)) != CLOBBER) | |
1023 || JUMP_P (real_insn) | |
1024 || CALL_P (real_insn)) | |
1025 { | |
1026 for (link = REG_NOTES (real_insn); link; link = XEXP (link, 1)) | |
1027 if (REG_NOTE_KIND (link) == REG_DEAD | |
1028 && REG_P (XEXP (link, 0)) | |
1029 && REGNO (XEXP (link, 0)) < FIRST_PSEUDO_REGISTER) | |
1030 add_to_hard_reg_set (&pending_dead_regs, | |
1031 GET_MODE (XEXP (link, 0)), | |
1032 REGNO (XEXP (link, 0))); | |
1033 | |
1034 note_stores (PATTERN (real_insn), update_live_status, NULL); | |
1035 | |
1036 /* If any registers were unused after this insn, kill them. | |
1037 These notes will always be accurate. */ | |
1038 for (link = REG_NOTES (real_insn); link; link = XEXP (link, 1)) | |
1039 if (REG_NOTE_KIND (link) == REG_UNUSED | |
1040 && REG_P (XEXP (link, 0)) | |
1041 && REGNO (XEXP (link, 0)) < FIRST_PSEUDO_REGISTER) | |
1042 remove_from_hard_reg_set (¤t_live_regs, | |
1043 GET_MODE (XEXP (link, 0)), | |
1044 REGNO (XEXP (link, 0))); | |
1045 } | |
1046 | |
1047 else if (LABEL_P (real_insn)) | |
1048 { | |
1049 /* A label clobbers the pending dead registers since neither | |
1050 reload nor jump will propagate a value across a label. */ | |
1051 AND_COMPL_HARD_REG_SET (current_live_regs, pending_dead_regs); | |
1052 CLEAR_HARD_REG_SET (pending_dead_regs); | |
1053 } | |
1054 | |
1055 /* The beginning of the epilogue corresponds to the end of the | |
1056 RTL chain when there are no epilogue insns. Certain resources | |
1057 are implicitly required at that point. */ | |
1058 else if (NOTE_P (real_insn) | |
1059 && NOTE_KIND (real_insn) == NOTE_INSN_EPILOGUE_BEG) | |
1060 IOR_HARD_REG_SET (current_live_regs, start_of_epilogue_needs.regs); | |
1061 } | |
1062 | |
1063 COPY_HARD_REG_SET (res->regs, current_live_regs); | |
1064 if (tinfo != NULL) | |
1065 { | |
1066 tinfo->block = b; | |
1067 tinfo->bb_tick = bb_ticks[b]; | |
1068 } | |
1069 } | |
1070 else | |
1071 /* We didn't find the start of a basic block. Assume everything | |
1072 in use. This should happen only extremely rarely. */ | |
1073 SET_HARD_REG_SET (res->regs); | |
1074 | |
1075 CLEAR_RESOURCE (&set); | |
1076 CLEAR_RESOURCE (&needed); | |
1077 | |
1078 jump_insn = find_dead_or_set_registers (target, res, &jump_target, 0, | |
1079 set, needed); | |
1080 | |
1081 /* If we hit an unconditional branch, we have another way of finding out | |
1082 what is live: we can see what is live at the branch target and include | |
1083 anything used but not set before the branch. We add the live | |
1084 resources found using the test below to those found until now. */ | |
1085 | |
1086 if (jump_insn) | |
1087 { | |
1088 struct resources new_resources; | |
1089 rtx stop_insn = next_active_insn (jump_insn); | |
1090 | |
1091 mark_target_live_regs (insns, next_active_insn (jump_target), | |
1092 &new_resources); | |
1093 CLEAR_RESOURCE (&set); | |
1094 CLEAR_RESOURCE (&needed); | |
1095 | |
1096 /* Include JUMP_INSN in the needed registers. */ | |
1097 for (insn = target; insn != stop_insn; insn = next_active_insn (insn)) | |
1098 { | |
1099 mark_referenced_resources (insn, &needed, 1); | |
1100 | |
1101 COPY_HARD_REG_SET (scratch, needed.regs); | |
1102 AND_COMPL_HARD_REG_SET (scratch, set.regs); | |
1103 IOR_HARD_REG_SET (new_resources.regs, scratch); | |
1104 | |
1105 mark_set_resources (insn, &set, 0, MARK_SRC_DEST_CALL); | |
1106 } | |
1107 | |
1108 IOR_HARD_REG_SET (res->regs, new_resources.regs); | |
1109 } | |
1110 | |
1111 if (tinfo != NULL) | |
1112 { | |
1113 COPY_HARD_REG_SET (tinfo->live_regs, res->regs); | |
1114 } | |
1115 } | |
1116 | |
1117 /* Initialize the resources required by mark_target_live_regs (). | |
1118 This should be invoked before the first call to mark_target_live_regs. */ | |
1119 | |
1120 void | |
1121 init_resource_info (rtx epilogue_insn) | |
1122 { | |
1123 int i; | |
1124 | |
1125 /* Indicate what resources are required to be valid at the end of the current | |
1126 function. The condition code never is and memory always is. If the | |
1127 frame pointer is needed, it is and so is the stack pointer unless | |
1128 EXIT_IGNORE_STACK is nonzero. If the frame pointer is not needed, the | |
1129 stack pointer is. Registers used to return the function value are | |
1130 needed. Registers holding global variables are needed. */ | |
1131 | |
1132 end_of_function_needs.cc = 0; | |
1133 end_of_function_needs.memory = 1; | |
1134 end_of_function_needs.unch_memory = 0; | |
1135 CLEAR_HARD_REG_SET (end_of_function_needs.regs); | |
1136 | |
1137 if (frame_pointer_needed) | |
1138 { | |
1139 SET_HARD_REG_BIT (end_of_function_needs.regs, FRAME_POINTER_REGNUM); | |
1140 #if HARD_FRAME_POINTER_REGNUM != FRAME_POINTER_REGNUM | |
1141 SET_HARD_REG_BIT (end_of_function_needs.regs, HARD_FRAME_POINTER_REGNUM); | |
1142 #endif | |
1143 if (! EXIT_IGNORE_STACK | |
1144 || current_function_sp_is_unchanging) | |
1145 SET_HARD_REG_BIT (end_of_function_needs.regs, STACK_POINTER_REGNUM); | |
1146 } | |
1147 else | |
1148 SET_HARD_REG_BIT (end_of_function_needs.regs, STACK_POINTER_REGNUM); | |
1149 | |
1150 if (crtl->return_rtx != 0) | |
1151 mark_referenced_resources (crtl->return_rtx, | |
1152 &end_of_function_needs, 1); | |
1153 | |
1154 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) | |
1155 if (global_regs[i] | |
1156 #ifdef EPILOGUE_USES | |
1157 || EPILOGUE_USES (i) | |
1158 #endif | |
1159 ) | |
1160 SET_HARD_REG_BIT (end_of_function_needs.regs, i); | |
1161 | |
1162 /* The registers required to be live at the end of the function are | |
1163 represented in the flow information as being dead just prior to | |
1164 reaching the end of the function. For example, the return of a value | |
1165 might be represented by a USE of the return register immediately | |
1166 followed by an unconditional jump to the return label where the | |
1167 return label is the end of the RTL chain. The end of the RTL chain | |
1168 is then taken to mean that the return register is live. | |
1169 | |
1170 This sequence is no longer maintained when epilogue instructions are | |
1171 added to the RTL chain. To reconstruct the original meaning, the | |
1172 start of the epilogue (NOTE_INSN_EPILOGUE_BEG) is regarded as the | |
1173 point where these registers become live (start_of_epilogue_needs). | |
1174 If epilogue instructions are present, the registers set by those | |
1175 instructions won't have been processed by flow. Thus, those | |
1176 registers are additionally required at the end of the RTL chain | |
1177 (end_of_function_needs). */ | |
1178 | |
1179 start_of_epilogue_needs = end_of_function_needs; | |
1180 | |
1181 while ((epilogue_insn = next_nonnote_insn (epilogue_insn))) | |
1182 { | |
1183 mark_set_resources (epilogue_insn, &end_of_function_needs, 0, | |
1184 MARK_SRC_DEST_CALL); | |
1185 if (return_insn_p (epilogue_insn)) | |
1186 break; | |
1187 } | |
1188 | |
1189 /* Allocate and initialize the tables used by mark_target_live_regs. */ | |
1190 target_hash_table = XCNEWVEC (struct target_info *, TARGET_HASH_PRIME); | |
1191 bb_ticks = XCNEWVEC (int, last_basic_block); | |
1192 } | |
1193 | |
1194 /* Free up the resources allocated to mark_target_live_regs (). This | |
1195 should be invoked after the last call to mark_target_live_regs (). */ | |
1196 | |
1197 void | |
1198 free_resource_info (void) | |
1199 { | |
1200 if (target_hash_table != NULL) | |
1201 { | |
1202 int i; | |
1203 | |
1204 for (i = 0; i < TARGET_HASH_PRIME; ++i) | |
1205 { | |
1206 struct target_info *ti = target_hash_table[i]; | |
1207 | |
1208 while (ti) | |
1209 { | |
1210 struct target_info *next = ti->next; | |
1211 free (ti); | |
1212 ti = next; | |
1213 } | |
1214 } | |
1215 | |
1216 free (target_hash_table); | |
1217 target_hash_table = NULL; | |
1218 } | |
1219 | |
1220 if (bb_ticks != NULL) | |
1221 { | |
1222 free (bb_ticks); | |
1223 bb_ticks = NULL; | |
1224 } | |
1225 } | |
1226 | |
1227 /* Clear any hashed information that we have stored for INSN. */ | |
1228 | |
1229 void | |
1230 clear_hashed_info_for_insn (rtx insn) | |
1231 { | |
1232 struct target_info *tinfo; | |
1233 | |
1234 if (target_hash_table != NULL) | |
1235 { | |
1236 for (tinfo = target_hash_table[INSN_UID (insn) % TARGET_HASH_PRIME]; | |
1237 tinfo; tinfo = tinfo->next) | |
1238 if (tinfo->uid == INSN_UID (insn)) | |
1239 break; | |
1240 | |
1241 if (tinfo) | |
1242 tinfo->block = -1; | |
1243 } | |
1244 } | |
1245 | |
1246 /* Increment the tick count for the basic block that contains INSN. */ | |
1247 | |
1248 void | |
1249 incr_ticks_for_insn (rtx insn) | |
1250 { | |
1251 int b = find_basic_block (insn, MAX_DELAY_SLOT_LIVE_SEARCH); | |
1252 | |
1253 if (b != -1) | |
1254 bb_ticks[b]++; | |
1255 } | |
1256 | |
1257 /* Add TRIAL to the set of resources used at the end of the current | |
1258 function. */ | |
1259 void | |
1260 mark_end_of_function_resources (rtx trial, int include_delayed_effects) | |
1261 { | |
1262 mark_referenced_resources (trial, &end_of_function_needs, | |
1263 include_delayed_effects); | |
1264 } |