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