00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "config.h"
00022 #include "system.h"
00023 #include "toplev.h"
00024 #include "rtl.h"
00025 #include "tm_p.h"
00026 #include "hard-reg-set.h"
00027 #include "basic-block.h"
00028 #include "function.h"
00029 #include "regs.h"
00030 #include "flags.h"
00031 #include "output.h"
00032 #include "resource.h"
00033 #include "except.h"
00034 #include "insn-attr.h"
00035 #include "params.h"
00036
00037
00038
00039
00040
00041
00042 struct target_info
00043 {
00044 int uid;
00045 struct target_info *next;
00046 HARD_REG_SET live_regs;
00047 int block;
00048 int bb_tick;
00049 };
00050
00051 #define TARGET_HASH_PRIME 257
00052
00053
00054 static struct resources start_of_epilogue_needs;
00055
00056
00057 static struct resources end_of_function_needs;
00058
00059
00060 static struct target_info **target_hash_table = NULL;
00061
00062
00063
00064
00065
00066
00067 static int *bb_ticks;
00068
00069
00070
00071
00072 static HARD_REG_SET current_live_regs;
00073
00074
00075
00076
00077 static HARD_REG_SET pending_dead_regs;
00078
00079 static void update_live_status PARAMS ((rtx, rtx, void *));
00080 static int find_basic_block PARAMS ((rtx, int));
00081 static rtx next_insn_no_annul PARAMS ((rtx));
00082 static rtx find_dead_or_set_registers PARAMS ((rtx, struct resources*,
00083 rtx*, int, struct resources,
00084 struct resources));
00085
00086
00087
00088
00089 static void
00090 update_live_status (dest, x, data)
00091 rtx dest;
00092 rtx x;
00093 void *data ATTRIBUTE_UNUSED;
00094 {
00095 int first_regno, last_regno;
00096 int i;
00097
00098 if (GET_CODE (dest) != REG
00099 && (GET_CODE (dest) != SUBREG || GET_CODE (SUBREG_REG (dest)) != REG))
00100 return;
00101
00102 if (GET_CODE (dest) == SUBREG)
00103 first_regno = subreg_regno (dest);
00104 else
00105 first_regno = REGNO (dest);
00106
00107 last_regno = first_regno + HARD_REGNO_NREGS (first_regno, GET_MODE (dest));
00108
00109 if (GET_CODE (x) == CLOBBER)
00110 for (i = first_regno; i < last_regno; i++)
00111 CLEAR_HARD_REG_BIT (current_live_regs, i);
00112 else
00113 for (i = first_regno; i < last_regno; i++)
00114 {
00115 SET_HARD_REG_BIT (current_live_regs, i);
00116 CLEAR_HARD_REG_BIT (pending_dead_regs, i);
00117 }
00118 }
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131 static int
00132 find_basic_block (insn, search_limit)
00133 rtx insn;
00134 int search_limit;
00135 {
00136 basic_block bb;
00137
00138
00139
00140 for (insn = prev_nonnote_insn (insn);
00141 insn && GET_CODE (insn) != BARRIER && search_limit != 0;
00142 insn = prev_nonnote_insn (insn), --search_limit)
00143 ;
00144
00145
00146 if (search_limit == 0)
00147 return -1;
00148
00149
00150 else if (insn == 0)
00151 return ENTRY_BLOCK_PTR->next_bb->index;
00152
00153
00154
00155 for (insn = next_nonnote_insn (insn);
00156 insn && GET_CODE (insn) == CODE_LABEL;
00157 insn = next_nonnote_insn (insn))
00158 {
00159 FOR_EACH_BB (bb)
00160 if (insn == bb->head)
00161 return bb->index;
00162 }
00163
00164 return -1;
00165 }
00166
00167
00168
00169
00170 static rtx
00171 next_insn_no_annul (insn)
00172 rtx insn;
00173 {
00174 if (insn)
00175 {
00176
00177
00178 if ((GET_CODE (insn) == JUMP_INSN
00179 || GET_CODE (insn) == CALL_INSN
00180 || GET_CODE (insn) == INSN)
00181 && INSN_ANNULLED_BRANCH_P (insn)
00182 && NEXT_INSN (PREV_INSN (insn)) != insn)
00183 {
00184 rtx next = NEXT_INSN (insn);
00185 enum rtx_code code = GET_CODE (next);
00186
00187 while ((code == INSN || code == JUMP_INSN || code == CALL_INSN)
00188 && INSN_FROM_TARGET_P (next))
00189 {
00190 insn = next;
00191 next = NEXT_INSN (insn);
00192 code = GET_CODE (next);
00193 }
00194 }
00195
00196 insn = NEXT_INSN (insn);
00197 if (insn && GET_CODE (insn) == INSN
00198 && GET_CODE (PATTERN (insn)) == SEQUENCE)
00199 insn = XVECEXP (PATTERN (insn), 0, 0);
00200 }
00201
00202 return insn;
00203 }
00204
00205
00206
00207
00208
00209
00210 void
00211 mark_referenced_resources (x, res, include_delayed_effects)
00212 rtx x;
00213 struct resources *res;
00214 int include_delayed_effects;
00215 {
00216 enum rtx_code code = GET_CODE (x);
00217 int i, j;
00218 unsigned int r;
00219 const char *format_ptr;
00220
00221
00222
00223 switch (code)
00224 {
00225 case CONST:
00226 case CONST_INT:
00227 case CONST_DOUBLE:
00228 case CONST_VECTOR:
00229 case PC:
00230 case SYMBOL_REF:
00231 case LABEL_REF:
00232 return;
00233
00234 case SUBREG:
00235 if (GET_CODE (SUBREG_REG (x)) != REG)
00236 mark_referenced_resources (SUBREG_REG (x), res, 0);
00237 else
00238 {
00239 unsigned int regno = subreg_regno (x);
00240 unsigned int last_regno
00241 = regno + HARD_REGNO_NREGS (regno, GET_MODE (x));
00242
00243 if (last_regno > FIRST_PSEUDO_REGISTER)
00244 abort ();
00245 for (r = regno; r < last_regno; r++)
00246 SET_HARD_REG_BIT (res->regs, r);
00247 }
00248 return;
00249
00250 case REG:
00251 {
00252 unsigned int regno = REGNO (x);
00253 unsigned int last_regno
00254 = regno + HARD_REGNO_NREGS (regno, GET_MODE (x));
00255
00256 if (last_regno > FIRST_PSEUDO_REGISTER)
00257 abort ();
00258 for (r = regno; r < last_regno; r++)
00259 SET_HARD_REG_BIT (res->regs, r);
00260 }
00261 return;
00262
00263 case MEM:
00264
00265
00266 if (RTX_UNCHANGING_P (x))
00267 res->unch_memory = 1;
00268 else
00269 res->memory = 1;
00270 res->volatil |= MEM_VOLATILE_P (x);
00271
00272
00273 mark_referenced_resources (XEXP (x, 0), res, 0);
00274 return;
00275
00276 case CC0:
00277 res->cc = 1;
00278 return;
00279
00280 case UNSPEC_VOLATILE:
00281 case ASM_INPUT:
00282
00283 res->volatil = 1;
00284 return;
00285
00286 case TRAP_IF:
00287 res->volatil = 1;
00288 break;
00289
00290 case ASM_OPERANDS:
00291 res->volatil |= MEM_VOLATILE_P (x);
00292
00293
00294
00295
00296
00297
00298 for (i = 0; i < ASM_OPERANDS_INPUT_LENGTH (x); i++)
00299 mark_referenced_resources (ASM_OPERANDS_INPUT (x, i), res, 0);
00300 return;
00301
00302 case CALL:
00303
00304
00305 mark_referenced_resources (XEXP (XEXP (x, 0), 0), res, 0);
00306 mark_referenced_resources (XEXP (x, 1), res, 0);
00307 return;
00308
00309 case SET:
00310
00311
00312
00313
00314 mark_referenced_resources (SET_SRC (x), res, 0);
00315
00316 x = SET_DEST (x);
00317 if (GET_CODE (x) == SIGN_EXTRACT
00318 || GET_CODE (x) == ZERO_EXTRACT
00319 || GET_CODE (x) == STRICT_LOW_PART)
00320 mark_referenced_resources (x, res, 0);
00321 else if (GET_CODE (x) == SUBREG)
00322 x = SUBREG_REG (x);
00323 if (GET_CODE (x) == MEM)
00324 mark_referenced_resources (XEXP (x, 0), res, 0);
00325 return;
00326
00327 case CLOBBER:
00328 return;
00329
00330 case CALL_INSN:
00331 if (include_delayed_effects)
00332 {
00333
00334
00335
00336
00337
00338
00339
00340 rtx insn = PREV_INSN (x);
00341 rtx sequence = 0;
00342 int seq_size = 0;
00343 int i;
00344
00345
00346 if (NEXT_INSN (insn) != x)
00347 {
00348 sequence = PATTERN (NEXT_INSN (insn));
00349 seq_size = XVECLEN (sequence, 0);
00350 if (GET_CODE (sequence) != SEQUENCE)
00351 abort ();
00352 }
00353
00354 res->memory = 1;
00355 SET_HARD_REG_BIT (res->regs, STACK_POINTER_REGNUM);
00356 if (frame_pointer_needed)
00357 {
00358 SET_HARD_REG_BIT (res->regs, FRAME_POINTER_REGNUM);
00359 #if FRAME_POINTER_REGNUM != HARD_FRAME_POINTER_REGNUM
00360 SET_HARD_REG_BIT (res->regs, HARD_FRAME_POINTER_REGNUM);
00361 #endif
00362 }
00363
00364 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
00365 if (global_regs[i])
00366 SET_HARD_REG_BIT (res->regs, i);
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376 if (find_reg_note (x, REG_SETJMP, NULL))
00377 SET_HARD_REG_SET (res->regs);
00378
00379 {
00380 rtx link;
00381
00382 for (link = CALL_INSN_FUNCTION_USAGE (x);
00383 link;
00384 link = XEXP (link, 1))
00385 if (GET_CODE (XEXP (link, 0)) == USE)
00386 {
00387 for (i = 1; i < seq_size; i++)
00388 {
00389 rtx slot_pat = PATTERN (XVECEXP (sequence, 0, i));
00390 if (GET_CODE (slot_pat) == SET
00391 && rtx_equal_p (SET_DEST (slot_pat),
00392 XEXP (XEXP (link, 0), 0)))
00393 break;
00394 }
00395 if (i >= seq_size)
00396 mark_referenced_resources (XEXP (XEXP (link, 0), 0),
00397 res, 0);
00398 }
00399 }
00400 }
00401
00402
00403
00404 case INSN:
00405 case JUMP_INSN:
00406
00407 #ifdef INSN_REFERENCES_ARE_DELAYED
00408 if (! include_delayed_effects
00409 && INSN_REFERENCES_ARE_DELAYED (x))
00410 return;
00411 #endif
00412
00413
00414 mark_referenced_resources (PATTERN (x), res, include_delayed_effects);
00415 return;
00416
00417 default:
00418 break;
00419 }
00420
00421
00422 format_ptr = GET_RTX_FORMAT (code);
00423 for (i = 0; i < GET_RTX_LENGTH (code); i++)
00424 switch (*format_ptr++)
00425 {
00426 case 'e':
00427 mark_referenced_resources (XEXP (x, i), res, include_delayed_effects);
00428 break;
00429
00430 case 'E':
00431 for (j = 0; j < XVECLEN (x, i); j++)
00432 mark_referenced_resources (XVECEXP (x, i, j), res,
00433 include_delayed_effects);
00434 break;
00435 }
00436 }
00437
00438
00439
00440
00441
00442
00443 static rtx
00444 find_dead_or_set_registers (target, res, jump_target, jump_count, set, needed)
00445 rtx target;
00446 struct resources *res;
00447 rtx *jump_target;
00448 int jump_count;
00449 struct resources set, needed;
00450 {
00451 HARD_REG_SET scratch;
00452 rtx insn, next;
00453 rtx jump_insn = 0;
00454 int i;
00455
00456 for (insn = target; insn; insn = next)
00457 {
00458 rtx this_jump_insn = insn;
00459
00460 next = NEXT_INSN (insn);
00461
00462
00463
00464
00465
00466 if (can_throw_internal (insn))
00467 break;
00468
00469 switch (GET_CODE (insn))
00470 {
00471 case CODE_LABEL:
00472
00473
00474 AND_COMPL_HARD_REG_SET (pending_dead_regs, needed.regs);
00475 AND_COMPL_HARD_REG_SET (res->regs, pending_dead_regs);
00476 CLEAR_HARD_REG_SET (pending_dead_regs);
00477
00478 continue;
00479
00480 case BARRIER:
00481 case NOTE:
00482 continue;
00483
00484 case INSN:
00485 if (GET_CODE (PATTERN (insn)) == USE)
00486 {
00487
00488
00489
00490 if (INSN_P (XEXP (PATTERN (insn), 0)))
00491 mark_set_resources (XEXP (PATTERN (insn), 0), res, 0,
00492 MARK_SRC_DEST_CALL);
00493
00494
00495 continue;
00496 }
00497 else if (GET_CODE (PATTERN (insn)) == CLOBBER)
00498 continue;
00499 else if (GET_CODE (PATTERN (insn)) == SEQUENCE)
00500 {
00501
00502
00503 for (i = 0; i < XVECLEN (PATTERN (insn), 0); i++)
00504 {
00505 this_jump_insn = XVECEXP (PATTERN (insn), 0, i);
00506 if (GET_CODE (this_jump_insn) == JUMP_INSN)
00507 break;
00508 }
00509 }
00510
00511 default:
00512 break;
00513 }
00514
00515 if (GET_CODE (this_jump_insn) == JUMP_INSN)
00516 {
00517 if (jump_count++ < 10)
00518 {
00519 if (any_uncondjump_p (this_jump_insn)
00520 || GET_CODE (PATTERN (this_jump_insn)) == RETURN)
00521 {
00522 next = JUMP_LABEL (this_jump_insn);
00523 if (jump_insn == 0)
00524 {
00525 jump_insn = insn;
00526 if (jump_target)
00527 *jump_target = JUMP_LABEL (this_jump_insn);
00528 }
00529 }
00530 else if (any_condjump_p (this_jump_insn))
00531 {
00532 struct resources target_set, target_res;
00533 struct resources fallthrough_res;
00534
00535
00536
00537
00538
00539
00540
00541
00542
00543 jump_count += 4;
00544 if (jump_count >= 10)
00545 break;
00546
00547 mark_referenced_resources (insn, &needed, 1);
00548
00549
00550
00551
00552
00553
00554
00555
00556
00557 if (GET_CODE (PATTERN (insn)) == SEQUENCE
00558 && INSN_ANNULLED_BRANCH_P (this_jump_insn))
00559 {
00560 for (i = 1; i < XVECLEN (PATTERN (insn), 0); i++)
00561 INSN_FROM_TARGET_P (XVECEXP (PATTERN (insn), 0, i))
00562 = ! INSN_FROM_TARGET_P (XVECEXP (PATTERN (insn), 0, i));
00563
00564 target_set = set;
00565 mark_set_resources (insn, &target_set, 0,
00566 MARK_SRC_DEST_CALL);
00567
00568 for (i = 1; i < XVECLEN (PATTERN (insn), 0); i++)
00569 INSN_FROM_TARGET_P (XVECEXP (PATTERN (insn), 0, i))
00570 = ! INSN_FROM_TARGET_P (XVECEXP (PATTERN (insn), 0, i));
00571
00572 mark_set_resources (insn, &set, 0, MARK_SRC_DEST_CALL);
00573 }
00574 else
00575 {
00576 mark_set_resources (insn, &set, 0, MARK_SRC_DEST_CALL);
00577 target_set = set;
00578 }
00579
00580 target_res = *res;
00581 COPY_HARD_REG_SET (scratch, target_set.regs);
00582 AND_COMPL_HARD_REG_SET (scratch, needed.regs);
00583 AND_COMPL_HARD_REG_SET (target_res.regs, scratch);
00584
00585 fallthrough_res = *res;
00586 COPY_HARD_REG_SET (scratch, set.regs);
00587 AND_COMPL_HARD_REG_SET (scratch, needed.regs);
00588 AND_COMPL_HARD_REG_SET (fallthrough_res.regs, scratch);
00589
00590 find_dead_or_set_registers (JUMP_LABEL (this_jump_insn),
00591 &target_res, 0, jump_count,
00592 target_set, needed);
00593 find_dead_or_set_registers (next,
00594 &fallthrough_res, 0, jump_count,
00595 set, needed);
00596 IOR_HARD_REG_SET (fallthrough_res.regs, target_res.regs);
00597 AND_HARD_REG_SET (res->regs, fallthrough_res.regs);
00598 break;
00599 }
00600 else
00601 break;
00602 }
00603 else
00604 {
00605
00606
00607
00608 jump_insn = 0;
00609 break;
00610 }
00611 }
00612
00613 mark_referenced_resources (insn, &needed, 1);
00614 mark_set_resources (insn, &set, 0, MARK_SRC_DEST_CALL);
00615
00616 COPY_HARD_REG_SET (scratch, set.regs);
00617 AND_COMPL_HARD_REG_SET (scratch, needed.regs);
00618 AND_COMPL_HARD_REG_SET (res->regs, scratch);
00619 }
00620
00621 return jump_insn;
00622 }
00623
00624
00625
00626
00627
00628
00629
00630
00631
00632
00633
00634
00635
00636
00637
00638 void
00639 mark_set_resources (x, res, in_dest, mark_type)
00640 rtx x;
00641 struct resources *res;
00642 int in_dest;
00643 enum mark_resource_type mark_type;
00644 {
00645 enum rtx_code code;
00646 int i, j;
00647 unsigned int r;
00648 const char *format_ptr;
00649
00650 restart:
00651
00652 code = GET_CODE (x);
00653
00654 switch (code)
00655 {
00656 case NOTE:
00657 case BARRIER:
00658 case CODE_LABEL:
00659 case USE:
00660 case CONST_INT:
00661 case CONST_DOUBLE:
00662 case CONST_VECTOR:
00663 case LABEL_REF:
00664 case SYMBOL_REF:
00665 case CONST:
00666 case PC:
00667
00668 return;
00669
00670 case CC0:
00671 if (in_dest)
00672 res->cc = 1;
00673 return;
00674
00675 case CALL_INSN:
00676
00677
00678
00679
00680 if (mark_type == MARK_SRC_DEST_CALL)
00681 {
00682 rtx link;
00683
00684 res->cc = res->memory = 1;
00685 for (r = 0; r < FIRST_PSEUDO_REGISTER; r++)
00686 if (call_used_regs[r] || global_regs[r])
00687 SET_HARD_REG_BIT (res->regs, r);
00688
00689 for (link = CALL_INSN_FUNCTION_USAGE (x);
00690 link; link = XEXP (link, 1))
00691 if (GET_CODE (XEXP (link, 0)) == CLOBBER)
00692 mark_set_resources (SET_DEST (XEXP (link, 0)), res, 1,
00693 MARK_SRC_DEST);
00694
00695
00696
00697 if (find_reg_note (x, REG_SETJMP, NULL))
00698 SET_HARD_REG_SET (res->regs);
00699 }
00700
00701
00702
00703 case JUMP_INSN:
00704 case INSN:
00705
00706
00707
00708
00709 #ifdef INSN_SETS_ARE_DELAYED
00710 if (mark_type != MARK_SRC_DEST_CALL
00711 && INSN_SETS_ARE_DELAYED (x))
00712 return;
00713 #endif
00714
00715 x = PATTERN (x);
00716 if (GET_CODE (x) != USE && GET_CODE (x) != CLOBBER)
00717 goto restart;
00718 return;
00719
00720 case SET:
00721
00722
00723
00724
00725 mark_set_resources (SET_DEST (x), res,
00726 (mark_type == MARK_SRC_DEST_CALL
00727 || GET_CODE (SET_SRC (x)) != CALL),
00728 mark_type);
00729
00730 if (mark_type != MARK_DEST)
00731 mark_set_resources (SET_SRC (x), res, 0, MARK_SRC_DEST);
00732 return;
00733
00734 case CLOBBER:
00735 mark_set_resources (XEXP (x, 0), res, 1, MARK_SRC_DEST);
00736 return;
00737
00738 case SEQUENCE:
00739 for (i = 0; i < XVECLEN (x, 0); i++)
00740 if (! (INSN_ANNULLED_BRANCH_P (XVECEXP (x, 0, 0))
00741 && INSN_FROM_TARGET_P (XVECEXP (x, 0, i))))
00742 mark_set_resources (XVECEXP (x, 0, i), res, 0, mark_type);
00743 return;
00744
00745 case POST_INC:
00746 case PRE_INC:
00747 case POST_DEC:
00748 case PRE_DEC:
00749 mark_set_resources (XEXP (x, 0), res, 1, MARK_SRC_DEST);
00750 return;
00751
00752 case PRE_MODIFY:
00753 case POST_MODIFY:
00754 mark_set_resources (XEXP (x, 0), res, 1, MARK_SRC_DEST);
00755 mark_set_resources (XEXP (XEXP (x, 1), 0), res, 0, MARK_SRC_DEST);
00756 mark_set_resources (XEXP (XEXP (x, 1), 1), res, 0, MARK_SRC_DEST);
00757 return;
00758
00759 case SIGN_EXTRACT:
00760 case ZERO_EXTRACT:
00761 if (! (mark_type == MARK_DEST && in_dest))
00762 {
00763 mark_set_resources (XEXP (x, 0), res, in_dest, MARK_SRC_DEST);
00764 mark_set_resources (XEXP (x, 1), res, 0, MARK_SRC_DEST);
00765 mark_set_resources (XEXP (x, 2), res, 0, MARK_SRC_DEST);
00766 }
00767 return;
00768
00769 case MEM:
00770 if (in_dest)
00771 {
00772 res->memory = 1;
00773 res->unch_memory |= RTX_UNCHANGING_P (x);
00774 res->volatil |= MEM_VOLATILE_P (x);
00775 }
00776
00777 mark_set_resources (XEXP (x, 0), res, 0, MARK_SRC_DEST);
00778 return;
00779
00780 case SUBREG:
00781 if (in_dest)
00782 {
00783 if (GET_CODE (SUBREG_REG (x)) != REG)
00784 mark_set_resources (SUBREG_REG (x), res, in_dest, mark_type);
00785 else
00786 {
00787 unsigned int regno = subreg_regno (x);
00788 unsigned int last_regno
00789 = regno + HARD_REGNO_NREGS (regno, GET_MODE (x));
00790
00791 if (last_regno > FIRST_PSEUDO_REGISTER)
00792 abort ();
00793 for (r = regno; r < last_regno; r++)
00794 SET_HARD_REG_BIT (res->regs, r);
00795 }
00796 }
00797 return;
00798
00799 case REG:
00800 if (in_dest)
00801 {
00802 unsigned int regno = REGNO (x);
00803 unsigned int last_regno
00804 = regno + HARD_REGNO_NREGS (regno, GET_MODE (x));
00805
00806 if (last_regno > FIRST_PSEUDO_REGISTER)
00807 abort ();
00808 for (r = regno; r < last_regno; r++)
00809 SET_HARD_REG_BIT (res->regs, r);
00810 }
00811 return;
00812
00813 case STRICT_LOW_PART:
00814 if (! (mark_type == MARK_DEST && in_dest))
00815 {
00816 mark_set_resources (XEXP (x, 0), res, 0, MARK_SRC_DEST);
00817 return;
00818 }
00819
00820 case UNSPEC_VOLATILE:
00821 case ASM_INPUT:
00822
00823 res->volatil = 1;
00824 return;
00825
00826 case TRAP_IF:
00827 res->volatil = 1;
00828 break;
00829
00830 case ASM_OPERANDS:
00831 res->volatil |= MEM_VOLATILE_P (x);
00832
00833
00834
00835
00836
00837
00838 for (i = 0; i < ASM_OPERANDS_INPUT_LENGTH (x); i++)
00839 mark_set_resources (ASM_OPERANDS_INPUT (x, i), res, in_dest,
00840 MARK_SRC_DEST);
00841 return;
00842
00843 default:
00844 break;
00845 }
00846
00847
00848 format_ptr = GET_RTX_FORMAT (code);
00849 for (i = 0; i < GET_RTX_LENGTH (code); i++)
00850 switch (*format_ptr++)
00851 {
00852 case 'e':
00853 mark_set_resources (XEXP (x, i), res, in_dest, mark_type);
00854 break;
00855
00856 case 'E':
00857 for (j = 0; j < XVECLEN (x, i); j++)
00858 mark_set_resources (XVECEXP (x, i, j), res, in_dest, mark_type);
00859 break;
00860 }
00861 }
00862
00863
00864
00865
00866
00867
00868
00869
00870
00871
00872
00873
00874
00875
00876
00877
00878
00879
00880
00881
00882
00883
00884
00885
00886
00887
00888
00889
00890
00891
00892
00893
00894
00895
00896
00897
00898
00899
00900
00901
00902 void
00903 mark_target_live_regs (insns, target, res)
00904 rtx insns;
00905 rtx target;
00906 struct resources *res;
00907 {
00908 int b = -1;
00909 unsigned int i;
00910 struct target_info *tinfo = NULL;
00911 rtx insn;
00912 rtx jump_insn = 0;
00913 rtx jump_target;
00914 HARD_REG_SET scratch;
00915 struct resources set, needed;
00916
00917
00918 if (target == 0)
00919 {
00920 *res = end_of_function_needs;
00921 return;
00922 }
00923
00924
00925 res->memory = 1;
00926 res->volatil = res->unch_memory = 0;
00927 res->cc = 0;
00928
00929
00930 if (target_hash_table != NULL)
00931 {
00932 for (tinfo = target_hash_table[INSN_UID (target) % TARGET_HASH_PRIME];
00933 tinfo; tinfo = tinfo->next)
00934 if (tinfo->uid == INSN_UID (target))
00935 break;
00936
00937
00938
00939
00940 if (tinfo && tinfo->block != -1
00941 && ! INSN_DELETED_P (BLOCK_HEAD (tinfo->block)))
00942 b = tinfo->block;
00943 }
00944
00945 if (b == -1)
00946 b = find_basic_block (target, MAX_DELAY_SLOT_LIVE_SEARCH);
00947
00948 if (target_hash_table != NULL)
00949 {
00950 if (tinfo)
00951 {
00952
00953
00954 if (b == tinfo->block && b != -1 && tinfo->bb_tick == bb_ticks[b])
00955 {
00956 COPY_HARD_REG_SET (res->regs, tinfo->live_regs);
00957 return;
00958 }
00959 }
00960 else
00961 {
00962
00963
00964 tinfo = (struct target_info *) xmalloc (sizeof (struct target_info));
00965 tinfo->uid = INSN_UID (target);
00966 tinfo->block = b;
00967 tinfo->next
00968 = target_hash_table[INSN_UID (target) % TARGET_HASH_PRIME];
00969 target_hash_table[INSN_UID (target) % TARGET_HASH_PRIME] = tinfo;
00970 }
00971 }
00972
00973 CLEAR_HARD_REG_SET (pending_dead_regs);
00974
00975
00976
00977
00978 if (b != -1)
00979 {
00980 regset regs_live = BASIC_BLOCK (b)->global_live_at_start;
00981 unsigned int j;
00982 unsigned int regno;
00983 rtx start_insn, stop_insn;
00984
00985
00986
00987
00988
00989 REG_SET_TO_HARD_REG_SET (current_live_regs, regs_live);
00990
00991 EXECUTE_IF_SET_IN_REG_SET
00992 (regs_live, FIRST_PSEUDO_REGISTER, i,
00993 {
00994 if (reg_renumber[i] >= 0)
00995 {
00996 regno = reg_renumber[i];
00997 for (j = regno;
00998 j < regno + HARD_REGNO_NREGS (regno,
00999 PSEUDO_REGNO_MODE (i));
01000 j++)
01001 SET_HARD_REG_BIT (current_live_regs, j);
01002 }
01003 });
01004
01005
01006
01007 start_insn = (b == 0 ? insns : BLOCK_HEAD (b));
01008 stop_insn = target;
01009
01010 if (GET_CODE (start_insn) == INSN
01011 && GET_CODE (PATTERN (start_insn)) == SEQUENCE)
01012 start_insn = XVECEXP (PATTERN (start_insn), 0, 0);
01013
01014 if (GET_CODE (stop_insn) == INSN
01015 && GET_CODE (PATTERN (stop_insn)) == SEQUENCE)
01016 stop_insn = next_insn (PREV_INSN (stop_insn));
01017
01018 for (insn = start_insn; insn != stop_insn;
01019 insn = next_insn_no_annul (insn))
01020 {
01021 rtx link;
01022 rtx real_insn = insn;
01023 enum rtx_code code = GET_CODE (insn);
01024
01025
01026
01027
01028 if ((code == INSN || code == JUMP_INSN || code == CALL_INSN)
01029 && INSN_FROM_TARGET_P (insn))
01030 continue;
01031
01032
01033
01034 if (code == INSN && GET_CODE (PATTERN (insn)) == USE
01035 && INSN_P (XEXP (PATTERN (insn), 0)))
01036 real_insn = XEXP (PATTERN (insn), 0);
01037
01038 if (GET_CODE (real_insn) == CALL_INSN)
01039 {
01040
01041
01042
01043 AND_COMPL_HARD_REG_SET (current_live_regs,
01044 regs_invalidated_by_call);
01045
01046
01047
01048 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
01049 if (global_regs[i])
01050 SET_HARD_REG_BIT (current_live_regs, i);
01051 }
01052
01053
01054
01055
01056
01057
01058 if ((GET_CODE (real_insn) == INSN
01059 && GET_CODE (PATTERN (real_insn)) != USE
01060 && GET_CODE (PATTERN (real_insn)) != CLOBBER)
01061 || GET_CODE (real_insn) == JUMP_INSN
01062 || GET_CODE (real_insn) == CALL_INSN)
01063 {
01064 for (link = REG_NOTES (real_insn); link; link = XEXP (link, 1))
01065 if (REG_NOTE_KIND (link) == REG_DEAD
01066 && GET_CODE (XEXP (link, 0)) == REG
01067 && REGNO (XEXP (link, 0)) < FIRST_PSEUDO_REGISTER)
01068 {
01069 unsigned int first_regno = REGNO (XEXP (link, 0));
01070 unsigned int last_regno
01071 = (first_regno
01072 + HARD_REGNO_NREGS (first_regno,
01073 GET_MODE (XEXP (link, 0))));
01074
01075 for (i = first_regno; i < last_regno; i++)
01076 SET_HARD_REG_BIT (pending_dead_regs, i);
01077 }
01078
01079 note_stores (PATTERN (real_insn), update_live_status, NULL);
01080
01081
01082
01083 for (link = REG_NOTES (real_insn); link; link = XEXP (link, 1))
01084 if (REG_NOTE_KIND (link) == REG_UNUSED
01085 && GET_CODE (XEXP (link, 0)) == REG
01086 && REGNO (XEXP (link, 0)) < FIRST_PSEUDO_REGISTER)
01087 {
01088 unsigned int first_regno = REGNO (XEXP (link, 0));
01089 unsigned int last_regno
01090 = (first_regno
01091 + HARD_REGNO_NREGS (first_regno,
01092 GET_MODE (XEXP (link, 0))));
01093
01094 for (i = first_regno; i < last_regno; i++)
01095 CLEAR_HARD_REG_BIT (current_live_regs, i);
01096 }
01097 }
01098
01099 else if (GET_CODE (real_insn) == CODE_LABEL)
01100 {
01101
01102
01103 AND_COMPL_HARD_REG_SET (current_live_regs, pending_dead_regs);
01104 CLEAR_HARD_REG_SET (pending_dead_regs);
01105 }
01106
01107
01108
01109
01110 else if (GET_CODE (real_insn) == NOTE
01111 && NOTE_LINE_NUMBER (real_insn) == NOTE_INSN_EPILOGUE_BEG)
01112 IOR_HARD_REG_SET (current_live_regs, start_of_epilogue_needs.regs);
01113 }
01114
01115 COPY_HARD_REG_SET (res->regs, current_live_regs);
01116 if (tinfo != NULL)
01117 {
01118 tinfo->block = b;
01119 tinfo->bb_tick = bb_ticks[b];
01120 }
01121 }
01122 else
01123
01124
01125 SET_HARD_REG_SET (res->regs);
01126
01127 CLEAR_RESOURCE (&set);
01128 CLEAR_RESOURCE (&needed);
01129
01130 jump_insn = find_dead_or_set_registers (target, res, &jump_target, 0,
01131 set, needed);
01132
01133
01134
01135
01136
01137
01138 if (jump_insn)
01139 {
01140 struct resources new_resources;
01141 rtx stop_insn = next_active_insn (jump_insn);
01142
01143 mark_target_live_regs (insns, next_active_insn (jump_target),
01144 &new_resources);
01145 CLEAR_RESOURCE (&set);
01146 CLEAR_RESOURCE (&needed);
01147
01148
01149 for (insn = target; insn != stop_insn; insn = next_active_insn (insn))
01150 {
01151 mark_referenced_resources (insn, &needed, 1);
01152
01153 COPY_HARD_REG_SET (scratch, needed.regs);
01154 AND_COMPL_HARD_REG_SET (scratch, set.regs);
01155 IOR_HARD_REG_SET (new_resources.regs, scratch);
01156
01157 mark_set_resources (insn, &set, 0, MARK_SRC_DEST_CALL);
01158 }
01159
01160 IOR_HARD_REG_SET (res->regs, new_resources.regs);
01161 }
01162
01163 if (tinfo != NULL)
01164 {
01165 COPY_HARD_REG_SET (tinfo->live_regs, res->regs);
01166 }
01167 }
01168
01169
01170
01171
01172 void
01173 init_resource_info (epilogue_insn)
01174 rtx epilogue_insn;
01175 {
01176 int i;
01177
01178
01179
01180
01181
01182
01183
01184
01185 end_of_function_needs.cc = 0;
01186 end_of_function_needs.memory = 1;
01187 end_of_function_needs.unch_memory = 0;
01188 CLEAR_HARD_REG_SET (end_of_function_needs.regs);
01189
01190 if (frame_pointer_needed)
01191 {
01192 SET_HARD_REG_BIT (end_of_function_needs.regs, FRAME_POINTER_REGNUM);
01193 #if HARD_FRAME_POINTER_REGNUM != FRAME_POINTER_REGNUM
01194 SET_HARD_REG_BIT (end_of_function_needs.regs, HARD_FRAME_POINTER_REGNUM);
01195 #endif
01196 #ifdef EXIT_IGNORE_STACK
01197 if (! EXIT_IGNORE_STACK
01198 || current_function_sp_is_unchanging)
01199 #endif
01200 SET_HARD_REG_BIT (end_of_function_needs.regs, STACK_POINTER_REGNUM);
01201 }
01202 else
01203 SET_HARD_REG_BIT (end_of_function_needs.regs, STACK_POINTER_REGNUM);
01204
01205 if (current_function_return_rtx != 0)
01206 mark_referenced_resources (current_function_return_rtx,
01207 &end_of_function_needs, 1);
01208
01209 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
01210 if (global_regs[i]
01211 #ifdef EPILOGUE_USES
01212 || EPILOGUE_USES (i)
01213 #endif
01214 )
01215 SET_HARD_REG_BIT (end_of_function_needs.regs, i);
01216
01217
01218
01219
01220
01221
01222
01223
01224
01225
01226
01227
01228
01229
01230
01231
01232
01233
01234 start_of_epilogue_needs = end_of_function_needs;
01235
01236 while ((epilogue_insn = next_nonnote_insn (epilogue_insn)))
01237 mark_set_resources (epilogue_insn, &end_of_function_needs, 0,
01238 MARK_SRC_DEST_CALL);
01239
01240
01241 target_hash_table = (struct target_info **)
01242 xcalloc (TARGET_HASH_PRIME, sizeof (struct target_info *));
01243 bb_ticks = (int *) xcalloc (last_basic_block, sizeof (int));
01244 }
01245
01246
01247
01248
01249 void
01250 free_resource_info ()
01251 {
01252 if (target_hash_table != NULL)
01253 {
01254 int i;
01255
01256 for (i = 0; i < TARGET_HASH_PRIME; ++i)
01257 {
01258 struct target_info *ti = target_hash_table[i];
01259
01260 while (ti)
01261 {
01262 struct target_info *next = ti->next;
01263 free (ti);
01264 ti = next;
01265 }
01266 }
01267
01268 free (target_hash_table);
01269 target_hash_table = NULL;
01270 }
01271
01272 if (bb_ticks != NULL)
01273 {
01274 free (bb_ticks);
01275 bb_ticks = NULL;
01276 }
01277 }
01278
01279
01280
01281 void
01282 clear_hashed_info_for_insn (insn)
01283 rtx insn;
01284 {
01285 struct target_info *tinfo;
01286
01287 if (target_hash_table != NULL)
01288 {
01289 for (tinfo = target_hash_table[INSN_UID (insn) % TARGET_HASH_PRIME];
01290 tinfo; tinfo = tinfo->next)
01291 if (tinfo->uid == INSN_UID (insn))
01292 break;
01293
01294 if (tinfo)
01295 tinfo->block = -1;
01296 }
01297 }
01298
01299
01300
01301 void
01302 incr_ticks_for_insn (insn)
01303 rtx insn;
01304 {
01305 int b = find_basic_block (insn, MAX_DELAY_SLOT_LIVE_SEARCH);
01306
01307 if (b != -1)
01308 bb_ticks[b]++;
01309 }
01310
01311
01312
01313 void
01314 mark_end_of_function_resources (trial, include_delayed_effects)
01315 rtx trial;
01316 int include_delayed_effects;
01317 {
01318 mark_referenced_resources (trial, &end_of_function_needs,
01319 include_delayed_effects);
01320 }