Mercurial > hg > CbC > CbC_gcc
comparison gcc/caller-save.c @ 55:77e2b8dfacca gcc-4.4.5
update it from 4.4.3 to 4.5.0
author | ryoma <e075725@ie.u-ryukyu.ac.jp> |
---|---|
date | Fri, 12 Feb 2010 23:39:51 +0900 |
parents | a06113de4d67 |
children | b7f97abdc517 |
comparison
equal
deleted
inserted
replaced
52:c156f1bd5cd9 | 55:77e2b8dfacca |
---|---|
96 /* Computed by mark_referenced_regs, all regs referenced in a given | 96 /* Computed by mark_referenced_regs, all regs referenced in a given |
97 insn. */ | 97 insn. */ |
98 static HARD_REG_SET referenced_regs; | 98 static HARD_REG_SET referenced_regs; |
99 | 99 |
100 | 100 |
101 typedef void refmarker_fn (rtx *loc, enum machine_mode mode, int hardregno, | |
102 void *mark_arg); | |
103 | |
101 static int reg_save_code (int, enum machine_mode); | 104 static int reg_save_code (int, enum machine_mode); |
102 static int reg_restore_code (int, enum machine_mode); | 105 static int reg_restore_code (int, enum machine_mode); |
103 | 106 |
104 struct saved_hard_reg; | 107 struct saved_hard_reg; |
105 static void initiate_saved_hard_regs (void); | 108 static void initiate_saved_hard_regs (void); |
106 static struct saved_hard_reg *new_saved_hard_reg (int, int); | 109 static struct saved_hard_reg *new_saved_hard_reg (int, int); |
107 static void finish_saved_hard_regs (void); | 110 static void finish_saved_hard_regs (void); |
108 static int saved_hard_reg_compare_func (const void *, const void *); | 111 static int saved_hard_reg_compare_func (const void *, const void *); |
109 | 112 |
110 static void mark_set_regs (rtx, const_rtx, void *); | 113 static void mark_set_regs (rtx, const_rtx, void *); |
111 static void add_stored_regs (rtx, const_rtx, void *); | 114 static void mark_referenced_regs (rtx *, refmarker_fn *mark, void *mark_arg); |
112 static void mark_referenced_regs (rtx); | 115 static refmarker_fn mark_reg_as_referenced; |
116 static refmarker_fn replace_reg_with_saved_mem; | |
113 static int insert_save (struct insn_chain *, int, int, HARD_REG_SET *, | 117 static int insert_save (struct insn_chain *, int, int, HARD_REG_SET *, |
114 enum machine_mode *); | 118 enum machine_mode *); |
115 static int insert_restore (struct insn_chain *, int, int, int, | 119 static int insert_restore (struct insn_chain *, int, int, int, |
116 enum machine_mode *); | 120 enum machine_mode *); |
117 static struct insn_chain *insert_one_insn (struct insn_chain *, int, int, | 121 static struct insn_chain *insert_one_insn (struct insn_chain *, int, int, |
209 the modes that they can have. If we can't find a mode to use, | 213 the modes that they can have. If we can't find a mode to use, |
210 we can't have the register live over calls. */ | 214 we can't have the register live over calls. */ |
211 | 215 |
212 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) | 216 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) |
213 { | 217 { |
214 if (call_used_regs[i] && ! call_fixed_regs[i]) | 218 if (call_used_regs[i] |
219 && !TEST_HARD_REG_BIT (call_fixed_reg_set, i)) | |
215 { | 220 { |
216 for (j = 1; j <= MOVE_MAX_WORDS; j++) | 221 for (j = 1; j <= MOVE_MAX_WORDS; j++) |
217 { | 222 { |
218 regno_save_mode[i][j] = HARD_REGNO_CALLER_SAVE_MODE (i, j, | 223 regno_save_mode[i][j] = HARD_REGNO_CALLER_SAVE_MODE (i, j, |
219 VOIDmode); | 224 VOIDmode); |
220 if (regno_save_mode[i][j] == VOIDmode && j == 1) | 225 if (regno_save_mode[i][j] == VOIDmode && j == 1) |
221 { | 226 { |
222 call_fixed_regs[i] = 1; | |
223 SET_HARD_REG_BIT (call_fixed_reg_set, i); | 227 SET_HARD_REG_BIT (call_fixed_reg_set, i); |
224 } | 228 } |
225 } | 229 } |
226 } | 230 } |
227 else | 231 else |
285 if (reg_save_code (i,regno_save_mode[i][j]) == -1) | 289 if (reg_save_code (i,regno_save_mode[i][j]) == -1) |
286 { | 290 { |
287 regno_save_mode[i][j] = VOIDmode; | 291 regno_save_mode[i][j] = VOIDmode; |
288 if (j == 1) | 292 if (j == 1) |
289 { | 293 { |
290 call_fixed_regs[i] = 1; | |
291 SET_HARD_REG_BIT (call_fixed_reg_set, i); | 294 SET_HARD_REG_BIT (call_fixed_reg_set, i); |
292 if (call_used_regs[i]) | 295 if (call_used_regs[i]) |
293 SET_HARD_REG_BIT (no_caller_save_reg_set, i); | 296 SET_HARD_REG_BIT (no_caller_save_reg_set, i); |
294 } | 297 } |
295 } | 298 } |
306 | 309 |
307 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) | 310 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) |
308 for (j = 1; j <= MOVE_MAX_WORDS; j++) | 311 for (j = 1; j <= MOVE_MAX_WORDS; j++) |
309 regno_save_mem[i][j] = 0; | 312 regno_save_mem[i][j] = 0; |
310 save_slots_num = 0; | 313 save_slots_num = 0; |
311 | 314 |
312 } | 315 } |
313 | 316 |
314 /* The structure represents a hard register which should be saved | 317 /* The structure represents a hard register which should be saved |
315 through the call. It is used when the integrated register | 318 through the call. It is used when the integrated register |
316 allocator (IRA) is used and sharing save slots is on. */ | 319 allocator (IRA) is used and sharing save slots is on. */ |
389 static int | 392 static int |
390 saved_hard_reg_compare_func (const void *v1p, const void *v2p) | 393 saved_hard_reg_compare_func (const void *v1p, const void *v2p) |
391 { | 394 { |
392 const struct saved_hard_reg *p1 = *(struct saved_hard_reg * const *) v1p; | 395 const struct saved_hard_reg *p1 = *(struct saved_hard_reg * const *) v1p; |
393 const struct saved_hard_reg *p2 = *(struct saved_hard_reg * const *) v2p; | 396 const struct saved_hard_reg *p2 = *(struct saved_hard_reg * const *) v2p; |
394 | 397 |
395 if (flag_omit_frame_pointer) | 398 if (flag_omit_frame_pointer) |
396 { | 399 { |
397 if (p1->call_freq - p2->call_freq != 0) | 400 if (p1->call_freq - p2->call_freq != 0) |
398 return p1->call_freq - p2->call_freq; | 401 return p1->call_freq - p2->call_freq; |
399 } | 402 } |
462 HARD_REG_SET hard_regs_to_save, used_regs, this_insn_sets; | 465 HARD_REG_SET hard_regs_to_save, used_regs, this_insn_sets; |
463 reg_set_iterator rsi; | 466 reg_set_iterator rsi; |
464 int best_slot_num; | 467 int best_slot_num; |
465 int prev_save_slots_num; | 468 int prev_save_slots_num; |
466 rtx prev_save_slots[FIRST_PSEUDO_REGISTER]; | 469 rtx prev_save_slots[FIRST_PSEUDO_REGISTER]; |
467 | 470 |
468 initiate_saved_hard_regs (); | 471 initiate_saved_hard_regs (); |
469 /* Create hard reg saved regs. */ | 472 /* Create hard reg saved regs. */ |
470 for (chain = reload_insn_chain; chain != 0; chain = next) | 473 for (chain = reload_insn_chain; chain != 0; chain = next) |
471 { | 474 { |
472 insn = chain->insn; | 475 insn = chain->insn; |
473 next = chain->next; | 476 next = chain->next; |
474 if (GET_CODE (insn) != CALL_INSN | 477 if (!CALL_P (insn) |
475 || find_reg_note (insn, REG_NORETURN, NULL)) | 478 || find_reg_note (insn, REG_NORETURN, NULL)) |
476 continue; | 479 continue; |
477 freq = REG_FREQ_FROM_BB (BLOCK_FOR_INSN (insn)); | 480 freq = REG_FREQ_FROM_BB (BLOCK_FOR_INSN (insn)); |
478 REG_SET_TO_HARD_REG_SET (hard_regs_to_save, | 481 REG_SET_TO_HARD_REG_SET (hard_regs_to_save, |
479 &chain->live_throughout); | 482 &chain->live_throughout); |
505 EXECUTE_IF_SET_IN_REG_SET | 508 EXECUTE_IF_SET_IN_REG_SET |
506 (&chain->live_throughout, FIRST_PSEUDO_REGISTER, regno, rsi) | 509 (&chain->live_throughout, FIRST_PSEUDO_REGISTER, regno, rsi) |
507 { | 510 { |
508 int r = reg_renumber[regno]; | 511 int r = reg_renumber[regno]; |
509 int bound; | 512 int bound; |
510 | 513 |
511 if (r < 0) | 514 if (r < 0) |
512 continue; | 515 continue; |
513 | 516 |
514 bound = r + hard_regno_nregs[r][PSEUDO_REGNO_MODE (regno)]; | 517 bound = r + hard_regno_nregs[r][PSEUDO_REGNO_MODE (regno)]; |
515 for (; r < bound; r++) | 518 for (; r < bound; r++) |
516 if (TEST_HARD_REG_BIT (used_regs, r)) | 519 if (TEST_HARD_REG_BIT (used_regs, r)) |
517 { | 520 { |
518 if (hard_reg_map[r] != NULL) | 521 if (hard_reg_map[r] != NULL) |
529 for (chain = reload_insn_chain; chain != 0; chain = next) | 532 for (chain = reload_insn_chain; chain != 0; chain = next) |
530 { | 533 { |
531 call_saved_regs_num = 0; | 534 call_saved_regs_num = 0; |
532 insn = chain->insn; | 535 insn = chain->insn; |
533 next = chain->next; | 536 next = chain->next; |
534 if (GET_CODE (insn) != CALL_INSN | 537 if (!CALL_P (insn) |
535 || find_reg_note (insn, REG_NORETURN, NULL)) | 538 || find_reg_note (insn, REG_NORETURN, NULL)) |
536 continue; | 539 continue; |
537 REG_SET_TO_HARD_REG_SET (hard_regs_to_save, | 540 REG_SET_TO_HARD_REG_SET (hard_regs_to_save, |
538 &chain->live_throughout); | 541 &chain->live_throughout); |
539 COPY_HARD_REG_SET (used_regs, call_used_reg_set); | 542 COPY_HARD_REG_SET (used_regs, call_used_reg_set); |
563 EXECUTE_IF_SET_IN_REG_SET | 566 EXECUTE_IF_SET_IN_REG_SET |
564 (&chain->live_throughout, FIRST_PSEUDO_REGISTER, regno, rsi) | 567 (&chain->live_throughout, FIRST_PSEUDO_REGISTER, regno, rsi) |
565 { | 568 { |
566 int r = reg_renumber[regno]; | 569 int r = reg_renumber[regno]; |
567 int bound; | 570 int bound; |
568 | 571 |
569 if (r < 0) | 572 if (r < 0) |
570 continue; | 573 continue; |
571 | 574 |
572 bound = r + hard_regno_nregs[r][PSEUDO_REGNO_MODE (regno)]; | 575 bound = r + hard_regno_nregs[r][PSEUDO_REGNO_MODE (regno)]; |
573 for (; r < bound; r++) | 576 for (; r < bound; r++) |
681 else | 684 else |
682 { | 685 { |
683 /* Now run through all the call-used hard-registers and allocate | 686 /* Now run through all the call-used hard-registers and allocate |
684 space for them in the caller-save area. Try to allocate space | 687 space for them in the caller-save area. Try to allocate space |
685 in a manner which allows multi-register saves/restores to be done. */ | 688 in a manner which allows multi-register saves/restores to be done. */ |
686 | 689 |
687 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) | 690 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) |
688 for (j = MOVE_MAX_WORDS; j > 0; j--) | 691 for (j = MOVE_MAX_WORDS; j > 0; j--) |
689 { | 692 { |
690 int do_save = 1; | 693 int do_save = 1; |
691 | 694 |
692 /* If no mode exists for this size, try another. Also break out | 695 /* If no mode exists for this size, try another. Also break out |
693 if we have already saved this hard register. */ | 696 if we have already saved this hard register. */ |
694 if (regno_save_mode[i][j] == VOIDmode || regno_save_mem[i][1] != 0) | 697 if (regno_save_mode[i][j] == VOIDmode || regno_save_mem[i][1] != 0) |
695 continue; | 698 continue; |
696 | 699 |
697 /* See if any register in this group has been saved. */ | 700 /* See if any register in this group has been saved. */ |
698 for (k = 0; k < j; k++) | 701 for (k = 0; k < j; k++) |
699 if (regno_save_mem[i + k][1]) | 702 if (regno_save_mem[i + k][1]) |
700 { | 703 { |
701 do_save = 0; | 704 do_save = 0; |
702 break; | 705 break; |
703 } | 706 } |
704 if (! do_save) | 707 if (! do_save) |
705 continue; | 708 continue; |
706 | 709 |
707 for (k = 0; k < j; k++) | 710 for (k = 0; k < j; k++) |
708 if (! TEST_HARD_REG_BIT (hard_regs_used, i + k)) | 711 if (! TEST_HARD_REG_BIT (hard_regs_used, i + k)) |
709 { | 712 { |
710 do_save = 0; | 713 do_save = 0; |
711 break; | 714 break; |
712 } | 715 } |
713 if (! do_save) | 716 if (! do_save) |
714 continue; | 717 continue; |
715 | 718 |
716 /* We have found an acceptable mode to store in. Since | 719 /* We have found an acceptable mode to store in. Since |
717 hard register is always saved in the widest mode | 720 hard register is always saved in the widest mode |
718 available, the mode may be wider than necessary, it is | 721 available, the mode may be wider than necessary, it is |
719 OK to reduce the alignment of spill space. We will | 722 OK to reduce the alignment of spill space. We will |
720 verify that it is equal to or greater than required | 723 verify that it is equal to or greater than required |
722 insert_restore and insert_save. */ | 725 insert_restore and insert_save. */ |
723 regno_save_mem[i][j] | 726 regno_save_mem[i][j] |
724 = assign_stack_local_1 (regno_save_mode[i][j], | 727 = assign_stack_local_1 (regno_save_mode[i][j], |
725 GET_MODE_SIZE (regno_save_mode[i][j]), | 728 GET_MODE_SIZE (regno_save_mode[i][j]), |
726 0, true); | 729 0, true); |
727 | 730 |
728 /* Setup single word save area just in case... */ | 731 /* Setup single word save area just in case... */ |
729 for (k = 0; k < j; k++) | 732 for (k = 0; k < j; k++) |
730 /* This should not depend on WORDS_BIG_ENDIAN. | 733 /* This should not depend on WORDS_BIG_ENDIAN. |
731 The order of words in regs is the same as in memory. */ | 734 The order of words in regs is the same as in memory. */ |
732 regno_save_mem[i + k][1] | 735 regno_save_mem[i + k][1] |
768 | 771 |
769 next = chain->next; | 772 next = chain->next; |
770 | 773 |
771 gcc_assert (!chain->is_caller_save_insn); | 774 gcc_assert (!chain->is_caller_save_insn); |
772 | 775 |
773 if (INSN_P (insn)) | 776 if (NONDEBUG_INSN_P (insn)) |
774 { | 777 { |
775 /* If some registers have been saved, see if INSN references | 778 /* If some registers have been saved, see if INSN references |
776 any of them. We must restore them before the insn if so. */ | 779 any of them. We must restore them before the insn if so. */ |
777 | 780 |
778 if (n_regs_saved) | 781 if (n_regs_saved) |
783 /* Restore all registers if this is a JUMP_INSN. */ | 786 /* Restore all registers if this is a JUMP_INSN. */ |
784 COPY_HARD_REG_SET (referenced_regs, hard_regs_saved); | 787 COPY_HARD_REG_SET (referenced_regs, hard_regs_saved); |
785 else | 788 else |
786 { | 789 { |
787 CLEAR_HARD_REG_SET (referenced_regs); | 790 CLEAR_HARD_REG_SET (referenced_regs); |
788 mark_referenced_regs (PATTERN (insn)); | 791 mark_referenced_regs (&PATTERN (insn), |
792 mark_reg_as_referenced, NULL); | |
789 AND_HARD_REG_SET (referenced_regs, hard_regs_saved); | 793 AND_HARD_REG_SET (referenced_regs, hard_regs_saved); |
790 } | 794 } |
791 | 795 |
792 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++) | 796 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++) |
793 if (TEST_HARD_REG_BIT (referenced_regs, regno)) | 797 if (TEST_HARD_REG_BIT (referenced_regs, regno)) |
856 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++) | 860 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++) |
857 if (TEST_HARD_REG_BIT (hard_regs_saved, regno)) | 861 if (TEST_HARD_REG_BIT (hard_regs_saved, regno)) |
858 n_regs_saved++; | 862 n_regs_saved++; |
859 } | 863 } |
860 } | 864 } |
865 else if (DEBUG_INSN_P (insn) && n_regs_saved) | |
866 mark_referenced_regs (&PATTERN (insn), | |
867 replace_reg_with_saved_mem, | |
868 save_mode); | |
861 | 869 |
862 if (chain->next == 0 || chain->next->block != chain->block) | 870 if (chain->next == 0 || chain->next->block != chain->block) |
863 { | 871 { |
864 int regno; | 872 int regno; |
865 /* At the end of the basic block, we must restore any registers that | 873 /* At the end of the basic block, we must restore any registers that |
945 SET_REGNO_REG_SET ((regset) data, i); | 953 SET_REGNO_REG_SET ((regset) data, i); |
946 } | 954 } |
947 | 955 |
948 /* Walk X and record all referenced registers in REFERENCED_REGS. */ | 956 /* Walk X and record all referenced registers in REFERENCED_REGS. */ |
949 static void | 957 static void |
950 mark_referenced_regs (rtx x) | 958 mark_referenced_regs (rtx *loc, refmarker_fn *mark, void *arg) |
951 { | 959 { |
952 enum rtx_code code = GET_CODE (x); | 960 enum rtx_code code = GET_CODE (*loc); |
953 const char *fmt; | 961 const char *fmt; |
954 int i, j; | 962 int i, j; |
955 | 963 |
956 if (code == SET) | 964 if (code == SET) |
957 mark_referenced_regs (SET_SRC (x)); | 965 mark_referenced_regs (&SET_SRC (*loc), mark, arg); |
958 if (code == SET || code == CLOBBER) | 966 if (code == SET || code == CLOBBER) |
959 { | 967 { |
960 x = SET_DEST (x); | 968 loc = &SET_DEST (*loc); |
961 code = GET_CODE (x); | 969 code = GET_CODE (*loc); |
962 if ((code == REG && REGNO (x) < FIRST_PSEUDO_REGISTER) | 970 if ((code == REG && REGNO (*loc) < FIRST_PSEUDO_REGISTER) |
963 || code == PC || code == CC0 | 971 || code == PC || code == CC0 |
964 || (code == SUBREG && REG_P (SUBREG_REG (x)) | 972 || (code == SUBREG && REG_P (SUBREG_REG (*loc)) |
965 && REGNO (SUBREG_REG (x)) < FIRST_PSEUDO_REGISTER | 973 && REGNO (SUBREG_REG (*loc)) < FIRST_PSEUDO_REGISTER |
966 /* If we're setting only part of a multi-word register, | 974 /* If we're setting only part of a multi-word register, |
967 we shall mark it as referenced, because the words | 975 we shall mark it as referenced, because the words |
968 that are not being set should be restored. */ | 976 that are not being set should be restored. */ |
969 && ((GET_MODE_SIZE (GET_MODE (x)) | 977 && ((GET_MODE_SIZE (GET_MODE (*loc)) |
970 >= GET_MODE_SIZE (GET_MODE (SUBREG_REG (x)))) | 978 >= GET_MODE_SIZE (GET_MODE (SUBREG_REG (*loc)))) |
971 || (GET_MODE_SIZE (GET_MODE (SUBREG_REG (x))) | 979 || (GET_MODE_SIZE (GET_MODE (SUBREG_REG (*loc))) |
972 <= UNITS_PER_WORD)))) | 980 <= UNITS_PER_WORD)))) |
973 return; | 981 return; |
974 } | 982 } |
975 if (code == MEM || code == SUBREG) | 983 if (code == MEM || code == SUBREG) |
976 { | 984 { |
977 x = XEXP (x, 0); | 985 loc = &XEXP (*loc, 0); |
978 code = GET_CODE (x); | 986 code = GET_CODE (*loc); |
979 } | 987 } |
980 | 988 |
981 if (code == REG) | 989 if (code == REG) |
982 { | 990 { |
983 int regno = REGNO (x); | 991 int regno = REGNO (*loc); |
984 int hardregno = (regno < FIRST_PSEUDO_REGISTER ? regno | 992 int hardregno = (regno < FIRST_PSEUDO_REGISTER ? regno |
985 : reg_renumber[regno]); | 993 : reg_renumber[regno]); |
986 | 994 |
987 if (hardregno >= 0) | 995 if (hardregno >= 0) |
988 add_to_hard_reg_set (&referenced_regs, GET_MODE (x), hardregno); | 996 mark (loc, GET_MODE (*loc), hardregno, arg); |
997 else if (arg) | |
998 /* ??? Will we ever end up with an equiv expression in a debug | |
999 insn, that would have required restoring a reg, or will | |
1000 reload take care of it for us? */ | |
1001 return; | |
989 /* If this is a pseudo that did not get a hard register, scan its | 1002 /* If this is a pseudo that did not get a hard register, scan its |
990 memory location, since it might involve the use of another | 1003 memory location, since it might involve the use of another |
991 register, which might be saved. */ | 1004 register, which might be saved. */ |
992 else if (reg_equiv_mem[regno] != 0) | 1005 else if (reg_equiv_mem[regno] != 0) |
993 mark_referenced_regs (XEXP (reg_equiv_mem[regno], 0)); | 1006 mark_referenced_regs (&XEXP (reg_equiv_mem[regno], 0), mark, arg); |
994 else if (reg_equiv_address[regno] != 0) | 1007 else if (reg_equiv_address[regno] != 0) |
995 mark_referenced_regs (reg_equiv_address[regno]); | 1008 mark_referenced_regs (®_equiv_address[regno], mark, arg); |
996 return; | 1009 return; |
997 } | 1010 } |
998 | 1011 |
999 fmt = GET_RTX_FORMAT (code); | 1012 fmt = GET_RTX_FORMAT (code); |
1000 for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--) | 1013 for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--) |
1001 { | 1014 { |
1002 if (fmt[i] == 'e') | 1015 if (fmt[i] == 'e') |
1003 mark_referenced_regs (XEXP (x, i)); | 1016 mark_referenced_regs (&XEXP (*loc, i), mark, arg); |
1004 else if (fmt[i] == 'E') | 1017 else if (fmt[i] == 'E') |
1005 for (j = XVECLEN (x, i) - 1; j >= 0; j--) | 1018 for (j = XVECLEN (*loc, i) - 1; j >= 0; j--) |
1006 mark_referenced_regs (XVECEXP (x, i, j)); | 1019 mark_referenced_regs (&XVECEXP (*loc, i, j), mark, arg); |
1007 } | 1020 } |
1008 } | 1021 } |
1022 | |
1023 /* Parameter function for mark_referenced_regs() that adds registers | |
1024 present in the insn and in equivalent mems and addresses to | |
1025 referenced_regs. */ | |
1026 | |
1027 static void | |
1028 mark_reg_as_referenced (rtx *loc ATTRIBUTE_UNUSED, | |
1029 enum machine_mode mode, | |
1030 int hardregno, | |
1031 void *arg ATTRIBUTE_UNUSED) | |
1032 { | |
1033 add_to_hard_reg_set (&referenced_regs, mode, hardregno); | |
1034 } | |
1035 | |
1036 /* Parameter function for mark_referenced_regs() that replaces | |
1037 registers referenced in a debug_insn that would have been restored, | |
1038 should it be a non-debug_insn, with their save locations. */ | |
1039 | |
1040 static void | |
1041 replace_reg_with_saved_mem (rtx *loc, | |
1042 enum machine_mode mode, | |
1043 int regno, | |
1044 void *arg) | |
1045 { | |
1046 unsigned int i, nregs = hard_regno_nregs [regno][mode]; | |
1047 rtx mem; | |
1048 enum machine_mode *save_mode = (enum machine_mode *)arg; | |
1049 | |
1050 for (i = 0; i < nregs; i++) | |
1051 if (TEST_HARD_REG_BIT (hard_regs_saved, regno + i)) | |
1052 break; | |
1053 | |
1054 /* If none of the registers in the range would need restoring, we're | |
1055 all set. */ | |
1056 if (i == nregs) | |
1057 return; | |
1058 | |
1059 while (++i < nregs) | |
1060 if (!TEST_HARD_REG_BIT (hard_regs_saved, regno + i)) | |
1061 break; | |
1062 | |
1063 if (i == nregs | |
1064 && regno_save_mem[regno][nregs]) | |
1065 { | |
1066 mem = copy_rtx (regno_save_mem[regno][nregs]); | |
1067 | |
1068 if (nregs == (unsigned int) hard_regno_nregs[regno][save_mode[regno]]) | |
1069 mem = adjust_address_nv (mem, save_mode[regno], 0); | |
1070 | |
1071 if (GET_MODE (mem) != mode) | |
1072 { | |
1073 /* This is gen_lowpart_if_possible(), but without validating | |
1074 the newly-formed address. */ | |
1075 int offset = 0; | |
1076 | |
1077 if (WORDS_BIG_ENDIAN) | |
1078 offset = (MAX (GET_MODE_SIZE (GET_MODE (mem)), UNITS_PER_WORD) | |
1079 - MAX (GET_MODE_SIZE (mode), UNITS_PER_WORD)); | |
1080 if (BYTES_BIG_ENDIAN) | |
1081 /* Adjust the address so that the address-after-the-data is | |
1082 unchanged. */ | |
1083 offset -= (MIN (UNITS_PER_WORD, GET_MODE_SIZE (mode)) | |
1084 - MIN (UNITS_PER_WORD, GET_MODE_SIZE (GET_MODE (mem)))); | |
1085 | |
1086 mem = adjust_address_nv (mem, mode, offset); | |
1087 } | |
1088 } | |
1089 else | |
1090 { | |
1091 mem = gen_rtx_CONCATN (mode, rtvec_alloc (nregs)); | |
1092 for (i = 0; i < nregs; i++) | |
1093 if (TEST_HARD_REG_BIT (hard_regs_saved, regno + i)) | |
1094 { | |
1095 gcc_assert (regno_save_mem[regno + i][1]); | |
1096 XVECEXP (mem, 0, i) = copy_rtx (regno_save_mem[regno + i][1]); | |
1097 } | |
1098 else | |
1099 { | |
1100 gcc_assert (save_mode[regno] != VOIDmode); | |
1101 XVECEXP (mem, 0, i) = gen_rtx_REG (save_mode [regno], | |
1102 regno + i); | |
1103 } | |
1104 } | |
1105 | |
1106 gcc_assert (GET_MODE (mem) == mode); | |
1107 *loc = mem; | |
1108 } | |
1109 | |
1009 | 1110 |
1010 /* Insert a sequence of insns to restore. Place these insns in front of | 1111 /* Insert a sequence of insns to restore. Place these insns in front of |
1011 CHAIN if BEFORE_P is nonzero, behind the insn otherwise. MAXRESTORE is | 1112 CHAIN if BEFORE_P is nonzero, behind the insn otherwise. MAXRESTORE is |
1012 the maximum number of registers which should be restored during this call. | 1113 the maximum number of registers which should be restored during this call. |
1013 It should never be less than 1 since we only work with entire registers. | 1114 It should never be less than 1 since we only work with entire registers. |