00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125 #include "config.h"
00126 #include "system.h"
00127 #ifdef SGI_MONGOOSE
00128
00129 #include "rtl.h"
00130 #endif
00131 #include "tree.h"
00132 #ifndef SGI_MONGOOSE
00133 #include "rtl.h"
00134 #endif
00135 #include "tm_p.h"
00136 #include "hard-reg-set.h"
00137 #include "basic-block.h"
00138 #include "insn-config.h"
00139 #include "regs.h"
00140 #include "flags.h"
00141 #include "output.h"
00142 #include "function.h"
00143 #include "except.h"
00144 #include "toplev.h"
00145 #include "recog.h"
00146 #include "expr.h"
00147 #include "ssa.h"
00148 #include "timevar.h"
00149
00150 #include "obstack.h"
00151 #include "splay-tree.h"
00152
00153
00154
00155
00156
00157 #ifndef EXIT_IGNORE_STACK
00158 #define EXIT_IGNORE_STACK 0
00159 #endif
00160
00161 #ifndef HAVE_epilogue
00162 #define HAVE_epilogue 0
00163 #endif
00164 #ifndef HAVE_prologue
00165 #define HAVE_prologue 0
00166 #endif
00167 #ifndef HAVE_sibcall_epilogue
00168 #define HAVE_sibcall_epilogue 0
00169 #endif
00170
00171 #ifndef LOCAL_REGNO
00172 #define LOCAL_REGNO(REGNO) 0
00173 #endif
00174 #ifndef EPILOGUE_USES
00175 #define EPILOGUE_USES(REGNO) 0
00176 #endif
00177 #ifndef EH_USES
00178 #define EH_USES(REGNO) 0
00179 #endif
00180
00181 #ifdef HAVE_conditional_execution
00182 #ifndef REVERSE_CONDEXEC_PREDICATES_P
00183 #define REVERSE_CONDEXEC_PREDICATES_P(x, y) ((x) == reverse_condition (y))
00184 #endif
00185 #endif
00186
00187
00188 int flow2_completed;
00189
00190
00191
00192 int max_regno;
00193
00194
00195
00196 varray_type reg_n_info;
00197
00198
00199
00200
00201 int regset_bytes;
00202 int regset_size;
00203
00204
00205
00206
00207 regset regs_live_at_setjmp;
00208
00209
00210
00211
00212
00213 rtx regs_may_share;
00214
00215
00216
00217 int (*lang_missing_noreturn_ok_p) PARAMS ((tree));
00218
00219
00220
00221
00222 static HARD_REG_SET elim_reg_set;
00223
00224
00225 struct reg_cond_life_info
00226 {
00227
00228 rtx condition;
00229
00230 rtx orig_condition;
00231
00232
00233
00234 rtx stores;
00235
00236
00237
00238 };
00239
00240
00241
00242
00243 struct propagate_block_info
00244 {
00245
00246 basic_block bb;
00247
00248
00249 regset reg_live;
00250
00251
00252 regset new_set;
00253
00254
00255
00256 rtx *reg_next_use;
00257
00258
00259
00260 rtx mem_set_list;
00261
00262
00263
00264 regset local_set;
00265
00266
00267
00268 regset cond_local_set;
00269
00270 #ifdef HAVE_conditional_execution
00271
00272
00273 splay_tree reg_cond_dead;
00274
00275
00276 regset reg_cond_reg;
00277 #endif
00278
00279
00280 int mem_set_list_len;
00281
00282
00283 int cc0_live;
00284
00285
00286 int flags;
00287 };
00288
00289
00290 static int ndead;
00291
00292
00293
00294 #define MAX_MEM_SET_LIST_LEN 100
00295
00296
00297 static int verify_wide_reg_1 PARAMS ((rtx *, void *));
00298 static void verify_wide_reg PARAMS ((int, basic_block));
00299 static void verify_local_live_at_start PARAMS ((regset, basic_block));
00300 static void notice_stack_pointer_modification_1 PARAMS ((rtx, rtx, void *));
00301 static void notice_stack_pointer_modification PARAMS ((rtx));
00302 static void mark_reg PARAMS ((rtx, void *));
00303 static void mark_regs_live_at_end PARAMS ((regset));
00304 static int set_phi_alternative_reg PARAMS ((rtx, int, int, void *));
00305 static void calculate_global_regs_live PARAMS ((sbitmap, sbitmap, int));
00306 static void propagate_block_delete_insn PARAMS ((rtx));
00307 static rtx propagate_block_delete_libcall PARAMS ((rtx, rtx));
00308 static int insn_dead_p PARAMS ((struct propagate_block_info *,
00309 rtx, int, rtx));
00310 static int libcall_dead_p PARAMS ((struct propagate_block_info *,
00311 rtx, rtx));
00312 static void mark_set_regs PARAMS ((struct propagate_block_info *,
00313 rtx, rtx));
00314 static void mark_set_1 PARAMS ((struct propagate_block_info *,
00315 enum rtx_code, rtx, rtx,
00316 rtx, int));
00317 static int find_regno_partial PARAMS ((rtx *, void *));
00318
00319 #ifdef HAVE_conditional_execution
00320 static int mark_regno_cond_dead PARAMS ((struct propagate_block_info *,
00321 int, rtx));
00322 static void free_reg_cond_life_info PARAMS ((splay_tree_value));
00323 static int flush_reg_cond_reg_1 PARAMS ((splay_tree_node, void *));
00324 static void flush_reg_cond_reg PARAMS ((struct propagate_block_info *,
00325 int));
00326 static rtx elim_reg_cond PARAMS ((rtx, unsigned int));
00327 static rtx ior_reg_cond PARAMS ((rtx, rtx, int));
00328 static rtx not_reg_cond PARAMS ((rtx));
00329 static rtx and_reg_cond PARAMS ((rtx, rtx, int));
00330 #endif
00331 #ifdef AUTO_INC_DEC
00332 static void attempt_auto_inc PARAMS ((struct propagate_block_info *,
00333 rtx, rtx, rtx, rtx, rtx));
00334 static void find_auto_inc PARAMS ((struct propagate_block_info *,
00335 rtx, rtx));
00336 static int try_pre_increment_1 PARAMS ((struct propagate_block_info *,
00337 rtx));
00338 static int try_pre_increment PARAMS ((rtx, rtx, HOST_WIDE_INT));
00339 #endif
00340 static void mark_used_reg PARAMS ((struct propagate_block_info *,
00341 rtx, rtx, rtx));
00342 static void mark_used_regs PARAMS ((struct propagate_block_info *,
00343 rtx, rtx, rtx));
00344 void dump_flow_info PARAMS ((FILE *));
00345 void debug_flow_info PARAMS ((void));
00346 static void add_to_mem_set_list PARAMS ((struct propagate_block_info *,
00347 rtx));
00348 static int invalidate_mems_from_autoinc PARAMS ((rtx *, void *));
00349 static void invalidate_mems_from_set PARAMS ((struct propagate_block_info *,
00350 rtx));
00351 static void clear_log_links PARAMS ((sbitmap));
00352
00353
00354 void
00355 check_function_return_warnings ()
00356 {
00357 if (warn_missing_noreturn
00358 && !TREE_THIS_VOLATILE (cfun->decl)
00359 && EXIT_BLOCK_PTR->pred == NULL
00360 && (lang_missing_noreturn_ok_p
00361 && !lang_missing_noreturn_ok_p (cfun->decl)))
00362 warning ("function might be possible candidate for attribute `noreturn'");
00363
00364
00365 if (TREE_THIS_VOLATILE (cfun->decl)
00366 && EXIT_BLOCK_PTR->pred != NULL)
00367 warning ("`noreturn' function does return");
00368
00369
00370
00371 else if (warn_return_type
00372 && cfun->x_clobber_return_insn != NULL
00373 && EXIT_BLOCK_PTR->pred != NULL)
00374 {
00375 int max_uid = get_max_uid ();
00376
00377
00378
00379
00380
00381 if (INSN_UID (cfun->x_clobber_return_insn) < max_uid)
00382 {
00383 rtx insn;
00384
00385 for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
00386 if (insn == cfun->x_clobber_return_insn)
00387 {
00388 warning ("control reaches end of non-void function");
00389 break;
00390 }
00391 }
00392 }
00393 }
00394
00395
00396
00397
00398 rtx
00399 first_insn_after_basic_block_note (block)
00400 basic_block block;
00401 {
00402 rtx insn;
00403
00404
00405 insn = block->head;
00406
00407 if (insn == NULL_RTX)
00408 return NULL_RTX;
00409 if (GET_CODE (insn) == CODE_LABEL)
00410 insn = NEXT_INSN (insn);
00411 if (!NOTE_INSN_BASIC_BLOCK_P (insn))
00412 abort ();
00413
00414 return NEXT_INSN (insn);
00415 }
00416
00417
00418
00419
00420
00421 void
00422 life_analysis (f, file, flags)
00423 rtx f;
00424 FILE *file;
00425 int flags;
00426 {
00427 #ifdef ELIMINABLE_REGS
00428 int i;
00429 static const struct {const int from, to; } eliminables[] = ELIMINABLE_REGS;
00430 #endif
00431
00432
00433
00434
00435 CLEAR_HARD_REG_SET (elim_reg_set);
00436
00437 #ifdef ELIMINABLE_REGS
00438 for (i = 0; i < (int) ARRAY_SIZE (eliminables); i++)
00439 SET_HARD_REG_BIT (elim_reg_set, eliminables[i].from);
00440 #else
00441 SET_HARD_REG_BIT (elim_reg_set, FRAME_POINTER_REGNUM);
00442 #endif
00443
00444
00445 #ifdef CANNOT_CHANGE_MODE_CLASS
00446 bitmap_initialize (&subregs_of_mode, 1);
00447 #endif
00448
00449 if (! optimize)
00450 flags &= ~(PROP_LOG_LINKS | PROP_AUTOINC | PROP_ALLOW_CFG_CHANGES);
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462 if (reload_completed)
00463 flags &= ~(PROP_REG_INFO | PROP_AUTOINC);
00464
00465
00466 if (optimize && (flags & PROP_SCAN_DEAD_STORES))
00467 init_alias_analysis ();
00468
00469
00470
00471 delete_noop_moves (f);
00472
00473
00474
00475
00476 if (! reload_completed)
00477 notice_stack_pointer_modification (f);
00478
00479
00480
00481 allocate_reg_life_data ();
00482 allocate_bb_life_data ();
00483
00484
00485 mark_regs_live_at_end (EXIT_BLOCK_PTR->global_live_at_start);
00486
00487
00488
00489
00490
00491 if (flags & PROP_REG_INFO)
00492 memset (regs_ever_live, 0, sizeof (regs_ever_live));
00493 update_life_info (NULL, UPDATE_LIFE_GLOBAL, flags);
00494
00495
00496 if (optimize && (flags & PROP_SCAN_DEAD_STORES))
00497 end_alias_analysis ();
00498
00499 if (file)
00500 dump_flow_info (file);
00501
00502 free_basic_block_vars (1);
00503
00504
00505 delete_dead_jumptables ();
00506 }
00507
00508
00509
00510
00511
00512 static int
00513 verify_wide_reg_1 (px, pregno)
00514 rtx *px;
00515 void *pregno;
00516 {
00517 rtx x = *px;
00518 unsigned int regno = *(int *) pregno;
00519
00520 if (GET_CODE (x) == REG && REGNO (x) == regno)
00521 {
00522 if (GET_MODE_BITSIZE (GET_MODE (x)) <= BITS_PER_WORD)
00523 return 2;
00524 return 1;
00525 }
00526 return 0;
00527 }
00528
00529
00530
00531
00532 static void
00533 verify_wide_reg (regno, bb)
00534 int regno;
00535 basic_block bb;
00536 {
00537 rtx head = bb->head, end = bb->end;
00538
00539 while (1)
00540 {
00541 if (INSN_P (head))
00542 {
00543 int r = for_each_rtx (&PATTERN (head), verify_wide_reg_1, ®no);
00544 if (r == 1)
00545 return;
00546 if (r == 2)
00547 break;
00548 }
00549 if (head == end)
00550 break;
00551 head = NEXT_INSN (head);
00552 }
00553
00554 if (rtl_dump_file)
00555 {
00556 fprintf (rtl_dump_file, "Register %d died unexpectedly.\n", regno);
00557 dump_bb (bb, rtl_dump_file);
00558 }
00559 abort ();
00560 }
00561
00562
00563
00564
00565 static void
00566 verify_local_live_at_start (new_live_at_start, bb)
00567 regset new_live_at_start;
00568 basic_block bb;
00569 {
00570 if (reload_completed)
00571 {
00572
00573
00574 if (! REG_SET_EQUAL_P (new_live_at_start, bb->global_live_at_start))
00575 {
00576 if (rtl_dump_file)
00577 {
00578 fprintf (rtl_dump_file,
00579 "live_at_start mismatch in bb %d, aborting\nNew:\n",
00580 bb->index);
00581 debug_bitmap_file (rtl_dump_file, new_live_at_start);
00582 fputs ("Old:\n", rtl_dump_file);
00583 dump_bb (bb, rtl_dump_file);
00584 }
00585 abort ();
00586 }
00587 }
00588 else
00589 {
00590 int i;
00591
00592
00593 XOR_REG_SET (new_live_at_start, bb->global_live_at_start);
00594
00595 EXECUTE_IF_SET_IN_REG_SET (new_live_at_start, 0, i,
00596 {
00597
00598 if (REGNO_REG_SET_P (bb->global_live_at_start, i))
00599 {
00600 if (rtl_dump_file)
00601 {
00602 fprintf (rtl_dump_file,
00603 "Register %d died unexpectedly.\n", i);
00604 dump_bb (bb, rtl_dump_file);
00605 }
00606 abort ();
00607 }
00608
00609
00610 verify_wide_reg (i, bb);
00611 });
00612 }
00613 }
00614
00615
00616
00617
00618
00619
00620
00621
00622
00623
00624
00625
00626
00627
00628
00629
00630
00631
00632 int
00633 update_life_info (blocks, extent, prop_flags)
00634 sbitmap blocks;
00635 enum update_life_extent extent;
00636 int prop_flags;
00637 {
00638 regset tmp;
00639 regset_head tmp_head;
00640 int i;
00641 int stabilized_prop_flags = prop_flags;
00642 basic_block bb;
00643
00644 tmp = INITIALIZE_REG_SET (tmp_head);
00645 ndead = 0;
00646
00647 timevar_push ((extent == UPDATE_LIFE_LOCAL || blocks)
00648 ? TV_LIFE_UPDATE : TV_LIFE);
00649
00650
00651
00652 if ((prop_flags & PROP_ALLOW_CFG_CHANGES)
00653 && (extent == UPDATE_LIFE_LOCAL || blocks))
00654 abort ();
00655
00656
00657 if (extent != UPDATE_LIFE_LOCAL)
00658 {
00659 for ( ; ; )
00660 {
00661 int changed = 0;
00662
00663 calculate_global_regs_live (blocks, blocks,
00664 prop_flags & (PROP_SCAN_DEAD_CODE
00665 | PROP_SCAN_DEAD_STORES
00666 | PROP_ALLOW_CFG_CHANGES));
00667
00668 if ((prop_flags & (PROP_KILL_DEAD_CODE | PROP_ALLOW_CFG_CHANGES))
00669 != (PROP_KILL_DEAD_CODE | PROP_ALLOW_CFG_CHANGES))
00670 break;
00671
00672
00673
00674 FOR_EACH_BB_REVERSE (bb)
00675 {
00676 COPY_REG_SET (tmp, bb->global_live_at_end);
00677 changed |= propagate_block (bb, tmp, NULL, NULL,
00678 prop_flags & (PROP_SCAN_DEAD_CODE
00679 | PROP_SCAN_DEAD_STORES
00680 | PROP_KILL_DEAD_CODE));
00681 }
00682
00683
00684
00685
00686
00687 stabilized_prop_flags
00688 &= ~(PROP_SCAN_DEAD_CODE | PROP_SCAN_DEAD_STORES
00689 | PROP_KILL_DEAD_CODE);
00690
00691 if (! changed)
00692 break;
00693
00694
00695
00696
00697
00698 cleanup_cfg (CLEANUP_EXPENSIVE);
00699 }
00700
00701
00702 if (extent == UPDATE_LIFE_GLOBAL_RM_NOTES)
00703 count_or_remove_death_notes (blocks, 1);
00704 }
00705
00706
00707 if (prop_flags & PROP_LOG_LINKS)
00708 clear_log_links (blocks);
00709
00710 if (blocks)
00711 {
00712 EXECUTE_IF_SET_IN_SBITMAP (blocks, 0, i,
00713 {
00714 bb = BASIC_BLOCK (i);
00715
00716 COPY_REG_SET (tmp, bb->global_live_at_end);
00717 propagate_block (bb, tmp, NULL, NULL, stabilized_prop_flags);
00718
00719 if (extent == UPDATE_LIFE_LOCAL)
00720 verify_local_live_at_start (tmp, bb);
00721 });
00722 }
00723 else
00724 {
00725 FOR_EACH_BB_REVERSE (bb)
00726 {
00727 COPY_REG_SET (tmp, bb->global_live_at_end);
00728
00729 propagate_block (bb, tmp, NULL, NULL, stabilized_prop_flags);
00730
00731 if (extent == UPDATE_LIFE_LOCAL)
00732 verify_local_live_at_start (tmp, bb);
00733 }
00734 }
00735
00736 FREE_REG_SET (tmp);
00737
00738 if (prop_flags & PROP_REG_INFO)
00739 {
00740
00741
00742
00743
00744 EXECUTE_IF_SET_IN_REG_SET (ENTRY_BLOCK_PTR->global_live_at_end,
00745 FIRST_PSEUDO_REGISTER, i,
00746 { REG_BASIC_BLOCK (i) = REG_BLOCK_GLOBAL; });
00747
00748
00749
00750
00751
00752
00753
00754
00755
00756 EXECUTE_IF_SET_IN_REG_SET (regs_live_at_setjmp,
00757 FIRST_PSEUDO_REGISTER, i,
00758 {
00759 if (regno_reg_rtx[i] != 0)
00760 {
00761 REG_LIVE_LENGTH (i) = -1;
00762 REG_BASIC_BLOCK (i) = REG_BLOCK_UNKNOWN;
00763 }
00764 });
00765 }
00766 timevar_pop ((extent == UPDATE_LIFE_LOCAL || blocks)
00767 ? TV_LIFE_UPDATE : TV_LIFE);
00768 if (ndead && rtl_dump_file)
00769 fprintf (rtl_dump_file, "deleted %i dead insns\n", ndead);
00770 return ndead;
00771 }
00772
00773
00774
00775 int
00776 update_life_info_in_dirty_blocks (extent, prop_flags)
00777 enum update_life_extent extent;
00778 int prop_flags;
00779 {
00780 sbitmap update_life_blocks = sbitmap_alloc (last_basic_block);
00781 int n = 0;
00782 basic_block bb;
00783 int retval = 0;
00784
00785 sbitmap_zero (update_life_blocks);
00786 FOR_EACH_BB (bb)
00787 {
00788 if (extent == UPDATE_LIFE_LOCAL)
00789 {
00790 if (bb->flags & BB_DIRTY)
00791 {
00792 SET_BIT (update_life_blocks, bb->index);
00793 n++;
00794 }
00795 }
00796 else
00797 {
00798
00799
00800 SET_BIT (update_life_blocks, bb->index);
00801 if (bb->flags & BB_DIRTY)
00802 n++;
00803 }
00804 }
00805
00806 if (n)
00807 retval = update_life_info (update_life_blocks, extent, prop_flags);
00808
00809 sbitmap_free (update_life_blocks);
00810 return retval;
00811 }
00812
00813
00814
00815
00816
00817 void
00818 free_basic_block_vars (keep_head_end_p)
00819 int keep_head_end_p;
00820 {
00821 if (! keep_head_end_p)
00822 {
00823 if (basic_block_info)
00824 {
00825 clear_edges ();
00826 VARRAY_FREE (basic_block_info);
00827 }
00828 n_basic_blocks = 0;
00829 last_basic_block = 0;
00830
00831 ENTRY_BLOCK_PTR->aux = NULL;
00832 ENTRY_BLOCK_PTR->global_live_at_end = NULL;
00833 EXIT_BLOCK_PTR->aux = NULL;
00834 EXIT_BLOCK_PTR->global_live_at_start = NULL;
00835 }
00836 }
00837
00838
00839
00840 int
00841 delete_noop_moves (f)
00842 rtx f ATTRIBUTE_UNUSED;
00843 {
00844 rtx insn, next;
00845 basic_block bb;
00846 int nnoops = 0;
00847
00848 FOR_EACH_BB (bb)
00849 {
00850 for (insn = bb->head; insn != NEXT_INSN (bb->end); insn = next)
00851 {
00852 next = NEXT_INSN (insn);
00853 if (INSN_P (insn) && noop_move_p (insn))
00854 {
00855 rtx note;
00856
00857
00858
00859
00860 if ((note = find_reg_note (insn, REG_LIBCALL, NULL_RTX))
00861 && XEXP (note, 0) != insn)
00862 {
00863 rtx new_libcall_insn = next_real_insn (insn);
00864 rtx retval_note = find_reg_note (XEXP (note, 0),
00865 REG_RETVAL, NULL_RTX);
00866 REG_NOTES (new_libcall_insn)
00867 = gen_rtx_INSN_LIST (REG_LIBCALL, XEXP (note, 0),
00868 REG_NOTES (new_libcall_insn));
00869 XEXP (retval_note, 0) = new_libcall_insn;
00870 }
00871
00872 delete_insn_and_edges (insn);
00873 nnoops++;
00874 }
00875 }
00876 }
00877 if (nnoops && rtl_dump_file)
00878 fprintf (rtl_dump_file, "deleted %i noop moves", nnoops);
00879 return nnoops;
00880 }
00881
00882
00883
00884
00885
00886 void
00887 delete_dead_jumptables ()
00888 {
00889 rtx insn, next;
00890 for (insn = get_insns (); insn; insn = next)
00891 {
00892 next = NEXT_INSN (insn);
00893 if (GET_CODE (insn) == CODE_LABEL
00894 && LABEL_NUSES (insn) == LABEL_PRESERVE_P (insn)
00895 && GET_CODE (next) == JUMP_INSN
00896 && (GET_CODE (PATTERN (next)) == ADDR_VEC
00897 || GET_CODE (PATTERN (next)) == ADDR_DIFF_VEC))
00898 {
00899 if (rtl_dump_file)
00900 fprintf (rtl_dump_file, "Dead jumptable %i removed\n", INSN_UID (insn));
00901 delete_insn (NEXT_INSN (insn));
00902 delete_insn (insn);
00903 next = NEXT_INSN (next);
00904 }
00905 }
00906 }
00907
00908
00909
00910
00911 static void
00912 notice_stack_pointer_modification_1 (x, pat, data)
00913 rtx x;
00914 rtx pat ATTRIBUTE_UNUSED;
00915 void *data ATTRIBUTE_UNUSED;
00916 {
00917 if (x == stack_pointer_rtx
00918
00919
00920
00921 || (GET_CODE (x) == MEM
00922 && GET_RTX_CLASS (GET_CODE (XEXP (x, 0))) == 'a'
00923 && XEXP (XEXP (x, 0), 0) == stack_pointer_rtx))
00924 current_function_sp_is_unchanging = 0;
00925 }
00926
00927 static void
00928 notice_stack_pointer_modification (f)
00929 rtx f;
00930 {
00931 rtx insn;
00932
00933
00934
00935 current_function_sp_is_unchanging = !current_function_calls_alloca;
00936 if (! current_function_sp_is_unchanging)
00937 return;
00938
00939 for (insn = f; insn; insn = NEXT_INSN (insn))
00940 {
00941 if (INSN_P (insn))
00942 {
00943
00944 note_stores (PATTERN (insn), notice_stack_pointer_modification_1,
00945 NULL);
00946 if (! current_function_sp_is_unchanging)
00947 return;
00948 }
00949 }
00950 }
00951
00952
00953
00954
00955 static void
00956 mark_reg (reg, xset)
00957 rtx reg;
00958 void *xset;
00959 {
00960 regset set = (regset) xset;
00961 int regno = REGNO (reg);
00962
00963 if (GET_MODE (reg) == BLKmode)
00964 abort ();
00965
00966 SET_REGNO_REG_SET (set, regno);
00967 if (regno < FIRST_PSEUDO_REGISTER)
00968 {
00969 int n = HARD_REGNO_NREGS (regno, GET_MODE (reg));
00970 while (--n > 0)
00971 SET_REGNO_REG_SET (set, regno + n);
00972 }
00973 }
00974
00975
00976
00977
00978 static void
00979 mark_regs_live_at_end (set)
00980 regset set;
00981 {
00982 unsigned int i;
00983
00984
00985
00986 if ((HAVE_epilogue && reload_completed)
00987 || ! EXIT_IGNORE_STACK
00988 || (! FRAME_POINTER_REQUIRED
00989 && ! current_function_calls_alloca
00990 && flag_omit_frame_pointer)
00991 || current_function_sp_is_unchanging)
00992 {
00993 SET_REGNO_REG_SET (set, STACK_POINTER_REGNUM);
00994 }
00995
00996
00997
00998
00999
01000 if (! reload_completed || frame_pointer_needed)
01001 {
01002 SET_REGNO_REG_SET (set, FRAME_POINTER_REGNUM);
01003 #if FRAME_POINTER_REGNUM != HARD_FRAME_POINTER_REGNUM
01004
01005 if (! LOCAL_REGNO (HARD_FRAME_POINTER_REGNUM))
01006 SET_REGNO_REG_SET (set, HARD_FRAME_POINTER_REGNUM);
01007 #endif
01008 }
01009
01010 #ifndef PIC_OFFSET_TABLE_REG_CALL_CLOBBERED
01011
01012
01013
01014 if (PIC_OFFSET_TABLE_REGNUM != INVALID_REGNUM
01015 && fixed_regs[PIC_OFFSET_TABLE_REGNUM])
01016 SET_REGNO_REG_SET (set, PIC_OFFSET_TABLE_REGNUM);
01017 #endif
01018
01019
01020
01021
01022 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
01023 if (global_regs[i] || EPILOGUE_USES (i))
01024 SET_REGNO_REG_SET (set, i);
01025
01026 if (HAVE_epilogue && reload_completed)
01027 {
01028
01029 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
01030 if (regs_ever_live[i] && ! LOCAL_REGNO (i)
01031 && ! TEST_HARD_REG_BIT (regs_invalidated_by_call, i))
01032 SET_REGNO_REG_SET (set, i);
01033 }
01034
01035 #ifdef EH_RETURN_DATA_REGNO
01036
01037 if (reload_completed && current_function_calls_eh_return)
01038 for (i = 0; ; ++i)
01039 {
01040 unsigned regno = EH_RETURN_DATA_REGNO(i);
01041 if (regno == INVALID_REGNUM)
01042 break;
01043 SET_REGNO_REG_SET (set, regno);
01044 }
01045 #endif
01046 #ifdef EH_RETURN_STACKADJ_RTX
01047 if ((! HAVE_epilogue || ! reload_completed)
01048 && current_function_calls_eh_return)
01049 {
01050 rtx tmp = EH_RETURN_STACKADJ_RTX;
01051 if (tmp && REG_P (tmp))
01052 mark_reg (tmp, set);
01053 }
01054 #endif
01055 #ifdef EH_RETURN_HANDLER_RTX
01056 if ((! HAVE_epilogue || ! reload_completed)
01057 && current_function_calls_eh_return)
01058 {
01059 rtx tmp = EH_RETURN_HANDLER_RTX;
01060 if (tmp && REG_P (tmp))
01061 mark_reg (tmp, set);
01062 }
01063 #endif
01064
01065
01066 diddle_return_value (mark_reg, set);
01067 }
01068
01069
01070
01071
01072
01073 static int
01074 set_phi_alternative_reg (insn, dest_regno, src_regno, data)
01075 rtx insn ATTRIBUTE_UNUSED;
01076 int dest_regno ATTRIBUTE_UNUSED;
01077 int src_regno;
01078 void *data;
01079 {
01080 regset live = (regset) data;
01081 SET_REGNO_REG_SET (live, src_regno);
01082 return 0;
01083 }
01084
01085
01086
01087
01088
01089
01090
01091 static void
01092 calculate_global_regs_live (blocks_in, blocks_out, flags)
01093 sbitmap blocks_in, blocks_out;
01094 int flags;
01095 {
01096 basic_block *queue, *qhead, *qtail, *qend, bb;
01097 regset tmp, new_live_at_end, invalidated_by_call;
01098 regset_head tmp_head, invalidated_by_call_head;
01099 regset_head new_live_at_end_head;
01100 int i;
01101
01102
01103
01104 #ifdef ENABLE_CHECKING
01105 FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR, NULL, next_bb)
01106 if (bb->aux)
01107 abort ();
01108 #endif
01109
01110 tmp = INITIALIZE_REG_SET (tmp_head);
01111 new_live_at_end = INITIALIZE_REG_SET (new_live_at_end_head);
01112 invalidated_by_call = INITIALIZE_REG_SET (invalidated_by_call_head);
01113
01114
01115 for (i = 0; i < FIRST_PSEUDO_REGISTER; ++i)
01116 if (TEST_HARD_REG_BIT (regs_invalidated_by_call, i))
01117 SET_REGNO_REG_SET (invalidated_by_call, i);
01118
01119
01120
01121
01122 queue = (basic_block *) xmalloc ((n_basic_blocks + 2) * sizeof (*queue));
01123 qtail = queue;
01124 qhead = qend = queue + n_basic_blocks + 2;
01125
01126
01127
01128
01129 if (blocks_in)
01130 {
01131 FOR_EACH_BB (bb)
01132 if (TEST_BIT (blocks_in, bb->index))
01133 {
01134 *--qhead = bb;
01135 bb->aux = bb;
01136 }
01137 }
01138 else
01139 {
01140 FOR_EACH_BB (bb)
01141 {
01142 *--qhead = bb;
01143 bb->aux = bb;
01144 }
01145 }
01146
01147
01148
01149
01150 ENTRY_BLOCK_PTR->aux = EXIT_BLOCK_PTR->aux = NULL;
01151
01152 if (blocks_out)
01153 sbitmap_zero (blocks_out);
01154
01155
01156
01157
01158
01159
01160
01161
01162
01163
01164
01165
01166
01167
01168
01169
01170
01171
01172
01173 while (qhead != qtail)
01174 {
01175 int rescan, changed;
01176 basic_block bb;
01177 edge e;
01178
01179 bb = *qhead++;
01180 if (qhead == qend)
01181 qhead = queue;
01182 bb->aux = NULL;
01183
01184
01185 CLEAR_REG_SET (new_live_at_end);
01186
01187 if (bb->succ)
01188 for (e = bb->succ; e; e = e->succ_next)
01189 {
01190 basic_block sb = e->dest;
01191
01192
01193
01194
01195
01196 if (e->flags & EDGE_EH)
01197 {
01198 bitmap_operation (tmp, sb->global_live_at_start,
01199 invalidated_by_call, BITMAP_AND_COMPL);
01200 IOR_REG_SET (new_live_at_end, tmp);
01201 }
01202 else
01203 IOR_REG_SET (new_live_at_end, sb->global_live_at_start);
01204
01205
01206
01207 if (e->flags & EDGE_EH)
01208 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
01209 if (EH_USES (i))
01210 SET_REGNO_REG_SET (new_live_at_end, i);
01211 }
01212 else
01213 {
01214
01215
01216
01217 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
01218 if (EH_USES (i))
01219 SET_REGNO_REG_SET (new_live_at_end, i);
01220 }
01221
01222
01223 SET_REGNO_REG_SET (new_live_at_end, STACK_POINTER_REGNUM);
01224
01225
01226
01227
01228 if (! reload_completed)
01229 {
01230
01231
01232 SET_REGNO_REG_SET (new_live_at_end, FRAME_POINTER_REGNUM);
01233
01234 #if FRAME_POINTER_REGNUM != ARG_POINTER_REGNUM
01235
01236
01237 if (fixed_regs[ARG_POINTER_REGNUM])
01238 SET_REGNO_REG_SET (new_live_at_end, ARG_POINTER_REGNUM);
01239 #endif
01240
01241
01242
01243 if (PIC_OFFSET_TABLE_REGNUM != INVALID_REGNUM
01244 && fixed_regs[PIC_OFFSET_TABLE_REGNUM])
01245 SET_REGNO_REG_SET (new_live_at_end, PIC_OFFSET_TABLE_REGNUM);
01246 }
01247
01248
01249
01250
01251
01252 if (in_ssa_form)
01253 for_each_successor_phi (bb, &set_phi_alternative_reg,
01254 new_live_at_end);
01255
01256 if (bb == ENTRY_BLOCK_PTR)
01257 {
01258 COPY_REG_SET (bb->global_live_at_end, new_live_at_end);
01259 continue;
01260 }
01261
01262
01263
01264
01265
01266 if (bb->local_set == NULL)
01267 {
01268 bb->local_set = OBSTACK_ALLOC_REG_SET (&flow_obstack);
01269 bb->cond_local_set = OBSTACK_ALLOC_REG_SET (&flow_obstack);
01270 rescan = 1;
01271 }
01272 else
01273 {
01274
01275
01276
01277
01278 CLEAR_REG_SET (tmp);
01279 rescan = bitmap_operation (tmp, bb->global_live_at_end,
01280 new_live_at_end, BITMAP_AND_COMPL);
01281
01282 if (! rescan)
01283 {
01284
01285
01286
01287
01288
01289
01290
01291 CLEAR_REG_SET (tmp);
01292 rescan = bitmap_operation (tmp, new_live_at_end,
01293 bb->cond_local_set, BITMAP_AND);
01294 }
01295
01296 if (! rescan)
01297 {
01298
01299
01300 CLEAR_REG_SET (tmp);
01301 changed = bitmap_operation (tmp, bb->global_live_at_end,
01302 new_live_at_end, BITMAP_XOR);
01303 if (! changed)
01304 continue;
01305
01306
01307
01308
01309 rescan = bitmap_operation (tmp, tmp, bb->local_set,
01310 BITMAP_AND_COMPL);
01311 }
01312 }
01313
01314
01315
01316 if (blocks_out)
01317 SET_BIT (blocks_out, bb->index);
01318
01319 if (! rescan)
01320 {
01321
01322
01323
01324 bitmap_operation (tmp, new_live_at_end, bb->global_live_at_end,
01325 BITMAP_AND_COMPL);
01326 COPY_REG_SET (bb->global_live_at_end, new_live_at_end);
01327
01328 changed = bitmap_operation (bb->global_live_at_start,
01329 bb->global_live_at_start,
01330 tmp, BITMAP_IOR);
01331 if (! changed)
01332 continue;
01333 }
01334 else
01335 {
01336 COPY_REG_SET (bb->global_live_at_end, new_live_at_end);
01337
01338
01339
01340 propagate_block (bb, new_live_at_end, bb->local_set,
01341 bb->cond_local_set, flags);
01342
01343
01344 if (REG_SET_EQUAL_P (bb->global_live_at_start, new_live_at_end))
01345 continue;
01346
01347 COPY_REG_SET (bb->global_live_at_start, new_live_at_end);
01348 }
01349
01350
01351
01352 for (e = bb->pred; e; e = e->pred_next)
01353 {
01354 basic_block pb = e->src;
01355 if (pb->aux == NULL)
01356 {
01357 *qtail++ = pb;
01358 if (qtail == qend)
01359 qtail = queue;
01360 pb->aux = pb;
01361 }
01362 }
01363 }
01364
01365 FREE_REG_SET (tmp);
01366 FREE_REG_SET (new_live_at_end);
01367 FREE_REG_SET (invalidated_by_call);
01368
01369 if (blocks_out)
01370 {
01371 EXECUTE_IF_SET_IN_SBITMAP (blocks_out, 0, i,
01372 {
01373 basic_block bb = BASIC_BLOCK (i);
01374 FREE_REG_SET (bb->local_set);
01375 FREE_REG_SET (bb->cond_local_set);
01376 });
01377 }
01378 else
01379 {
01380 FOR_EACH_BB (bb)
01381 {
01382 FREE_REG_SET (bb->local_set);
01383 FREE_REG_SET (bb->cond_local_set);
01384 }
01385 }
01386
01387 free (queue);
01388 }
01389
01390
01391
01392
01393
01394
01395
01396 typedef struct {
01397 unsigned regno_to_find;
01398 rtx retval;
01399 } find_regno_partial_param;
01400
01401
01402
01403
01404
01405 static int
01406 find_regno_partial (ptr, data)
01407 rtx *ptr;
01408 void *data;
01409 {
01410 find_regno_partial_param *param = (find_regno_partial_param *)data;
01411 unsigned reg = param->regno_to_find;
01412 param->retval = NULL_RTX;
01413
01414 if (*ptr == NULL_RTX)
01415 return 0;
01416
01417 switch (GET_CODE (*ptr))
01418 {
01419 case ZERO_EXTRACT:
01420 case SIGN_EXTRACT:
01421 case STRICT_LOW_PART:
01422 if (GET_CODE (XEXP (*ptr, 0)) == REG && REGNO (XEXP (*ptr, 0)) == reg)
01423 {
01424 param->retval = XEXP (*ptr, 0);
01425 return 1;
01426 }
01427 break;
01428
01429 case SUBREG:
01430 if (GET_CODE (SUBREG_REG (*ptr)) == REG
01431 && REGNO (SUBREG_REG (*ptr)) == reg)
01432 {
01433 param->retval = SUBREG_REG (*ptr);
01434 return 1;
01435 }
01436 break;
01437
01438 default:
01439 break;
01440 }
01441
01442 return 0;
01443 }
01444
01445
01446
01447
01448
01449
01450
01451
01452 int
01453 initialize_uninitialized_subregs ()
01454 {
01455 rtx insn;
01456 edge e;
01457 int reg, did_something = 0;
01458 find_regno_partial_param param;
01459
01460 for (e = ENTRY_BLOCK_PTR->succ; e; e = e->succ_next)
01461 {
01462 basic_block bb = e->dest;
01463 regset map = bb->global_live_at_start;
01464 EXECUTE_IF_SET_IN_REG_SET (map,
01465 FIRST_PSEUDO_REGISTER, reg,
01466 {
01467 int uid = REGNO_FIRST_UID (reg);
01468 rtx i;
01469
01470
01471
01472
01473
01474
01475 for (i = get_insns (); i && INSN_UID (i) != uid; i = NEXT_INSN (i))
01476 ;
01477 if (i != NULL_RTX)
01478 {
01479
01480 param.regno_to_find = reg;
01481 for_each_rtx (&i, find_regno_partial, ¶m);
01482 if (param.retval != NULL_RTX)
01483 {
01484 start_sequence ();
01485 emit_move_insn (param.retval,
01486 CONST0_RTX (GET_MODE (param.retval)));
01487 insn = get_insns ();
01488 end_sequence ();
01489 insert_insn_on_edge (insn, e);
01490 did_something = 1;
01491 }
01492 }
01493 });
01494 }
01495
01496 if (did_something)
01497 commit_edge_insertions ();
01498 return did_something;
01499 }
01500
01501
01502
01503
01504
01505
01506
01507 void
01508 allocate_bb_life_data ()
01509 {
01510 basic_block bb;
01511
01512 FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR, NULL, next_bb)
01513 {
01514 bb->global_live_at_start = OBSTACK_ALLOC_REG_SET (&flow_obstack);
01515 bb->global_live_at_end = OBSTACK_ALLOC_REG_SET (&flow_obstack);
01516 }
01517
01518 regs_live_at_setjmp = OBSTACK_ALLOC_REG_SET (&flow_obstack);
01519 }
01520
01521 void
01522 allocate_reg_life_data ()
01523 {
01524 int i;
01525
01526 max_regno = max_reg_num ();
01527
01528
01529
01530 allocate_reg_info (max_regno, FALSE, FALSE);
01531
01532
01533
01534 for (i = 0; i < max_regno; i++)
01535 {
01536 REG_N_SETS (i) = 0;
01537 REG_N_REFS (i) = 0;
01538 REG_N_DEATHS (i) = 0;
01539 REG_N_CALLS_CROSSED (i) = 0;
01540 REG_LIVE_LENGTH (i) = 0;
01541 REG_BASIC_BLOCK (i) = REG_BLOCK_UNKNOWN;
01542 }
01543 }
01544
01545
01546
01547 static void
01548 propagate_block_delete_insn (insn)
01549 rtx insn;
01550 {
01551 rtx inote = find_reg_note (insn, REG_LABEL, NULL_RTX);
01552
01553
01554
01555
01556
01557
01558
01559
01560
01561
01562
01563 if (inote && GET_CODE (inote) == CODE_LABEL)
01564 {
01565 rtx label = XEXP (inote, 0);
01566 rtx next;
01567
01568
01569
01570
01571 if (LABEL_NUSES (label) == 1 + LABEL_PRESERVE_P (label)
01572 && (next = next_nonnote_insn (label)) != NULL
01573 && GET_CODE (next) == JUMP_INSN
01574 && (GET_CODE (PATTERN (next)) == ADDR_VEC
01575 || GET_CODE (PATTERN (next)) == ADDR_DIFF_VEC))
01576 {
01577 rtx pat = PATTERN (next);
01578 int diff_vec_p = GET_CODE (pat) == ADDR_DIFF_VEC;
01579 int len = XVECLEN (pat, diff_vec_p);
01580 int i;
01581
01582 for (i = 0; i < len; i++)
01583 LABEL_NUSES (XEXP (XVECEXP (pat, diff_vec_p, i), 0))--;
01584
01585 delete_insn_and_edges (next);
01586 ndead++;
01587 }
01588 }
01589
01590 delete_insn_and_edges (insn);
01591 ndead++;
01592 }
01593
01594
01595
01596
01597 static rtx
01598 propagate_block_delete_libcall ( insn, note)
01599 rtx insn, note;
01600 {
01601 rtx first = XEXP (note, 0);
01602 rtx before = PREV_INSN (first);
01603
01604 delete_insn_chain_and_edges (first, insn);
01605 ndead++;
01606 return before;
01607 }
01608
01609
01610
01611 rtx
01612 propagate_one_insn (pbi, insn)
01613 struct propagate_block_info *pbi;
01614 rtx insn;
01615 {
01616 rtx prev = PREV_INSN (insn);
01617 int flags = pbi->flags;
01618 int insn_is_dead = 0;
01619 int libcall_is_dead = 0;
01620 rtx note;
01621 int i;
01622
01623 if (! INSN_P (insn))
01624 return prev;
01625
01626 note = find_reg_note (insn, REG_RETVAL, NULL_RTX);
01627 if (flags & PROP_SCAN_DEAD_CODE)
01628 {
01629 insn_is_dead = insn_dead_p (pbi, PATTERN (insn), 0, REG_NOTES (insn));
01630 libcall_is_dead = (insn_is_dead && note != 0
01631 && libcall_dead_p (pbi, note, insn));
01632 }
01633
01634
01635
01636 if ((flags & PROP_KILL_DEAD_CODE) && insn_is_dead)
01637 {
01638
01639
01640
01641
01642
01643 if (reload_completed
01644 && !(TREE_CODE (TREE_TYPE (current_function_decl)) == FUNCTION_TYPE
01645 && (TYPE_RETURNS_STACK_DEPRESSED
01646 (TREE_TYPE (current_function_decl))))
01647 && (((HAVE_epilogue || HAVE_prologue)
01648 && prologue_epilogue_contains (insn))
01649 || (HAVE_sibcall_epilogue
01650 && sibcall_epilogue_contains (insn)))
01651 && find_reg_note (insn, REG_MAYBE_DEAD, NULL_RTX) == 0)
01652 fatal_insn ("Attempt to delete prologue/epilogue insn:", insn);
01653
01654
01655
01656 mark_set_regs (pbi, PATTERN (insn), insn);
01657
01658
01659
01660
01661 pbi->cc0_live = 0;
01662
01663 if (libcall_is_dead)
01664 prev = propagate_block_delete_libcall ( insn, note);
01665 else
01666 {
01667
01668
01669
01670
01671
01672
01673
01674
01675
01676
01677
01678 if (note)
01679 {
01680 rtx libcall_note;
01681
01682 libcall_note
01683 = find_reg_note (XEXP (note, 0), REG_LIBCALL, NULL_RTX);
01684 remove_note (XEXP (note, 0), libcall_note);
01685 }
01686
01687
01688
01689 note = find_reg_note (insn, REG_LIBCALL, NULL_RTX);
01690 if (note)
01691 {
01692 rtx retval_note;
01693
01694 retval_note
01695 = find_reg_note (XEXP (note, 0), REG_RETVAL, NULL_RTX);
01696 remove_note (XEXP (note, 0), retval_note);
01697 }
01698
01699
01700 propagate_block_delete_insn (insn);
01701 }
01702
01703 return prev;
01704 }
01705
01706
01707
01708 #ifdef AUTO_INC_DEC
01709 {
01710 rtx x = single_set (insn);
01711
01712
01713 if ((flags & PROP_AUTOINC)
01714 && x != 0
01715 && GET_CODE (SET_DEST (x)) == REG
01716 && (GET_CODE (SET_SRC (x)) == PLUS
01717 || GET_CODE (SET_SRC (x)) == MINUS)
01718 && XEXP (SET_SRC (x), 0) == SET_DEST (x)
01719 && GET_CODE (XEXP (SET_SRC (x), 1)) == CONST_INT
01720
01721
01722
01723
01724 && try_pre_increment_1 (pbi, insn))
01725 return prev;
01726 }
01727 #endif
01728
01729 CLEAR_REG_SET (pbi->new_set);
01730
01731
01732
01733
01734 if (libcall_is_dead)
01735 {
01736
01737 mark_set_regs (pbi, PATTERN (insn), insn);
01738
01739 insn = XEXP (note, 0);
01740 return PREV_INSN (insn);
01741 }
01742 else if (GET_CODE (PATTERN (insn)) == SET
01743 && SET_DEST (PATTERN (insn)) == stack_pointer_rtx
01744 && GET_CODE (SET_SRC (PATTERN (insn))) == PLUS
01745 && XEXP (SET_SRC (PATTERN (insn)), 0) == stack_pointer_rtx
01746 && GET_CODE (XEXP (SET_SRC (PATTERN (insn)), 1)) == CONST_INT)
01747
01748
01749
01750
01751
01752 invalidate_mems_from_set (pbi, stack_pointer_rtx);
01753 else
01754 {
01755 rtx note;
01756
01757
01758
01759
01760 if (GET_CODE (insn) == CALL_INSN && (flags & PROP_REG_INFO))
01761 EXECUTE_IF_SET_IN_REG_SET (pbi->reg_live, 0, i,
01762 { REG_N_CALLS_CROSSED (i)++; });
01763
01764
01765
01766 mark_set_regs (pbi, PATTERN (insn), insn);
01767
01768 if (GET_CODE (insn) == CALL_INSN)
01769 {
01770 regset live_at_end;
01771 bool sibcall_p;
01772 rtx note, cond;
01773 int i;
01774
01775 cond = NULL_RTX;
01776 if (GET_CODE (PATTERN (insn)) == COND_EXEC)
01777 cond = COND_EXEC_TEST (PATTERN (insn));
01778
01779
01780
01781
01782 if (! CONST_OR_PURE_CALL_P (insn))
01783 {
01784 free_EXPR_LIST_list (&pbi->mem_set_list);
01785 pbi->mem_set_list_len = 0;
01786 }
01787 else
01788 invalidate_mems_from_set (pbi, stack_pointer_rtx);
01789
01790
01791 for (note = CALL_INSN_FUNCTION_USAGE (insn);
01792 note;
01793 note = XEXP (note, 1))
01794 if (GET_CODE (XEXP (note, 0)) == CLOBBER)
01795 mark_set_1 (pbi, CLOBBER, XEXP (XEXP (note, 0), 0),
01796 cond, insn, pbi->flags);
01797
01798
01799
01800
01801
01802 sibcall_p = SIBLING_CALL_P (insn);
01803 live_at_end = EXIT_BLOCK_PTR->global_live_at_start;
01804 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
01805 if (TEST_HARD_REG_BIT (regs_invalidated_by_call, i)
01806 && ! (sibcall_p
01807 && REGNO_REG_SET_P (live_at_end, i)
01808 && ! refers_to_regno_p (i, i+1,
01809 current_function_return_rtx,
01810 (rtx *) 0)))
01811 {
01812
01813 mark_set_1 (pbi, CLOBBER, regno_reg_rtx[i], cond, insn,
01814 pbi->flags & ~(PROP_DEATH_NOTES | PROP_REG_INFO));
01815 }
01816 }
01817
01818
01819
01820
01821 pbi->cc0_live = 0;
01822
01823
01824 if (! insn_is_dead)
01825 mark_used_regs (pbi, PATTERN (insn), NULL_RTX, insn);
01826 if ((flags & PROP_EQUAL_NOTES)
01827 && ((note = find_reg_note (insn, REG_EQUAL, NULL_RTX))
01828 || (note = find_reg_note (insn, REG_EQUIV, NULL_RTX))))
01829 mark_used_regs (pbi, XEXP (note, 0), NULL_RTX, insn);
01830
01831
01832
01833 #ifdef AUTO_INC_DEC
01834 prev = PREV_INSN (insn);
01835 #endif
01836
01837 if (! insn_is_dead && GET_CODE (insn) == CALL_INSN)
01838 {
01839 int i;
01840 rtx note, cond;
01841
01842 cond = NULL_RTX;
01843 if (GET_CODE (PATTERN (insn)) == COND_EXEC)
01844 cond = COND_EXEC_TEST (PATTERN (insn));
01845
01846
01847 for (note = CALL_INSN_FUNCTION_USAGE (insn);
01848 note;
01849 note = XEXP (note, 1))
01850 if (GET_CODE (XEXP (note, 0)) == USE)
01851 mark_used_regs (pbi, XEXP (XEXP (note, 0), 0),
01852 cond, insn);
01853
01854
01855 SET_REGNO_REG_SET (pbi->reg_live, STACK_POINTER_REGNUM);
01856
01857
01858
01859 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
01860 if (global_regs[i])
01861 mark_used_reg (pbi, regno_reg_rtx[i], cond, insn);
01862 }
01863 }
01864
01865
01866
01867 if (flags & PROP_REG_INFO)
01868 EXECUTE_IF_SET_IN_REG_SET (pbi->reg_live, 0, i,
01869 { REG_LIVE_LENGTH (i)++; });
01870
01871 return prev;
01872 }
01873
01874
01875
01876
01877
01878 struct propagate_block_info *
01879 init_propagate_block_info (bb, live, local_set, cond_local_set, flags)
01880 basic_block bb;
01881 regset live, local_set, cond_local_set;
01882 int flags;
01883 {
01884 struct propagate_block_info *pbi = xmalloc (sizeof (*pbi));
01885
01886 pbi->bb = bb;
01887 pbi->reg_live = live;
01888 pbi->mem_set_list = NULL_RTX;
01889 pbi->mem_set_list_len = 0;
01890 pbi->local_set = local_set;
01891 pbi->cond_local_set = cond_local_set;
01892 pbi->cc0_live = 0;
01893 pbi->flags = flags;
01894
01895 if (flags & (PROP_LOG_LINKS | PROP_AUTOINC))
01896 pbi->reg_next_use = (rtx *) xcalloc (max_reg_num (), sizeof (rtx));
01897 else
01898 pbi->reg_next_use = NULL;
01899
01900 pbi->new_set = BITMAP_XMALLOC ();
01901
01902 #ifdef HAVE_conditional_execution
01903 pbi->reg_cond_dead = splay_tree_new (splay_tree_compare_ints, NULL,
01904 free_reg_cond_life_info);
01905 pbi->reg_cond_reg = BITMAP_XMALLOC ();
01906
01907
01908
01909
01910 if (GET_CODE (bb->end) == JUMP_INSN
01911 && any_condjump_p (bb->end))
01912 {
01913 regset_head diff_head;
01914 regset diff = INITIALIZE_REG_SET (diff_head);
01915 basic_block bb_true, bb_false;
01916 rtx cond_true, cond_false, set_src;
01917 int i;
01918
01919
01920 bb_true = bb->succ->dest;
01921 if (bb->succ->succ_next != NULL)
01922 {
01923 bb_false = bb->succ->succ_next->dest;
01924
01925 if (bb->succ->flags & EDGE_FALLTHRU)
01926 {
01927 basic_block t = bb_false;
01928 bb_false = bb_true;
01929 bb_true = t;
01930 }
01931 else if (! (bb->succ->succ_next->flags & EDGE_FALLTHRU))
01932 abort ();
01933 }
01934 else
01935 {
01936
01937 if (JUMP_LABEL (bb->end) != bb_true->head)
01938 abort ();
01939
01940
01941 bb_false = bb_true;
01942 }
01943
01944
01945 set_src = SET_SRC (pc_set (bb->end));
01946 cond_true = XEXP (set_src, 0);
01947 cond_false = gen_rtx_fmt_ee (reverse_condition (GET_CODE (cond_true)),
01948 GET_MODE (cond_true), XEXP (cond_true, 0),
01949 XEXP (cond_true, 1));
01950 if (GET_CODE (XEXP (set_src, 1)) == PC)
01951 {
01952 rtx t = cond_false;
01953 cond_false = cond_true;
01954 cond_true = t;
01955 }
01956
01957
01958 if (bitmap_operation (diff, bb_true->global_live_at_start,
01959 bb_false->global_live_at_start, BITMAP_XOR))
01960 {
01961 rtx reg = XEXP (cond_true, 0);
01962
01963 if (GET_CODE (reg) == SUBREG)
01964 reg = SUBREG_REG (reg);
01965
01966 if (GET_CODE (reg) != REG)
01967 abort ();
01968
01969 SET_REGNO_REG_SET (pbi->reg_cond_reg, REGNO (reg));
01970
01971
01972 EXECUTE_IF_SET_IN_REG_SET
01973 (diff, 0, i,
01974 {
01975 struct reg_cond_life_info *rcli;
01976 rtx cond;
01977
01978 rcli = (struct reg_cond_life_info *) xmalloc (sizeof (*rcli));
01979
01980 if (REGNO_REG_SET_P (bb_true->global_live_at_start, i))
01981 cond = cond_false;
01982 else
01983 cond = cond_true;
01984 rcli->condition = cond;
01985 rcli->stores = const0_rtx;
01986 rcli->orig_condition = cond;
01987
01988 splay_tree_insert (pbi->reg_cond_dead, i,
01989 (splay_tree_value) rcli);
01990 });
01991 }
01992
01993 FREE_REG_SET (diff);
01994 }
01995 #endif
01996
01997
01998
01999
02000
02001 if (optimize
02002 && ! (TREE_CODE (TREE_TYPE (current_function_decl)) == FUNCTION_TYPE
02003 && (TYPE_RETURNS_STACK_DEPRESSED
02004 (TREE_TYPE (current_function_decl))))
02005 && (flags & PROP_SCAN_DEAD_STORES)
02006 && (bb->succ == NULL
02007 || (bb->succ->succ_next == NULL
02008 && bb->succ->dest == EXIT_BLOCK_PTR
02009 && ! current_function_calls_eh_return)))
02010 {
02011 rtx insn, set;
02012 for (insn = bb->end; insn != bb->head; insn = PREV_INSN (insn))
02013 if (GET_CODE (insn) == INSN
02014 && (set = single_set (insn))
02015 && GET_CODE (SET_DEST (set)) == MEM)
02016 {
02017 rtx mem = SET_DEST (set);
02018 rtx canon_mem = canon_rtx (mem);
02019
02020
02021
02022
02023
02024 if (RTX_UNCHANGING_P (canon_mem))
02025 continue;
02026
02027 if (XEXP (canon_mem, 0) == frame_pointer_rtx
02028 || (GET_CODE (XEXP (canon_mem, 0)) == PLUS
02029 && XEXP (XEXP (canon_mem, 0), 0) == frame_pointer_rtx
02030 && GET_CODE (XEXP (XEXP (canon_mem, 0), 1)) == CONST_INT))
02031 add_to_mem_set_list (pbi, canon_mem);
02032 }
02033 }
02034
02035 return pbi;
02036 }
02037
02038
02039
02040 void
02041 free_propagate_block_info (pbi)
02042 struct propagate_block_info *pbi;
02043 {
02044 free_EXPR_LIST_list (&pbi->mem_set_list);
02045
02046 BITMAP_XFREE (pbi->new_set);
02047
02048 #ifdef HAVE_conditional_execution
02049 splay_tree_delete (pbi->reg_cond_dead);
02050 BITMAP_XFREE (pbi->reg_cond_reg);
02051 #endif
02052
02053 if (pbi->reg_next_use)
02054 free (pbi->reg_next_use);
02055
02056 free (pbi);
02057 }
02058
02059
02060
02061
02062
02063
02064
02065
02066
02067
02068
02069
02070
02071
02072
02073
02074
02075
02076
02077 int
02078 propagate_block (bb, live, local_set, cond_local_set, flags)
02079 basic_block bb;
02080 regset live;
02081 regset local_set;
02082 regset cond_local_set;
02083 int flags;
02084 {
02085 struct propagate_block_info *pbi;
02086 rtx insn, prev;
02087 int changed;
02088
02089 pbi = init_propagate_block_info (bb, live, local_set, cond_local_set, flags);
02090
02091 if (flags & PROP_REG_INFO)
02092 {
02093 int i;
02094
02095
02096
02097 EXECUTE_IF_SET_IN_REG_SET (live, 0, i,
02098 { REG_BASIC_BLOCK (i) = REG_BLOCK_GLOBAL; });
02099 }
02100
02101
02102
02103 changed = 0;
02104 for (insn = bb->end;; insn = prev)
02105 {
02106
02107
02108 if ((flags & PROP_REG_INFO)
02109 && GET_CODE (insn) == CALL_INSN
02110 && find_reg_note (insn, REG_SETJMP, NULL))
02111 IOR_REG_SET (regs_live_at_setjmp, pbi->reg_live);
02112
02113 prev = propagate_one_insn (pbi, insn);
02114 changed |= NEXT_INSN (prev) != insn;
02115
02116 if (insn == bb->head)
02117 break;
02118 }
02119
02120 free_propagate_block_info (pbi);
02121
02122 return changed;
02123 }
02124
02125
02126
02127
02128
02129
02130
02131
02132
02133
02134 static int
02135 insn_dead_p (pbi, x, call_ok, notes)
02136 struct propagate_block_info *pbi;
02137 rtx x;
02138 int call_ok;
02139 rtx notes ATTRIBUTE_UNUSED;
02140 {
02141 enum rtx_code code = GET_CODE (x);
02142
02143
02144 if (flag_non_call_exceptions && may_trap_p (x))
02145 return 0;
02146
02147 #ifdef AUTO_INC_DEC
02148
02149
02150 for (; notes; notes = XEXP (notes, 1))
02151 {
02152 if (REG_NOTE_KIND (notes) == REG_INC)
02153 {
02154 int regno = REGNO (XEXP (notes, 0));
02155
02156
02157 if ((regno < FIRST_PSEUDO_REGISTER && global_regs[regno])
02158 || REGNO_REG_SET_P (pbi->reg_live, regno))
02159 return 0;
02160 }
02161 }
02162 #endif
02163
02164
02165
02166
02167 if (code == SET)
02168 {
02169 rtx r = SET_DEST (x);
02170
02171 #ifdef HAVE_cc0
02172 if (GET_CODE (r) == CC0)
02173 return ! pbi->cc0_live;
02174 #endif
02175
02176
02177 if (GET_CODE (SET_SRC (x)) == CALL)
02178 {
02179 if (! call_ok)
02180 return 0;
02181 }
02182
02183
02184 else if (volatile_refs_p (SET_SRC (x)))
02185 return 0;
02186
02187 if (GET_CODE (r) == MEM)
02188 {
02189 rtx temp, canon_r;
02190
02191 if (MEM_VOLATILE_P (r) || GET_MODE (r) == BLKmode)
02192 return 0;
02193
02194 canon_r = canon_rtx (r);
02195
02196
02197
02198
02199
02200
02201
02202 for (temp = pbi->mem_set_list; temp != 0; temp = XEXP (temp, 1))
02203 if (anti_dependence (r, XEXP (temp, 0)))
02204 {
02205 rtx mem = XEXP (temp, 0);
02206
02207 if (rtx_equal_p (XEXP (canon_r, 0), XEXP (mem, 0))
02208 && (GET_MODE_SIZE (GET_MODE (canon_r))
02209 <= GET_MODE_SIZE (GET_MODE (mem))))
02210 return 1;
02211
02212 #ifdef AUTO_INC_DEC
02213
02214
02215 if (GET_MODE (mem) == GET_MODE (r)
02216 && (GET_CODE (XEXP (mem, 0)) == POST_DEC
02217 || GET_CODE (XEXP (mem, 0)) == POST_INC
02218 || GET_CODE (XEXP (mem, 0)) == POST_MODIFY)
02219 && GET_MODE (XEXP (mem, 0)) == GET_MODE (r)
02220 && rtx_equal_p (XEXP (XEXP (mem, 0), 0), XEXP (r, 0)))
02221 return 1;
02222 #endif
02223 }
02224 }
02225 else
02226 {
02227 while (GET_CODE (r) == SUBREG
02228 || GET_CODE (r) == STRICT_LOW_PART
02229 || GET_CODE (r) == ZERO_EXTRACT)
02230 r = XEXP (r, 0);
02231
02232 if (GET_CODE (r) == REG)
02233 {
02234 int regno = REGNO (r);
02235
02236
02237 if (REGNO_REG_SET_P (pbi->reg_live, regno))
02238 return 0;
02239
02240
02241
02242 if (regno < FIRST_PSEUDO_REGISTER)
02243 {
02244 int n = HARD_REGNO_NREGS (regno, GET_MODE (r));
02245
02246 while (--n > 0)
02247 if (REGNO_REG_SET_P (pbi->reg_live, regno+n))
02248 return 0;
02249 }
02250
02251
02252 if (regno < FIRST_PSEUDO_REGISTER && global_regs[regno])
02253 return 0;
02254
02255
02256 if (regno == STACK_POINTER_REGNUM)
02257 return 0;
02258
02259
02260
02261
02262
02263
02264 if (regno == FRAME_POINTER_REGNUM
02265 && (! reload_completed || frame_pointer_needed))
02266 return 0;
02267 #if FRAME_POINTER_REGNUM != HARD_FRAME_POINTER_REGNUM
02268 if (regno == HARD_FRAME_POINTER_REGNUM
02269 && (! reload_completed || frame_pointer_needed))
02270 return 0;
02271 #endif
02272
02273 #if FRAME_POINTER_REGNUM != ARG_POINTER_REGNUM
02274
02275
02276
02277 if (regno == ARG_POINTER_REGNUM && fixed_regs[regno])
02278 return 0;
02279 #endif
02280
02281
02282 return 1;
02283 }
02284 }
02285 }
02286
02287
02288
02289
02290
02291 else if (code == PARALLEL)
02292 {
02293 int i = XVECLEN (x, 0);
02294
02295 for (i--; i >= 0; i--)
02296 if (GET_CODE (XVECEXP (x, 0, i)) != CLOBBER
02297 && GET_CODE (XVECEXP (x, 0, i)) != USE
02298 && ! insn_dead_p (pbi, XVECEXP (x, 0, i), call_ok, NULL_RTX))
02299 return 0;
02300
02301 return 1;
02302 }
02303
02304
02305
02306 else if (code == CLOBBER && GET_CODE (XEXP (x, 0)) == REG
02307 && REGNO (XEXP (x, 0)) >= FIRST_PSEUDO_REGISTER
02308 && ! REGNO_REG_SET_P (pbi->reg_live, REGNO (XEXP (x, 0))))
02309 return 1;
02310
02311
02312
02313 return 0;
02314 }
02315
02316
02317
02318
02319
02320
02321
02322
02323
02324
02325
02326
02327
02328
02329
02330
02331 static int
02332 libcall_dead_p (pbi, note, insn)
02333 struct propagate_block_info *pbi;
02334 rtx note;
02335 rtx insn;
02336 {
02337 rtx x = single_set (insn);
02338
02339 if (x)
02340 {
02341 rtx r = SET_SRC (x);
02342
02343 if (GET_CODE (r) == REG)
02344 {
02345 rtx call = XEXP (note, 0);
02346 rtx call_pat;
02347 int i;
02348
02349
02350 while (call != insn && GET_CODE (call) != CALL_INSN)
02351 call = NEXT_INSN (call);
02352
02353
02354
02355 if (call == insn)
02356 return 0;
02357
02358
02359
02360 call_pat = PATTERN (call);
02361 if (GET_CODE (call_pat) == PARALLEL)
02362 {
02363 for (i = XVECLEN (call_pat, 0) - 1; i >= 0; i--)
02364 if (GET_CODE (XVECEXP (call_pat, 0, i)) == SET
02365 && GET_CODE (SET_SRC (XVECEXP (call_pat, 0, i))) == CALL)
02366 break;
02367
02368
02369
02370
02371 if (i < 0)
02372 return 0;
02373
02374 call_pat = XVECEXP (call_pat, 0, i);
02375 }
02376
02377 return insn_dead_p (pbi, call_pat, 1, REG_NOTES (call));
02378 }
02379 }
02380 return 1;
02381 }
02382
02383
02384
02385
02386
02387
02388 int
02389 regno_uninitialized (regno)
02390 unsigned int regno;
02391 {
02392 if (n_basic_blocks == 0
02393 || (regno < FIRST_PSEUDO_REGISTER
02394 && (global_regs[regno]
02395 || fixed_regs[regno]
02396 || FUNCTION_ARG_REGNO_P (regno))))
02397 return 0;
02398
02399 return REGNO_REG_SET_P (ENTRY_BLOCK_PTR->next_bb->global_live_at_start, regno);
02400 }
02401
02402
02403
02404
02405
02406 int
02407 regno_clobbered_at_setjmp (regno)
02408 int regno;
02409 {
02410 if (n_basic_blocks == 0)
02411 return 0;
02412
02413 return ((REG_N_SETS (regno) > 1
02414 || REGNO_REG_SET_P (ENTRY_BLOCK_PTR->next_bb->global_live_at_start, regno))
02415 && REGNO_REG_SET_P (regs_live_at_setjmp, regno));
02416 }
02417
02418
02419
02420 static void
02421 add_to_mem_set_list (pbi, mem)
02422 struct propagate_block_info *pbi;
02423 rtx mem;
02424 {
02425 rtx i;
02426
02427
02428
02429 if (GET_MODE (mem) == BLKmode)
02430 return;
02431
02432 for (i = pbi->mem_set_list; i ; i = XEXP (i, 1))
02433 {
02434 rtx e = XEXP (i, 0);
02435 if (rtx_equal_p (XEXP (mem, 0), XEXP (e, 0)))
02436 {
02437 if (GET_MODE_SIZE (GET_MODE (mem)) > GET_MODE_SIZE (GET_MODE (e)))
02438 {
02439 #ifdef AUTO_INC_DEC
02440
02441
02442 if (pbi->flags & PROP_AUTOINC)
02443 PUT_MODE (e, GET_MODE (mem));
02444 else
02445 #endif
02446 XEXP (i, 0) = mem;
02447 }
02448 return;
02449 }
02450 }
02451
02452 if (pbi->mem_set_list_len < MAX_MEM_SET_LIST_LEN)
02453 {
02454 #ifdef AUTO_INC_DEC
02455
02456
02457 if (pbi->flags & PROP_AUTOINC)
02458 mem = shallow_copy_rtx (mem);
02459 #endif
02460 pbi->mem_set_list = alloc_EXPR_LIST (0, mem, pbi->mem_set_list);
02461 pbi->mem_set_list_len++;
02462 }
02463 }
02464
02465
02466
02467
02468
02469 static int
02470 invalidate_mems_from_autoinc (px, data)
02471 rtx *px;
02472 void *data;
02473 {
02474 rtx x = *px;
02475 struct propagate_block_info *pbi = data;
02476
02477 if (GET_RTX_CLASS (GET_CODE (x)) == 'a')
02478 {
02479 invalidate_mems_from_set (pbi, XEXP (x, 0));
02480 return -1;
02481 }
02482
02483 return 0;
02484 }
02485
02486
02487
02488 static void
02489 invalidate_mems_from_set (pbi, exp)
02490 struct propagate_block_info *pbi;
02491 rtx exp;
02492 {
02493 rtx temp = pbi->mem_set_list;
02494 rtx prev = NULL_RTX;
02495 rtx next;
02496
02497 while (temp)
02498 {
02499 next = XEXP (temp, 1);
02500 if (reg_overlap_mentioned_p (exp, XEXP (temp, 0)))
02501 {
02502
02503 if (prev)
02504 XEXP (prev, 1) = next;
02505 else
02506 pbi->mem_set_list = next;
02507 free_EXPR_LIST_node (temp);
02508 pbi->mem_set_list_len--;
02509 }
02510 else
02511 prev = temp;
02512 temp = next;
02513 }
02514 }
02515
02516
02517
02518
02519
02520
02521
02522
02523 static void
02524 mark_set_regs (pbi, x, insn)
02525 struct propagate_block_info *pbi;
02526 rtx x, insn;
02527 {
02528 rtx cond = NULL_RTX;
02529 rtx link;
02530 enum rtx_code code;
02531
02532 if (insn)
02533 for (link = REG_NOTES (insn); link; link = XEXP (link, 1))
02534 {
02535 if (REG_NOTE_KIND (link) == REG_INC)
02536 mark_set_1 (pbi, SET, XEXP (link, 0),
02537 (GET_CODE (x) == COND_EXEC
02538 ? COND_EXEC_TEST (x) : NULL_RTX),
02539 insn, pbi->flags);
02540 }
02541 retry:
02542 switch (code = GET_CODE (x))
02543 {
02544 case SET:
02545 case CLOBBER:
02546 mark_set_1 (pbi, code, SET_DEST (x), cond, insn, pbi->flags);
02547 return;
02548
02549 case COND_EXEC:
02550 cond = COND_EXEC_TEST (x);
02551 x = COND_EXEC_CODE (x);
02552 goto retry;
02553
02554 case PARALLEL:
02555 {
02556 int i;
02557
02558 for (i = XVECLEN (x, 0) - 1; i >= 0; i--)
02559 {
02560 rtx sub = XVECEXP (x, 0, i);
02561 switch (code = GET_CODE (sub))
02562 {
02563 case COND_EXEC:
02564 if (cond != NULL_RTX)
02565 abort ();
02566
02567 cond = COND_EXEC_TEST (sub);
02568 sub = COND_EXEC_CODE (sub);
02569 if (GET_CODE (sub) != SET && GET_CODE (sub) != CLOBBER)
02570 break;
02571
02572
02573 case SET:
02574 case CLOBBER:
02575 mark_set_1 (pbi, code, SET_DEST (sub), cond, insn, pbi->flags);
02576 break;
02577
02578 default:
02579 break;
02580 }
02581 }
02582 break;
02583 }
02584
02585 default:
02586 break;
02587 }
02588 }
02589
02590
02591
02592
02593
02594
02595
02596 static void
02597 mark_set_1 (pbi, code, reg, cond, insn, flags)
02598 struct propagate_block_info *pbi;
02599 enum rtx_code code;
02600 rtx reg, cond, insn;
02601 int flags;
02602 {
02603 int regno_first = -1, regno_last = -1;
02604 unsigned long not_dead = 0;
02605 int i;
02606
02607
02608
02609
02610
02611 switch (GET_CODE (reg))
02612 {
02613 case PARALLEL:
02614
02615
02616
02617 for (i = XVECLEN (reg, 0) - 1; i >= 0; i--)
02618 if (XEXP (XVECEXP (reg, 0, i), 0) != 0)
02619 mark_set_1 (pbi, code, XEXP (XVECEXP (reg, 0, i), 0), cond, insn,
02620 flags);
02621 return;
02622
02623 case ZERO_EXTRACT:
02624 case SIGN_EXTRACT:
02625 case STRICT_LOW_PART:
02626
02627 do
02628 reg = XEXP (reg, 0);
02629 while (GET_CODE (reg) == SUBREG
02630 || GET_CODE (reg) == ZERO_EXTRACT
02631 || GET_CODE (reg) == SIGN_EXTRACT
02632 || GET_CODE (reg) == STRICT_LOW_PART);
02633 if (GET_CODE (reg) == MEM)
02634 break;
02635 not_dead = (unsigned long) REGNO_REG_SET_P (pbi->reg_live, REGNO (reg));
02636
02637
02638 case REG:
02639 regno_last = regno_first = REGNO (reg);
02640 if (regno_first < FIRST_PSEUDO_REGISTER)
02641 regno_last += HARD_REGNO_NREGS (regno_first, GET_MODE (reg)) - 1;
02642 break;
02643
02644 case SUBREG:
02645 if (GET_CODE (SUBREG_REG (reg)) == REG)
02646 {
02647 enum machine_mode outer_mode = GET_MODE (reg);
02648 enum machine_mode inner_mode = GET_MODE (SUBREG_REG (reg));
02649
02650
02651
02652
02653 regno_last = regno_first = REGNO (SUBREG_REG (reg));
02654 if (regno_first < FIRST_PSEUDO_REGISTER)
02655 {
02656 regno_first += subreg_regno_offset (regno_first, inner_mode,
02657 SUBREG_BYTE (reg),
02658 outer_mode);
02659 regno_last = (regno_first
02660 + HARD_REGNO_NREGS (regno_first, outer_mode) - 1);
02661
02662
02663
02664
02665
02666 reg = gen_rtx_REG (outer_mode, regno_first);
02667 }
02668 else
02669 {
02670
02671
02672
02673
02674
02675
02676 if (((GET_MODE_SIZE (outer_mode)
02677 + UNITS_PER_WORD - 1) / UNITS_PER_WORD)
02678 < ((GET_MODE_SIZE (inner_mode)
02679 + UNITS_PER_WORD - 1) / UNITS_PER_WORD))
02680 not_dead = (unsigned long) REGNO_REG_SET_P (pbi->reg_live,
02681 regno_first);
02682
02683 reg = SUBREG_REG (reg);
02684 }
02685 }
02686 else
02687 reg = SUBREG_REG (reg);
02688 break;
02689
02690 default:
02691 break;
02692 }
02693
02694
02695
02696 if (optimize && (flags & PROP_SCAN_DEAD_STORES))
02697 {
02698 if (GET_CODE (reg) == REG)
02699 invalidate_mems_from_set (pbi, reg);
02700
02701
02702
02703
02704 if (insn && GET_CODE (reg) == MEM)
02705 for_each_rtx (&PATTERN (insn), invalidate_mems_from_autoinc, pbi);
02706
02707 if (GET_CODE (reg) == MEM && ! side_effects_p (reg)
02708
02709 && ! cond)
02710 add_to_mem_set_list (pbi, canon_rtx (reg));
02711 }
02712
02713 if (GET_CODE (reg) == REG
02714 && ! (regno_first == FRAME_POINTER_REGNUM
02715 && (! reload_completed || frame_pointer_needed))
02716 #if FRAME_POINTER_REGNUM != HARD_FRAME_POINTER_REGNUM
02717 && ! (regno_first == HARD_FRAME_POINTER_REGNUM
02718 && (! reload_completed || frame_pointer_needed))
02719 #endif
02720 #if FRAME_POINTER_REGNUM != ARG_POINTER_REGNUM
02721 && ! (regno_first == ARG_POINTER_REGNUM && fixed_regs[regno_first])
02722 #endif
02723 )
02724 {
02725 int some_was_live = 0, some_was_dead = 0;
02726
02727 for (i = regno_first; i <= regno_last; ++i)
02728 {
02729 int needed_regno = REGNO_REG_SET_P (pbi->reg_live, i);
02730 if (pbi->local_set)
02731 {
02732
02733
02734 CLEAR_REGNO_REG_SET (pbi->cond_local_set, i);
02735 if (cond != NULL_RTX
02736 && ! REGNO_REG_SET_P (pbi->local_set, i))
02737 SET_REGNO_REG_SET (pbi->cond_local_set, i);
02738 else
02739 SET_REGNO_REG_SET (pbi->local_set, i);
02740 }
02741 if (code != CLOBBER)
02742 SET_REGNO_REG_SET (pbi->new_set, i);
02743
02744 some_was_live |= needed_regno;
02745 some_was_dead |= ! needed_regno;
02746 }
02747
02748 #ifdef HAVE_conditional_execution
02749
02750
02751 if (some_was_live && ! not_dead
02752
02753
02754
02755
02756 && regno_first != STACK_POINTER_REGNUM)
02757 {
02758 for (i = regno_first; i <= regno_last; ++i)
02759 if (! mark_regno_cond_dead (pbi, i, cond))
02760 not_dead |= ((unsigned long) 1) << (i - regno_first);
02761 }
02762 #endif
02763
02764
02765 if (flags & (PROP_LOG_LINKS | PROP_REG_INFO
02766 | PROP_DEATH_NOTES | PROP_AUTOINC))
02767 {
02768 rtx y;
02769 int blocknum = pbi->bb->index;
02770
02771 y = NULL_RTX;
02772 if (flags & (PROP_LOG_LINKS | PROP_AUTOINC))
02773 {
02774 y = pbi->reg_next_use[regno_first];
02775
02776
02777 for (i = regno_first; i <= regno_last; ++i)
02778 pbi->reg_next_use[i] = 0;
02779 }
02780
02781 if (flags & PROP_REG_INFO)
02782 {
02783 for (i = regno_first; i <= regno_last; ++i)
02784 {
02785
02786
02787 REG_N_SETS (i) += 1;
02788 REG_N_REFS (i) += 1;
02789 REG_FREQ (i) += REG_FREQ_FROM_BB (pbi->bb);
02790
02791
02792
02793
02794
02795 REG_LIVE_LENGTH (i) += 1;
02796 }
02797
02798
02799 if (regno_first < FIRST_PSEUDO_REGISTER)
02800 {
02801 for (i = regno_first; i <= regno_last; i++)
02802 regs_ever_live[i] = 1;
02803 }
02804 else
02805 {
02806
02807 if (REG_BASIC_BLOCK (regno_first) == REG_BLOCK_UNKNOWN)
02808 REG_BASIC_BLOCK (regno_first) = blocknum;
02809 else if (REG_BASIC_BLOCK (regno_first) != blocknum)
02810 REG_BASIC_BLOCK (regno_first) = REG_BLOCK_GLOBAL;
02811 }
02812 }
02813
02814 if (! some_was_dead)
02815 {
02816 if (flags & PROP_LOG_LINKS)
02817 {
02818
02819
02820
02821
02822
02823
02824
02825
02826
02827 if (y && (BLOCK_NUM (y) == blocknum)
02828 && (regno_first >= FIRST_PSEUDO_REGISTER
02829 || asm_noperands (PATTERN (y)) < 0))
02830 LOG_LINKS (y) = alloc_INSN_LIST (insn, LOG_LINKS (y));
02831 }
02832 }
02833 else if (not_dead)
02834 ;
02835 else if (! some_was_live)
02836 {
02837 if (flags & PROP_REG_INFO)
02838 REG_N_DEATHS (regno_first) += 1;
02839
02840 if (flags & PROP_DEATH_NOTES)
02841 {
02842
02843
02844
02845
02846
02847 REG_NOTES (insn)
02848 = alloc_EXPR_LIST (REG_UNUSED, reg, REG_NOTES (insn));
02849 }
02850 }
02851 else
02852 {
02853 if (flags & PROP_DEATH_NOTES)
02854 {
02855
02856
02857
02858
02859
02860
02861 for (i = regno_first; i <= regno_last; ++i)
02862 if (! REGNO_REG_SET_P (pbi->reg_live, i))
02863 REG_NOTES (insn)
02864 = alloc_EXPR_LIST (REG_UNUSED,
02865 regno_reg_rtx[i],
02866 REG_NOTES (insn));
02867 }
02868 }
02869 }
02870
02871
02872 if (some_was_live
02873
02874
02875
02876
02877 && regno_first != STACK_POINTER_REGNUM)
02878 {
02879 for (i = regno_first; i <= regno_last; ++i)
02880 if (!(not_dead & (((unsigned long) 1) << (i - regno_first))))
02881 CLEAR_REGNO_REG_SET (pbi->reg_live, i);
02882 }
02883 }
02884 else if (GET_CODE (reg) == REG)
02885 {
02886 if (flags & (PROP_LOG_LINKS | PROP_AUTOINC))
02887 pbi->reg_next_use[regno_first] = 0;
02888 }
02889
02890
02891
02892 else if (GET_CODE (reg) == SCRATCH)
02893 {
02894 if (flags & PROP_DEATH_NOTES)
02895 REG_NOTES (insn)
02896 = alloc_EXPR_LIST (REG_UNUSED, reg, REG_NOTES (insn));
02897 }
02898 }
02899
02900 #ifdef HAVE_conditional_execution
02901
02902
02903
02904 static int
02905 mark_regno_cond_dead (pbi, regno, cond)
02906 struct propagate_block_info *pbi;
02907 int regno;
02908 rtx cond;
02909 {
02910
02911
02912
02913
02914
02915 if (REGNO_REG_SET_P (pbi->reg_cond_reg, regno))
02916 flush_reg_cond_reg (pbi, regno);
02917
02918
02919
02920 if (cond == NULL_RTX)
02921 splay_tree_remove (pbi->reg_cond_dead, regno);
02922 else
02923 {
02924 splay_tree_node node;
02925 struct reg_cond_life_info *rcli;
02926 rtx ncond;
02927
02928
02929
02930
02931
02932 node = splay_tree_lookup (pbi->reg_cond_dead, regno);
02933 if (node == NULL)
02934 {
02935
02936
02937
02938 rcli = (struct reg_cond_life_info *) xmalloc (sizeof (*rcli));
02939 rcli->condition = cond;
02940 rcli->stores = cond;
02941 rcli->orig_condition = const0_rtx;
02942 splay_tree_insert (pbi->reg_cond_dead, regno,
02943 (splay_tree_value) rcli);
02944
02945 SET_REGNO_REG_SET (pbi->reg_cond_reg, REGNO (XEXP (cond, 0)));
02946
02947
02948 return 0;
02949 }
02950 else
02951 {
02952
02953
02954 rcli = (struct reg_cond_life_info *) node->value;
02955 ncond = rcli->condition;
02956 ncond = ior_reg_cond (ncond, cond, 1);
02957 if (rcli->stores == const0_rtx)
02958 rcli->stores = cond;
02959 else if (rcli->stores != const1_rtx)
02960 rcli->stores = ior_reg_cond (rcli->stores, cond, 1);
02961
02962
02963
02964
02965
02966
02967
02968
02969
02970 if (ncond == const1_rtx
02971 || (ncond == rcli->orig_condition && rcli->stores == const1_rtx))
02972 splay_tree_remove (pbi->reg_cond_dead, regno);
02973 else
02974 {
02975 rcli->condition = ncond;
02976
02977 SET_REGNO_REG_SET (pbi->reg_cond_reg, REGNO (XEXP (cond, 0)));
02978
02979
02980 return 0;
02981 }
02982 }
02983 }
02984
02985 return 1;
02986 }
02987
02988
02989
02990 static void
02991 free_reg_cond_life_info (value)
02992 splay_tree_value value;
02993 {
02994 struct reg_cond_life_info *rcli = (struct reg_cond_life_info *) value;
02995 free (rcli);
02996 }
02997
02998
02999
03000 static int
03001 flush_reg_cond_reg_1 (node, data)
03002 splay_tree_node node;
03003 void *data;
03004 {
03005 struct reg_cond_life_info *rcli;
03006 int *xdata = (int *) data;
03007 unsigned int regno = xdata[0];
03008
03009
03010
03011 if (xdata[1] >= (int) node->key)
03012 return 0;
03013
03014
03015 rcli = (struct reg_cond_life_info *) node->value;
03016 rcli->condition = elim_reg_cond (rcli->condition, regno);
03017 if (rcli->stores != const0_rtx && rcli->stores != const1_rtx)
03018 rcli->stores = elim_reg_cond (rcli->stores, regno);
03019
03020
03021 if (rcli->condition == const0_rtx)
03022 {
03023 xdata[1] = node->key;
03024 return -1;
03025 }
03026 else if (rcli->condition == const1_rtx)
03027 abort ();
03028
03029 return 0;
03030 }
03031
03032
03033
03034 static void
03035 flush_reg_cond_reg (pbi, regno)
03036 struct propagate_block_info *pbi;
03037 int regno;
03038 {
03039 int pair[2];
03040
03041 pair[0] = regno;
03042 pair[1] = -1;
03043 while (splay_tree_foreach (pbi->reg_cond_dead,
03044 flush_reg_cond_reg_1, pair) == -1)
03045 splay_tree_remove (pbi->reg_cond_dead, pair[1]);
03046
03047 CLEAR_REGNO_REG_SET (pbi->reg_cond_reg, regno);
03048 }
03049
03050
03051
03052
03053
03054
03055
03056
03057
03058
03059 static rtx
03060 ior_reg_cond (old, x, add)
03061 rtx old, x;
03062 int add;
03063 {
03064 rtx op0, op1;
03065
03066 if (GET_RTX_CLASS (GET_CODE (old)) == '<')
03067 {
03068 if (GET_RTX_CLASS (GET_CODE (x)) == '<'
03069 && REVERSE_CONDEXEC_PREDICATES_P (GET_CODE (x), GET_CODE (old))
03070 && REGNO (XEXP (x, 0)) == REGNO (XEXP (old, 0)))
03071 return const1_rtx;
03072 if (GET_CODE (x) == GET_CODE (old)
03073 && REGNO (XEXP (x, 0)) == REGNO (XEXP (old, 0)))
03074 return old;
03075 if (! add)
03076 return NULL;
03077 return gen_rtx_IOR (0, old, x);
03078 }
03079
03080 switch (GET_CODE (old))
03081 {
03082 case IOR:
03083 op0 = ior_reg_cond (XEXP (old, 0), x, 0);
03084 op1 = ior_reg_cond (XEXP (old, 1), x, 0);
03085 if (op0 != NULL || op1 != NULL)
03086 {
03087 if (op0 == const0_rtx)
03088 return op1 ? op1 : gen_rtx_IOR (0, XEXP (old, 1), x);
03089 if (op1 == const0_rtx)
03090 return op0 ? op0 : gen_rtx_IOR (0, XEXP (old, 0), x);
03091 if (op0 == const1_rtx || op1 == const1_rtx)
03092 return const1_rtx;
03093 if (op0 == NULL)
03094 op0 = gen_rtx_IOR (0, XEXP (old, 0), x);
03095 else if (rtx_equal_p (x, op0))
03096
03097 return old;
03098 if (op1 == NULL)
03099 op1 = gen_rtx_IOR (0, XEXP (old, 1), x);
03100 else if (rtx_equal_p (x, op1))
03101
03102 return old;
03103 return gen_rtx_IOR (0, op0, op1);
03104 }
03105 if (! add)
03106 return NULL;
03107 return gen_rtx_IOR (0, old, x);
03108
03109 case AND:
03110 op0 = ior_reg_cond (XEXP (old, 0), x, 0);
03111 op1 = ior_reg_cond (XEXP (old, 1), x, 0);
03112 if (op0 != NULL || op1 != NULL)
03113 {
03114 if (op0 == const1_rtx)
03115 return op1 ? op1 : gen_rtx_IOR (0, XEXP (old, 1), x);
03116 if (op1 == const1_rtx)
03117 return op0 ? op0 : gen_rtx_IOR (0, XEXP (old, 0), x);
03118 if (op0 == const0_rtx || op1 == const0_rtx)
03119 return const0_rtx;
03120 if (op0 == NULL)
03121 op0 = gen_rtx_IOR (0, XEXP (old, 0), x);
03122 else if (rtx_equal_p (x, op0))
03123
03124 return op0;
03125 if (op1 == NULL)
03126 op1 = gen_rtx_IOR (0, XEXP (old, 1), x);
03127 else if (rtx_equal_p (x, op1))
03128
03129 return op1;
03130 return gen_rtx_AND (0, op0, op1);
03131 }
03132 if (! add)
03133 return NULL;
03134 return gen_rtx_IOR (0, old, x);
03135
03136 case NOT:
03137 op0 = and_reg_cond (XEXP (old, 0), not_reg_cond (x), 0);
03138 if (op0 != NULL)
03139 return not_reg_cond (op0);
03140 if (! add)
03141 return NULL;
03142 return gen_rtx_IOR (0, old, x);
03143
03144 default:
03145 abort ();
03146 }
03147 }
03148
03149 static rtx
03150 not_reg_cond (x)
03151 rtx x;
03152 {
03153 enum rtx_code x_code;
03154
03155 if (x == const0_rtx)
03156 return const1_rtx;
03157 else if (x == const1_rtx)
03158 return const0_rtx;
03159 x_code = GET_CODE (x);
03160 if (x_code == NOT)
03161 return XEXP (x, 0);
03162 if (GET_RTX_CLASS (x_code) == '<'
03163 && GET_CODE (XEXP (x, 0)) == REG)
03164 {
03165 if (XEXP (x, 1) != const0_rtx)
03166 abort ();
03167
03168 return gen_rtx_fmt_ee (reverse_condition (x_code),
03169 VOIDmode, XEXP (x, 0), const0_rtx);
03170 }
03171 return gen_rtx_NOT (0, x);
03172 }
03173
03174 static rtx
03175 and_reg_cond (old, x, add)
03176 rtx old, x;
03177 int add;
03178 {
03179 rtx op0, op1;
03180
03181 if (GET_RTX_CLASS (GET_CODE (old)) == '<')
03182 {
03183 if (GET_RTX_CLASS (GET_CODE (x)) == '<'
03184 && GET_CODE (x) == reverse_condition (GET_CODE (old))
03185 && REGNO (XEXP (x, 0)) == REGNO (XEXP (old, 0)))
03186 return const0_rtx;
03187 if (GET_CODE (x) == GET_CODE (old)
03188 && REGNO (XEXP (x, 0)) == REGNO (XEXP (old, 0)))
03189 return old;
03190 if (! add)
03191 return NULL;
03192 return gen_rtx_AND (0, old, x);
03193 }
03194
03195 switch (GET_CODE (old))
03196 {
03197 case IOR:
03198 op0 = and_reg_cond (XEXP (old, 0), x, 0);
03199 op1 = and_reg_cond (XEXP (old, 1), x, 0);
03200 if (op0 != NULL || op1 != NULL)
03201 {
03202 if (op0 == const0_rtx)
03203 return op1 ? op1 : gen_rtx_AND (0, XEXP (old, 1), x);
03204 if (op1 == const0_rtx)
03205 return op0 ? op0 : gen_rtx_AND (0, XEXP (old, 0), x);
03206 if (op0 == const1_rtx || op1 == const1_rtx)
03207 return const1_rtx;
03208 if (op0 == NULL)
03209 op0 = gen_rtx_AND (0, XEXP (old, 0), x);
03210 else if (rtx_equal_p (x, op0))
03211
03212 return op0;
03213 if (op1 == NULL)
03214 op1 = gen_rtx_AND (0, XEXP (old, 1), x);
03215 else if (rtx_equal_p (x, op1))
03216
03217 return op1;
03218 return gen_rtx_IOR (0, op0, op1);
03219 }
03220 if (! add)
03221 return NULL;
03222 return gen_rtx_AND (0, old, x);
03223
03224 case AND:
03225 op0 = and_reg_cond (XEXP (old, 0), x, 0);
03226 op1 = and_reg_cond (XEXP (old, 1), x, 0);
03227 if (op0 != NULL || op1 != NULL)
03228 {
03229 if (op0 == const1_rtx)
03230 return op1 ? op1 : gen_rtx_AND (0, XEXP (old, 1), x);
03231 if (op1 == const1_rtx)
03232 return op0 ? op0 : gen_rtx_AND (0, XEXP (old, 0), x);
03233 if (op0 == const0_rtx || op1 == const0_rtx)
03234 return const0_rtx;
03235 if (op0 == NULL)
03236 op0 = gen_rtx_AND (0, XEXP (old, 0), x);
03237 else if (rtx_equal_p (x, op0))
03238
03239 return old;
03240 if (op1 == NULL)
03241 op1 = gen_rtx_AND (0, XEXP (old, 1), x);
03242 else if (rtx_equal_p (x, op1))
03243
03244 return old;
03245 return gen_rtx_AND (0, op0, op1);
03246 }
03247 if (! add)
03248 return NULL;
03249 return gen_rtx_AND (0, old, x);
03250
03251 case NOT:
03252 op0 = ior_reg_cond (XEXP (old, 0), not_reg_cond (x), 0);
03253 if (op0 != NULL)
03254 return not_reg_cond (op0);
03255 if (! add)
03256 return NULL;
03257 return gen_rtx_AND (0, old, x);
03258
03259 default:
03260 abort ();
03261 }
03262 }
03263
03264
03265
03266
03267
03268
03269 static rtx
03270 elim_reg_cond (x, regno)
03271 rtx x;
03272 unsigned int regno;
03273 {
03274 rtx op0, op1;
03275
03276 if (GET_RTX_CLASS (GET_CODE (x)) == '<')
03277 {
03278 if (REGNO (XEXP (x, 0)) == regno)
03279 return const0_rtx;
03280 return x;
03281 }
03282
03283 switch (GET_CODE (x))
03284 {
03285 case AND:
03286 op0 = elim_reg_cond (XEXP (x, 0), regno);
03287 op1 = elim_reg_cond (XEXP (x, 1), regno);
03288 if (op0 == const0_rtx || op1 == const0_rtx)
03289 return const0_rtx;
03290 if (op0 == const1_rtx)
03291 return op1;
03292 if (op1 == const1_rtx)
03293 return op0;
03294 if (op0 == XEXP (x, 0) && op1 == XEXP (x, 1))
03295 return x;
03296 return gen_rtx_AND (0, op0, op1);
03297
03298 case IOR:
03299 op0 = elim_reg_cond (XEXP (x, 0), regno);
03300 op1 = elim_reg_cond (XEXP (x, 1), regno);
03301 if (op0 == const1_rtx || op1 == const1_rtx)
03302 return const1_rtx;
03303 if (op0 == const0_rtx)
03304 return op1;
03305 if (op1 == const0_rtx)
03306 return op0;
03307 if (op0 == XEXP (x, 0) && op1 == XEXP (x, 1))
03308 return x;
03309 return gen_rtx_IOR (0, op0, op1);
03310
03311 case NOT:
03312 op0 = elim_reg_cond (XEXP (x, 0), regno);
03313 if (op0 == const0_rtx)
03314 return const1_rtx;
03315 if (op0 == const1_rtx)
03316 return const0_rtx;
03317 if (op0 != XEXP (x, 0))
03318 return not_reg_cond (op0);
03319 return x;
03320
03321 default:
03322 abort ();
03323 }
03324 }
03325 #endif
03326
03327 #ifdef AUTO_INC_DEC
03328
03329
03330
03331
03332
03333
03334
03335 static void
03336 attempt_auto_inc (pbi, inc, insn, mem, incr, incr_reg)
03337 struct propagate_block_info *pbi;
03338 rtx inc, insn, mem, incr, incr_reg;
03339 {
03340 int regno = REGNO (incr_reg);
03341 rtx set = single_set (incr);
03342 rtx q = SET_DEST (set);
03343 rtx y = SET_SRC (set);
03344 int opnum = XEXP (y, 0) == incr_reg ? 0 : 1;
03345
03346
03347 if (count_occurrences (PATTERN (insn), incr_reg, 1) != 1)
03348 return;
03349
03350 if (dead_or_set_p (incr, incr_reg)
03351
03352 && (regno >= FIRST_PSEUDO_REGISTER
03353 || ! TEST_HARD_REG_BIT (elim_reg_set, regno)))
03354 {
03355
03356
03357
03358 if (! validate_change (insn, &XEXP (mem, 0), inc, 0))
03359 return;
03360 }
03361 else if (GET_CODE (q) == REG
03362
03363
03364 && ! reg_used_between_p (q, PREV_INSN (insn), incr)
03365
03366
03367
03368 && ! reg_set_between_p (q, PREV_INSN (insn), incr))
03369 {
03370
03371
03372
03373
03374
03375 rtx insns, temp;
03376
03377 start_sequence ();
03378 emit_move_insn (q, incr_reg);
03379 insns = get_insns ();
03380 end_sequence ();
03381
03382
03383
03384
03385
03386
03387 XEXP (inc, 0) = q;
03388 validate_change (insn, &XEXP (mem, 0), inc, 1);
03389 validate_change (incr, &XEXP (y, opnum), q, 1);
03390 if (! apply_change_group ())
03391 return;
03392
03393
03394
03395 emit_insn_before (insns, insn);
03396
03397 if (pbi->bb->head == insn)
03398 pbi->bb->head = insns;
03399
03400
03401
03402
03403
03404 if (GET_CODE (PREV_INSN (insn)) == INSN
03405 && GET_CODE (PATTERN (PREV_INSN (insn))) == SET
03406 && SET_SRC (PATTERN (PREV_INSN (insn))) == incr_reg)
03407 pbi->reg_next_use[regno] = PREV_INSN (insn);
03408 else
03409 pbi->reg_next_use[regno] = 0;
03410
03411 incr_reg = q;
03412 regno = REGNO (q);
03413
03414
03415
03416
03417
03418 SET_REGNO_REG_SET (pbi->reg_live, regno);
03419
03420
03421
03422 for (temp = insn; temp != incr; temp = NEXT_INSN (temp))
03423 if (GET_CODE (temp) == CALL_INSN)
03424 REG_N_CALLS_CROSSED (regno)++;
03425
03426
03427 clear_reg_alias_info (q);
03428 }
03429 else
03430 return;
03431
03432
03433
03434
03435
03436 REG_NOTES (insn) = alloc_EXPR_LIST (REG_INC, incr_reg, REG_NOTES (insn));
03437
03438
03439
03440 if (! validate_change (incr, &SET_SRC (set), incr_reg, 0))
03441 abort ();
03442
03443
03444
03445
03446 if (REGNO (SET_DEST (set)) == REGNO (incr_reg))
03447 {
03448
03449 rtx note;
03450
03451 while ((note = find_reg_note (incr, REG_DEAD, NULL_RTX)) != NULL_RTX)
03452 {
03453 remove_note (incr, note);
03454 if (XEXP (note, 0) != incr_reg)
03455 CLEAR_REGNO_REG_SET (pbi->reg_live, REGNO (XEXP (note, 0)));
03456 }
03457
03458 PUT_CODE (incr, NOTE);
03459 NOTE_LINE_NUMBER (incr) = NOTE_INSN_DELETED;
03460 NOTE_SOURCE_FILE (incr) = 0;
03461 }
03462
03463 if (regno >= FIRST_PSEUDO_REGISTER)
03464 {
03465
03466
03467
03468 REG_FREQ (regno) += REG_FREQ_FROM_BB (pbi->bb);
03469
03470
03471
03472 REG_N_SETS (regno)++;
03473 }
03474 }
03475
03476
03477
03478
03479 static void
03480 find_auto_inc (pbi, x, insn)
03481 struct propagate_block_info *pbi;
03482 rtx x;
03483 rtx insn;
03484 {
03485 rtx addr = XEXP (x, 0);
03486 HOST_WIDE_INT offset = 0;
03487 rtx set, y, incr, inc_val;
03488 int regno;
03489 int size = GET_MODE_SIZE (GET_MODE (x));
03490
03491 if (GET_CODE (insn) == JUMP_INSN)
03492 return;
03493
03494
03495
03496
03497 if (GET_CODE (addr) == PLUS && GET_CODE (XEXP (addr, 1)) == CONST_INT)
03498 offset = INTVAL (XEXP (addr, 1)), addr = XEXP (addr, 0);
03499
03500 if (GET_CODE (addr) != REG)
03501 return;
03502
03503 regno = REGNO (addr);
03504
03505
03506 incr = pbi->reg_next_use[regno];
03507 if (incr == 0 || BLOCK_NUM (incr) != BLOCK_NUM (insn))
03508 return;
03509 set = single_set (incr);
03510 if (set == 0 || GET_CODE (set) != SET)
03511 return;
03512 y = SET_SRC (set);
03513
03514 if (GET_CODE (y) != PLUS)
03515 return;
03516
03517 if (REG_P (XEXP (y, 0)) && REGNO (XEXP (y, 0)) == REGNO (addr))
03518 inc_val = XEXP (y, 1);
03519 else if (REG_P (XEXP (y, 1)) && REGNO (XEXP (y, 1)) == REGNO (addr))
03520 inc_val = XEXP (y, 0);
03521 else
03522 return;
03523
03524 if (GET_CODE (inc_val) == CONST_INT)
03525 {
03526 if (HAVE_POST_INCREMENT
03527 && (INTVAL (inc_val) == size && offset == 0))
03528 attempt_auto_inc (pbi, gen_rtx_POST_INC (Pmode, addr), insn, x,
03529 incr, addr);
03530 else if (HAVE_POST_DECREMENT
03531 && (INTVAL (inc_val) == -size && offset == 0))
03532 attempt_auto_inc (pbi, gen_rtx_POST_DEC (Pmode, addr), insn, x,
03533 incr, addr);
03534 else if (HAVE_PRE_INCREMENT
03535 && (INTVAL (inc_val) == size && offset == size))
03536 attempt_auto_inc (pbi, gen_rtx_PRE_INC (Pmode, addr), insn, x,
03537 incr, addr);
03538 else if (HAVE_PRE_DECREMENT
03539 && (INTVAL (inc_val) == -size && offset == -size))
03540 attempt_auto_inc (pbi, gen_rtx_PRE_DEC (Pmode, addr), insn, x,
03541 incr, addr);
03542 else if (HAVE_POST_MODIFY_DISP && offset == 0)
03543 attempt_auto_inc (pbi, gen_rtx_POST_MODIFY (Pmode, addr,
03544 gen_rtx_PLUS (Pmode,
03545 addr,
03546 inc_val)),
03547 insn, x, incr, addr);
03548 }
03549 else if (GET_CODE (inc_val) == REG
03550 && ! reg_set_between_p (inc_val, PREV_INSN (insn),
03551 NEXT_INSN (incr)))
03552
03553 {
03554 if (HAVE_POST_MODIFY_REG && offset == 0)
03555 attempt_auto_inc (pbi, gen_rtx_POST_MODIFY (Pmode, addr,
03556 gen_rtx_PLUS (Pmode,
03557 addr,
03558 inc_val)),
03559 insn, x, incr, addr);
03560 }
03561 }
03562
03563 #endif
03564
03565 static void
03566 mark_used_reg (pbi, reg, cond, insn)
03567 struct propagate_block_info *pbi;
03568 rtx reg;
03569 rtx cond ATTRIBUTE_UNUSED;
03570 rtx insn;
03571 {
03572 unsigned int regno_first, regno_last, i;
03573 int some_was_live, some_was_dead, some_not_set;
03574
03575 regno_last = regno_first = REGNO (reg);
03576 if (regno_first < FIRST_PSEUDO_REGISTER)
03577 regno_last += HARD_REGNO_NREGS (regno_first, GET_MODE (reg)) - 1;
03578
03579
03580 some_was_live = some_was_dead = 0;
03581 for (i = regno_first; i <= regno_last; ++i)
03582 {
03583 int needed_regno = REGNO_REG_SET_P (pbi->reg_live, i);
03584 some_was_live |= needed_regno;
03585 some_was_dead |= ! needed_regno;
03586 }
03587
03588
03589 some_not_set = 0;
03590 for (i = regno_first; i <= regno_last; ++i)
03591 some_not_set |= ! REGNO_REG_SET_P (pbi->new_set, i);
03592
03593 if (pbi->flags & (PROP_LOG_LINKS | PROP_AUTOINC))
03594 {
03595
03596
03597 pbi->reg_next_use[regno_first] = insn;
03598 }
03599
03600 if (pbi->flags & PROP_REG_INFO)
03601 {
03602 if (regno_first < FIRST_PSEUDO_REGISTER)
03603 {
03604
03605
03606
03607
03608
03609
03610
03611
03612
03613
03614
03615
03616 if (! (TEST_HARD_REG_BIT (elim_reg_set, regno_first)
03617 && (regno_first == FRAME_POINTER_REGNUM
03618 || regno_first == ARG_POINTER_REGNUM)))
03619 for (i = regno_first; i <= regno_last; ++i)
03620 regs_ever_live[i] = 1;
03621 }
03622 else
03623 {
03624
03625
03626 int blocknum = pbi->bb->index;
03627 if (REG_BASIC_BLOCK (regno_first) == REG_BLOCK_UNKNOWN)
03628 REG_BASIC_BLOCK (regno_first) = blocknum;
03629 else if (REG_BASIC_BLOCK (regno_first) != blocknum)
03630 REG_BASIC_BLOCK (regno_first) = REG_BLOCK_GLOBAL;
03631
03632
03633 REG_FREQ (regno_first) += REG_FREQ_FROM_BB (pbi->bb);
03634 REG_N_REFS (regno_first)++;
03635 }
03636 }
03637
03638
03639
03640
03641
03642 if ((pbi->flags & (PROP_DEATH_NOTES | PROP_REG_INFO))
03643 && some_was_dead
03644 && some_not_set)
03645 {
03646
03647
03648 if (regno_first != regno_last)
03649 for (i = regno_first; i <= regno_last; ++i)
03650 some_was_live |= REGNO_REG_SET_P (pbi->new_set, i);
03651
03652
03653
03654 if (! some_was_live)
03655 {
03656 if ((pbi->flags & PROP_DEATH_NOTES)
03657 && ! find_regno_note (insn, REG_DEAD, regno_first))
03658 REG_NOTES (insn)
03659 = alloc_EXPR_LIST (REG_DEAD, reg, REG_NOTES (insn));
03660
03661 if (pbi->flags & PROP_REG_INFO)
03662 REG_N_DEATHS (regno_first)++;
03663 }
03664 else
03665 {
03666
03667
03668 for (i = regno_first; i <= regno_last; ++i)
03669 if (! REGNO_REG_SET_P (pbi->reg_live, i)
03670 && ! dead_or_set_regno_p (insn, i))
03671 REG_NOTES (insn)
03672 = alloc_EXPR_LIST (REG_DEAD,
03673 regno_reg_rtx[i],
03674 REG_NOTES (insn));
03675 }
03676 }
03677
03678
03679 for (i = regno_first; i <= regno_last; ++i)
03680 {
03681 #ifdef HAVE_conditional_execution
03682 int this_was_live = REGNO_REG_SET_P (pbi->reg_live, i);
03683 #endif
03684
03685 SET_REGNO_REG_SET (pbi->reg_live, i);
03686
03687 #ifdef HAVE_conditional_execution
03688
03689
03690 if (cond != NULL_RTX)
03691 {
03692 splay_tree_node node;
03693 struct reg_cond_life_info *rcli;
03694 rtx ncond;
03695
03696 if (this_was_live)
03697 {
03698 node = splay_tree_lookup (pbi->reg_cond_dead, i);
03699 if (node == NULL)
03700 {
03701
03702
03703 }
03704 else
03705 {
03706
03707
03708 rcli = (struct reg_cond_life_info *) node->value;
03709 ncond = rcli->condition;
03710 ncond = and_reg_cond (ncond, not_reg_cond (cond), 1);
03711
03712
03713
03714 if (ncond == const0_rtx)
03715 splay_tree_remove (pbi->reg_cond_dead, i);
03716 else
03717 {
03718 rcli->condition = ncond;
03719 SET_REGNO_REG_SET (pbi->reg_cond_reg,
03720 REGNO (XEXP (cond, 0)));
03721 }
03722 }
03723 }
03724 else
03725 {
03726
03727
03728 rcli = (struct reg_cond_life_info *) xmalloc (sizeof (*rcli));
03729 rcli->condition = not_reg_cond (cond);
03730 rcli->stores = const0_rtx;
03731 rcli->orig_condition = const0_rtx;
03732 splay_tree_insert (pbi->reg_cond_dead, i,
03733 (splay_tree_value) rcli);
03734
03735 SET_REGNO_REG_SET (pbi->reg_cond_reg, REGNO (XEXP (cond, 0)));
03736 }
03737 }
03738 else if (this_was_live)
03739 {
03740
03741
03742
03743
03744 splay_tree_remove (pbi->reg_cond_dead, i);
03745 }
03746 #endif
03747 }
03748 }
03749
03750
03751
03752
03753
03754
03755
03756
03757 static void
03758 mark_used_regs (pbi, x, cond, insn)
03759 struct propagate_block_info *pbi;
03760 rtx x, cond, insn;
03761 {
03762 RTX_CODE code;
03763 int regno;
03764 int flags = pbi->flags;
03765
03766 retry:
03767 if (!x)
03768 return;
03769 code = GET_CODE (x);
03770 switch (code)
03771 {
03772 case LABEL_REF:
03773 case SYMBOL_REF:
03774 case CONST_INT:
03775 case CONST:
03776 case CONST_DOUBLE:
03777 case CONST_VECTOR:
03778 case PC:
03779 case ADDR_VEC:
03780 case ADDR_DIFF_VEC:
03781 return;
03782
03783 #ifdef HAVE_cc0
03784 case CC0:
03785 pbi->cc0_live = 1;
03786 return;
03787 #endif
03788
03789 case CLOBBER:
03790
03791
03792 if (GET_CODE (XEXP (x, 0)) == MEM)
03793 mark_used_regs (pbi, XEXP (XEXP (x, 0), 0), cond, insn);
03794 return;
03795
03796 case MEM:
03797
03798
03799 if (optimize && (flags & PROP_SCAN_DEAD_STORES))
03800 {
03801
03802
03803 if (GET_CODE (XEXP (x, 0)) == SYMBOL_REF
03804 && CONSTANT_POOL_ADDRESS_P (XEXP (x, 0)))
03805
03806 ;
03807 else
03808 {
03809 rtx temp = pbi->mem_set_list;
03810 rtx prev = NULL_RTX;
03811 rtx next;
03812
03813 while (temp)
03814 {
03815 next = XEXP (temp, 1);
03816 if (anti_dependence (XEXP (temp, 0), x))
03817 {
03818
03819 if (prev)
03820 XEXP (prev, 1) = next;
03821 else
03822 pbi->mem_set_list = next;
03823 free_EXPR_LIST_node (temp);
03824 pbi->mem_set_list_len--;
03825 }
03826 else
03827 prev = temp;
03828 temp = next;
03829 }
03830 }
03831
03832
03833
03834
03835 if (insn)
03836 for_each_rtx (&PATTERN (insn), invalidate_mems_from_autoinc, pbi);
03837 }
03838
03839 #ifdef AUTO_INC_DEC
03840 if (flags & PROP_AUTOINC)
03841 find_auto_inc (pbi, x, insn);
03842 #endif
03843 break;
03844
03845 case SUBREG:
03846 #ifdef CANNOT_CHANGE_MODE_CLASS
03847 if (GET_CODE (SUBREG_REG (x)) == REG
03848 && REGNO (SUBREG_REG (x)) >= FIRST_PSEUDO_REGISTER)
03849 bitmap_set_bit (&subregs_of_mode, REGNO (SUBREG_REG (x))
03850 * MAX_MACHINE_MODE
03851 + GET_MODE (x));
03852 #endif
03853
03854
03855 x = SUBREG_REG (x);
03856 if (GET_CODE (x) != REG)
03857 goto retry;
03858
03859
03860 case REG:
03861
03862 mark_used_reg (pbi, x, cond, insn);
03863 return;
03864
03865 case SET:
03866 {
03867 rtx testreg = SET_DEST (x);
03868 int mark_dest = 0;
03869
03870
03871
03872 if (GET_CODE (testreg) == MEM)
03873 {
03874 #ifdef AUTO_INC_DEC
03875 if (flags & PROP_AUTOINC)
03876 find_auto_inc (pbi, testreg, insn);
03877 #endif
03878 mark_used_regs (pbi, XEXP (testreg, 0), cond, insn);
03879 mark_used_regs (pbi, SET_SRC (x), cond, insn);
03880 return;
03881 }
03882
03883
03884
03885
03886
03887
03888
03889
03890 while (GET_CODE (testreg) == STRICT_LOW_PART
03891 || GET_CODE (testreg) == ZERO_EXTRACT
03892 || GET_CODE (testreg) == SIGN_EXTRACT
03893 || GET_CODE (testreg) == SUBREG)
03894 {
03895 #ifdef CANNOT_CHANGE_MODE_CLASS
03896 if (GET_CODE (testreg) == SUBREG
03897 && GET_CODE (SUBREG_REG (testreg)) == REG
03898 && REGNO (SUBREG_REG (testreg)) >= FIRST_PSEUDO_REGISTER)
03899 bitmap_set_bit (&subregs_of_mode, REGNO (SUBREG_REG (testreg))
03900 * MAX_MACHINE_MODE
03901 + GET_MODE (testreg));
03902 #endif
03903
03904
03905
03906
03907 if (GET_CODE (testreg) == SUBREG
03908 && !((REG_BYTES (SUBREG_REG (testreg))
03909 + UNITS_PER_WORD - 1) / UNITS_PER_WORD
03910 > (REG_BYTES (testreg)
03911 + UNITS_PER_WORD - 1) / UNITS_PER_WORD))
03912 ;
03913 else
03914 mark_dest = 1;
03915
03916 testreg = XEXP (testreg, 0);
03917 }
03918
03919
03920
03921
03922 if ((GET_CODE (testreg) == PARALLEL
03923 && GET_MODE (testreg) == BLKmode)
03924 || (GET_CODE (testreg) == REG
03925 && (regno = REGNO (testreg),
03926 ! (regno == FRAME_POINTER_REGNUM
03927 && (! reload_completed || frame_pointer_needed)))
03928 #if FRAME_POINTER_REGNUM != HARD_FRAME_POINTER_REGNUM
03929 && ! (regno == HARD_FRAME_POINTER_REGNUM
03930 && (! reload_completed || frame_pointer_needed))
03931 #endif
03932 #if FRAME_POINTER_REGNUM != ARG_POINTER_REGNUM
03933 && ! (regno == ARG_POINTER_REGNUM && fixed_regs[regno])
03934 #endif
03935 ))
03936 {
03937 if (mark_dest)
03938 mark_used_regs (pbi, SET_DEST (x), cond, insn);
03939 mark_used_regs (pbi, SET_SRC (x), cond, insn);
03940 return;
03941 }
03942 }
03943 break;
03944
03945 case ASM_OPERANDS:
03946 case UNSPEC_VOLATILE:
03947 case TRAP_IF:
03948 case ASM_INPUT:
03949 {
03950
03951
03952
03953
03954
03955
03956
03957
03958
03959
03960
03961
03962
03963
03964 if (code != ASM_OPERANDS || MEM_VOLATILE_P (x))
03965 {
03966 free_EXPR_LIST_list (&pbi->mem_set_list);
03967 pbi->mem_set_list_len = 0;
03968 }
03969
03970
03971
03972
03973
03974 if (code == ASM_OPERANDS)
03975 {
03976 int j;
03977
03978 for (j = 0; j < ASM_OPERANDS_INPUT_LENGTH (x); j++)
03979 mark_used_regs (pbi, ASM_OPERANDS_INPUT (x, j), cond, insn);
03980 }
03981 break;
03982 }
03983
03984 case COND_EXEC:
03985 if (cond != NULL_RTX)
03986 abort ();
03987
03988 mark_used_regs (pbi, COND_EXEC_TEST (x), NULL_RTX, insn);
03989
03990 cond = COND_EXEC_TEST (x);
03991 x = COND_EXEC_CODE (x);
03992 goto retry;
03993
03994 case PHI:
03995
03996
03997
03998
03999
04000 return;
04001
04002 default:
04003 break;
04004 }
04005
04006
04007
04008 {
04009 const char * const fmt = GET_RTX_FORMAT (code);
04010 int i;
04011
04012 for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
04013 {
04014 if (fmt[i] == 'e')
04015 {
04016
04017 if (i == 0)
04018 {
04019 x = XEXP (x, 0);
04020 goto retry;
04021 }
04022 mark_used_regs (pbi, XEXP (x, i), cond, insn);
04023 }
04024 else if (fmt[i] == 'E')
04025 {
04026 int j;
04027 for (j = 0; j < XVECLEN (x, i); j++)
04028 mark_used_regs (pbi, XVECEXP (x, i, j), cond, insn);
04029 }
04030 }
04031 }
04032 }
04033
04034 #ifdef AUTO_INC_DEC
04035
04036 static int
04037 try_pre_increment_1 (pbi, insn)
04038 struct propagate_block_info *pbi;
04039 rtx insn;
04040 {
04041
04042
04043 rtx x = single_set (insn);
04044 HOST_WIDE_INT amount = ((GET_CODE (SET_SRC (x)) == PLUS ? 1 : -1)
04045 * INTVAL (XEXP (SET_SRC (x), 1)));
04046 int regno = REGNO (SET_DEST (x));
04047 rtx y = pbi->reg_next_use[regno];
04048 if (y != 0
04049 && SET_DEST (x) != stack_pointer_rtx
04050 && BLOCK_NUM (y) == BLOCK_NUM (insn)
04051
04052
04053 && ! dead_or_set_p (y, SET_DEST (x))
04054 && try_pre_increment (y, SET_DEST (x), amount))
04055 {
04056
04057
04058 propagate_block_delete_insn (insn);
04059
04060
04061
04062
04063 if (regno >= FIRST_PSEUDO_REGISTER)
04064 {
04065 REG_FREQ (regno) += REG_FREQ_FROM_BB (pbi->bb);
04066 REG_N_SETS (regno)++;
04067 }
04068
04069
04070
04071 invalidate_mems_from_set (pbi, SET_DEST (x));
04072
04073 return 1;
04074 }
04075 return 0;
04076 }
04077
04078
04079
04080
04081
04082
04083
04084 static int
04085 try_pre_increment (insn, reg, amount)
04086 rtx insn, reg;
04087 HOST_WIDE_INT amount;
04088 {
04089 rtx use;
04090
04091
04092
04093 int pre_ok = 0;
04094
04095
04096
04097
04098 int post_ok = 0;
04099
04100
04101 int do_post = 0;
04102
04103
04104
04105 if (HAVE_PRE_INCREMENT && amount > 0)
04106 pre_ok = 1;
04107 if (HAVE_POST_INCREMENT && amount > 0)
04108 post_ok = 1;
04109
04110 if (HAVE_PRE_DECREMENT && amount < 0)
04111 pre_ok = 1;
04112 if (HAVE_POST_DECREMENT && amount < 0)
04113 post_ok = 1;
04114
04115 if (! (pre_ok || post_ok))
04116 return 0;
04117
04118
04119
04120
04121
04122 if (GET_CODE (insn) == JUMP_INSN)
04123 return 0;
04124
04125 use = 0;
04126 if (pre_ok)
04127 use = find_use_as_address (PATTERN (insn), reg, 0);
04128 if (post_ok && (use == 0 || use == (rtx) (size_t) 1))
04129 {
04130 use = find_use_as_address (PATTERN (insn), reg, -amount);
04131 do_post = 1;
04132 }
04133
04134 if (use == 0 || use == (rtx) (size_t) 1)
04135 return 0;
04136
04137 if (GET_MODE_SIZE (GET_MODE (use)) != (amount > 0 ? amount : - amount))
04138 return 0;
04139
04140
04141 if (! validate_change (insn, &XEXP (use, 0),
04142 gen_rtx_fmt_e (amount > 0
04143 ? (do_post ? POST_INC : PRE_INC)
04144 : (do_post ? POST_DEC : PRE_DEC),
04145 Pmode, reg), 0))
04146 return 0;
04147
04148
04149 REG_NOTES (insn) = alloc_EXPR_LIST (REG_INC, reg, REG_NOTES (insn));
04150 return 1;
04151 }
04152
04153 #endif
04154
04155
04156
04157
04158
04159
04160
04161
04162
04163
04164 rtx
04165 find_use_as_address (x, reg, plusconst)
04166 rtx x;
04167 rtx reg;
04168 HOST_WIDE_INT plusconst;
04169 {
04170 enum rtx_code code = GET_CODE (x);
04171 const char * const fmt = GET_RTX_FORMAT (code);
04172 int i;
04173 rtx value = 0;
04174 rtx tem;
04175
04176 if (code == MEM && XEXP (x, 0) == reg && plusconst == 0)
04177 return x;
04178
04179 if (code == MEM && GET_CODE (XEXP (x, 0)) == PLUS
04180 && XEXP (XEXP (x, 0), 0) == reg
04181 && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT
04182 && INTVAL (XEXP (XEXP (x, 0), 1)) == plusconst)
04183 return x;
04184
04185 if (code == SIGN_EXTRACT || code == ZERO_EXTRACT)
04186 {
04187
04188
04189 if (find_use_as_address (XEXP (x, 0), reg, 0) != 0)
04190 return (rtx) (size_t) 1;
04191 }
04192
04193 if (x == reg)
04194 return (rtx) (size_t) 1;
04195
04196 for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
04197 {
04198 if (fmt[i] == 'e')
04199 {
04200 tem = find_use_as_address (XEXP (x, i), reg, plusconst);
04201 if (value == 0)
04202 value = tem;
04203 else if (tem != 0)
04204 return (rtx) (size_t) 1;
04205 }
04206 else if (fmt[i] == 'E')
04207 {
04208 int j;
04209 for (j = XVECLEN (x, i) - 1; j >= 0; j--)
04210 {
04211 tem = find_use_as_address (XVECEXP (x, i, j), reg, plusconst);
04212 if (value == 0)
04213 value = tem;
04214 else if (tem != 0)
04215 return (rtx) (size_t) 1;
04216 }
04217 }
04218 }
04219
04220 return value;
04221 }
04222
04223
04224
04225
04226 void
04227 dump_regset (r, outf)
04228 regset r;
04229 FILE *outf;
04230 {
04231 int i;
04232 if (r == NULL)
04233 {
04234 fputs (" (nil)", outf);
04235 return;
04236 }
04237
04238 EXECUTE_IF_SET_IN_REG_SET (r, 0, i,
04239 {
04240 fprintf (outf, " %d", i);
04241 if (i < FIRST_PSEUDO_REGISTER)
04242 fprintf (outf, " [%s]",
04243 reg_names[i]);
04244 });
04245 }
04246
04247
04248
04249
04250
04251 void
04252 debug_regset (r)
04253 regset r;
04254 {
04255 dump_regset (r, stderr);
04256 putc ('\n', stderr);
04257 }
04258
04259
04260
04261
04262
04263
04264
04265
04266
04267
04268
04269
04270
04271
04272
04273
04274
04275
04276
04277
04278 void
04279 recompute_reg_usage (f, loop_step)
04280 rtx f ATTRIBUTE_UNUSED;
04281 int loop_step ATTRIBUTE_UNUSED;
04282 {
04283 allocate_reg_life_data ();
04284 update_life_info (NULL, UPDATE_LIFE_LOCAL, PROP_REG_INFO);
04285 }
04286
04287
04288
04289
04290
04291 int
04292 count_or_remove_death_notes (blocks, kill)
04293 sbitmap blocks;
04294 int kill;
04295 {
04296 int count = 0;
04297 basic_block bb;
04298
04299 FOR_EACH_BB_REVERSE (bb)
04300 {
04301 rtx insn;
04302
04303 if (blocks && ! TEST_BIT (blocks, bb->index))
04304 continue;
04305
04306 for (insn = bb->head;; insn = NEXT_INSN (insn))
04307 {
04308 if (INSN_P (insn))
04309 {
04310 rtx *pprev = ®_NOTES (insn);
04311 rtx link = *pprev;
04312
04313 while (link)
04314 {
04315 switch (REG_NOTE_KIND (link))
04316 {
04317 case REG_DEAD:
04318 if (GET_CODE (XEXP (link, 0)) == REG)
04319 {
04320 rtx reg = XEXP (link, 0);
04321 int n;
04322
04323 if (REGNO (reg) >= FIRST_PSEUDO_REGISTER)
04324 n = 1;
04325 else
04326 n = HARD_REGNO_NREGS (REGNO (reg), GET_MODE (reg));
04327 count += n;
04328 }
04329
04330
04331 case REG_UNUSED:
04332 if (kill)
04333 {
04334 rtx next = XEXP (link, 1);
04335 free_EXPR_LIST_node (link);
04336 *pprev = link = next;
04337 break;
04338 }
04339
04340
04341 default:
04342 pprev = &XEXP (link, 1);
04343 link = *pprev;
04344 break;
04345 }
04346 }
04347 }
04348
04349 if (insn == bb->end)
04350 break;
04351 }
04352 }
04353
04354 return count;
04355 }
04356
04357
04358
04359 static void
04360 clear_log_links (blocks)
04361 sbitmap blocks;
04362 {
04363 rtx insn;
04364 int i;
04365
04366 if (!blocks)
04367 {
04368 for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
04369 if (INSN_P (insn))
04370 free_INSN_LIST_list (&LOG_LINKS (insn));
04371 }
04372 else
04373 EXECUTE_IF_SET_IN_SBITMAP (blocks, 0, i,
04374 {
04375 basic_block bb = BASIC_BLOCK (i);
04376
04377 for (insn = bb->head; insn != NEXT_INSN (bb->end);
04378 insn = NEXT_INSN (insn))
04379 if (INSN_P (insn))
04380 free_INSN_LIST_list (&LOG_LINKS (insn));
04381 });
04382 }
04383
04384
04385
04386
04387
04388
04389 void
04390 reg_set_to_hard_reg_set (to, from)
04391 HARD_REG_SET *to;
04392 bitmap from;
04393 {
04394 int i;
04395
04396 EXECUTE_IF_SET_IN_BITMAP
04397 (from, 0, i,
04398 {
04399 if (i >= FIRST_PSEUDO_REGISTER)
04400 return;
04401 SET_HARD_REG_BIT (*to, i);
04402 });
04403 }