00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146 #include "config.h"
00147 #include "system.h"
00148 #include "coretypes.h"
00149 #include "tm.h"
00150 #include "toplev.h"
00151
00152 #include "rtl.h"
00153 #include "tree.h"
00154 #include "tm_p.h"
00155 #include "regs.h"
00156 #include "hard-reg-set.h"
00157 #include "flags.h"
00158 #include "real.h"
00159 #include "insn-config.h"
00160 #include "recog.h"
00161 #include "basic-block.h"
00162 #include "output.h"
00163 #include "function.h"
00164 #include "expr.h"
00165 #include "except.h"
00166 #include "ggc.h"
00167 #include "params.h"
00168 #include "cselib.h"
00169 #include "intl.h"
00170 #include "obstack.h"
00171 #include "timevar.h"
00172 #include "tree-pass.h"
00173 #include "hashtab.h"
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280 static int run_jump_opt_after_gcse;
00281
00282
00283 static struct obstack gcse_obstack;
00284
00285 struct reg_use {rtx reg_rtx; };
00286
00287
00288
00289 struct expr
00290 {
00291
00292 rtx expr;
00293
00294 int bitmap_index;
00295
00296 struct expr *next_same_hash;
00297
00298
00299
00300
00301
00302 struct occr *antic_occr;
00303
00304
00305
00306
00307 struct occr *avail_occr;
00308
00309
00310
00311 rtx reaching_reg;
00312 };
00313
00314
00315
00316
00317
00318 struct occr
00319 {
00320
00321 struct occr *next;
00322
00323 rtx insn;
00324
00325 char deleted_p;
00326
00327
00328
00329
00330 char copied_p;
00331 };
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342 struct hash_table
00343 {
00344
00345
00346 struct expr **table;
00347
00348
00349 unsigned int size;
00350
00351
00352 unsigned int n_elems;
00353
00354
00355 int set_p;
00356 };
00357
00358
00359 static struct hash_table expr_hash_table;
00360
00361
00362 static struct hash_table set_hash_table;
00363
00364
00365
00366 static int *uid_cuid;
00367
00368
00369 static int max_uid;
00370
00371
00372 #ifdef ENABLE_CHECKING
00373 #define INSN_CUID(INSN) \
00374 (gcc_assert (INSN_UID (INSN) <= max_uid), uid_cuid[INSN_UID (INSN)])
00375 #else
00376 #define INSN_CUID(INSN) (uid_cuid[INSN_UID (INSN)])
00377 #endif
00378
00379
00380 static int max_cuid;
00381
00382
00383 static rtx *cuid_insn;
00384
00385
00386 #define CUID_INSN(CUID) (cuid_insn[CUID])
00387
00388
00389
00390
00391 static unsigned int max_gcse_regno;
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411
00412
00413
00414
00415
00416 typedef struct reg_set
00417 {
00418
00419 struct reg_set *next;
00420
00421 int bb_index;
00422 } reg_set;
00423
00424 static reg_set **reg_set_table;
00425
00426
00427
00428
00429 static int reg_set_table_size;
00430
00431
00432 #define REG_SET_TABLE_SLOP 100
00433
00434
00435
00436
00437
00438
00439
00440
00441
00442
00443
00444
00445 struct ls_expr
00446 {
00447 struct expr * expr;
00448 rtx pattern;
00449 rtx pattern_regs;
00450 rtx loads;
00451 rtx stores;
00452 struct ls_expr * next;
00453 int invalid;
00454 int index;
00455 unsigned int hash_index;
00456 rtx reaching_reg;
00457 };
00458
00459
00460 static rtx *implicit_sets;
00461
00462
00463 static struct ls_expr * pre_ldst_mems = NULL;
00464
00465
00466 static htab_t pre_ldst_table = NULL;
00467
00468
00469
00470
00471 static regset reg_set_bitmap;
00472
00473
00474
00475
00476
00477
00478 static sbitmap *reg_set_in_block;
00479
00480
00481
00482 static rtx * modify_mem_list;
00483 static bitmap modify_mem_list_set;
00484
00485
00486 static rtx * canon_modify_mem_list;
00487
00488
00489
00490 static bitmap blocks_with_calls;
00491
00492
00493
00494
00495
00496
00497 static int bytes_used;
00498
00499
00500 static int gcse_subst_count;
00501
00502 static int gcse_create_count;
00503
00504 static int local_const_prop_count;
00505
00506 static int local_copy_prop_count;
00507
00508 static int global_const_prop_count;
00509
00510 static int global_copy_prop_count;
00511
00512
00513 static sbitmap *ae_kill, *ae_gen;
00514
00515 static void compute_can_copy (void);
00516 static void *gmalloc (size_t) ATTRIBUTE_MALLOC;
00517 static void *gcalloc (size_t, size_t) ATTRIBUTE_MALLOC;
00518 static void *grealloc (void *, size_t);
00519 static void *gcse_alloc (unsigned long);
00520 static void alloc_gcse_mem (void);
00521 static void free_gcse_mem (void);
00522 static void alloc_reg_set_mem (int);
00523 static void free_reg_set_mem (void);
00524 static void record_one_set (int, rtx);
00525 static void record_set_info (rtx, rtx, void *);
00526 static void compute_sets (void);
00527 static void hash_scan_insn (rtx, struct hash_table *, int);
00528 static void hash_scan_set (rtx, rtx, struct hash_table *);
00529 static void hash_scan_clobber (rtx, rtx, struct hash_table *);
00530 static void hash_scan_call (rtx, rtx, struct hash_table *);
00531 static int want_to_gcse_p (rtx);
00532 static bool can_assign_to_reg_p (rtx);
00533 static bool gcse_constant_p (rtx);
00534 static int oprs_unchanged_p (rtx, rtx, int);
00535 static int oprs_anticipatable_p (rtx, rtx);
00536 static int oprs_available_p (rtx, rtx);
00537 static void insert_expr_in_table (rtx, enum machine_mode, rtx, int, int,
00538 struct hash_table *);
00539 static void insert_set_in_table (rtx, rtx, struct hash_table *);
00540 static unsigned int hash_expr (rtx, enum machine_mode, int *, int);
00541 static unsigned int hash_set (int, int);
00542 static int expr_equiv_p (rtx, rtx);
00543 static void record_last_reg_set_info (rtx, int);
00544 static void record_last_mem_set_info (rtx);
00545 static void record_last_set_info (rtx, rtx, void *);
00546 static void compute_hash_table (struct hash_table *);
00547 static void alloc_hash_table (int, struct hash_table *, int);
00548 static void free_hash_table (struct hash_table *);
00549 static void compute_hash_table_work (struct hash_table *);
00550 static void dump_hash_table (FILE *, const char *, struct hash_table *);
00551 static struct expr *lookup_set (unsigned int, struct hash_table *);
00552 static struct expr *next_set (unsigned int, struct expr *);
00553 static void reset_opr_set_tables (void);
00554 static int oprs_not_set_p (rtx, rtx);
00555 static void mark_call (rtx);
00556 static void mark_set (rtx, rtx);
00557 static void mark_clobber (rtx, rtx);
00558 static void mark_oprs_set (rtx);
00559 static void alloc_cprop_mem (int, int);
00560 static void free_cprop_mem (void);
00561 static void compute_transp (rtx, int, sbitmap *, int);
00562 static void compute_transpout (void);
00563 static void compute_local_properties (sbitmap *, sbitmap *, sbitmap *,
00564 struct hash_table *);
00565 static void compute_cprop_data (void);
00566 static void find_used_regs (rtx *, void *);
00567 static int try_replace_reg (rtx, rtx, rtx);
00568 static struct expr *find_avail_set (int, rtx);
00569 static int cprop_jump (basic_block, rtx, rtx, rtx, rtx);
00570 static void mems_conflict_for_gcse_p (rtx, rtx, void *);
00571 static int load_killed_in_block_p (basic_block, int, rtx, int);
00572 static void canon_list_insert (rtx, rtx, void *);
00573 static int cprop_insn (rtx, int);
00574 static int cprop (int);
00575 static void find_implicit_sets (void);
00576 static int one_cprop_pass (int, bool, bool);
00577 static bool constprop_register (rtx, rtx, rtx, bool);
00578 static struct expr *find_bypass_set (int, int);
00579 static bool reg_killed_on_edge (rtx, edge);
00580 static int bypass_block (basic_block, rtx, rtx);
00581 static int bypass_conditional_jumps (void);
00582 static void alloc_pre_mem (int, int);
00583 static void free_pre_mem (void);
00584 static void compute_pre_data (void);
00585 static int pre_expr_reaches_here_p (basic_block, struct expr *,
00586 basic_block);
00587 static void insert_insn_end_bb (struct expr *, basic_block, int);
00588 static void pre_insert_copy_insn (struct expr *, rtx);
00589 static void pre_insert_copies (void);
00590 static int pre_delete (void);
00591 static int pre_gcse (void);
00592 static int one_pre_gcse_pass (int);
00593 static void add_label_notes (rtx, rtx);
00594 static void alloc_code_hoist_mem (int, int);
00595 static void free_code_hoist_mem (void);
00596 static void compute_code_hoist_vbeinout (void);
00597 static void compute_code_hoist_data (void);
00598 static int hoist_expr_reaches_here_p (basic_block, int, basic_block, char *);
00599 static void hoist_code (void);
00600 static int one_code_hoisting_pass (void);
00601 static rtx process_insert_insn (struct expr *);
00602 static int pre_edge_insert (struct edge_list *, struct expr **);
00603 static int pre_expr_reaches_here_p_work (basic_block, struct expr *,
00604 basic_block, char *);
00605 static struct ls_expr * ldst_entry (rtx);
00606 static void free_ldst_entry (struct ls_expr *);
00607 static void free_ldst_mems (void);
00608 static void print_ldst_list (FILE *);
00609 static struct ls_expr * find_rtx_in_ldst (rtx);
00610 static int enumerate_ldsts (void);
00611 static inline struct ls_expr * first_ls_expr (void);
00612 static inline struct ls_expr * next_ls_expr (struct ls_expr *);
00613 static int simple_mem (rtx);
00614 static void invalidate_any_buried_refs (rtx);
00615 static void compute_ld_motion_mems (void);
00616 static void trim_ld_motion_mems (void);
00617 static void update_ld_motion_stores (struct expr *);
00618 static void reg_set_info (rtx, rtx, void *);
00619 static void reg_clear_last_set (rtx, rtx, void *);
00620 static bool store_ops_ok (rtx, int *);
00621 static rtx extract_mentioned_regs (rtx);
00622 static rtx extract_mentioned_regs_helper (rtx, rtx);
00623 static void find_moveable_store (rtx, int *, int *);
00624 static int compute_store_table (void);
00625 static bool load_kills_store (rtx, rtx, int);
00626 static bool find_loads (rtx, rtx, int);
00627 static bool store_killed_in_insn (rtx, rtx, rtx, int);
00628 static bool store_killed_after (rtx, rtx, rtx, basic_block, int *, rtx *);
00629 static bool store_killed_before (rtx, rtx, rtx, basic_block, int *);
00630 static void build_store_vectors (void);
00631 static void insert_insn_start_bb (rtx, basic_block);
00632 static int insert_store (struct ls_expr *, edge);
00633 static void remove_reachable_equiv_notes (basic_block, struct ls_expr *);
00634 static void replace_store_insn (rtx, rtx, basic_block, struct ls_expr *);
00635 static void delete_store (struct ls_expr *, basic_block);
00636 static void free_store_memory (void);
00637 static void store_motion (void);
00638 static void free_insn_expr_list_list (rtx *);
00639 static void clear_modify_mem_tables (void);
00640 static void free_modify_mem_tables (void);
00641 static rtx gcse_emit_move_after (rtx, rtx, rtx);
00642 static void local_cprop_find_used_regs (rtx *, void *);
00643 static bool do_local_cprop (rtx, rtx, bool, rtx*);
00644 static bool adjust_libcall_notes (rtx, rtx, rtx, rtx*);
00645 static void local_cprop_pass (bool);
00646 static bool is_too_expensive (const char *);
00647
00648
00649
00650
00651
00652
00653 static int
00654 gcse_main (rtx f ATTRIBUTE_UNUSED)
00655 {
00656 int changed, pass;
00657
00658 int initial_bytes_used;
00659
00660 int max_pass_bytes;
00661
00662 char *gcse_obstack_bottom;
00663
00664
00665
00666 if (current_function_calls_setjmp)
00667 return 0;
00668
00669
00670 run_jump_opt_after_gcse = 0;
00671
00672
00673
00674 max_gcse_regno = max_reg_num ();
00675
00676 if (dump_file)
00677 dump_flow_info (dump_file, dump_flags);
00678
00679
00680 if (n_basic_blocks <= NUM_FIXED_BLOCKS + 1
00681 || is_too_expensive (_("GCSE disabled")))
00682 return 0;
00683
00684 gcc_obstack_init (&gcse_obstack);
00685 bytes_used = 0;
00686
00687
00688 init_alias_analysis ();
00689
00690
00691
00692
00693
00694
00695
00696
00697
00698 alloc_reg_set_mem (max_gcse_regno);
00699 compute_sets ();
00700
00701 pass = 0;
00702 initial_bytes_used = bytes_used;
00703 max_pass_bytes = 0;
00704 gcse_obstack_bottom = gcse_alloc (1);
00705 changed = 1;
00706 while (changed && pass < MAX_GCSE_PASSES)
00707 {
00708 changed = 0;
00709 if (dump_file)
00710 fprintf (dump_file, "GCSE pass %d\n\n", pass + 1);
00711
00712
00713
00714 bytes_used = initial_bytes_used;
00715
00716
00717 max_gcse_regno = max_reg_num ();
00718
00719 alloc_gcse_mem ();
00720
00721
00722
00723 timevar_push (TV_CPROP1);
00724 changed = one_cprop_pass (pass + 1, false, false);
00725 timevar_pop (TV_CPROP1);
00726
00727 if (optimize_size)
00728 ;
00729 else
00730 {
00731 timevar_push (TV_PRE);
00732 changed |= one_pre_gcse_pass (pass + 1);
00733
00734
00735
00736 if (changed)
00737 {
00738 free_modify_mem_tables ();
00739 modify_mem_list = gcalloc (last_basic_block, sizeof (rtx));
00740 canon_modify_mem_list = gcalloc (last_basic_block, sizeof (rtx));
00741 }
00742 free_reg_set_mem ();
00743 alloc_reg_set_mem (max_reg_num ());
00744 compute_sets ();
00745 run_jump_opt_after_gcse = 1;
00746 timevar_pop (TV_PRE);
00747 }
00748
00749 if (max_pass_bytes < bytes_used)
00750 max_pass_bytes = bytes_used;
00751
00752
00753
00754
00755
00756 free_gcse_mem ();
00757
00758
00759
00760
00761
00762 if (optimize_size)
00763 {
00764 timevar_push (TV_HOIST);
00765 max_gcse_regno = max_reg_num ();
00766 alloc_gcse_mem ();
00767 changed |= one_code_hoisting_pass ();
00768 free_gcse_mem ();
00769
00770 if (max_pass_bytes < bytes_used)
00771 max_pass_bytes = bytes_used;
00772 timevar_pop (TV_HOIST);
00773 }
00774
00775 if (dump_file)
00776 {
00777 fprintf (dump_file, "\n");
00778 fflush (dump_file);
00779 }
00780
00781 obstack_free (&gcse_obstack, gcse_obstack_bottom);
00782 pass++;
00783 }
00784
00785
00786
00787
00788 max_gcse_regno = max_reg_num ();
00789 alloc_gcse_mem ();
00790
00791 timevar_push (TV_CPROP2);
00792 one_cprop_pass (pass + 1, true, false);
00793 timevar_pop (TV_CPROP2);
00794 free_gcse_mem ();
00795
00796 if (dump_file)
00797 {
00798 fprintf (dump_file, "GCSE of %s: %d basic blocks, ",
00799 current_function_name (), n_basic_blocks);
00800 fprintf (dump_file, "%d pass%s, %d bytes\n\n",
00801 pass, pass > 1 ? "es" : "", max_pass_bytes);
00802 }
00803
00804 obstack_free (&gcse_obstack, NULL);
00805 free_reg_set_mem ();
00806
00807
00808 end_alias_analysis ();
00809 allocate_reg_info (max_reg_num (), FALSE, FALSE);
00810
00811 if (!optimize_size && flag_gcse_sm)
00812 {
00813 timevar_push (TV_LSM);
00814 store_motion ();
00815 timevar_pop (TV_LSM);
00816 }
00817
00818
00819 return run_jump_opt_after_gcse;
00820 }
00821
00822
00823
00824
00825
00826
00827 static char can_copy[(int) NUM_MACHINE_MODES];
00828
00829
00830
00831 static void
00832 compute_can_copy (void)
00833 {
00834 int i;
00835 #ifndef AVOID_CCMODE_COPIES
00836 rtx reg, insn;
00837 #endif
00838 memset (can_copy, 0, NUM_MACHINE_MODES);
00839
00840 start_sequence ();
00841 for (i = 0; i < NUM_MACHINE_MODES; i++)
00842 if (GET_MODE_CLASS (i) == MODE_CC)
00843 {
00844 #ifdef AVOID_CCMODE_COPIES
00845 can_copy[i] = 0;
00846 #else
00847 reg = gen_rtx_REG ((enum machine_mode) i, LAST_VIRTUAL_REGISTER + 1);
00848 insn = emit_insn (gen_rtx_SET (VOIDmode, reg, reg));
00849 if (recog (PATTERN (insn), insn, NULL) >= 0)
00850 can_copy[i] = 1;
00851 #endif
00852 }
00853 else
00854 can_copy[i] = 1;
00855
00856 end_sequence ();
00857 }
00858
00859
00860
00861 bool
00862 can_copy_p (enum machine_mode mode)
00863 {
00864 static bool can_copy_init_p = false;
00865
00866 if (! can_copy_init_p)
00867 {
00868 compute_can_copy ();
00869 can_copy_init_p = true;
00870 }
00871
00872 return can_copy[mode] != 0;
00873 }
00874
00875
00876
00877 static void *
00878 gmalloc (size_t size)
00879 {
00880 bytes_used += size;
00881 return xmalloc (size);
00882 }
00883
00884
00885
00886 static void *
00887 gcalloc (size_t nelem, size_t elsize)
00888 {
00889 bytes_used += nelem * elsize;
00890 return xcalloc (nelem, elsize);
00891 }
00892
00893
00894
00895
00896
00897 static void *
00898 grealloc (void *ptr, size_t size)
00899 {
00900 return xrealloc (ptr, size);
00901 }
00902
00903
00904
00905 static void *
00906 gcse_alloc (unsigned long size)
00907 {
00908 bytes_used += size;
00909 return obstack_alloc (&gcse_obstack, size);
00910 }
00911
00912
00913
00914
00915
00916
00917 static void
00918 alloc_gcse_mem (void)
00919 {
00920 int i;
00921 basic_block bb;
00922 rtx insn;
00923
00924
00925
00926
00927
00928
00929
00930 max_uid = get_max_uid ();
00931 uid_cuid = gcalloc (max_uid + 1, sizeof (int));
00932 i = 0;
00933 FOR_EACH_BB (bb)
00934 FOR_BB_INSNS (bb, insn)
00935 {
00936 if (INSN_P (insn))
00937 uid_cuid[INSN_UID (insn)] = i++;
00938 else
00939 uid_cuid[INSN_UID (insn)] = i;
00940 }
00941
00942
00943
00944 max_cuid = i;
00945 cuid_insn = gcalloc (max_cuid + 1, sizeof (rtx));
00946 i = 0;
00947 FOR_EACH_BB (bb)
00948 FOR_BB_INSNS (bb, insn)
00949 if (INSN_P (insn))
00950 CUID_INSN (i++) = insn;
00951
00952
00953 reg_set_bitmap = BITMAP_ALLOC (NULL);
00954
00955
00956 reg_set_in_block = sbitmap_vector_alloc (last_basic_block, max_gcse_regno);
00957
00958
00959 modify_mem_list = gcalloc (last_basic_block, sizeof (rtx));
00960 canon_modify_mem_list = gcalloc (last_basic_block, sizeof (rtx));
00961 modify_mem_list_set = BITMAP_ALLOC (NULL);
00962 blocks_with_calls = BITMAP_ALLOC (NULL);
00963 }
00964
00965
00966
00967 static void
00968 free_gcse_mem (void)
00969 {
00970 free (uid_cuid);
00971 free (cuid_insn);
00972
00973 BITMAP_FREE (reg_set_bitmap);
00974
00975 sbitmap_vector_free (reg_set_in_block);
00976 free_modify_mem_tables ();
00977 BITMAP_FREE (modify_mem_list_set);
00978 BITMAP_FREE (blocks_with_calls);
00979 }
00980
00981
00982
00983
00984
00985
00986
00987
00988
00989
00990
00991
00992
00993
00994
00995
00996
00997
00998
00999
01000
01001
01002
01003
01004
01005
01006
01007
01008 static void
01009 compute_local_properties (sbitmap *transp, sbitmap *comp, sbitmap *antloc,
01010 struct hash_table *table)
01011 {
01012 unsigned int i;
01013
01014
01015 if (transp)
01016 {
01017 if (table->set_p)
01018 sbitmap_vector_zero (transp, last_basic_block);
01019 else
01020 sbitmap_vector_ones (transp, last_basic_block);
01021 }
01022
01023 if (comp)
01024 sbitmap_vector_zero (comp, last_basic_block);
01025 if (antloc)
01026 sbitmap_vector_zero (antloc, last_basic_block);
01027
01028 for (i = 0; i < table->size; i++)
01029 {
01030 struct expr *expr;
01031
01032 for (expr = table->table[i]; expr != NULL; expr = expr->next_same_hash)
01033 {
01034 int indx = expr->bitmap_index;
01035 struct occr *occr;
01036
01037
01038
01039
01040 if (transp)
01041 compute_transp (expr->expr, indx, transp, table->set_p);
01042
01043
01044
01045 if (antloc)
01046 for (occr = expr->antic_occr; occr != NULL; occr = occr->next)
01047 {
01048 SET_BIT (antloc[BLOCK_NUM (occr->insn)], indx);
01049
01050
01051
01052 occr->deleted_p = 0;
01053 }
01054
01055
01056
01057 if (comp)
01058 for (occr = expr->avail_occr; occr != NULL; occr = occr->next)
01059 {
01060 SET_BIT (comp[BLOCK_NUM (occr->insn)], indx);
01061
01062
01063
01064 occr->copied_p = 0;
01065 }
01066
01067
01068
01069 expr->reaching_reg = 0;
01070 }
01071 }
01072 }
01073
01074
01075
01076
01077
01078
01079 static struct obstack reg_set_obstack;
01080
01081 static void
01082 alloc_reg_set_mem (int n_regs)
01083 {
01084 reg_set_table_size = n_regs + REG_SET_TABLE_SLOP;
01085 reg_set_table = gcalloc (reg_set_table_size, sizeof (struct reg_set *));
01086
01087 gcc_obstack_init (®_set_obstack);
01088 }
01089
01090 static void
01091 free_reg_set_mem (void)
01092 {
01093 free (reg_set_table);
01094 obstack_free (®_set_obstack, NULL);
01095 }
01096
01097
01098
01099 static void
01100 record_one_set (int regno, rtx insn)
01101 {
01102
01103 struct reg_set *new_reg_info;
01104
01105
01106 if (regno >= reg_set_table_size)
01107 {
01108 int new_size = regno + REG_SET_TABLE_SLOP;
01109
01110 reg_set_table = grealloc (reg_set_table,
01111 new_size * sizeof (struct reg_set *));
01112 memset (reg_set_table + reg_set_table_size, 0,
01113 (new_size - reg_set_table_size) * sizeof (struct reg_set *));
01114 reg_set_table_size = new_size;
01115 }
01116
01117 new_reg_info = obstack_alloc (®_set_obstack, sizeof (struct reg_set));
01118 bytes_used += sizeof (struct reg_set);
01119 new_reg_info->bb_index = BLOCK_NUM (insn);
01120 new_reg_info->next = reg_set_table[regno];
01121 reg_set_table[regno] = new_reg_info;
01122 }
01123
01124
01125
01126
01127
01128 static void
01129 record_set_info (rtx dest, rtx setter ATTRIBUTE_UNUSED, void *data)
01130 {
01131 rtx record_set_insn = (rtx) data;
01132
01133 if (REG_P (dest) && REGNO (dest) >= FIRST_PSEUDO_REGISTER)
01134 record_one_set (REGNO (dest), record_set_insn);
01135 }
01136
01137
01138
01139
01140
01141
01142 static void
01143 compute_sets (void)
01144 {
01145 basic_block bb;
01146 rtx insn;
01147
01148 FOR_EACH_BB (bb)
01149 FOR_BB_INSNS (bb, insn)
01150 if (INSN_P (insn))
01151 note_stores (PATTERN (insn), record_set_info, insn);
01152 }
01153
01154
01155
01156 struct reg_avail_info
01157 {
01158 basic_block last_bb;
01159 int first_set;
01160 int last_set;
01161 };
01162
01163 static struct reg_avail_info *reg_avail_info;
01164 static basic_block current_bb;
01165
01166
01167
01168
01169
01170 static int
01171 want_to_gcse_p (rtx x)
01172 {
01173 #ifdef STACK_REGS
01174
01175
01176
01177 if (IS_STACK_MODE (GET_MODE (x)))
01178 x = avoid_constant_pool_reference (x);
01179 #endif
01180
01181 switch (GET_CODE (x))
01182 {
01183 case REG:
01184 case SUBREG:
01185 case CONST_INT:
01186 case CONST_DOUBLE:
01187 case CONST_VECTOR:
01188 case CALL:
01189 return 0;
01190
01191 default:
01192 return can_assign_to_reg_p (x);
01193 }
01194 }
01195
01196
01197
01198 static GTY(()) rtx test_insn;
01199
01200
01201
01202 static bool
01203 can_assign_to_reg_p (rtx x)
01204 {
01205 int num_clobbers = 0;
01206 int icode;
01207
01208
01209 if (general_operand (x, GET_MODE (x)))
01210 return 1;
01211 else if (GET_MODE (x) == VOIDmode)
01212 return 0;
01213
01214
01215
01216 if (test_insn == 0)
01217 {
01218 test_insn
01219 = make_insn_raw (gen_rtx_SET (VOIDmode,
01220 gen_rtx_REG (word_mode,
01221 FIRST_PSEUDO_REGISTER * 2),
01222 const0_rtx));
01223 NEXT_INSN (test_insn) = PREV_INSN (test_insn) = 0;
01224 }
01225
01226
01227
01228 PUT_MODE (SET_DEST (PATTERN (test_insn)), GET_MODE (x));
01229 SET_SRC (PATTERN (test_insn)) = x;
01230 return ((icode = recog (PATTERN (test_insn), test_insn, &num_clobbers)) >= 0
01231 && (num_clobbers == 0 || ! added_clobbers_hard_reg_p (icode)));
01232 }
01233
01234
01235
01236
01237
01238 static int
01239 oprs_unchanged_p (rtx x, rtx insn, int avail_p)
01240 {
01241 int i, j;
01242 enum rtx_code code;
01243 const char *fmt;
01244
01245 if (x == 0)
01246 return 1;
01247
01248 code = GET_CODE (x);
01249 switch (code)
01250 {
01251 case REG:
01252 {
01253 struct reg_avail_info *info = ®_avail_info[REGNO (x)];
01254
01255 if (info->last_bb != current_bb)
01256 return 1;
01257 if (avail_p)
01258 return info->last_set < INSN_CUID (insn);
01259 else
01260 return info->first_set >= INSN_CUID (insn);
01261 }
01262
01263 case MEM:
01264 if (load_killed_in_block_p (current_bb, INSN_CUID (insn),
01265 x, avail_p))
01266 return 0;
01267 else
01268 return oprs_unchanged_p (XEXP (x, 0), insn, avail_p);
01269
01270 case PRE_DEC:
01271 case PRE_INC:
01272 case POST_DEC:
01273 case POST_INC:
01274 case PRE_MODIFY:
01275 case POST_MODIFY:
01276 return 0;
01277
01278 case PC:
01279 case CC0:
01280 case CONST:
01281 case CONST_INT:
01282 case CONST_DOUBLE:
01283 case CONST_VECTOR:
01284 case SYMBOL_REF:
01285 case LABEL_REF:
01286 case ADDR_VEC:
01287 case ADDR_DIFF_VEC:
01288 return 1;
01289
01290 default:
01291 break;
01292 }
01293
01294 for (i = GET_RTX_LENGTH (code) - 1, fmt = GET_RTX_FORMAT (code); i >= 0; i--)
01295 {
01296 if (fmt[i] == 'e')
01297 {
01298
01299
01300
01301 if (i == 0)
01302 return oprs_unchanged_p (XEXP (x, i), insn, avail_p);
01303
01304 else if (! oprs_unchanged_p (XEXP (x, i), insn, avail_p))
01305 return 0;
01306 }
01307 else if (fmt[i] == 'E')
01308 for (j = 0; j < XVECLEN (x, i); j++)
01309 if (! oprs_unchanged_p (XVECEXP (x, i, j), insn, avail_p))
01310 return 0;
01311 }
01312
01313 return 1;
01314 }
01315
01316
01317
01318
01319 static int gcse_mems_conflict_p;
01320
01321
01322
01323
01324
01325 static rtx gcse_mem_operand;
01326
01327
01328
01329
01330
01331 static void
01332 mems_conflict_for_gcse_p (rtx dest, rtx setter ATTRIBUTE_UNUSED,
01333 void *data ATTRIBUTE_UNUSED)
01334 {
01335 while (GET_CODE (dest) == SUBREG
01336 || GET_CODE (dest) == ZERO_EXTRACT
01337 || GET_CODE (dest) == STRICT_LOW_PART)
01338 dest = XEXP (dest, 0);
01339
01340
01341
01342
01343 if (! MEM_P (dest))
01344 return;
01345
01346
01347
01348
01349 if (expr_equiv_p (dest, gcse_mem_operand) && pre_ldst_mems != NULL)
01350 {
01351 if (!find_rtx_in_ldst (dest))
01352 gcse_mems_conflict_p = 1;
01353 return;
01354 }
01355
01356 if (true_dependence (dest, GET_MODE (dest), gcse_mem_operand,
01357 rtx_addr_varies_p))
01358 gcse_mems_conflict_p = 1;
01359 }
01360
01361
01362
01363
01364
01365
01366
01367
01368
01369 static int
01370 load_killed_in_block_p (basic_block bb, int uid_limit, rtx x, int avail_p)
01371 {
01372 rtx list_entry = modify_mem_list[bb->index];
01373
01374
01375 if (MEM_READONLY_P (x))
01376 return 0;
01377
01378 while (list_entry)
01379 {
01380 rtx setter;
01381
01382 if ((avail_p
01383 && INSN_CUID (XEXP (list_entry, 0)) < uid_limit)
01384 || (! avail_p
01385 && INSN_CUID (XEXP (list_entry, 0)) > uid_limit))
01386 {
01387 list_entry = XEXP (list_entry, 1);
01388 continue;
01389 }
01390
01391 setter = XEXP (list_entry, 0);
01392
01393
01394
01395
01396 if (CALL_P (setter))
01397 return 1;
01398
01399
01400
01401
01402
01403
01404 gcse_mem_operand = x;
01405 gcse_mems_conflict_p = 0;
01406 note_stores (PATTERN (setter), mems_conflict_for_gcse_p, NULL);
01407 if (gcse_mems_conflict_p)
01408 return 1;
01409 list_entry = XEXP (list_entry, 1);
01410 }
01411 return 0;
01412 }
01413
01414
01415
01416
01417 static int
01418 oprs_anticipatable_p (rtx x, rtx insn)
01419 {
01420 return oprs_unchanged_p (x, insn, 0);
01421 }
01422
01423
01424
01425
01426 static int
01427 oprs_available_p (rtx x, rtx insn)
01428 {
01429 return oprs_unchanged_p (x, insn, 1);
01430 }
01431
01432
01433
01434
01435
01436
01437
01438
01439 static unsigned int
01440 hash_expr (rtx x, enum machine_mode mode, int *do_not_record_p,
01441 int hash_table_size)
01442 {
01443 unsigned int hash;
01444
01445 *do_not_record_p = 0;
01446
01447 hash = hash_rtx (x, mode, do_not_record_p,
01448 NULL, false);
01449 return hash % hash_table_size;
01450 }
01451
01452
01453
01454
01455
01456
01457
01458
01459 static unsigned int
01460 hash_set (int regno, int hash_table_size)
01461 {
01462 unsigned int hash;
01463
01464 hash = regno;
01465 return hash % hash_table_size;
01466 }
01467
01468
01469
01470 static int
01471 expr_equiv_p (rtx x, rtx y)
01472 {
01473 return exp_equiv_p (x, y, 0, true);
01474 }
01475
01476
01477
01478
01479
01480
01481
01482
01483
01484
01485
01486 static void
01487 insert_expr_in_table (rtx x, enum machine_mode mode, rtx insn, int antic_p,
01488 int avail_p, struct hash_table *table)
01489 {
01490 int found, do_not_record_p;
01491 unsigned int hash;
01492 struct expr *cur_expr, *last_expr = NULL;
01493 struct occr *antic_occr, *avail_occr;
01494
01495 hash = hash_expr (x, mode, &do_not_record_p, table->size);
01496
01497
01498
01499
01500 if (do_not_record_p)
01501 return;
01502
01503 cur_expr = table->table[hash];
01504 found = 0;
01505
01506 while (cur_expr && 0 == (found = expr_equiv_p (cur_expr->expr, x)))
01507 {
01508
01509
01510 last_expr = cur_expr;
01511 cur_expr = cur_expr->next_same_hash;
01512 }
01513
01514 if (! found)
01515 {
01516 cur_expr = gcse_alloc (sizeof (struct expr));
01517 bytes_used += sizeof (struct expr);
01518 if (table->table[hash] == NULL)
01519
01520 table->table[hash] = cur_expr;
01521 else
01522
01523 last_expr->next_same_hash = cur_expr;
01524
01525
01526 cur_expr->expr = x;
01527 cur_expr->bitmap_index = table->n_elems++;
01528 cur_expr->next_same_hash = NULL;
01529 cur_expr->antic_occr = NULL;
01530 cur_expr->avail_occr = NULL;
01531 }
01532
01533
01534 if (antic_p)
01535 {
01536 antic_occr = cur_expr->antic_occr;
01537
01538 if (antic_occr && BLOCK_NUM (antic_occr->insn) != BLOCK_NUM (insn))
01539 antic_occr = NULL;
01540
01541 if (antic_occr)
01542
01543
01544
01545 ;
01546 else
01547 {
01548
01549 antic_occr = gcse_alloc (sizeof (struct occr));
01550 bytes_used += sizeof (struct occr);
01551 antic_occr->insn = insn;
01552 antic_occr->next = cur_expr->antic_occr;
01553 antic_occr->deleted_p = 0;
01554 cur_expr->antic_occr = antic_occr;
01555 }
01556 }
01557
01558 if (avail_p)
01559 {
01560 avail_occr = cur_expr->avail_occr;
01561
01562 if (avail_occr && BLOCK_NUM (avail_occr->insn) == BLOCK_NUM (insn))
01563 {
01564
01565
01566
01567
01568 avail_occr->insn = insn;
01569 }
01570 else
01571 {
01572
01573 avail_occr = gcse_alloc (sizeof (struct occr));
01574 bytes_used += sizeof (struct occr);
01575 avail_occr->insn = insn;
01576 avail_occr->next = cur_expr->avail_occr;
01577 avail_occr->deleted_p = 0;
01578 cur_expr->avail_occr = avail_occr;
01579 }
01580 }
01581 }
01582
01583
01584
01585
01586
01587
01588 static void
01589 insert_set_in_table (rtx x, rtx insn, struct hash_table *table)
01590 {
01591 int found;
01592 unsigned int hash;
01593 struct expr *cur_expr, *last_expr = NULL;
01594 struct occr *cur_occr;
01595
01596 gcc_assert (GET_CODE (x) == SET && REG_P (SET_DEST (x)));
01597
01598 hash = hash_set (REGNO (SET_DEST (x)), table->size);
01599
01600 cur_expr = table->table[hash];
01601 found = 0;
01602
01603 while (cur_expr && 0 == (found = expr_equiv_p (cur_expr->expr, x)))
01604 {
01605
01606
01607 last_expr = cur_expr;
01608 cur_expr = cur_expr->next_same_hash;
01609 }
01610
01611 if (! found)
01612 {
01613 cur_expr = gcse_alloc (sizeof (struct expr));
01614 bytes_used += sizeof (struct expr);
01615 if (table->table[hash] == NULL)
01616
01617 table->table[hash] = cur_expr;
01618 else
01619
01620 last_expr->next_same_hash = cur_expr;
01621
01622
01623
01624
01625 cur_expr->expr = copy_rtx (x);
01626 cur_expr->bitmap_index = table->n_elems++;
01627 cur_expr->next_same_hash = NULL;
01628 cur_expr->antic_occr = NULL;
01629 cur_expr->avail_occr = NULL;
01630 }
01631
01632
01633 cur_occr = cur_expr->avail_occr;
01634
01635 if (cur_occr && BLOCK_NUM (cur_occr->insn) == BLOCK_NUM (insn))
01636 {
01637
01638
01639
01640
01641 cur_occr->insn = insn;
01642 }
01643 else
01644 {
01645
01646 cur_occr = gcse_alloc (sizeof (struct occr));
01647 bytes_used += sizeof (struct occr);
01648
01649 cur_occr->insn = insn;
01650 cur_occr->next = cur_expr->avail_occr;
01651 cur_occr->deleted_p = 0;
01652 cur_expr->avail_occr = cur_occr;
01653 }
01654 }
01655
01656
01657
01658
01659 static bool
01660 gcse_constant_p (rtx x)
01661 {
01662
01663 if (GET_CODE (x) == COMPARE
01664 && GET_CODE (XEXP (x, 0)) == CONST_INT
01665 && GET_CODE (XEXP (x, 1)) == CONST_INT)
01666 return true;
01667
01668
01669
01670 if (GET_CODE(x) == COMPARE
01671 && REG_P (XEXP (x, 0)) && REG_P (XEXP (x, 1))
01672 && REGNO (XEXP (x, 0)) == REGNO (XEXP (x, 1))
01673 && ! FLOAT_MODE_P (GET_MODE (XEXP (x, 0)))
01674 && ! FLOAT_MODE_P (GET_MODE (XEXP (x, 1))))
01675 return true;
01676
01677 return CONSTANT_P (x);
01678 }
01679
01680
01681
01682
01683 static void
01684 hash_scan_set (rtx pat, rtx insn, struct hash_table *table)
01685 {
01686 rtx src = SET_SRC (pat);
01687 rtx dest = SET_DEST (pat);
01688 rtx note;
01689
01690 if (GET_CODE (src) == CALL)
01691 hash_scan_call (src, insn, table);
01692
01693 else if (REG_P (dest))
01694 {
01695 unsigned int regno = REGNO (dest);
01696 rtx tmp;
01697
01698
01699
01700
01701
01702 note = find_reg_equal_equiv_note (insn);
01703 if (note != 0
01704 && (table->set_p
01705 ? gcse_constant_p (XEXP (note, 0))
01706 : want_to_gcse_p (XEXP (note, 0))))
01707 src = XEXP (note, 0), pat = gen_rtx_SET (VOIDmode, dest, src);
01708
01709
01710 if (! table->set_p
01711 && regno >= FIRST_PSEUDO_REGISTER
01712
01713 && can_copy_p (GET_MODE (dest))
01714
01715
01716
01717 && !find_reg_note (insn, REG_EH_REGION, NULL_RTX)
01718
01719 && want_to_gcse_p (src)
01720
01721 && ! set_noop_p (pat)
01722
01723
01724
01725
01726
01727 && (note == NULL_RTX || ! MEM_P (XEXP (note, 0))))
01728 {
01729
01730
01731
01732 int antic_p = oprs_anticipatable_p (src, insn) && single_set (insn);
01733
01734
01735
01736
01737 int avail_p = (oprs_available_p (src, insn)
01738 && ! JUMP_P (insn));
01739
01740 insert_expr_in_table (src, GET_MODE (dest), insn, antic_p, avail_p, table);
01741 }
01742
01743
01744 else if (table->set_p
01745 && regno >= FIRST_PSEUDO_REGISTER
01746 && ((REG_P (src)
01747 && REGNO (src) >= FIRST_PSEUDO_REGISTER
01748 && can_copy_p (GET_MODE (dest))
01749 && REGNO (src) != regno)
01750 || gcse_constant_p (src))
01751
01752
01753
01754 && (insn == BB_END (BLOCK_FOR_INSN (insn))
01755 || ((tmp = next_nonnote_insn (insn)) != NULL_RTX
01756 && oprs_available_p (pat, tmp))))
01757 insert_set_in_table (pat, insn, table);
01758 }
01759
01760
01761
01762 else if (flag_gcse_las && REG_P (src) && MEM_P (dest))
01763 {
01764 unsigned int regno = REGNO (src);
01765
01766
01767 if (! table->set_p
01768
01769 && regno >= FIRST_PSEUDO_REGISTER
01770
01771 && can_copy_p (GET_MODE (src))
01772
01773
01774
01775 && ! find_reg_note (insn, REG_EH_REGION, NULL_RTX)
01776
01777 && want_to_gcse_p (dest)
01778
01779 && ! set_noop_p (pat)
01780
01781
01782
01783
01784
01785 && ((note = find_reg_note (insn, REG_EQUIV, NULL_RTX)) == 0
01786 || ! MEM_P (XEXP (note, 0))))
01787 {
01788
01789 int antic_p = 0;
01790
01791
01792
01793
01794 int avail_p = oprs_available_p (dest, insn)
01795 && ! JUMP_P (insn);
01796
01797
01798 insert_expr_in_table (dest, GET_MODE (dest), insn,
01799 antic_p, avail_p, table);
01800 }
01801 }
01802 }
01803
01804 static void
01805 hash_scan_clobber (rtx x ATTRIBUTE_UNUSED, rtx insn ATTRIBUTE_UNUSED,
01806 struct hash_table *table ATTRIBUTE_UNUSED)
01807 {
01808
01809 }
01810
01811 static void
01812 hash_scan_call (rtx x ATTRIBUTE_UNUSED, rtx insn ATTRIBUTE_UNUSED,
01813 struct hash_table *table ATTRIBUTE_UNUSED)
01814 {
01815
01816 }
01817
01818
01819
01820
01821
01822
01823
01824
01825
01826
01827
01828
01829
01830
01831 static void
01832 hash_scan_insn (rtx insn, struct hash_table *table, int in_libcall_block)
01833 {
01834 rtx pat = PATTERN (insn);
01835 int i;
01836
01837 if (in_libcall_block)
01838 return;
01839
01840
01841
01842
01843 if (GET_CODE (pat) == SET)
01844 hash_scan_set (pat, insn, table);
01845 else if (GET_CODE (pat) == PARALLEL)
01846 for (i = 0; i < XVECLEN (pat, 0); i++)
01847 {
01848 rtx x = XVECEXP (pat, 0, i);
01849
01850 if (GET_CODE (x) == SET)
01851 hash_scan_set (x, insn, table);
01852 else if (GET_CODE (x) == CLOBBER)
01853 hash_scan_clobber (x, insn, table);
01854 else if (GET_CODE (x) == CALL)
01855 hash_scan_call (x, insn, table);
01856 }
01857
01858 else if (GET_CODE (pat) == CLOBBER)
01859 hash_scan_clobber (pat, insn, table);
01860 else if (GET_CODE (pat) == CALL)
01861 hash_scan_call (pat, insn, table);
01862 }
01863
01864 static void
01865 dump_hash_table (FILE *file, const char *name, struct hash_table *table)
01866 {
01867 int i;
01868
01869 struct expr **flat_table;
01870 unsigned int *hash_val;
01871 struct expr *expr;
01872
01873 flat_table = xcalloc (table->n_elems, sizeof (struct expr *));
01874 hash_val = xmalloc (table->n_elems * sizeof (unsigned int));
01875
01876 for (i = 0; i < (int) table->size; i++)
01877 for (expr = table->table[i]; expr != NULL; expr = expr->next_same_hash)
01878 {
01879 flat_table[expr->bitmap_index] = expr;
01880 hash_val[expr->bitmap_index] = i;
01881 }
01882
01883 fprintf (file, "%s hash table (%d buckets, %d entries)\n",
01884 name, table->size, table->n_elems);
01885
01886 for (i = 0; i < (int) table->n_elems; i++)
01887 if (flat_table[i] != 0)
01888 {
01889 expr = flat_table[i];
01890 fprintf (file, "Index %d (hash value %d)\n ",
01891 expr->bitmap_index, hash_val[i]);
01892 print_rtl (file, expr->expr);
01893 fprintf (file, "\n");
01894 }
01895
01896 fprintf (file, "\n");
01897
01898 free (flat_table);
01899 free (hash_val);
01900 }
01901
01902
01903
01904
01905
01906
01907
01908
01909
01910
01911
01912
01913
01914
01915
01916 static void
01917 record_last_reg_set_info (rtx insn, int regno)
01918 {
01919 struct reg_avail_info *info = ®_avail_info[regno];
01920 int cuid = INSN_CUID (insn);
01921
01922 info->last_set = cuid;
01923 if (info->last_bb != current_bb)
01924 {
01925 info->last_bb = current_bb;
01926 info->first_set = cuid;
01927 SET_BIT (reg_set_in_block[current_bb->index], regno);
01928 }
01929 }
01930
01931
01932
01933
01934
01935
01936 static void
01937 canon_list_insert (rtx dest ATTRIBUTE_UNUSED, rtx unused1 ATTRIBUTE_UNUSED,
01938 void * v_insn)
01939 {
01940 rtx dest_addr, insn;
01941 int bb;
01942
01943 while (GET_CODE (dest) == SUBREG
01944 || GET_CODE (dest) == ZERO_EXTRACT
01945 || GET_CODE (dest) == STRICT_LOW_PART)
01946 dest = XEXP (dest, 0);
01947
01948
01949
01950
01951
01952 if (! MEM_P (dest))
01953 return;
01954
01955 dest_addr = get_addr (XEXP (dest, 0));
01956 dest_addr = canon_rtx (dest_addr);
01957 insn = (rtx) v_insn;
01958 bb = BLOCK_NUM (insn);
01959
01960 canon_modify_mem_list[bb] =
01961 alloc_EXPR_LIST (VOIDmode, dest_addr, canon_modify_mem_list[bb]);
01962 canon_modify_mem_list[bb] =
01963 alloc_EXPR_LIST (VOIDmode, dest, canon_modify_mem_list[bb]);
01964 }
01965
01966
01967
01968
01969
01970 static void
01971 record_last_mem_set_info (rtx insn)
01972 {
01973 int bb = BLOCK_NUM (insn);
01974
01975
01976
01977 modify_mem_list[bb] = alloc_INSN_LIST (insn, modify_mem_list[bb]);
01978 bitmap_set_bit (modify_mem_list_set, bb);
01979
01980 if (CALL_P (insn))
01981 {
01982
01983
01984
01985 canon_modify_mem_list[bb] =
01986 alloc_INSN_LIST (insn, canon_modify_mem_list[bb]);
01987 bitmap_set_bit (blocks_with_calls, bb);
01988 }
01989 else
01990 note_stores (PATTERN (insn), canon_list_insert, (void*) insn);
01991 }
01992
01993
01994
01995
01996
01997 static void
01998 record_last_set_info (rtx dest, rtx setter ATTRIBUTE_UNUSED, void *data)
01999 {
02000 rtx last_set_insn = (rtx) data;
02001
02002 if (GET_CODE (dest) == SUBREG)
02003 dest = SUBREG_REG (dest);
02004
02005 if (REG_P (dest))
02006 record_last_reg_set_info (last_set_insn, REGNO (dest));
02007 else if (MEM_P (dest)
02008
02009 && ! push_operand (dest, GET_MODE (dest)))
02010 record_last_mem_set_info (last_set_insn);
02011 }
02012
02013
02014
02015
02016
02017
02018
02019
02020
02021
02022
02023
02024
02025
02026
02027
02028
02029 static void
02030 compute_hash_table_work (struct hash_table *table)
02031 {
02032 unsigned int i;
02033
02034
02035
02036
02037
02038 sbitmap_vector_zero (reg_set_in_block, last_basic_block);
02039
02040
02041 clear_modify_mem_tables ();
02042
02043 reg_avail_info = gmalloc (max_gcse_regno * sizeof (struct reg_avail_info));
02044
02045 for (i = 0; i < max_gcse_regno; ++i)
02046 reg_avail_info[i].last_bb = NULL;
02047
02048 FOR_EACH_BB (current_bb)
02049 {
02050 rtx insn;
02051 unsigned int regno;
02052 int in_libcall_block;
02053
02054
02055
02056
02057
02058
02059 FOR_BB_INSNS (current_bb, insn)
02060 {
02061 if (! INSN_P (insn))
02062 continue;
02063
02064 if (CALL_P (insn))
02065 {
02066 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
02067 if (TEST_HARD_REG_BIT (regs_invalidated_by_call, regno))
02068 record_last_reg_set_info (insn, regno);
02069
02070 mark_call (insn);
02071 }
02072
02073 note_stores (PATTERN (insn), record_last_set_info, insn);
02074 }
02075
02076
02077 if (table->set_p
02078 && implicit_sets[current_bb->index] != NULL_RTX)
02079 hash_scan_set (implicit_sets[current_bb->index],
02080 BB_HEAD (current_bb), table);
02081
02082
02083 in_libcall_block = 0;
02084 FOR_BB_INSNS (current_bb, insn)
02085 if (INSN_P (insn))
02086 {
02087 if (find_reg_note (insn, REG_LIBCALL, NULL_RTX))
02088 in_libcall_block = 1;
02089 else if (table->set_p && find_reg_note (insn, REG_RETVAL, NULL_RTX))
02090 in_libcall_block = 0;
02091 hash_scan_insn (insn, table, in_libcall_block);
02092 if (!table->set_p && find_reg_note (insn, REG_RETVAL, NULL_RTX))
02093 in_libcall_block = 0;
02094 }
02095 }
02096
02097 free (reg_avail_info);
02098 reg_avail_info = NULL;
02099 }
02100
02101
02102
02103
02104
02105
02106
02107 static void
02108 alloc_hash_table (int n_insns, struct hash_table *table, int set_p)
02109 {
02110 int n;
02111
02112 table->size = n_insns / 4;
02113 if (table->size < 11)
02114 table->size = 11;
02115
02116
02117
02118
02119 table->size |= 1;
02120 n = table->size * sizeof (struct expr *);
02121 table->table = gmalloc (n);
02122 table->set_p = set_p;
02123 }
02124
02125
02126
02127 static void
02128 free_hash_table (struct hash_table *table)
02129 {
02130 free (table->table);
02131 }
02132
02133
02134
02135
02136 static void
02137 compute_hash_table (struct hash_table *table)
02138 {
02139
02140 table->n_elems = 0;
02141 memset (table->table, 0, table->size * sizeof (struct expr *));
02142
02143 compute_hash_table_work (table);
02144 }
02145
02146
02147
02148
02149
02150
02151 static struct expr *
02152 lookup_set (unsigned int regno, struct hash_table *table)
02153 {
02154 unsigned int hash = hash_set (regno, table->size);
02155 struct expr *expr;
02156
02157 expr = table->table[hash];
02158
02159 while (expr && REGNO (SET_DEST (expr->expr)) != regno)
02160 expr = expr->next_same_hash;
02161
02162 return expr;
02163 }
02164
02165
02166
02167 static struct expr *
02168 next_set (unsigned int regno, struct expr *expr)
02169 {
02170 do
02171 expr = expr->next_same_hash;
02172 while (expr && REGNO (SET_DEST (expr->expr)) != regno);
02173
02174 return expr;
02175 }
02176
02177
02178
02179
02180 static void
02181 free_insn_expr_list_list (rtx *listp)
02182 {
02183 rtx list, next;
02184
02185 for (list = *listp; list ; list = next)
02186 {
02187 next = XEXP (list, 1);
02188 if (GET_CODE (list) == EXPR_LIST)
02189 free_EXPR_LIST_node (list);
02190 else
02191 free_INSN_LIST_node (list);
02192 }
02193
02194 *listp = NULL;
02195 }
02196
02197
02198 static void
02199 clear_modify_mem_tables (void)
02200 {
02201 unsigned i;
02202 bitmap_iterator bi;
02203
02204 EXECUTE_IF_SET_IN_BITMAP (modify_mem_list_set, 0, i, bi)
02205 {
02206 free_INSN_LIST_list (modify_mem_list + i);
02207 free_insn_expr_list_list (canon_modify_mem_list + i);
02208 }
02209 bitmap_clear (modify_mem_list_set);
02210 bitmap_clear (blocks_with_calls);
02211 }
02212
02213
02214
02215 static void
02216 free_modify_mem_tables (void)
02217 {
02218 clear_modify_mem_tables ();
02219 free (modify_mem_list);
02220 free (canon_modify_mem_list);
02221 modify_mem_list = 0;
02222 canon_modify_mem_list = 0;
02223 }
02224
02225
02226
02227
02228 static void
02229 reset_opr_set_tables (void)
02230 {
02231
02232
02233 CLEAR_REG_SET (reg_set_bitmap);
02234
02235
02236
02237
02238 clear_modify_mem_tables ();
02239 }
02240
02241
02242
02243
02244 static int
02245 oprs_not_set_p (rtx x, rtx insn)
02246 {
02247 int i, j;
02248 enum rtx_code code;
02249 const char *fmt;
02250
02251 if (x == 0)
02252 return 1;
02253
02254 code = GET_CODE (x);
02255 switch (code)
02256 {
02257 case PC:
02258 case CC0:
02259 case CONST:
02260 case CONST_INT:
02261 case CONST_DOUBLE:
02262 case CONST_VECTOR:
02263 case SYMBOL_REF:
02264 case LABEL_REF:
02265 case ADDR_VEC:
02266 case ADDR_DIFF_VEC:
02267 return 1;
02268
02269 case MEM:
02270 if (load_killed_in_block_p (BLOCK_FOR_INSN (insn),
02271 INSN_CUID (insn), x, 0))
02272 return 0;
02273 else
02274 return oprs_not_set_p (XEXP (x, 0), insn);
02275
02276 case REG:
02277 return ! REGNO_REG_SET_P (reg_set_bitmap, REGNO (x));
02278
02279 default:
02280 break;
02281 }
02282
02283 for (i = GET_RTX_LENGTH (code) - 1, fmt = GET_RTX_FORMAT (code); i >= 0; i--)
02284 {
02285 if (fmt[i] == 'e')
02286 {
02287
02288
02289
02290 if (i == 0)
02291 return oprs_not_set_p (XEXP (x, i), insn);
02292
02293 if (! oprs_not_set_p (XEXP (x, i), insn))
02294 return 0;
02295 }
02296 else if (fmt[i] == 'E')
02297 for (j = 0; j < XVECLEN (x, i); j++)
02298 if (! oprs_not_set_p (XVECEXP (x, i, j), insn))
02299 return 0;
02300 }
02301
02302 return 1;
02303 }
02304
02305
02306
02307 static void
02308 mark_call (rtx insn)
02309 {
02310 if (! CONST_OR_PURE_CALL_P (insn))
02311 record_last_mem_set_info (insn);
02312 }
02313
02314
02315
02316 static void
02317 mark_set (rtx pat, rtx insn)
02318 {
02319 rtx dest = SET_DEST (pat);
02320
02321 while (GET_CODE (dest) == SUBREG
02322 || GET_CODE (dest) == ZERO_EXTRACT
02323 || GET_CODE (dest) == STRICT_LOW_PART)
02324 dest = XEXP (dest, 0);
02325
02326 if (REG_P (dest))
02327 SET_REGNO_REG_SET (reg_set_bitmap, REGNO (dest));
02328 else if (MEM_P (dest))
02329 record_last_mem_set_info (insn);
02330
02331 if (GET_CODE (SET_SRC (pat)) == CALL)
02332 mark_call (insn);
02333 }
02334
02335
02336
02337 static void
02338 mark_clobber (rtx pat, rtx insn)
02339 {
02340 rtx clob = XEXP (pat, 0);
02341
02342 while (GET_CODE (clob) == SUBREG || GET_CODE (clob) == STRICT_LOW_PART)
02343 clob = XEXP (clob, 0);
02344
02345 if (REG_P (clob))
02346 SET_REGNO_REG_SET (reg_set_bitmap, REGNO (clob));
02347 else
02348 record_last_mem_set_info (insn);
02349 }
02350
02351
02352
02353
02354 static void
02355 mark_oprs_set (rtx insn)
02356 {
02357 rtx pat = PATTERN (insn);
02358 int i;
02359
02360 if (GET_CODE (pat) == SET)
02361 mark_set (pat, insn);
02362 else if (GET_CODE (pat) == PARALLEL)
02363 for (i = 0; i < XVECLEN (pat, 0); i++)
02364 {
02365 rtx x = XVECEXP (pat, 0, i);
02366
02367 if (GET_CODE (x) == SET)
02368 mark_set (x, insn);
02369 else if (GET_CODE (x) == CLOBBER)
02370 mark_clobber (x, insn);
02371 else if (GET_CODE (x) == CALL)
02372 mark_call (insn);
02373 }
02374
02375 else if (GET_CODE (pat) == CLOBBER)
02376 mark_clobber (pat, insn);
02377 else if (GET_CODE (pat) == CALL)
02378 mark_call (insn);
02379 }
02380
02381
02382
02383
02384
02385 static sbitmap *cprop_pavloc;
02386 static sbitmap *cprop_absaltered;
02387
02388
02389 static sbitmap *cprop_avin;
02390 static sbitmap *cprop_avout;
02391
02392
02393
02394
02395 static void
02396 alloc_cprop_mem (int n_blocks, int n_sets)
02397 {
02398 cprop_pavloc = sbitmap_vector_alloc (n_blocks, n_sets);
02399 cprop_absaltered = sbitmap_vector_alloc (n_blocks, n_sets);
02400
02401 cprop_avin = sbitmap_vector_alloc (n_blocks, n_sets);
02402 cprop_avout = sbitmap_vector_alloc (n_blocks, n_sets);
02403 }
02404
02405
02406
02407 static void
02408 free_cprop_mem (void)
02409 {
02410 sbitmap_vector_free (cprop_pavloc);
02411 sbitmap_vector_free (cprop_absaltered);
02412 sbitmap_vector_free (cprop_avin);
02413 sbitmap_vector_free (cprop_avout);
02414 }
02415
02416
02417
02418
02419
02420
02421
02422 static void
02423 compute_transp (rtx x, int indx, sbitmap *bmap, int set_p)
02424 {
02425 int i, j;
02426 basic_block bb;
02427 enum rtx_code code;
02428 reg_set *r;
02429 const char *fmt;
02430
02431
02432
02433 repeat:
02434
02435 if (x == 0)
02436 return;
02437
02438 code = GET_CODE (x);
02439 switch (code)
02440 {
02441 case REG:
02442 if (set_p)
02443 {
02444 if (REGNO (x) < FIRST_PSEUDO_REGISTER)
02445 {
02446 FOR_EACH_BB (bb)
02447 if (TEST_BIT (reg_set_in_block[bb->index], REGNO (x)))
02448 SET_BIT (bmap[bb->index], indx);
02449 }
02450 else
02451 {
02452 for (r = reg_set_table[REGNO (x)]; r != NULL; r = r->next)
02453 SET_BIT (bmap[r->bb_index], indx);
02454 }
02455 }
02456 else
02457 {
02458 if (REGNO (x) < FIRST_PSEUDO_REGISTER)
02459 {
02460 FOR_EACH_BB (bb)
02461 if (TEST_BIT (reg_set_in_block[bb->index], REGNO (x)))
02462 RESET_BIT (bmap[bb->index], indx);
02463 }
02464 else
02465 {
02466 for (r = reg_set_table[REGNO (x)]; r != NULL; r = r->next)
02467 RESET_BIT (bmap[r->bb_index], indx);
02468 }
02469 }
02470
02471 return;
02472
02473 case MEM:
02474 if (! MEM_READONLY_P (x))
02475 {
02476 bitmap_iterator bi;
02477 unsigned bb_index;
02478
02479
02480
02481 EXECUTE_IF_SET_IN_BITMAP (blocks_with_calls, 0, bb_index, bi)
02482 {
02483 if (set_p)
02484 SET_BIT (bmap[bb_index], indx);
02485 else
02486 RESET_BIT (bmap[bb_index], indx);
02487 }
02488
02489
02490
02491 EXECUTE_IF_AND_COMPL_IN_BITMAP (modify_mem_list_set,
02492 blocks_with_calls,
02493 0, bb_index, bi)
02494 {
02495 rtx list_entry = canon_modify_mem_list[bb_index];
02496
02497 while (list_entry)
02498 {
02499 rtx dest, dest_addr;
02500
02501
02502
02503
02504 dest = XEXP (list_entry, 0);
02505 list_entry = XEXP (list_entry, 1);
02506 dest_addr = XEXP (list_entry, 0);
02507
02508 if (canon_true_dependence (dest, GET_MODE (dest), dest_addr,
02509 x, rtx_addr_varies_p))
02510 {
02511 if (set_p)
02512 SET_BIT (bmap[bb_index], indx);
02513 else
02514 RESET_BIT (bmap[bb_index], indx);
02515 break;
02516 }
02517 list_entry = XEXP (list_entry, 1);
02518 }
02519 }
02520 }
02521
02522 x = XEXP (x, 0);
02523 goto repeat;
02524
02525 case PC:
02526 case CC0:
02527 case CONST:
02528 case CONST_INT:
02529 case CONST_DOUBLE:
02530 case CONST_VECTOR:
02531 case SYMBOL_REF:
02532 case LABEL_REF:
02533 case ADDR_VEC:
02534 case ADDR_DIFF_VEC:
02535 return;
02536
02537 default:
02538 break;
02539 }
02540
02541 for (i = GET_RTX_LENGTH (code) - 1, fmt = GET_RTX_FORMAT (code); i >= 0; i--)
02542 {
02543 if (fmt[i] == 'e')
02544 {
02545
02546
02547
02548 if (i == 0)
02549 {
02550 x = XEXP (x, i);
02551 goto repeat;
02552 }
02553
02554 compute_transp (XEXP (x, i), indx, bmap, set_p);
02555 }
02556 else if (fmt[i] == 'E')
02557 for (j = 0; j < XVECLEN (x, i); j++)
02558 compute_transp (XVECEXP (x, i, j), indx, bmap, set_p);
02559 }
02560 }
02561
02562
02563
02564
02565 static void
02566 compute_cprop_data (void)
02567 {
02568 compute_local_properties (cprop_absaltered, cprop_pavloc, NULL, &set_hash_table);
02569 compute_available (cprop_pavloc, cprop_absaltered,
02570 cprop_avout, cprop_avin);
02571 }
02572
02573
02574
02575
02576 #define MAX_USES 8
02577
02578
02579
02580 static struct reg_use reg_use_table[MAX_USES];
02581
02582
02583 static int reg_use_count;
02584
02585
02586
02587
02588
02589
02590
02591
02592 static void
02593 find_used_regs (rtx *xptr, void *data ATTRIBUTE_UNUSED)
02594 {
02595 int i, j;
02596 enum rtx_code code;
02597 const char *fmt;
02598 rtx x = *xptr;
02599
02600
02601
02602 repeat:
02603 if (x == 0)
02604 return;
02605
02606 code = GET_CODE (x);
02607 if (REG_P (x))
02608 {
02609 if (reg_use_count == MAX_USES)
02610 return;
02611
02612 reg_use_table[reg_use_count].reg_rtx = x;
02613 reg_use_count++;
02614 }
02615
02616
02617
02618 for (i = GET_RTX_LENGTH (code) - 1, fmt = GET_RTX_FORMAT (code); i >= 0; i--)
02619 {
02620 if (fmt[i] == 'e')
02621 {
02622
02623
02624
02625 if (i == 0)
02626 {
02627 x = XEXP (x, 0);
02628 goto repeat;
02629 }
02630
02631 find_used_regs (&XEXP (x, i), data);
02632 }
02633 else if (fmt[i] == 'E')
02634 for (j = 0; j < XVECLEN (x, i); j++)
02635 find_used_regs (&XVECEXP (x, i, j), data);
02636 }
02637 }
02638
02639
02640
02641
02642 static int
02643 try_replace_reg (rtx from, rtx to, rtx insn)
02644 {
02645 rtx note = find_reg_equal_equiv_note (insn);
02646 rtx src = 0;
02647 int success = 0;
02648 rtx set = single_set (insn);
02649
02650 validate_replace_src_group (from, to, insn);
02651 if (num_changes_pending () && apply_change_group ())
02652 success = 1;
02653
02654
02655 if (success && set && CONSTANT_P (to))
02656 {
02657 src = simplify_rtx (SET_SRC (set));
02658
02659 if (src)
02660 validate_change (insn, &SET_SRC (set), src, 0);
02661 }
02662
02663
02664
02665 if (note != 0 && REG_NOTE_KIND (note) == REG_EQUAL)
02666 XEXP (note, 0) = simplify_replace_rtx (XEXP (note, 0), from, to);
02667
02668 if (!success && set && reg_mentioned_p (from, SET_SRC (set)))
02669 {
02670
02671
02672
02673 src = simplify_replace_rtx (SET_SRC (set), from, to);
02674
02675 if (!rtx_equal_p (src, SET_SRC (set))
02676 && validate_change (insn, &SET_SRC (set), src, 0))
02677 success = 1;
02678
02679
02680
02681
02682 if (!success && note == 0 && set != 0
02683 && GET_CODE (SET_DEST (set)) != ZERO_EXTRACT
02684 && GET_CODE (SET_DEST (set)) != STRICT_LOW_PART)
02685 note = set_unique_reg_note (insn, REG_EQUAL, copy_rtx (src));
02686 }
02687
02688
02689
02690
02691
02692 if (note && REG_NOTE_KIND (note) == REG_EQUAL && REG_P (XEXP (note, 0)))
02693 remove_note (insn, note);
02694
02695 return success;
02696 }
02697
02698
02699
02700
02701 static struct expr *
02702 find_avail_set (int regno, rtx insn)
02703 {
02704
02705
02706 struct expr *set1 = 0;
02707
02708
02709
02710
02711
02712
02713
02714
02715
02716
02717 while (1)
02718 {
02719 rtx src;
02720 struct expr *set = lookup_set (regno, &set_hash_table);
02721
02722
02723
02724 while (set)
02725 {
02726 if (TEST_BIT (cprop_avin[BLOCK_NUM (insn)], set->bitmap_index))
02727 break;
02728 set = next_set (regno, set);
02729 }
02730
02731
02732
02733 if (set == 0)
02734 break;
02735
02736 gcc_assert (GET_CODE (set->expr) == SET);
02737
02738 src = SET_SRC (set->expr);
02739
02740
02741
02742
02743
02744
02745
02746
02747 if (gcse_constant_p (src) || oprs_not_set_p (src, insn))
02748 set1 = set;
02749
02750
02751
02752 if (! REG_P (src))
02753 break;
02754
02755
02756
02757 regno = REGNO (src);
02758 }
02759
02760
02761
02762 return set1;
02763 }
02764
02765
02766
02767
02768
02769
02770
02771
02772 static int
02773 cprop_jump (basic_block bb, rtx setcc, rtx jump, rtx from, rtx src)
02774 {
02775 rtx new, set_src, note_src;
02776 rtx set = pc_set (jump);
02777 rtx note = find_reg_equal_equiv_note (jump);
02778
02779 if (note)
02780 {
02781 note_src = XEXP (note, 0);
02782 if (GET_CODE (note_src) == EXPR_LIST)
02783 note_src = NULL_RTX;
02784 }
02785 else note_src = NULL_RTX;
02786
02787
02788 set_src = note_src ? note_src : SET_SRC (set);
02789
02790
02791
02792 if (setcc != NULL_RTX
02793 && !modified_between_p (from, setcc, jump)
02794 && !modified_between_p (src, setcc, jump))
02795 {
02796 rtx setcc_src;
02797 rtx setcc_set = single_set (setcc);
02798 rtx setcc_note = find_reg_equal_equiv_note (setcc);
02799 setcc_src = (setcc_note && GET_CODE (XEXP (setcc_note, 0)) != EXPR_LIST)
02800 ? XEXP (setcc_note, 0) : SET_SRC (setcc_set);
02801 set_src = simplify_replace_rtx (set_src, SET_DEST (setcc_set),
02802 setcc_src);
02803 }
02804 else
02805 setcc = NULL_RTX;
02806
02807 new = simplify_replace_rtx (set_src, from, src);
02808
02809
02810 if (rtx_equal_p (new, SET_SRC (set)))
02811 return 0;
02812
02813
02814 if (new == pc_rtx)
02815 delete_insn (jump);
02816 else
02817 {
02818
02819
02820 if (setcc && modified_in_p (new, setcc))
02821 return 0;
02822 if (! validate_change (jump, &SET_SRC (set), new, 0))
02823 {
02824
02825
02826
02827
02828
02829
02830
02831
02832
02833 if (!rtx_equal_p (new, note_src))
02834 set_unique_reg_note (jump, REG_EQUAL, copy_rtx (new));
02835 return 0;
02836 }
02837
02838
02839 if (note_src)
02840 remove_note (jump, note);
02841
02842
02843
02844
02845 if (GET_CODE (SET_SRC (set)) == LABEL_REF)
02846 emit_barrier_after (jump);
02847 }
02848
02849 #ifdef HAVE_cc0
02850
02851 if (setcc != NULL && CC0_P (SET_DEST (single_set (setcc))))
02852 delete_insn (setcc);
02853 #endif
02854
02855 run_jump_opt_after_gcse = 1;
02856
02857 global_const_prop_count++;
02858 if (dump_file != NULL)
02859 {
02860 fprintf (dump_file,
02861 "GLOBAL CONST-PROP: Replacing reg %d in jump_insn %d with constant ",
02862 REGNO (from), INSN_UID (jump));
02863 print_rtl (dump_file, src);
02864 fprintf (dump_file, "\n");
02865 }
02866 purge_dead_edges (bb);
02867
02868 return 1;
02869 }
02870
02871 static bool
02872 constprop_register (rtx insn, rtx from, rtx to, bool alter_jumps)
02873 {
02874 rtx sset;
02875
02876
02877
02878 if (alter_jumps
02879 && (sset = single_set (insn)) != NULL
02880 && NEXT_INSN (insn)
02881 && any_condjump_p (NEXT_INSN (insn)) && onlyjump_p (NEXT_INSN (insn)))
02882 {
02883 rtx dest = SET_DEST (sset);
02884 if ((REG_P (dest) || CC0_P (dest))
02885 && cprop_jump (BLOCK_FOR_INSN (insn), insn, NEXT_INSN (insn), from, to))
02886 return 1;
02887 }
02888
02889
02890 if (NONJUMP_INSN_P (insn)
02891 && try_replace_reg (from, to, insn))
02892 return 1;
02893
02894
02895
02896
02897
02898
02899
02900 else if (alter_jumps && any_condjump_p (insn) && onlyjump_p (insn))
02901 return cprop_jump (BLOCK_FOR_INSN (insn), NULL, insn, from, to);
02902 return 0;
02903 }
02904
02905
02906
02907
02908 static int
02909 cprop_insn (rtx insn, int alter_jumps)
02910 {
02911 struct reg_use *reg_used;
02912 int changed = 0;
02913 rtx note;
02914
02915 if (!INSN_P (insn))
02916 return 0;
02917
02918 reg_use_count = 0;
02919 note_uses (&PATTERN (insn), find_used_regs, NULL);
02920
02921 note = find_reg_equal_equiv_note (insn);
02922
02923
02924 if (note)
02925 find_used_regs (&XEXP (note, 0), NULL);
02926
02927 for (reg_used = ®_use_table[0]; reg_use_count > 0;
02928 reg_used++, reg_use_count--)
02929 {
02930 unsigned int regno = REGNO (reg_used->reg_rtx);
02931 rtx pat, src;
02932 struct expr *set;
02933
02934
02935
02936 if (regno >= max_gcse_regno)
02937 continue;
02938
02939
02940
02941 if (! oprs_not_set_p (reg_used->reg_rtx, insn))
02942 continue;
02943
02944
02945
02946 set = find_avail_set (regno, insn);
02947 if (! set)
02948 continue;
02949
02950 pat = set->expr;
02951
02952 gcc_assert (GET_CODE (pat) == SET);
02953
02954 src = SET_SRC (pat);
02955
02956
02957 if (gcse_constant_p (src))
02958 {
02959 if (constprop_register (insn, reg_used->reg_rtx, src, alter_jumps))
02960 {
02961 changed = 1;
02962 global_const_prop_count++;
02963 if (dump_file != NULL)
02964 {
02965 fprintf (dump_file, "GLOBAL CONST-PROP: Replacing reg %d in ", regno);
02966 fprintf (dump_file, "insn %d with constant ", INSN_UID (insn));
02967 print_rtl (dump_file, src);
02968 fprintf (dump_file, "\n");
02969 }
02970 if (INSN_DELETED_P (insn))
02971 return 1;
02972 }
02973 }
02974 else if (REG_P (src)
02975 && REGNO (src) >= FIRST_PSEUDO_REGISTER
02976 && REGNO (src) != regno)
02977 {
02978 if (try_replace_reg (reg_used->reg_rtx, src, insn))
02979 {
02980 changed = 1;
02981 global_copy_prop_count++;
02982 if (dump_file != NULL)
02983 {
02984 fprintf (dump_file, "GLOBAL COPY-PROP: Replacing reg %d in insn %d",
02985 regno, INSN_UID (insn));
02986 fprintf (dump_file, " with reg %d\n", REGNO (src));
02987 }
02988
02989
02990
02991
02992
02993
02994 }
02995 }
02996 }
02997
02998 return changed;
02999 }
03000
03001
03002
03003
03004
03005
03006 static void
03007 local_cprop_find_used_regs (rtx *xptr, void *data)
03008 {
03009 rtx x = *xptr;
03010
03011 if (x == 0)
03012 return;
03013
03014 switch (GET_CODE (x))
03015 {
03016 case ZERO_EXTRACT:
03017 case SIGN_EXTRACT:
03018 case STRICT_LOW_PART:
03019 return;
03020
03021 case PRE_DEC:
03022 case PRE_INC:
03023 case POST_DEC:
03024 case POST_INC:
03025 case PRE_MODIFY:
03026 case POST_MODIFY:
03027
03028
03029
03030 return;
03031
03032 case SUBREG:
03033
03034
03035 if (GET_MODE_BITSIZE (GET_MODE (SUBREG_REG (x))) > BITS_PER_WORD)
03036 return;
03037 break;
03038
03039 default:
03040 break;
03041 }
03042
03043 find_used_regs (xptr, data);
03044 }
03045
03046
03047
03048
03049 static bool
03050 do_local_cprop (rtx x, rtx insn, bool alter_jumps, rtx *libcall_sp)
03051 {
03052 rtx newreg = NULL, newcnst = NULL;
03053
03054
03055
03056 if (REG_P (x)
03057 && (REGNO (x) >= FIRST_PSEUDO_REGISTER
03058 || (GET_CODE (PATTERN (insn)) != USE
03059 && asm_noperands (PATTERN (insn)) < 0)))
03060 {
03061 cselib_val *val = cselib_lookup (x, GET_MODE (x), 0);
03062 struct elt_loc_list *l;
03063
03064 if (!val)
03065 return false;
03066 for (l = val->locs; l; l = l->next)
03067 {
03068 rtx this_rtx = l->loc;
03069 rtx note;
03070
03071
03072 if (l->in_libcall && ! CONSTANT_P (this_rtx))
03073 continue;
03074
03075 if (gcse_constant_p (this_rtx))
03076 newcnst = this_rtx;
03077 if (REG_P (this_rtx) && REGNO (this_rtx) >= FIRST_PSEUDO_REGISTER
03078
03079
03080
03081
03082
03083 && (!(note = find_reg_note (l->setting_insn, REG_EQUIV, NULL_RTX))
03084 || ! MEM_P (XEXP (note, 0))))
03085 newreg = this_rtx;
03086 }
03087 if (newcnst && constprop_register (insn, x, newcnst, alter_jumps))
03088 {
03089
03090
03091
03092
03093
03094 bool adjusted;
03095
03096 adjusted = adjust_libcall_notes (x, newcnst, insn, libcall_sp);
03097 gcc_assert (adjusted);
03098
03099 if (dump_file != NULL)
03100 {
03101 fprintf (dump_file, "LOCAL CONST-PROP: Replacing reg %d in ",
03102 REGNO (x));
03103 fprintf (dump_file, "insn %d with constant ",
03104 INSN_UID (insn));
03105 print_rtl (dump_file, newcnst);
03106 fprintf (dump_file, "\n");
03107 }
03108 local_const_prop_count++;
03109 return true;
03110 }
03111 else if (newreg && newreg != x && try_replace_reg (x, newreg, insn))
03112 {
03113 adjust_libcall_notes (x, newreg, insn, libcall_sp);
03114 if (dump_file != NULL)
03115 {
03116 fprintf (dump_file,
03117 "LOCAL COPY-PROP: Replacing reg %d in insn %d",
03118 REGNO (x), INSN_UID (insn));
03119 fprintf (dump_file, " with reg %d\n", REGNO (newreg));
03120 }
03121 local_copy_prop_count++;
03122 return true;
03123 }
03124 }
03125 return false;
03126 }
03127
03128
03129
03130
03131
03132 static bool
03133 adjust_libcall_notes (rtx oldreg, rtx newval, rtx insn, rtx *libcall_sp)
03134 {
03135 rtx end;
03136
03137 while ((end = *libcall_sp++))
03138 {
03139 rtx note = find_reg_equal_equiv_note (end);
03140
03141 if (! note)
03142 continue;
03143
03144 if (REG_P (newval))
03145 {
03146 if (reg_set_between_p (newval, PREV_INSN (insn), end))
03147 {
03148 do
03149 {
03150 note = find_reg_equal_equiv_note (end);
03151 if (! note)
03152 continue;
03153 if (reg_mentioned_p (newval, XEXP (note, 0)))
03154 return false;
03155 }
03156 while ((end = *libcall_sp++));
03157 return true;
03158 }
03159 }
03160 XEXP (note, 0) = simplify_replace_rtx (XEXP (note, 0), oldreg, newval);
03161 insn = end;
03162 }
03163 return true;
03164 }
03165
03166 #define MAX_NESTED_LIBCALLS 9
03167
03168
03169
03170
03171
03172 static void
03173 local_cprop_pass (bool alter_jumps)
03174 {
03175 basic_block bb;
03176 rtx insn;
03177 struct reg_use *reg_used;
03178 rtx libcall_stack[MAX_NESTED_LIBCALLS + 1], *libcall_sp;
03179 bool changed = false;
03180
03181 cselib_init (false);
03182 libcall_sp = &libcall_stack[MAX_NESTED_LIBCALLS];
03183 *libcall_sp = 0;
03184 FOR_EACH_BB (bb)
03185 {
03186 FOR_BB_INSNS (bb, insn)
03187 {
03188 if (INSN_P (insn))
03189 {
03190 rtx note = find_reg_note (insn, REG_LIBCALL, NULL_RTX);
03191
03192 if (note)
03193 {
03194 gcc_assert (libcall_sp != libcall_stack);
03195 *--libcall_sp = XEXP (note, 0);
03196 }
03197 note = find_reg_note (insn, REG_RETVAL, NULL_RTX);
03198 if (note)
03199 libcall_sp++;
03200 note = find_reg_equal_equiv_note (insn);
03201 do
03202 {
03203 reg_use_count = 0;
03204 note_uses (&PATTERN (insn), local_cprop_find_used_regs,
03205 NULL);
03206 if (note)
03207 local_cprop_find_used_regs (&XEXP (note, 0), NULL);
03208
03209 for (reg_used = ®_use_table[0]; reg_use_count > 0;
03210 reg_used++, reg_use_count--)
03211 if (do_local_cprop (reg_used->reg_rtx, insn, alter_jumps,
03212 libcall_sp))
03213 {
03214 changed = true;
03215 break;
03216 }
03217 if (INSN_DELETED_P (insn))
03218 break;
03219 }
03220 while (reg_use_count);
03221 }
03222 cselib_process_insn (insn);
03223 }
03224
03225
03226
03227 cselib_clear_table ();
03228 gcc_assert (libcall_sp == &libcall_stack[MAX_NESTED_LIBCALLS]);
03229 }
03230
03231 cselib_finish ();
03232
03233
03234 if (changed && alter_jumps)
03235 {
03236 delete_unreachable_blocks ();
03237 free_reg_set_mem ();
03238 alloc_reg_set_mem (max_reg_num ());
03239 compute_sets ();
03240 }
03241 }
03242
03243
03244
03245
03246 static int
03247 cprop (int alter_jumps)
03248 {
03249 int changed;
03250 basic_block bb;
03251 rtx insn;
03252
03253
03254 if (ENTRY_BLOCK_PTR->next_bb == EXIT_BLOCK_PTR)
03255 {
03256 if (dump_file != NULL)
03257 fprintf (dump_file, "\n");
03258 return 0;
03259 }
03260
03261 changed = 0;
03262 FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR->next_bb->next_bb, EXIT_BLOCK_PTR, next_bb)
03263 {
03264
03265
03266 reset_opr_set_tables ();
03267
03268 FOR_BB_INSNS (bb, insn)
03269 if (INSN_P (insn))
03270 {
03271 changed |= cprop_insn (insn, alter_jumps);
03272
03273
03274
03275
03276 if (! NOTE_P (insn))
03277 mark_oprs_set (insn);
03278 }
03279 }
03280
03281 if (dump_file != NULL)
03282 fprintf (dump_file, "\n");
03283
03284 return changed;
03285 }
03286
03287
03288
03289
03290
03291
03292
03293
03294
03295
03296
03297 rtx
03298 fis_get_condition (rtx jump)
03299 {
03300 return get_condition (jump, NULL, false, true);
03301 }
03302
03303
03304
03305
03306 static bool
03307 implicit_set_cond_p (rtx cond)
03308 {
03309 enum machine_mode mode = GET_MODE (XEXP (cond, 0));
03310 rtx cst = XEXP (cond, 1);
03311
03312
03313
03314 if (HONOR_SIGNED_ZEROS (mode))
03315 {
03316
03317
03318
03319
03320
03321 if (GET_CODE (cst) == CONST_DOUBLE)
03322 {
03323 REAL_VALUE_TYPE d;
03324 REAL_VALUE_FROM_CONST_DOUBLE (d, cst);
03325 if (REAL_VALUES_EQUAL (d, dconst0))
03326 return 0;
03327 }
03328 else
03329 return 0;
03330 }
03331
03332 return gcse_constant_p (cst);
03333 }
03334
03335
03336
03337
03338
03339
03340
03341
03342 static void
03343 find_implicit_sets (void)
03344 {
03345 basic_block bb, dest;
03346 unsigned int count;
03347 rtx cond, new;
03348
03349 count = 0;
03350 FOR_EACH_BB (bb)
03351
03352 if (EDGE_COUNT (bb->succs) > 1)
03353 {
03354 cond = fis_get_condition (BB_END (bb));
03355
03356 if (cond
03357 && (GET_CODE (cond) == EQ || GET_CODE (cond) == NE)
03358 && REG_P (XEXP (cond, 0))
03359 && REGNO (XEXP (cond, 0)) >= FIRST_PSEUDO_REGISTER
03360 && implicit_set_cond_p (cond))
03361 {
03362 dest = GET_CODE (cond) == EQ ? BRANCH_EDGE (bb)->dest
03363 : FALLTHRU_EDGE (bb)->dest;
03364
03365 if (dest && single_pred_p (dest)
03366 && dest != EXIT_BLOCK_PTR)
03367 {
03368 new = gen_rtx_SET (VOIDmode, XEXP (cond, 0),
03369 XEXP (cond, 1));
03370 implicit_sets[dest->index] = new;
03371 if (dump_file)
03372 {
03373 fprintf(dump_file, "Implicit set of reg %d in ",
03374 REGNO (XEXP (cond, 0)));
03375 fprintf(dump_file, "basic block %d\n", dest->index);
03376 }
03377 count++;
03378 }
03379 }
03380 }
03381
03382 if (dump_file)
03383 fprintf (dump_file, "Found %d implicit sets\n", count);
03384 }
03385
03386
03387
03388
03389
03390
03391 static int
03392 one_cprop_pass (int pass, bool cprop_jumps, bool bypass_jumps)
03393 {
03394 int changed = 0;
03395
03396 global_const_prop_count = local_const_prop_count = 0;
03397 global_copy_prop_count = local_copy_prop_count = 0;
03398
03399 local_cprop_pass (cprop_jumps);
03400
03401
03402 implicit_sets = XCNEWVEC (rtx, last_basic_block);
03403 find_implicit_sets ();
03404
03405 alloc_hash_table (max_cuid, &set_hash_table, 1);
03406 compute_hash_table (&set_hash_table);
03407
03408
03409 free (implicit_sets);
03410 implicit_sets = NULL;
03411
03412 if (dump_file)
03413 dump_hash_table (dump_file, "SET", &set_hash_table);
03414 if (set_hash_table.n_elems > 0)
03415 {
03416 alloc_cprop_mem (last_basic_block, set_hash_table.n_elems);
03417 compute_cprop_data ();
03418 changed = cprop (cprop_jumps);
03419 if (bypass_jumps)
03420 changed |= bypass_conditional_jumps ();
03421 free_cprop_mem ();
03422 }
03423
03424 free_hash_table (&set_hash_table);
03425
03426 if (dump_file)
03427 {
03428 fprintf (dump_file, "CPROP of %s, pass %d: %d bytes needed, ",
03429 current_function_name (), pass, bytes_used);
03430 fprintf (dump_file, "%d local const props, %d local copy props, ",
03431 local_const_prop_count, local_copy_prop_count);
03432 fprintf (dump_file, "%d global const props, %d global copy props\n\n",
03433 global_const_prop_count, global_copy_prop_count);
03434 }
03435
03436 if (changed && cprop_jumps)
03437 delete_unreachable_blocks ();
03438
03439 return changed;
03440 }
03441
03442
03443
03444
03445
03446
03447
03448
03449 static int bypass_last_basic_block;
03450
03451
03452
03453
03454
03455 static struct expr *
03456 find_bypass_set (int regno, int bb)
03457 {
03458 struct expr *result = 0;
03459
03460 for (;;)
03461 {
03462 rtx src;
03463 struct expr *set = lookup_set (regno, &set_hash_table);
03464
03465 while (set)
03466 {
03467 if (TEST_BIT (cprop_avout[bb], set->bitmap_index))
03468 break;
03469 set = next_set (regno, set);
03470 }
03471
03472 if (set == 0)
03473 break;
03474
03475 gcc_assert (GET_CODE (set->expr) == SET);
03476
03477 src = SET_SRC (set->expr);
03478 if (gcse_constant_p (src))
03479 result = set;
03480
03481 if (! REG_P (src))
03482 break;
03483
03484 regno = REGNO (src);
03485 }
03486 return result;
03487 }
03488
03489
03490
03491
03492
03493
03494
03495
03496 static bool
03497 reg_killed_on_edge (rtx reg, edge e)
03498 {
03499 rtx insn;
03500
03501 for (insn = e->insns.r; insn; insn = NEXT_INSN (insn))
03502 if (INSN_P (insn) && reg_set_p (reg, insn))
03503 return true;
03504
03505 return false;
03506 }
03507
03508
03509
03510
03511
03512
03513
03514
03515
03516
03517
03518 static int
03519 bypass_block (basic_block bb, rtx setcc, rtx jump)
03520 {
03521 rtx insn, note;
03522 edge e, edest;
03523 int i, change;
03524 int may_be_loop_header;
03525 unsigned removed_p;
03526 edge_iterator ei;
03527
03528 insn = (setcc != NULL) ? setcc : jump;
03529
03530
03531 reg_use_count = 0;
03532 note_uses (&PATTERN (insn), find_used_regs, NULL);
03533 note = find_reg_equal_equiv_note (insn);
03534 if (note)
03535 find_used_regs (&XEXP (note, 0), NULL);
03536
03537 may_be_loop_header = false;
03538 FOR_EACH_EDGE (e, ei, bb->preds)
03539 if (e->flags & EDGE_DFS_BACK)
03540 {
03541 may_be_loop_header = true;
03542 break;
03543 }
03544
03545 change = 0;
03546 for (ei = ei_start (bb->preds); (e = ei_safe_edge (ei)); )
03547 {
03548 removed_p = 0;
03549
03550 if (e->flags & EDGE_COMPLEX)
03551 {
03552 ei_next (&ei);
03553 continue;
03554 }
03555
03556
03557 if (e->src->index >= bypass_last_basic_block)
03558 {
03559 ei_next (&ei);
03560 continue;
03561 }
03562
03563
03564
03565
03566 if (may_be_loop_header
03567 && !(e->flags & EDGE_DFS_BACK))
03568 {
03569 ei_next (&ei);
03570 continue;
03571 }
03572
03573 for (i = 0; i < reg_use_count; i++)
03574 {
03575 struct reg_use *reg_used = ®_use_table[i];
03576 unsigned int regno = REGNO (reg_used->reg_rtx);
03577 basic_block dest, old_dest;
03578 struct expr *set;
03579 rtx src, new;
03580
03581 if (regno >= max_gcse_regno)
03582 continue;
03583
03584 set = find_bypass_set (regno, e->src->index);
03585
03586 if (! set)
03587 continue;
03588
03589
03590 if (e->insns.r && reg_killed_on_edge (reg_used->reg_rtx, e))
03591 continue;
03592
03593 src = SET_SRC (pc_set (jump));
03594
03595 if (setcc != NULL)
03596 src = simplify_replace_rtx (src,
03597 SET_DEST (PATTERN (setcc)),
03598 SET_SRC (PATTERN (setcc)));
03599
03600 new = simplify_replace_rtx (src, reg_used->reg_rtx,
03601 SET_SRC (set->expr));
03602
03603
03604
03605
03606
03607
03608 if (new == pc_rtx)
03609 {
03610 edest = FALLTHRU_EDGE (bb);
03611 dest = edest->insns.r ? NULL : edest->dest;
03612 }
03613 else if (GET_CODE (new) == LABEL_REF)
03614 {
03615 dest = BLOCK_FOR_INSN (XEXP (new, 0));
03616
03617 edest = find_edge (bb, dest);
03618 if (edest && edest->insns.r)
03619 dest = NULL;
03620 }
03621 else
03622 dest = NULL;
03623
03624
03625
03626
03627
03628 if (dest && setcc && !CC0_P (SET_DEST (PATTERN (setcc)))
03629 && find_edge (e->src, dest))
03630 dest = NULL;
03631
03632 old_dest = e->dest;
03633 if (dest != NULL
03634 && dest != old_dest
03635 && dest != EXIT_BLOCK_PTR)
03636 {
03637 redirect_edge_and_branch_force (e, dest);
03638
03639
03640
03641 if (setcc)
03642 {
03643 rtx pat = PATTERN (setcc);
03644 if (!CC0_P (SET_DEST (pat)))
03645 insert_insn_on_edge (copy_insn (pat), e);
03646 }
03647
03648 if (dump_file != NULL)
03649 {
03650 fprintf (dump_file, "JUMP-BYPASS: Proved reg %d "
03651 "in jump_insn %d equals constant ",
03652 regno, INSN_UID (jump));
03653 print_rtl (dump_file, SET_SRC (set->expr));
03654 fprintf (dump_file, "\nBypass edge from %d->%d to %d\n",
03655 e->src->index, old_dest->index, dest->index);
03656 }
03657 change = 1;
03658 removed_p = 1;
03659 break;
03660 }
03661 }
03662 if (!removed_p)
03663 ei_next (&ei);
03664 }
03665 return change;
03666 }
03667
03668
03669
03670
03671
03672
03673
03674
03675 static int
03676 bypass_conditional_jumps (void)
03677 {
03678 basic_block bb;
03679 int changed;
03680 rtx setcc;
03681 rtx insn;
03682 rtx dest;
03683
03684
03685 if (ENTRY_BLOCK_PTR->next_bb == EXIT_BLOCK_PTR)
03686 return 0;
03687
03688 bypass_last_basic_block = last_basic_block;
03689 mark_dfs_back_edges ();
03690
03691 changed = 0;
03692 FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR->next_bb->next_bb,
03693 EXIT_BLOCK_PTR, next_bb)
03694 {
03695
03696 if (!single_pred_p (bb))
03697 {
03698 setcc = NULL_RTX;
03699 FOR_BB_INSNS (bb, insn)
03700 if (NONJUMP_INSN_P (insn))
03701 {
03702 if (setcc)
03703 break;
03704 if (GET_CODE (PATTERN (insn)) != SET)
03705 break;
03706
03707 dest = SET_DEST (PATTERN (insn));
03708 if (REG_P (dest) || CC0_P (dest))
03709 setcc = insn;
03710 else
03711 break;
03712 }
03713 else if (JUMP_P (insn))
03714 {
03715 if ((any_condjump_p (insn) || computed_jump_p (insn))
03716 && onlyjump_p (insn))
03717 changed |= bypass_block (bb, setcc, insn);
03718 break;
03719 }
03720 else if (INSN_P (insn))
03721 break;
03722 }
03723 }
03724
03725
03726
03727 if (changed)
03728 commit_edge_insertions();
03729
03730 return changed;
03731 }
03732
03733
03734
03735
03736
03737 static sbitmap *transp;
03738
03739
03740
03741
03742 static sbitmap *transpout;
03743
03744
03745 static sbitmap *comp;
03746
03747
03748 static sbitmap *antloc;
03749
03750
03751
03752 static sbitmap *pre_optimal;
03753
03754
03755 static sbitmap *pre_redundant;
03756
03757
03758 static sbitmap *pre_insert_map;
03759
03760
03761 static sbitmap *pre_delete_map;
03762
03763
03764 static struct edge_list *edge_list;
03765
03766
03767 static sbitmap pre_redundant_insns;
03768
03769
03770
03771 static void
03772 alloc_pre_mem (int n_blocks, int n_exprs)
03773 {
03774 transp = sbitmap_vector_alloc (n_blocks, n_exprs);
03775 comp = sbitmap_vector_alloc (n_blocks, n_exprs);
03776 antloc = sbitmap_vector_alloc (n_blocks, n_exprs);
03777
03778 pre_optimal = NULL;
03779 pre_redundant = NULL;
03780 pre_insert_map = NULL;
03781 pre_delete_map = NULL;
03782 ae_kill = sbitmap_vector_alloc (n_blocks, n_exprs);
03783
03784
03785 }
03786
03787
03788
03789 static void
03790 free_pre_mem (void)
03791 {
03792 sbitmap_vector_free (transp);
03793 sbitmap_vector_free (comp);
03794
03795
03796
03797 if (pre_optimal)
03798 sbitmap_vector_free (pre_optimal);
03799 if (pre_redundant)
03800 sbitmap_vector_free (pre_redundant);
03801 if (pre_insert_map)
03802 sbitmap_vector_free (pre_insert_map);
03803 if (pre_delete_map)
03804 sbitmap_vector_free (pre_delete_map);
03805
03806 transp = comp = NULL;
03807 pre_optimal = pre_redundant = pre_insert_map = pre_delete_map = NULL;
03808 }
03809
03810
03811
03812 static void
03813 compute_pre_data (void)
03814 {
03815 sbitmap trapping_expr;
03816 basic_block bb;
03817 unsigned int ui;
03818
03819 compute_local_properties (transp, comp, antloc, &expr_hash_table);
03820 sbitmap_vector_zero (ae_kill, last_basic_block);
03821
03822
03823 trapping_expr = sbitmap_alloc (expr_hash_table.n_elems);
03824 sbitmap_zero (trapping_expr);
03825 for (ui = 0; ui < expr_hash_table.size; ui++)
03826 {
03827 struct expr *e;
03828 for (e = expr_hash_table.table[ui]; e != NULL; e = e->next_same_hash)
03829 if (may_trap_p (e->expr))
03830 SET_BIT (trapping_expr, e->bitmap_index);
03831 }
03832
03833
03834
03835
03836
03837
03838 FOR_EACH_BB (bb)
03839 {
03840 edge e;
03841 edge_iterator ei;
03842
03843
03844
03845
03846
03847 FOR_EACH_EDGE (e, ei, bb->preds)
03848 if (e->flags & EDGE_ABNORMAL)
03849 {
03850 sbitmap_difference (antloc[bb->index], antloc[bb->index], trapping_expr);
03851 sbitmap_difference (transp[bb->index], transp[bb->index], trapping_expr);
03852 break;
03853 }
03854
03855 sbitmap_a_or_b (ae_kill[bb->index], transp[bb->index], comp[bb->index]);
03856 sbitmap_not (ae_kill[bb->index], ae_kill[bb->index]);
03857 }
03858
03859 edge_list = pre_edge_lcm (expr_hash_table.n_elems, transp, comp, antloc,
03860 ae_kill, &pre_insert_map, &pre_delete_map);
03861 sbitmap_vector_free (antloc);
03862 antloc = NULL;
03863 sbitmap_vector_free (ae_kill);
03864 ae_kill = NULL;
03865 sbitmap_free (trapping_expr);
03866 }
03867
03868
03869
03870
03871
03872
03873
03874
03875
03876
03877
03878
03879
03880
03881
03882
03883 static int
03884 pre_expr_reaches_here_p_work (basic_block occr_bb, struct expr *expr, basic_block bb, char *visited)
03885 {
03886 edge pred;
03887 edge_iterator ei;
03888
03889 FOR_EACH_EDGE (pred, ei, bb->preds)
03890 {
03891 basic_block pred_bb = pred->src;
03892
03893 if (pred->src == ENTRY_BLOCK_PTR
03894
03895 || visited[pred_bb->index])
03896 ;
03897
03898
03899 else if (TEST_BIT (comp[pred_bb->index], expr->bitmap_index))
03900 {
03901
03902
03903
03904 if (occr_bb == pred_bb)
03905 return 1;
03906
03907 visited[pred_bb->index] = 1;
03908 }
03909
03910 else if (! TEST_BIT (transp[pred_bb->index], expr->bitmap_index))
03911 visited[pred_bb->index] = 1;
03912
03913
03914 else
03915 {
03916 visited[pred_bb->index] = 1;
03917 if (pre_expr_reaches_here_p_work (occr_bb, expr, pred_bb, visited))
03918 return 1;
03919 }
03920 }
03921
03922
03923 return 0;
03924 }
03925
03926
03927
03928
03929 static int
03930 pre_expr_reaches_here_p (basic_block occr_bb, struct expr *expr, basic_block bb)
03931 {
03932 int rval;
03933 char *visited = XCNEWVEC (char, last_basic_block);
03934
03935 rval = pre_expr_reaches_here_p_work (occr_bb, expr, bb, visited);
03936
03937 free (visited);
03938 return rval;
03939 }
03940
03941
03942
03943
03944
03945
03946 static rtx
03947 process_insert_insn (struct expr *expr)
03948 {
03949 rtx reg = expr->reaching_reg;
03950 rtx exp = copy_rtx (expr->expr);
03951 rtx pat;
03952
03953 start_sequence ();
03954
03955
03956
03957 if (general_operand (exp, GET_MODE (reg)))
03958 emit_move_insn (reg, exp);
03959
03960
03961
03962
03963 else
03964 {
03965 rtx insn = emit_insn (gen_rtx_SET (VOIDmode, reg, exp));
03966
03967 if (insn_invalid_p (insn))
03968 gcc_unreachable ();
03969 }
03970
03971
03972 pat = get_insns ();
03973 end_sequence ();
03974
03975 return pat;
03976 }
03977
03978
03979
03980
03981
03982
03983
03984
03985
03986 static void
03987 insert_insn_end_bb (struct expr *expr, basic_block bb, int pre)
03988 {
03989 rtx insn = BB_END (bb);
03990 rtx new_insn;
03991 rtx reg = expr->reaching_reg;
03992 int regno = REGNO (reg);
03993 rtx pat, pat_end;
03994
03995 pat = process_insert_insn (expr);
03996 gcc_assert (pat && INSN_P (pat));
03997
03998 pat_end = pat;
03999 while (NEXT_INSN (pat_end) != NULL_RTX)
04000 pat_end = NEXT_INSN (pat_end);
04001
04002
04003
04004
04005
04006 if (JUMP_P (insn)
04007 || (NONJUMP_INSN_P (insn)
04008 && (!single_succ_p (bb)
04009 || single_succ_edge (bb)->flags & EDGE_ABNORMAL)))
04010 {
04011 #ifdef HAVE_cc0
04012 rtx note;
04013 #endif
04014
04015
04016
04017 gcc_assert (!NONJUMP_INSN_P (insn) || !pre
04018 || TEST_BIT (antloc[bb->index], expr->bitmap_index)
04019 || TEST_BIT (transp[bb->index], expr->bitmap_index));
04020
04021
04022
04023
04024 if (GET_CODE (PATTERN (insn)) == ADDR_VEC
04025 || GET_CODE (PATTERN (insn)) == ADDR_DIFF_VEC)
04026 insn = prev_real_insn (insn);
04027
04028 #ifdef HAVE_cc0
04029
04030
04031 note = find_reg_note (insn, REG_CC_SETTER, NULL_RTX);
04032 if (note)
04033 insn = XEXP (note, 0);
04034 else
04035 {
04036 rtx maybe_cc0_setter = prev_nonnote_insn (insn);
04037 if (maybe_cc0_setter
04038 && INSN_P (maybe_cc0_setter)
04039 && sets_cc0_p (PATTERN (maybe_cc0_setter)))
04040 insn = maybe_cc0_setter;
04041 }
04042 #endif
04043
04044 new_insn = emit_insn_before_noloc (pat, insn);
04045 }
04046
04047
04048
04049 else if (CALL_P (insn)
04050 && (!single_succ_p (bb)
04051 || single_succ_edge (bb)->flags & EDGE_ABNORMAL))
04052 {
04053
04054
04055
04056
04057
04058
04059
04060
04061
04062 gcc_assert (!pre
04063 || TEST_BIT (antloc[bb->index], expr->bitmap_index)
04064 || TEST_BIT (transp[bb->index], expr->bitmap_index));
04065
04066
04067
04068
04069 insn = find_first_parameter_load (insn, BB_HEAD (bb));
04070
04071
04072
04073
04074
04075
04076
04077
04078
04079 while (LABEL_P (insn)
04080 || NOTE_INSN_BASIC_BLOCK_P (insn))
04081 insn = NEXT_INSN (insn);
04082
04083 new_insn = emit_insn_before_noloc (pat, insn);
04084 }
04085 else
04086 new_insn = emit_insn_after_noloc (pat, insn);
04087
04088 while (1)
04089 {
04090 if (INSN_P (pat))
04091 {
04092 add_label_notes (PATTERN (pat), new_insn);
04093 note_stores (PATTERN (pat), record_set_info, pat);
04094 }
04095 if (pat == pat_end)
04096 break;
04097 pat = NEXT_INSN (pat);
04098 }
04099
04100 gcse_create_count++;
04101
04102 if (dump_file)
04103 {
04104 fprintf (dump_file, "PRE/HOIST: end of bb %d, insn %d, ",
04105 bb->index, INSN_UID (new_insn));
04106 fprintf (dump_file, "copying expression %d to reg %d\n",
04107 expr->bitmap_index, regno);
04108 }
04109 }
04110
04111
04112
04113
04114 static int
04115 pre_edge_insert (struct edge_list *edge_list, struct expr **index_map)
04116 {
04117 int e, i, j, num_edges, set_size, did_insert = 0;
04118 sbitmap *inserted;
04119
04120
04121
04122
04123 set_size = pre_insert_map[0]->size;
04124 num_edges = NUM_EDGES (edge_list);
04125 inserted = sbitmap_vector_alloc (num_edges, expr_hash_table.n_elems);
04126 sbitmap_vector_zero (inserted, num_edges);
04127
04128 for (e = 0; e < num_edges; e++)
04129 {
04130 int indx;
04131 basic_block bb = INDEX_EDGE_PRED_BB (edge_list, e);
04132
04133 for (i = indx = 0; i < set_size; i++, indx += SBITMAP_ELT_BITS)
04134 {
04135 SBITMAP_ELT_TYPE insert = pre_insert_map[e]->elms[i];
04136
04137 for (j = indx; insert && j < (int) expr_hash_table.n_elems; j++, insert >>= 1)
04138 if ((insert & 1) != 0 && index_map[j]->reaching_reg != NULL_RTX)
04139 {
04140 struct expr *expr = index_map[j];
04141 struct occr *occr;
04142
04143
04144 for (occr = expr->antic_occr; occr != NULL; occr = occr->next)
04145 {
04146 if (! occr->deleted_p)
04147 continue;
04148
04149
04150
04151 if (!TEST_BIT (inserted[e], j))
04152 {
04153 rtx insn;
04154 edge eg = INDEX_EDGE (edge_list, e);
04155
04156
04157
04158
04159
04160
04161
04162
04163 if (eg->flags & EDGE_ABNORMAL)
04164 insert_insn_end_bb (index_map[j], bb, 0);
04165 else
04166 {
04167 insn = process_insert_insn (index_map[j]);
04168 insert_insn_on_edge (insn, eg);
04169 }
04170
04171 if (dump_file)
04172 {
04173 fprintf (dump_file, "PRE/HOIST: edge (%d,%d), ",
04174 bb->index,
04175 INDEX_EDGE_SUCC_BB (edge_list, e)->index);
04176 fprintf (dump_file, "copy expression %d\n",
04177 expr->bitmap_index);
04178 }
04179
04180 update_ld_motion_stores (expr);
04181 SET_BIT (inserted[e], j);
04182 did_insert = 1;
04183 gcse_create_count++;
04184 }
04185 }
04186 }
04187 }
04188 }
04189
04190 sbitmap_vector_free (inserted);
04191 return did_insert;
04192 }
04193
04194
04195
04196
04197
04198
04199
04200
04201
04202
04203
04204
04205
04206
04207
04208
04209 static void
04210 pre_insert_copy_insn (struct expr *expr, rtx insn)
04211 {
04212 rtx reg = expr->reaching_reg;
04213 int regno = REGNO (reg);
04214 int indx = expr->bitmap_index;
04215 rtx pat = PATTERN (insn);
04216 rtx set, first_set, new_insn;
04217 rtx old_reg;
04218 int i;
04219
04220
04221 switch (GET_CODE (pat))
04222 {
04223 case SET:
04224 set = pat;
04225 break;
04226
04227 case PARALLEL:
04228
04229
04230 first_set = NULL_RTX;
04231 set = NULL_RTX;
04232 for (i = 0; i < XVECLEN (pat, 0); i++)
04233 {
04234 rtx x = XVECEXP (pat, 0, i);
04235 if (GET_CODE (x) == SET)
04236 {
04237
04238
04239
04240 if (first_set == NULL_RTX)
04241 first_set = x;
04242 if (expr_equiv_p (SET_SRC (x), expr->expr))
04243 {
04244 set = x;
04245 break;
04246 }
04247 }
04248 }
04249
04250 gcc_assert (first_set);
04251 if (set == NULL_RTX)
04252 set = first_set;
04253 break;
04254
04255 default:
04256 gcc_unreachable ();
04257 }
04258
04259 if (REG_P (SET_DEST (set)))
04260 {
04261 old_reg = SET_DEST (set);
04262
04263 if (validate_change (insn, &SET_DEST (set), reg, 0))
04264 {
04265 new_insn = gen_move_insn (old_reg, reg);
04266 new_insn = emit_insn_after (new_insn, insn);
04267
04268
04269 record_one_set (regno, insn);
04270 }
04271 else
04272 {
04273 new_insn = gen_move_insn (reg, old_reg);
04274 new_insn = emit_insn_after (new_insn, insn);
04275
04276
04277 record_one_set (regno, new_insn);
04278 }
04279 }
04280 else
04281 {
04282 old_reg = SET_SRC (set);
04283 new_insn = gen_move_insn (reg, old_reg);
04284
04285
04286 if (validate_change (insn, &SET_SRC (set), reg, 0))
04287 new_insn = emit_insn_before (new_insn, insn);
04288 else
04289 new_insn = emit_insn_after (new_insn, insn);
04290
04291
04292 record_one_set (regno, new_insn);
04293 }
04294
04295 gcse_create_count++;
04296
04297 if (dump_file)
04298 fprintf (dump_file,
04299 "PRE: bb %d, insn %d, copy expression %d in insn %d to reg %d\n",
04300 BLOCK_NUM (insn), INSN_UID (new_insn), indx,
04301 INSN_UID (insn), regno);
04302 }
04303
04304
04305
04306
04307 static void
04308 pre_insert_copies (void)
04309 {
04310 unsigned int i, added_copy;
04311 struct expr *expr;
04312 struct occr *occr;
04313 struct occr *avail;
04314
04315
04316
04317
04318
04319
04320
04321 for (i = 0; i < expr_hash_table.size; i++)
04322 for (expr = expr_hash_table.table[i]; expr != NULL; expr = expr->next_same_hash)
04323 {
04324
04325
04326
04327
04328
04329 if (expr->reaching_reg == NULL)
04330 continue;
04331
04332
04333 added_copy = 0;
04334
04335 for (occr = expr->antic_occr; occr != NULL; occr = occr->next)
04336 {
04337 if (! occr->deleted_p)
04338 continue;
04339
04340 for (avail = expr->avail_occr; avail != NULL; avail = avail->next)
04341 {
04342 rtx insn = avail->insn;
04343
04344
04345 if (avail->copied_p)
04346 continue;
04347
04348
04349 if (TEST_BIT (pre_redundant_insns, INSN_CUID (insn)))
04350 continue;
04351
04352
04353 if (! pre_expr_reaches_here_p (BLOCK_FOR_INSN (avail->insn),
04354 expr,
04355 BLOCK_FOR_INSN (occr->insn)))
04356 continue;
04357
04358 added_copy = 1;
04359
04360
04361 pre_insert_copy_insn (expr, insn);
04362 avail->copied_p = 1;
04363 }
04364 }
04365
04366 if (added_copy)
04367 update_ld_motion_stores (expr);
04368 }
04369 }
04370
04371
04372
04373 static rtx
04374 gcse_emit_move_after (rtx src, rtx dest, rtx insn)
04375 {
04376 rtx new;
04377 rtx set = single_set (insn), set2;
04378 rtx note;
04379 rtx eqv;
04380
04381
04382
04383
04384 new = emit_insn_after (gen_move_insn (dest, src), insn);
04385
04386
04387 set2 = single_set (new);
04388 if (!set2 || !rtx_equal_p (SET_DEST (set2), dest))
04389 return new;
04390 if ((note = find_reg_equal_equiv_note (insn)))
04391 eqv = XEXP (note, 0);
04392 else
04393 eqv = SET_SRC (set);
04394
04395 set_unique_reg_note (new, REG_EQUAL, copy_insn_1 (eqv));
04396
04397 return new;
04398 }
04399
04400
04401
04402
04403
04404
04405
04406
04407 static int
04408 pre_delete (void)
04409 {
04410 unsigned int i;
04411 int changed;
04412 struct expr *expr;
04413 struct occr *occr;
04414
04415 changed = 0;
04416 for (i = 0; i < expr_hash_table.size; i++)
04417 for (expr = expr_hash_table.table[i];
04418 expr != NULL;
04419 expr = expr->next_same_hash)
04420 {
04421 int indx = expr->bitmap_index;
04422
04423
04424
04425
04426 for (occr = expr->antic_occr; occr != NULL; occr = occr->next)
04427 {
04428 rtx insn = occr->insn;
04429 rtx set;
04430 basic_block bb = BLOCK_FOR_INSN (insn);
04431
04432
04433 if (TEST_BIT (pre_delete_map[bb->index], indx)
04434 && (set = single_set (insn)) != 0)
04435 {
04436
04437
04438
04439 if (expr->reaching_reg == NULL)
04440 expr->reaching_reg
04441 = gen_reg_rtx (GET_MODE (SET_DEST (set)));
04442
04443 gcse_emit_move_after (expr->reaching_reg, SET_DEST (set), insn);
04444 delete_insn (insn);
04445 occr->deleted_p = 1;
04446 SET_BIT (pre_redundant_insns, INSN_CUID (insn));
04447 changed = 1;
04448 gcse_subst_count++;
04449
04450 if (dump_file)
04451 {
04452 fprintf (dump_file,
04453 "PRE: redundant insn %d (expression %d) in ",
04454 INSN_UID (insn), indx);
04455 fprintf (dump_file, "bb %d, reaching reg is %d\n",
04456 bb->index, REGNO (expr->reaching_reg));
04457 }
04458 }
04459 }
04460 }
04461
04462 return changed;
04463 }
04464
04465
04466
04467
04468
04469
04470
04471
04472
04473
04474
04475
04476
04477
04478
04479
04480
04481
04482
04483
04484
04485 static int
04486 pre_gcse (void)
04487 {
04488 unsigned int i;
04489 int did_insert, changed;
04490 struct expr **index_map;
04491 struct expr *expr;
04492
04493
04494
04495
04496 index_map = XCNEWVEC (struct expr *, expr_hash_table.n_elems);
04497 for (i = 0; i < expr_hash_table.size; i++)
04498 for (expr = expr_hash_table.table[i]; expr != NULL; expr = expr->next_same_hash)
04499 index_map[expr->bitmap_index] = expr;
04500
04501
04502 pre_redundant_insns = sbitmap_alloc (max_cuid);
04503 sbitmap_zero (pre_redundant_insns);
04504
04505
04506
04507
04508
04509
04510 changed = pre_delete ();
04511
04512 did_insert = pre_edge_insert (edge_list, index_map);
04513
04514
04515
04516 pre_insert_copies ();
04517 if (did_insert)
04518 {
04519 commit_edge_insertions ();
04520 changed = 1;
04521 }
04522
04523 free (index_map);
04524 sbitmap_free (pre_redundant_insns);
04525 return changed;
04526 }
04527
04528
04529
04530
04531
04532 static int
04533 one_pre_gcse_pass (int pass)
04534 {
04535 int changed = 0;
04536
04537 gcse_subst_count = 0;
04538 gcse_create_count = 0;
04539
04540 alloc_hash_table (max_cuid, &expr_hash_table, 0);
04541 add_noreturn_fake_exit_edges ();
04542 if (flag_gcse_lm)
04543 compute_ld_motion_mems ();
04544
04545 compute_hash_table (&expr_hash_table);
04546 trim_ld_motion_mems ();
04547 if (dump_file)
04548 dump_hash_table (dump_file, "Expression", &expr_hash_table);
04549
04550 if (expr_hash_table.n_elems > 0)
04551 {
04552 alloc_pre_mem (last_basic_block, expr_hash_table.n_elems);
04553 compute_pre_data ();
04554 changed |= pre_gcse ();
04555 free_edge_list (edge_list);
04556 free_pre_mem ();
04557 }
04558
04559 free_ldst_mems ();
04560 remove_fake_exit_edges ();
04561 free_hash_table (&expr_hash_table);
04562
04563 if (dump_file)
04564 {
04565 fprintf (dump_file, "\nPRE GCSE of %s, pass %d: %d bytes needed, ",
04566 current_function_name (), pass, bytes_used);
04567 fprintf (dump_file, "%d substs, %d insns created\n",
04568 gcse_subst_count, gcse_create_count);
04569 }
04570
04571 return changed;
04572 }
04573
04574
04575
04576
04577
04578
04579
04580
04581
04582
04583 static void
04584 add_label_notes (rtx x, rtx insn)
04585 {
04586 enum rtx_code code = GET_CODE (x);
04587 int i, j;
04588 const char *fmt;
04589
04590 if (code == LABEL_REF && !LABEL_REF_NONLOCAL_P (x))
04591 {
04592
04593
04594
04595
04596
04597
04598 REG_NOTES (insn) = gen_rtx_INSN_LIST (REG_LABEL, XEXP (x, 0),
04599 REG_NOTES (insn));
04600 if (LABEL_P (XEXP (x, 0)))
04601 LABEL_NUSES (XEXP (x, 0))++;
04602 return;
04603 }
04604
04605 for (i = GET_RTX_LENGTH (code) - 1, fmt = GET_RTX_FORMAT (code); i >= 0; i--)
04606 {
04607 if (fmt[i] == 'e')
04608 add_label_notes (XEXP (x, i), insn);
04609 else if (fmt[i] == 'E')
04610 for (j = XVECLEN (x, i) - 1; j >= 0; j--)
04611 add_label_notes (XVECEXP (x, i, j), insn);
04612 }
04613 }
04614
04615
04616
04617
04618
04619
04620
04621
04622
04623
04624
04625
04626
04627
04628 static void
04629 compute_transpout (void)
04630 {
04631 basic_block bb;
04632 unsigned int i;
04633 struct expr *expr;
04634
04635 sbitmap_vector_ones (transpout, last_basic_block);
04636
04637 FOR_EACH_BB (bb)
04638 {
04639
04640
04641
04642 if (! CALL_P (BB_END (bb)))
04643 continue;
04644
04645 for (i = 0; i < expr_hash_table.size; i++)
04646 for (expr = expr_hash_table.table[i]; expr ; expr = expr->next_same_hash)
04647 if (MEM_P (expr->expr))
04648 {
04649 if (GET_CODE (XEXP (expr->expr, 0)) == SYMBOL_REF
04650 && CONSTANT_POOL_ADDRESS_P (XEXP (expr->expr, 0)))
04651 continue;
04652
04653
04654
04655
04656 RESET_BIT (transpout[bb->index], expr->bitmap_index);
04657 }
04658 }
04659 }
04660
04661
04662
04663
04664 static sbitmap *hoist_vbein;
04665 static sbitmap *hoist_vbeout;
04666
04667
04668 static sbitmap *hoist_exprs;
04669
04670
04671
04672
04673
04674
04675
04676
04677
04678
04679 static void
04680 alloc_code_hoist_mem (int n_blocks, int n_exprs)
04681 {
04682 antloc = sbitmap_vector_alloc (n_blocks, n_exprs);
04683 transp = sbitmap_vector_alloc (n_blocks, n_exprs);
04684 comp = sbitmap_vector_alloc (n_blocks, n_exprs);
04685
04686 hoist_vbein = sbitmap_vector_alloc (n_blocks, n_exprs);
04687 hoist_vbeout = sbitmap_vector_alloc (n_blocks, n_exprs);
04688 hoist_exprs = sbitmap_vector_alloc (n_blocks, n_exprs);
04689 transpout = sbitmap_vector_alloc (n_blocks, n_exprs);
04690 }
04691
04692
04693
04694 static void
04695 free_code_hoist_mem (void)
04696 {
04697 sbitmap_vector_free (antloc);
04698 sbitmap_vector_free (transp);
04699 sbitmap_vector_free (comp);
04700
04701 sbitmap_vector_free (hoist_vbein);
04702 sbitmap_vector_free (hoist_vbeout);
04703 sbitmap_vector_free (hoist_exprs);
04704 sbitmap_vector_free (transpout);
04705
04706 free_dominance_info (CDI_DOMINATORS);
04707 }
04708
04709
04710
04711
04712
04713
04714 static void
04715 compute_code_hoist_vbeinout (void)
04716 {
04717 int changed, passes;
04718 basic_block bb;
04719
04720 sbitmap_vector_zero (hoist_vbeout, last_basic_block);
04721 sbitmap_vector_zero (hoist_vbein, last_basic_block);
04722
04723 passes = 0;
04724 changed = 1;
04725
04726 while (changed)
04727 {
04728 changed = 0;
04729
04730
04731
04732 FOR_EACH_BB_REVERSE (bb)
04733 {
04734 changed |= sbitmap_a_or_b_and_c_cg (hoist_vbein[bb->index], antloc[bb->index],
04735 hoist_vbeout[bb->index], transp[bb->index]);
04736 if (bb->next_bb != EXIT_BLOCK_PTR)
04737 sbitmap_intersection_of_succs (hoist_vbeout[bb->index], hoist_vbein, bb->index);
04738 }
04739
04740 passes++;
04741 }
04742
04743 if (dump_file)
04744 fprintf (dump_file, "hoisting vbeinout computation: %d passes\n", passes);
04745 }
04746
04747
04748
04749 static void
04750 compute_code_hoist_data (void)
04751 {
04752 compute_local_properties (transp, comp, antloc, &expr_hash_table);
04753 compute_transpout ();
04754 compute_code_hoist_vbeinout ();
04755 calculate_dominance_info (CDI_DOMINATORS);
04756 if (dump_file)
04757 fprintf (dump_file, "\n");
04758 }
04759
04760
04761
04762
04763
04764
04765
04766
04767
04768
04769
04770
04771
04772
04773 static int
04774 hoist_expr_reaches_here_p (basic_block expr_bb, int expr_index, basic_block bb, char *visited)
04775 {
04776 edge pred;
04777 edge_iterator ei;
04778 int visited_allocated_locally = 0;
04779
04780
04781 if (visited == NULL)
04782 {
04783 visited_allocated_locally = 1;
04784 visited = XCNEWVEC (char, last_basic_block);
04785 }
04786
04787 FOR_EACH_EDGE (pred, ei, bb->preds)
04788 {
04789 basic_block pred_bb = pred->src;
04790
04791 if (pred->src == ENTRY_BLOCK_PTR)
04792 break;
04793 else if (pred_bb == expr_bb)
04794 continue;
04795 else if (visited[pred_bb->index])
04796 continue;
04797
04798
04799 else if (TEST_BIT (comp[pred_bb->index], expr_index))
04800 break;
04801 else if (! TEST_BIT (transp[pred_bb->index], expr_index))
04802 break;
04803
04804
04805 else
04806 {
04807 visited[pred_bb->index] = 1;
04808 if (! hoist_expr_reaches_here_p (expr_bb, expr_index,
04809 pred_bb, visited))
04810 break;
04811 }
04812 }
04813 if (visited_allocated_locally)
04814 free (visited);
04815
04816 return (pred == NULL);
04817 }
04818
04819
04820
04821 static void
04822 hoist_code (void)
04823 {
04824 basic_block bb, dominated;
04825 basic_block *domby;
04826 unsigned int domby_len;
04827 unsigned int i,j;
04828 struct expr **index_map;
04829 struct expr *expr;
04830
04831 sbitmap_vector_zero (hoist_exprs, last_basic_block);
04832
04833
04834
04835
04836 index_map = XCNEWVEC (struct expr *, expr_hash_table.n_elems);
04837 for (i = 0; i < expr_hash_table.size; i++)
04838 for (expr = expr_hash_table.table[i]; expr != NULL; expr = expr->next_same_hash)
04839 index_map[expr->bitmap_index] = expr;
04840
04841
04842
04843 FOR_EACH_BB (bb)
04844 {
04845 int found = 0;
04846 int insn_inserted_p;
04847
04848 domby_len = get_dominated_by (CDI_DOMINATORS, bb, &domby);
04849
04850
04851 for (i = 0; i < hoist_vbeout[bb->index]->n_bits; i++)
04852 {
04853 int hoistable = 0;
04854
04855 if (TEST_BIT (hoist_vbeout[bb->index], i)
04856 && TEST_BIT (transpout[bb->index], i))
04857 {
04858
04859
04860
04861 for (j = 0; j < domby_len; j++)
04862 {
04863 dominated = domby[j];
04864
04865 if (bb == dominated)
04866 continue;
04867
04868
04869
04870 if (!TEST_BIT (antloc[dominated->index], i))
04871 continue;
04872
04873
04874
04875
04876
04877
04878 if (hoist_expr_reaches_here_p (bb, i, dominated, NULL))
04879 hoistable++;
04880 }
04881
04882
04883
04884
04885
04886
04887
04888
04889
04890
04891
04892 if (hoistable > 1)
04893 {
04894 SET_BIT (hoist_exprs[bb->index], i);
04895 found = 1;
04896 }
04897 }
04898 }
04899
04900 if (! found)
04901 {
04902 free (domby);
04903 continue;
04904 }
04905
04906
04907 for (i = 0; i < hoist_exprs[bb->index]->n_bits; i++)
04908 {
04909
04910
04911 insn_inserted_p = 0;
04912
04913
04914 if (TEST_BIT (hoist_exprs[bb->index], i))
04915 {
04916
04917
04918
04919 for (j = 0; j < domby_len; j++)
04920 {
04921 dominated = domby[j];
04922
04923 if (bb == dominated)
04924 continue;
04925
04926
04927
04928
04929 if (!TEST_BIT (antloc[dominated->index], i))
04930 continue;
04931
04932
04933
04934
04935
04936
04937 if (hoist_expr_reaches_here_p (bb, i, dominated, NULL))
04938 {
04939 struct expr *expr = index_map[i];
04940 struct occr *occr = expr->antic_occr;
04941 rtx insn;
04942 rtx set;
04943
04944
04945 while (BLOCK_FOR_INSN (occr->insn) != dominated && occr)
04946 occr = occr->next;
04947
04948 gcc_assert (occr);
04949 insn = occr->insn;
04950 set = single_set (insn);
04951 gcc_assert (set);
04952
04953
04954
04955
04956 if (expr->reaching_reg == NULL)
04957 expr->reaching_reg
04958 = gen_reg_rtx (GET_MODE (SET_DEST (set)));
04959
04960 gcse_emit_move_after (expr->reaching_reg, SET_DEST (set), insn);
04961 delete_insn (insn);
04962 occr->deleted_p = 1;
04963 if (!insn_inserted_p)
04964 {
04965 insert_insn_end_bb (index_map[i], bb, 0);
04966 insn_inserted_p = 1;
04967 }
04968 }
04969 }
04970 }
04971 }
04972 free (domby);
04973 }
04974
04975 free (index_map);
04976 }
04977
04978
04979
04980
04981
04982 static int
04983 one_code_hoisting_pass (void)
04984 {
04985 int changed = 0;
04986
04987 alloc_hash_table (max_cuid, &expr_hash_table, 0);
04988 compute_hash_table (&expr_hash_table);
04989 if (dump_file)
04990 dump_hash_table (dump_file, "Code Hosting Expressions", &expr_hash_table);
04991
04992 if (expr_hash_table.n_elems > 0)
04993 {
04994 alloc_code_hoist_mem (last_basic_block, expr_hash_table.n_elems);
04995 compute_code_hoist_data ();
04996 hoist_code ();
04997 free_code_hoist_mem ();
04998 }
04999
05000 free_hash_table (&expr_hash_table);
05001
05002 return changed;
05003 }
05004
05005
05006
05007
05008
05009
05010
05011
05012
05013
05014
05015
05016
05017
05018
05019
05020
05021
05022
05023
05024
05025
05026
05027
05028
05029
05030 static hashval_t
05031 pre_ldst_expr_hash (const void *p)
05032 {
05033 int do_not_record_p = 0;
05034 const struct ls_expr *x = p;
05035 return hash_rtx (x->pattern, GET_MODE (x->pattern), &do_not_record_p, NULL, false);
05036 }
05037
05038 static int
05039 pre_ldst_expr_eq (const void *p1, const void *p2)
05040 {
05041 const struct ls_expr *ptr1 = p1, *ptr2 = p2;
05042 return expr_equiv_p (ptr1->pattern, ptr2->pattern);
05043 }
05044
05045
05046
05047
05048 static struct ls_expr *
05049 ldst_entry (rtx x)
05050 {
05051 int do_not_record_p = 0;
05052 struct ls_expr * ptr;
05053 unsigned int hash;
05054 void **slot;
05055 struct ls_expr e;
05056
05057 hash = hash_rtx (x, GET_MODE (x), &do_not_record_p,
05058 NULL, false);
05059
05060 e.pattern = x;
05061 slot = htab_find_slot_with_hash (pre_ldst_table, &e, hash, INSERT);
05062 if (*slot)
05063 return (struct ls_expr *)*slot;
05064
05065 ptr = XNEW (struct ls_expr);
05066
05067 ptr->next = pre_ldst_mems;
05068 ptr->expr = NULL;
05069 ptr->pattern = x;
05070 ptr->pattern_regs = NULL_RTX;
05071 ptr->loads = NULL_RTX;
05072 ptr->stores = NULL_RTX;
05073 ptr->reaching_reg = NULL_RTX;
05074 ptr->invalid = 0;
05075 ptr->index = 0;
05076 ptr->hash_index = hash;
05077 pre_ldst_mems = ptr;
05078 *slot = ptr;
05079
05080 return ptr;
05081 }
05082
05083
05084
05085 static void
05086 free_ldst_entry (struct ls_expr * ptr)
05087 {
05088 free_INSN_LIST_list (& ptr->loads);
05089 free_INSN_LIST_list (& ptr->stores);
05090
05091 free (ptr);
05092 }
05093
05094
05095
05096 static void
05097 free_ldst_mems (void)
05098 {
05099 if (pre_ldst_table)
05100 htab_delete (pre_ldst_table);
05101 pre_ldst_table = NULL;
05102
05103 while (pre_ldst_mems)
05104 {
05105 struct ls_expr * tmp = pre_ldst_mems;
05106
05107 pre_ldst_mems = pre_ldst_mems->next;
05108
05109 free_ldst_entry (tmp);
05110 }
05111
05112 pre_ldst_mems = NULL;
05113 }
05114
05115
05116
05117 static void
05118 print_ldst_list (FILE * file)
05119 {
05120 struct ls_expr * ptr;
05121
05122 fprintf (file, "LDST list: \n");
05123
05124 for (ptr = first_ls_expr(); ptr != NULL; ptr = next_ls_expr (ptr))
05125 {
05126 fprintf (file, " Pattern (%3d): ", ptr->index);
05127
05128 print_rtl (file, ptr->pattern);
05129
05130 fprintf (file, "\n Loads : ");
05131
05132 if (ptr->loads)
05133 print_rtl (file, ptr->loads);
05134 else
05135 fprintf (file, "(nil)");
05136
05137 fprintf (file, "\n Stores : ");
05138
05139 if (ptr->stores)
05140 print_rtl (file, ptr->stores);
05141 else
05142 fprintf (file, "(nil)");
05143
05144 fprintf (file, "\n\n");
05145 }
05146
05147 fprintf (file, "\n");
05148 }
05149
05150
05151
05152 static struct ls_expr *
05153 find_rtx_in_ldst (rtx x)
05154 {
05155 struct ls_expr e;
05156 void **slot;
05157 if (!pre_ldst_table)
05158 return NULL;
05159 e.pattern = x;
05160 slot = htab_find_slot (pre_ldst_table, &e, NO_INSERT);
05161 if (!slot || ((struct ls_expr *)*slot)->invalid)
05162 return NULL;
05163 return *slot;
05164 }
05165
05166
05167
05168 static int
05169 enumerate_ldsts (void)
05170 {
05171 struct ls_expr * ptr;
05172 int n = 0;
05173
05174 for (ptr = pre_ldst_mems; ptr != NULL; ptr = ptr->next)
05175 ptr->index = n++;
05176
05177 return n;
05178 }
05179
05180
05181
05182 static inline struct ls_expr *
05183 first_ls_expr (void)
05184 {
05185 return pre_ldst_mems;
05186 }
05187
05188
05189
05190 static inline struct ls_expr *
05191 next_ls_expr (struct ls_expr * ptr)
05192 {
05193 return ptr->next;
05194 }
05195
05196
05197
05198
05199
05200
05201
05202 static int
05203 simple_mem (rtx x)
05204 {
05205 if (! MEM_P (x))
05206 return 0;
05207
05208 if (MEM_VOLATILE_P (x))
05209 return 0;
05210
05211 if (GET_MODE (x) == BLKmode)
05212 return 0;
05213
05214
05215
05216
05217 if (flag_non_call_exceptions && may_trap_p (x))
05218 return 0;
05219
05220 if (side_effects_p (x))
05221 return 0;
05222
05223
05224 if (reg_mentioned_p (stack_pointer_rtx, x))
05225 return 0;
05226
05227 if (flag_float_store && FLOAT_MODE_P (GET_MODE (x)))
05228 return 0;
05229
05230 return 1;
05231 }
05232
05233
05234
05235
05236
05237
05238
05239
05240
05241 static void
05242 invalidate_any_buried_refs (rtx x)
05243 {
05244 const char * fmt;
05245 int i, j;
05246 struct ls_expr * ptr;
05247
05248
05249 if (MEM_P (x) && simple_mem (x))
05250 {
05251 ptr = ldst_entry (x);
05252 ptr->invalid = 1;
05253 }
05254
05255
05256 fmt = GET_RTX_FORMAT (GET_CODE (x));
05257
05258 for (i = GET_RTX_LENGTH (GET_CODE (x)) - 1; i >= 0; i--)
05259 {
05260 if (fmt[i] == 'e')
05261 invalidate_any_buried_refs (XEXP (x, i));
05262 else if (fmt[i] == 'E')
05263 for (j = XVECLEN (x, i) - 1; j >= 0; j--)
05264 invalidate_any_buried_refs (XVECEXP (x, i, j));
05265 }
05266 }
05267
05268
05269
05270
05271
05272
05273
05274
05275
05276 static void
05277 compute_ld_motion_mems (void)
05278 {
05279 struct ls_expr * ptr;
05280 basic_block bb;
05281 rtx insn;
05282
05283 pre_ldst_mems = NULL;
05284 pre_ldst_table = htab_create (13, pre_ldst_expr_hash,
05285 pre_ldst_expr_eq, NULL);
05286
05287 FOR_EACH_BB (bb)
05288 {
05289 FOR_BB_INSNS (bb, insn)
05290 {
05291 if (INSN_P (insn))
05292 {
05293 if (GET_CODE (PATTERN (insn)) == SET)
05294 {
05295 rtx src = SET_SRC (PATTERN (insn));
05296 rtx dest = SET_DEST (PATTERN (insn));
05297
05298
05299 if (MEM_P (src) && simple_mem (src))
05300 {
05301 ptr = ldst_entry (src);
05302 if (REG_P (dest))
05303 ptr->loads = alloc_INSN_LIST (insn, ptr->loads);
05304 else
05305 ptr->invalid = 1;
05306 }
05307 else
05308 {
05309
05310 invalidate_any_buried_refs (src);
05311 }
05312
05313
05314
05315
05316
05317 if (MEM_P (dest) && simple_mem (dest))
05318 {
05319 ptr = ldst_entry (dest);
05320
05321 if (! MEM_P (src)
05322 && GET_CODE (src) != ASM_OPERANDS
05323
05324
05325 && can_assign_to_reg_p (src))
05326 ptr->stores = alloc_INSN_LIST (insn, ptr->stores);
05327 else
05328 ptr->invalid = 1;
05329 }
05330 }
05331 else
05332 invalidate_any_buried_refs (PATTERN (insn));
05333 }
05334 }
05335 }
05336 }
05337
05338
05339
05340
05341 static void
05342 trim_ld_motion_mems (void)
05343 {
05344 struct ls_expr * * last = & pre_ldst_mems;
05345 struct ls_expr * ptr = pre_ldst_mems;
05346
05347 while (ptr != NULL)
05348 {
05349 struct expr * expr;
05350
05351
05352 if (! ptr->invalid)
05353 {
05354
05355 unsigned int hash = ptr->hash_index % expr_hash_table.size;
05356
05357 for (expr = expr_hash_table.table[hash];
05358 expr != NULL;
05359 expr = expr->next_same_hash)
05360 if (expr_equiv_p (expr->expr, ptr->pattern))
05361 break;
05362 }
05363 else
05364 expr = (struct expr *) 0;
05365
05366 if (expr)
05367 {
05368
05369 ptr->expr = expr;
05370 last = & ptr->next;
05371 ptr = ptr->next;
05372 }
05373 else
05374 {
05375 *last = ptr->next;
05376 htab_remove_elt_with_hash (pre_ldst_table, ptr, ptr->hash_index);
05377 free_ldst_entry (ptr);
05378 ptr = * last;
05379 }
05380 }
05381
05382
05383 if (dump_file && pre_ldst_mems != NULL)
05384 print_ldst_list (dump_file);
05385 }
05386
05387
05388
05389
05390
05391
05392
05393
05394 static void
05395 update_ld_motion_stores (struct expr * expr)
05396 {
05397 struct ls_expr * mem_ptr;
05398
05399 if ((mem_ptr = find_rtx_in_ldst (expr->expr)))
05400 {
05401
05402
05403
05404
05405
05406
05407
05408
05409 rtx list = mem_ptr->stores;
05410
05411 for ( ; list != NULL_RTX; list = XEXP (list, 1))
05412 {
05413 rtx insn = XEXP (list, 0);
05414 rtx pat = PATTERN (insn);
05415 rtx src = SET_SRC (pat);
05416 rtx reg = expr->reaching_reg;
05417 rtx copy, new;
05418
05419
05420 if (expr->reaching_reg == src)
05421 continue;
05422
05423 if (dump_file)
05424 {
05425 fprintf (dump_file, "PRE: store updated with reaching reg ");
05426 print_rtl (dump_file, expr->reaching_reg);
05427 fprintf (dump_file, ":\n ");
05428 print_inline_rtx (dump_file, insn, 8);
05429 fprintf (dump_file, "\n");
05430 }
05431
05432 copy = gen_move_insn ( reg, copy_rtx (SET_SRC (pat)));
05433 new = emit_insn_before (copy, insn);
05434 record_one_set (REGNO (reg), new);
05435 SET_SRC (pat) = reg;
05436
05437
05438 INSN_CODE (insn) = -1;
05439 gcse_create_count++;
05440 }
05441 }
05442 }
05443
05444
05445
05446 #define ANTIC_STORE_LIST(x) ((x)->loads)
05447 #define AVAIL_STORE_LIST(x) ((x)->stores)
05448 #define LAST_AVAIL_CHECK_FAILURE(x) ((x)->reaching_reg)
05449
05450
05451
05452 static int * regvec;
05453
05454
05455 static rtx compute_store_table_current_insn;
05456
05457
05458 static sbitmap * st_antloc;
05459
05460
05461 static int num_stores;
05462
05463
05464
05465
05466 static void
05467 reg_set_info (rtx dest, rtx setter ATTRIBUTE_UNUSED,
05468 void *data)
05469 {
05470 sbitmap bb_reg = data;
05471
05472 if (GET_CODE (dest) == SUBREG)
05473 dest = SUBREG_REG (dest);
05474
05475 if (REG_P (dest))
05476 {
05477 regvec[REGNO (dest)] = INSN_UID (compute_store_table_current_insn);
05478 if (bb_reg)
05479 SET_BIT (bb_reg, REGNO (dest));
05480 }
05481 }
05482
05483
05484
05485
05486 static void
05487 reg_clear_last_set (rtx dest, rtx setter ATTRIBUTE_UNUSED,
05488 void *data)
05489 {
05490 int *dead_vec = data;
05491
05492 if (GET_CODE (dest) == SUBREG)
05493 dest = SUBREG_REG (dest);
05494
05495 if (REG_P (dest) &&
05496 dead_vec[REGNO (dest)] == INSN_UID (compute_store_table_current_insn))
05497 dead_vec[REGNO (dest)] = 0;
05498 }
05499
05500
05501
05502
05503 static bool
05504 store_ops_ok (rtx x, int *regs_set)
05505 {
05506 rtx reg;
05507
05508 for (; x; x = XEXP (x, 1))
05509 {
05510 reg = XEXP (x, 0);
05511 if (regs_set[REGNO(reg)])
05512 return false;
05513 }
05514
05515 return true;
05516 }
05517
05518
05519 static rtx
05520 extract_mentioned_regs (rtx x)
05521 {
05522 return extract_mentioned_regs_helper (x, NULL_RTX);
05523 }
05524
05525
05526
05527 static rtx
05528 extract_mentioned_regs_helper (rtx x, rtx accum)
05529 {
05530 int i;
05531 enum rtx_code code;
05532 const char * fmt;
05533
05534
05535 repeat:
05536
05537 if (x == 0)
05538 return accum;
05539
05540 code = GET_CODE (x);
05541 switch (code)
05542 {
05543 case REG:
05544 return alloc_EXPR_LIST (0, x, accum);
05545
05546 case MEM:
05547 x = XEXP (x, 0);
05548 goto repeat;
05549
05550 case PRE_DEC:
05551 case PRE_INC:
05552 case POST_DEC:
05553 case POST_INC:
05554
05555 gcc_unreachable ();
05556
05557 case PC:
05558 case CC0:
05559 case CONST:
05560 case CONST_INT:
05561 case CONST_DOUBLE:
05562 case CONST_VECTOR:
05563 case SYMBOL_REF:
05564 case LABEL_REF:
05565 case ADDR_VEC:
05566 case ADDR_DIFF_VEC:
05567 return accum;
05568
05569 default:
05570 break;
05571 }
05572
05573 i = GET_RTX_LENGTH (code) - 1;
05574 fmt = GET_RTX_FORMAT (code);
05575
05576 for (; i >= 0; i--)
05577 {
05578 if (fmt[i] == 'e')
05579 {
05580 rtx tem = XEXP (x, i);
05581
05582
05583
05584 if (i == 0)
05585 {
05586 x = tem;
05587 goto repeat;
05588 }
05589
05590 accum = extract_mentioned_regs_helper (tem, accum);
05591 }
05592 else if (fmt[i] == 'E')
05593 {
05594 int j;
05595
05596 for (j = 0; j < XVECLEN (x, i); j++)
05597 accum = extract_mentioned_regs_helper (XVECEXP (x, i, j), accum);
05598 }
05599 }
05600
05601 return accum;
05602 }
05603
05604
05605
05606
05607
05608
05609
05610
05611
05612
05613
05614
05615
05616
05617
05618
05619
05620
05621
05622
05623
05624
05625
05626 static void
05627 find_moveable_store (rtx insn, int *regs_set_before, int *regs_set_after)
05628 {
05629 struct ls_expr * ptr;
05630 rtx dest, set, tmp;
05631 int check_anticipatable, check_available;
05632 basic_block bb = BLOCK_FOR_INSN (insn);
05633
05634 set = single_set (insn);
05635 if (!set)
05636 return;
05637
05638 dest = SET_DEST (set);
05639
05640 if (! MEM_P (dest) || MEM_VOLATILE_P (dest)
05641 || GET_MODE (dest) == BLKmode)
05642 return;
05643
05644 if (side_effects_p (dest))
05645 return;
05646
05647
05648
05649
05650 if (flag_non_call_exceptions && may_trap_p (dest))
05651 return;
05652
05653
05654
05655 if (find_reg_note (insn, REG_EH_REGION, NULL_RTX))
05656 return;
05657
05658
05659
05660
05661
05662
05663 if (!can_assign_to_reg_p (SET_SRC (set)))
05664 return;
05665
05666 ptr = ldst_entry (dest);
05667 if (!ptr->pattern_regs)
05668 ptr->pattern_regs = extract_mentioned_regs (dest);
05669
05670
05671
05672 check_anticipatable = 0;
05673 if (!ANTIC_STORE_LIST (ptr))
05674 check_anticipatable = 1;
05675 else
05676 {
05677 tmp = XEXP (ANTIC_STORE_LIST (ptr), 0);
05678 if (tmp != NULL_RTX
05679 && BLOCK_FOR_INSN (tmp) != bb)
05680 check_anticipatable = 1;
05681 }
05682 if (check_anticipatable)
05683 {
05684 if (store_killed_before (dest, ptr->pattern_regs, insn, bb, regs_set_before))
05685 tmp = NULL_RTX;
05686 else
05687 tmp = insn;
05688 ANTIC_STORE_LIST (ptr) = alloc_INSN_LIST (tmp,
05689 ANTIC_STORE_LIST (ptr));
05690 }
05691
05692
05693
05694
05695 check_available = 0;
05696 if (!AVAIL_STORE_LIST (ptr))
05697 check_available = 1;
05698 else
05699 {
05700 tmp = XEXP (AVAIL_STORE_LIST (ptr), 0);
05701 if (BLOCK_FOR_INSN (tmp) != bb)
05702 check_available = 1;
05703 }
05704 if (check_available)
05705 {
05706
05707
05708 if (LAST_AVAIL_CHECK_FAILURE (ptr))
05709 {
05710 for (tmp = BB_END (bb);
05711 tmp != insn && tmp != LAST_AVAIL_CHECK_FAILURE (ptr);
05712 tmp = PREV_INSN (tmp))
05713 continue;
05714 if (tmp == insn)
05715 check_available = 0;
05716 }
05717 else
05718 check_available = store_killed_after (dest, ptr->pattern_regs, insn,
05719 bb, regs_set_after,
05720 &LAST_AVAIL_CHECK_FAILURE (ptr));
05721 }
05722 if (!check_available)
05723 AVAIL_STORE_LIST (ptr) = alloc_INSN_LIST (insn, AVAIL_STORE_LIST (ptr));
05724 }
05725
05726
05727
05728 static int
05729 compute_store_table (void)
05730 {
05731 int ret;
05732 basic_block bb;
05733 unsigned regno;
05734 rtx insn, pat, tmp;
05735 int *last_set_in, *already_set;
05736 struct ls_expr * ptr, **prev_next_ptr_ptr;
05737
05738 max_gcse_regno = max_reg_num ();
05739
05740 reg_set_in_block = sbitmap_vector_alloc (last_basic_block,
05741 max_gcse_regno);
05742 sbitmap_vector_zero (reg_set_in_block, last_basic_block);
05743 pre_ldst_mems = 0;
05744 pre_ldst_table = htab_create (13, pre_ldst_expr_hash,
05745 pre_ldst_expr_eq, NULL);
05746 last_set_in = XCNEWVEC (int, max_gcse_regno);
05747 already_set = XNEWVEC (int, max_gcse_regno);
05748
05749
05750 FOR_EACH_BB (bb)
05751 {
05752
05753 regvec = last_set_in;
05754
05755 FOR_BB_INSNS (bb, insn)
05756 {
05757 if (! INSN_P (insn))
05758 continue;
05759
05760 if (CALL_P (insn))
05761 {
05762 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
05763 if (TEST_HARD_REG_BIT (regs_invalidated_by_call, regno))
05764 {
05765 last_set_in[regno] = INSN_UID (insn);
05766 SET_BIT (reg_set_in_block[bb->index], regno);
05767 }
05768 }
05769
05770 pat = PATTERN (insn);
05771 compute_store_table_current_insn = insn;
05772 note_stores (pat, reg_set_info, reg_set_in_block[bb->index]);
05773 }
05774
05775
05776 memset (already_set, 0, sizeof (int) * max_gcse_regno);
05777 regvec = already_set;
05778 FOR_BB_INSNS (bb, insn)
05779 {
05780 if (! INSN_P (insn))
05781 continue;
05782
05783 if (CALL_P (insn))
05784 {
05785 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
05786 if (TEST_HARD_REG_BIT (regs_invalidated_by_call, regno))
05787 already_set[regno] = 1;
05788 }
05789
05790 pat = PATTERN (insn);
05791 note_stores (pat, reg_set_info, NULL);
05792
05793
05794 find_moveable_store (insn, already_set, last_set_in);
05795
05796
05797 compute_store_table_current_insn = insn;
05798 note_stores (pat, reg_clear_last_set, last_set_in);
05799 if (CALL_P (insn))
05800 {
05801 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
05802 if (TEST_HARD_REG_BIT (regs_invalidated_by_call, regno)
05803 && last_set_in[regno] == INSN_UID (insn))
05804 last_set_in[regno] = 0;
05805 }
05806 }
05807
05808 #ifdef ENABLE_CHECKING
05809
05810 for (regno = 0; regno < max_gcse_regno; regno++)
05811 gcc_assert (!last_set_in[regno]);
05812 #endif
05813
05814
05815 for (ptr = first_ls_expr (); ptr != NULL; ptr = next_ls_expr (ptr))
05816 {
05817 LAST_AVAIL_CHECK_FAILURE(ptr) = NULL_RTX;
05818 if (ANTIC_STORE_LIST (ptr)
05819 && (tmp = XEXP (ANTIC_STORE_LIST (ptr), 0)) == NULL_RTX)
05820 ANTIC_STORE_LIST (ptr) = XEXP (ANTIC_STORE_LIST (ptr), 1);
05821 }
05822 }
05823
05824
05825
05826 for (ptr = pre_ldst_mems, prev_next_ptr_ptr = &pre_ldst_mems;
05827 ptr != NULL;
05828 ptr = *prev_next_ptr_ptr)
05829 {
05830 if (!AVAIL_STORE_LIST (ptr))
05831 {
05832 *prev_next_ptr_ptr = ptr->next;
05833 htab_remove_elt_with_hash (pre_ldst_table, ptr, ptr->hash_index);
05834 free_ldst_entry (ptr);
05835 }
05836 else
05837 prev_next_ptr_ptr = &ptr->next;
05838 }
05839
05840 ret = enumerate_ldsts ();
05841
05842 if (dump_file)
05843 {
05844 fprintf (dump_file, "ST_avail and ST_antic (shown under loads..)\n");
05845 print_ldst_list (dump_file);
05846 }
05847
05848 free (last_set_in);
05849 free (already_set);
05850 return ret;
05851 }
05852
05853
05854
05855
05856
05857 static bool
05858 load_kills_store (rtx x, rtx store_pattern, int after)
05859 {
05860 if (after)
05861 return anti_dependence (x, store_pattern);
05862 else
05863 return true_dependence (store_pattern, GET_MODE (store_pattern), x,
05864 rtx_addr_varies_p);
05865 }
05866
05867
05868
05869
05870
05871
05872 static bool
05873 find_loads (rtx x, rtx store_pattern, int after)
05874 {
05875 const char * fmt;
05876 int i, j;
05877 int ret = false;
05878
05879 if (!x)
05880 return false;
05881
05882 if (GET_CODE (x) == SET)
05883 x = SET_SRC (x);
05884
05885 if (MEM_P (x))
05886 {
05887 if (load_kills_store (x, store_pattern, after))
05888 return true;
05889 }
05890
05891
05892 fmt = GET_RTX_FORMAT (GET_CODE (x));
05893
05894 for (i = GET_RTX_LENGTH (GET_CODE (x)) - 1; i >= 0 && !ret; i--)
05895 {
05896 if (fmt[i] == 'e')
05897 ret |= find_loads (XEXP (x, i), store_pattern, after);
05898 else if (fmt[i] == 'E')
05899 for (j = XVECLEN (x, i) - 1; j >= 0; j--)
05900 ret |= find_loads (XVECEXP (x, i, j), store_pattern, after);
05901 }
05902 return ret;
05903 }
05904
05905
05906
05907
05908
05909 static bool
05910 store_killed_in_insn (rtx x, rtx x_regs, rtx insn, int after)
05911 {
05912 rtx reg, base, note;
05913
05914 if (!INSN_P (insn))
05915 return false;
05916
05917 if (CALL_P (insn))
05918 {
05919
05920
05921 if (! CONST_OR_PURE_CALL_P (insn) || pure_call_p (insn))
05922 return true;
05923
05924
05925
05926 for (reg = x_regs; reg; reg = XEXP (reg, 1))
05927 {
05928 base = find_base_term (XEXP (reg, 0));
05929 if (!base
05930 || (GET_CODE (base) == ADDRESS
05931 && GET_MODE (base) == Pmode
05932 && XEXP (base, 0) == stack_pointer_rtx))
05933 return true;
05934 }
05935
05936 return false;
05937 }
05938
05939 if (GET_CODE (PATTERN (insn)) == SET)
05940 {
05941 rtx pat = PATTERN (insn);
05942 rtx dest = SET_DEST (pat);
05943
05944 if (GET_CODE (dest) == ZERO_EXTRACT)
05945 dest = XEXP (dest, 0);
05946
05947
05948 if (MEM_P (dest)
05949 && !expr_equiv_p (dest, x))
05950 {
05951 if (after)
05952 {
05953 if (output_dependence (dest, x))
05954 return true;
05955 }
05956 else
05957 {
05958 if (output_dependence (x, dest))
05959 return true;
05960 }
05961 }
05962 if (find_loads (SET_SRC (pat), x, after))
05963 return true;
05964 }
05965 else if (find_loads (PATTERN (insn), x, after))
05966 return true;
05967
05968
05969
05970 note = find_reg_equal_equiv_note (insn);
05971 if (! note)
05972 return false;
05973 note = XEXP (note, 0);
05974
05975
05976
05977 if (expr_equiv_p (note, x))
05978 return false;
05979
05980
05981 return find_loads (note, x, after);
05982 }
05983
05984
05985
05986
05987
05988
05989 static bool
05990 store_killed_after (rtx x, rtx x_regs, rtx insn, basic_block bb,
05991 int *regs_set_after, rtx *fail_insn)
05992 {
05993 rtx last = BB_END (bb), act;
05994
05995 if (!store_ops_ok (x_regs, regs_set_after))
05996 {
05997
05998 if (fail_insn)
05999 *fail_insn = NULL_RTX;
06000 return true;
06001 }
06002
06003
06004 for (act = last; act != PREV_INSN (insn); act = PREV_INSN (act))
06005 if (store_killed_in_insn (x, x_regs, act, false))
06006 {
06007 if (fail_insn)
06008 *fail_insn = act;
06009 return true;
06010 }
06011
06012 return false;
06013 }
06014
06015
06016
06017
06018 static bool
06019 store_killed_before (rtx x, rtx x_regs, rtx insn, basic_block bb,
06020 int *regs_set_before)
06021 {
06022 rtx first = BB_HEAD (bb);
06023
06024 if (!store_ops_ok (x_regs, regs_set_before))
06025 return true;
06026
06027 for ( ; insn != PREV_INSN (first); insn = PREV_INSN (insn))
06028 if (store_killed_in_insn (x, x_regs, insn, true))
06029 return true;
06030
06031 return false;
06032 }
06033
06034
06035
06036 static void
06037 build_store_vectors (void)
06038 {
06039 basic_block bb;
06040 int *regs_set_in_block;
06041 rtx insn, st;
06042 struct ls_expr * ptr;
06043 unsigned regno;
06044
06045
06046
06047 ae_gen = sbitmap_vector_alloc (last_basic_block, num_stores);
06048 sbitmap_vector_zero (ae_gen, last_basic_block);
06049
06050 st_antloc = sbitmap_vector_alloc (last_basic_block, num_stores);
06051 sbitmap_vector_zero (st_antloc, last_basic_block);
06052
06053 for (ptr = first_ls_expr (); ptr != NULL; ptr = next_ls_expr (ptr))
06054 {
06055 for (st = AVAIL_STORE_LIST (ptr); st != NULL; st = XEXP (st, 1))
06056 {
06057 insn = XEXP (st, 0);
06058 bb = BLOCK_FOR_INSN (insn);
06059
06060
06061
06062
06063
06064 if (TEST_BIT (ae_gen[bb->index], ptr->index))
06065 {
06066 rtx r = gen_reg_rtx (GET_MODE (ptr->pattern));
06067 if (dump_file)
06068 fprintf (dump_file, "Removing redundant store:\n");
06069 replace_store_insn (r, XEXP (st, 0), bb, ptr);
06070 continue;
06071 }
06072 SET_BIT (ae_gen[bb->index], ptr->index);
06073 }
06074
06075 for (st = ANTIC_STORE_LIST (ptr); st != NULL; st = XEXP (st, 1))
06076 {
06077 insn = XEXP (st, 0);
06078 bb = BLOCK_FOR_INSN (insn);
06079 SET_BIT (st_antloc[bb->index], ptr->index);
06080 }
06081 }
06082
06083 ae_kill = sbitmap_vector_alloc (last_basic_block, num_stores);
06084 sbitmap_vector_zero (ae_kill, last_basic_block);
06085
06086 transp = sbitmap_vector_alloc (last_basic_block, num_stores);
06087 sbitmap_vector_zero (transp, last_basic_block);
06088 regs_set_in_block = XNEWVEC (int, max_gcse_regno);
06089
06090 FOR_EACH_BB (bb)
06091 {
06092 for (regno = 0; regno < max_gcse_regno; regno++)
06093 regs_set_in_block[regno] = TEST_BIT (reg_set_in_block[bb->index], regno);
06094
06095 for (ptr = first_ls_expr (); ptr != NULL; ptr = next_ls_expr (ptr))
06096 {
06097 if (store_killed_after (ptr->pattern, ptr->pattern_regs, BB_HEAD (bb),
06098 bb, regs_set_in_block, NULL))
06099 {
06100
06101
06102 if (!TEST_BIT (st_antloc[bb->index], ptr->index)
06103 || !TEST_BIT (ae_gen[bb->index], ptr->index))
06104 SET_BIT (ae_kill[bb->index], ptr->index);
06105 }
06106 else
06107 SET_BIT (transp[bb->index], ptr->index);
06108 }
06109 }
06110
06111 free (regs_set_in_block);
06112
06113 if (dump_file)
06114 {
06115 dump_sbitmap_vector (dump_file, "st_antloc", "", st_antloc, last_basic_block);
06116 dump_sbitmap_vector (dump_file, "st_kill", "", ae_kill, last_basic_block);
06117 dump_sbitmap_vector (dump_file, "Transpt", "", transp, last_basic_block);
06118 dump_sbitmap_vector (dump_file, "st_avloc", "", ae_gen, last_basic_block);
06119 }
06120 }
06121
06122
06123
06124
06125 static void
06126 insert_insn_start_bb (rtx insn, basic_block bb)
06127 {
06128
06129 rtx prev = PREV_INSN (BB_HEAD (bb));
06130 rtx before = BB_HEAD (bb);
06131 while (before != 0)
06132 {
06133 if (! LABEL_P (before)
06134 && (! NOTE_P (before)
06135 || NOTE_LINE_NUMBER (before) != NOTE_INSN_BASIC_BLOCK))
06136 break;
06137 prev = before;
06138 if (prev == BB_END (bb))
06139 break;
06140 before = NEXT_INSN (before);
06141 }
06142
06143 insn = emit_insn_after_noloc (insn, prev);
06144
06145 if (dump_file)
06146 {
06147 fprintf (dump_file, "STORE_MOTION insert store at start of BB %d:\n",
06148 bb->index);
06149 print_inline_rtx (dump_file, insn, 6);
06150 fprintf (dump_file, "\n");
06151 }
06152 }
06153
06154
06155
06156
06157
06158 static int
06159 insert_store (struct ls_expr * expr, edge e)
06160 {
06161 rtx reg, insn;
06162 basic_block bb;
06163 edge tmp;
06164 edge_iterator ei;
06165
06166
06167
06168 if (expr->reaching_reg == NULL_RTX)
06169 return 0;
06170
06171 if (e->flags & EDGE_FAKE)
06172 return 0;
06173
06174 reg = expr->reaching_reg;
06175 insn = gen_move_insn (copy_rtx (expr->pattern), reg);
06176
06177
06178
06179
06180 bb = e->dest;
06181 FOR_EACH_EDGE (tmp, ei, e->dest->preds)
06182 if (!(tmp->flags & EDGE_FAKE))
06183 {
06184 int index = EDGE_INDEX (edge_list, tmp->src, tmp->dest);
06185
06186 gcc_assert (index != EDGE_INDEX_NO_EDGE);
06187 if (! TEST_BIT (pre_insert_map[index], expr->index))
06188 break;
06189 }
06190
06191
06192
06193 if (!tmp && bb != EXIT_BLOCK_PTR)
06194 {
06195 FOR_EACH_EDGE (tmp, ei, e->dest->preds)
06196 {
06197 int index = EDGE_INDEX (edge_list, tmp->src, tmp->dest);
06198 RESET_BIT (pre_insert_map[index], expr->index);
06199 }
06200 insert_insn_start_bb (insn, bb);
06201 return 0;
06202 }
06203
06204
06205
06206 gcc_assert (!(e->flags & EDGE_ABNORMAL));
06207
06208 insert_insn_on_edge (insn, e);
06209
06210 if (dump_file)
06211 {
06212 fprintf (dump_file, "STORE_MOTION insert insn on edge (%d, %d):\n",
06213 e->src->index, e->dest->index);
06214 print_inline_rtx (dump_file, insn, 6);
06215 fprintf (dump_file, "\n");
06216 }
06217
06218 return 1;
06219 }
06220
06221
06222
06223
06224
06225
06226 static void
06227 remove_reachable_equiv_notes (basic_block bb, struct ls_expr *smexpr)
06228 {
06229 edge_iterator *stack, ei;
06230 int sp;
06231 edge act;
06232 sbitmap visited = sbitmap_alloc (last_basic_block);
06233 rtx last, insn, note;
06234 rtx mem = smexpr->pattern;
06235
06236 stack = XNEWVEC (edge_iterator, n_basic_blocks);
06237 sp = 0;
06238 ei = ei_start (bb->succs);
06239
06240 sbitmap_zero (visited);
06241
06242 act = (EDGE_COUNT (ei_container (ei)) > 0 ? EDGE_I (ei_container (ei), 0) : NULL);
06243 while (1)
06244 {
06245 if (!act)
06246 {
06247 if (!sp)
06248 {
06249 free (stack);
06250 sbitmap_free (visited);
06251 return;
06252 }
06253 act = ei_edge (stack[--sp]);
06254 }
06255 bb = act->dest;
06256
06257 if (bb == EXIT_BLOCK_PTR
06258 || TEST_BIT (visited, bb->index))
06259 {
06260 if (!ei_end_p (ei))
06261 ei_next (&ei);
06262 act = (! ei_end_p (ei)) ? ei_edge (ei) : NULL;
06263 continue;
06264 }
06265 SET_BIT (visited, bb->index);
06266
06267 if (TEST_BIT (st_antloc[bb->index], smexpr->index))
06268 {
06269 for (last = ANTIC_STORE_LIST (smexpr);
06270 BLOCK_FOR_INSN (XEXP (last, 0)) != bb;
06271 last = XEXP (last, 1))
06272 continue;
06273 last = XEXP (last, 0);
06274 }
06275 else
06276 last = NEXT_INSN (BB_END (bb));
06277
06278 for (insn = BB_HEAD (bb); insn != last; insn = NEXT_INSN (insn))
06279 if (INSN_P (insn))
06280 {
06281 note = find_reg_equal_equiv_note (insn);
06282 if (!note || !expr_equiv_p (XEXP (note, 0), mem))
06283 continue;
06284
06285 if (dump_file)
06286 fprintf (dump_file, "STORE_MOTION drop REG_EQUAL note at insn %d:\n",
06287 INSN_UID (insn));
06288 remove_note (insn, note);
06289 }
06290
06291 if (!ei_end_p (ei))
06292 ei_next (&ei);
06293 act = (! ei_end_p (ei)) ? ei_edge (ei) : NULL;
06294
06295 if (EDGE_COUNT (bb->succs) > 0)
06296 {
06297 if (act)
06298 stack[sp++] = ei;
06299 ei = ei_start (bb->succs);
06300 act = (EDGE_COUNT (ei_container (ei)) > 0 ? EDGE_I (ei_container (ei), 0) : NULL);
06301 }
06302 }
06303 }
06304
06305
06306
06307 static void
06308 replace_store_insn (rtx reg, rtx del, basic_block bb, struct ls_expr *smexpr)
06309 {
06310 rtx insn, mem, note, set, ptr, pair;
06311
06312 mem = smexpr->pattern;
06313 insn = gen_move_insn (reg, SET_SRC (single_set (del)));
06314 insn = emit_insn_after (insn, del);
06315
06316 if (dump_file)
06317 {
06318 fprintf (dump_file,
06319 "STORE_MOTION delete insn in BB %d:\n ", bb->index);
06320 print_inline_rtx (dump_file, del, 6);
06321 fprintf (dump_file, "\nSTORE MOTION replaced with insn:\n ");
06322 print_inline_rtx (dump_file, insn, 6);
06323 fprintf (dump_file, "\n");
06324 }
06325
06326 for (ptr = ANTIC_STORE_LIST (smexpr); ptr; ptr = XEXP (ptr, 1))
06327 if (XEXP (ptr, 0) == del)
06328 {
06329 XEXP (ptr, 0) = insn;
06330 break;
06331 }
06332
06333
06334
06335 REG_NOTES (insn) = REG_NOTES (del);
06336
06337 note = find_reg_note (insn, REG_RETVAL, NULL_RTX);
06338 if (note)
06339 {
06340 pair = XEXP (note, 0);
06341 note = find_reg_note (pair, REG_LIBCALL, NULL_RTX);
06342 XEXP (note, 0) = insn;
06343 }
06344 note = find_reg_note (insn, REG_LIBCALL, NULL_RTX);
06345 if (note)
06346 {
06347 pair = XEXP (note, 0);
06348 note = find_reg_note (pair, REG_RETVAL, NULL_RTX);
06349 XEXP (note, 0) = insn;
06350 }
06351
06352 delete_insn (del);
06353
06354
06355
06356
06357 for (; insn != NEXT_INSN (BB_END (bb)); insn = NEXT_INSN (insn))
06358 if (INSN_P (insn))
06359 {
06360 set = single_set (insn);
06361 if (!set)
06362 continue;
06363 if (expr_equiv_p (SET_DEST (set), mem))
06364 return;
06365 note = find_reg_equal_equiv_note (insn);
06366 if (!note || !expr_equiv_p (XEXP (note, 0), mem))
06367 continue;
06368
06369 if (dump_file)
06370 fprintf (dump_file, "STORE_MOTION drop REG_EQUAL note at insn %d:\n",
06371 INSN_UID (insn));
06372 remove_note (insn, note);
06373 }
06374 remove_reachable_equiv_notes (bb, smexpr);
06375 }
06376
06377
06378
06379
06380
06381 static void
06382 delete_store (struct ls_expr * expr, basic_block bb)
06383 {
06384 rtx reg, i, del;
06385
06386 if (expr->reaching_reg == NULL_RTX)
06387 expr->reaching_reg = gen_reg_rtx (GET_MODE (expr->pattern));
06388
06389 reg = expr->reaching_reg;
06390
06391 for (i = AVAIL_STORE_LIST (expr); i; i = XEXP (i, 1))
06392 {
06393 del = XEXP (i, 0);
06394 if (BLOCK_FOR_INSN (del) == bb)
06395 {
06396
06397
06398 replace_store_insn (reg, del, bb, expr);
06399 break;
06400 }
06401 }
06402 }
06403
06404
06405
06406 static void
06407 free_store_memory (void)
06408 {
06409 free_ldst_mems ();
06410
06411 if (ae_gen)
06412 sbitmap_vector_free (ae_gen);
06413 if (ae_kill)
06414 sbitmap_vector_free (ae_kill);
06415 if (transp)
06416 sbitmap_vector_free (transp);
06417 if (st_antloc)
06418 sbitmap_vector_free (st_antloc);
06419 if (pre_insert_map)
06420 sbitmap_vector_free (pre_insert_map);
06421 if (pre_delete_map)
06422 sbitmap_vector_free (pre_delete_map);
06423 if (reg_set_in_block)
06424 sbitmap_vector_free (reg_set_in_block);
06425
06426 ae_gen = ae_kill = transp = st_antloc = NULL;
06427 pre_insert_map = pre_delete_map = reg_set_in_block = NULL;
06428 }
06429
06430
06431
06432
06433 static void
06434 store_motion (void)
06435 {
06436 basic_block bb;
06437 int x;
06438 struct ls_expr * ptr;
06439 int update_flow = 0;
06440
06441 if (dump_file)
06442 {
06443 fprintf (dump_file, "before store motion\n");
06444 print_rtl (dump_file, get_insns ());
06445 }
06446
06447 init_alias_analysis ();
06448
06449
06450 num_stores = compute_store_table ();
06451 if (num_stores == 0)
06452 {
06453 htab_delete (pre_ldst_table);
06454 pre_ldst_table = NULL;
06455 sbitmap_vector_free (reg_set_in_block);
06456 end_alias_analysis ();
06457 return;
06458 }
06459
06460
06461 build_store_vectors ();
06462 add_noreturn_fake_exit_edges ();
06463 connect_infinite_loops_to_exit ();
06464
06465 edge_list = pre_edge_rev_lcm (num_stores, transp, ae_gen,
06466 st_antloc, ae_kill, &pre_insert_map,
06467 &pre_delete_map);
06468
06469
06470 for (ptr = first_ls_expr (); ptr != NULL; ptr = next_ls_expr (ptr))
06471 {
06472
06473
06474 for (x = NUM_EDGES (edge_list) - 1; x >= 0; x--)
06475 if (TEST_BIT (pre_insert_map[x], ptr->index)
06476 && (INDEX_EDGE (edge_list, x)->flags & EDGE_ABNORMAL))
06477 break;
06478
06479 if (x >= 0)
06480 {
06481 if (dump_file != NULL)
06482 fprintf (dump_file,
06483 "Can't replace store %d: abnormal edge from %d to %d\n",
06484 ptr->index, INDEX_EDGE (edge_list, x)->src->index,
06485 INDEX_EDGE (edge_list, x)->dest->index);
06486 continue;
06487 }
06488
06489
06490
06491 FOR_EACH_BB (bb)
06492 if (TEST_BIT (pre_delete_map[bb->index], ptr->index))
06493 delete_store (ptr, bb);
06494
06495 for (x = 0; x < NUM_EDGES (edge_list); x++)
06496 if (TEST_BIT (pre_insert_map[x], ptr->index))
06497 update_flow |= insert_store (ptr, INDEX_EDGE (edge_list, x));
06498 }
06499
06500 if (update_flow)
06501 commit_edge_insertions ();
06502
06503 free_store_memory ();
06504 free_edge_list (edge_list);
06505 remove_fake_exit_edges ();
06506 end_alias_analysis ();
06507 }
06508
06509
06510
06511
06512 static int
06513 bypass_jumps (void)
06514 {
06515 int changed;
06516
06517
06518
06519 if (current_function_calls_setjmp)
06520 return 0;
06521
06522
06523
06524 max_gcse_regno = max_reg_num ();
06525
06526 if (dump_file)
06527 dump_flow_info (dump_file, dump_flags);
06528
06529
06530 if (n_basic_blocks <= NUM_FIXED_BLOCKS + 1
06531 || is_too_expensive (_ ("jump bypassing disabled")))
06532 return 0;
06533
06534 gcc_obstack_init (&gcse_obstack);
06535 bytes_used = 0;
06536
06537
06538 init_alias_analysis ();
06539
06540
06541
06542
06543
06544
06545
06546
06547
06548
06549 alloc_reg_set_mem (max_gcse_regno);
06550 compute_sets ();
06551
06552 max_gcse_regno = max_reg_num ();
06553 alloc_gcse_mem ();
06554 changed = one_cprop_pass (MAX_GCSE_PASSES + 2, true, true);
06555 free_gcse_mem ();
06556
06557 if (dump_file)
06558 {
06559 fprintf (dump_file, "BYPASS of %s: %d basic blocks, ",
06560 current_function_name (), n_basic_blocks);
06561 fprintf (dump_file, "%d bytes\n\n", bytes_used);
06562 }
06563
06564 obstack_free (&gcse_obstack, NULL);
06565 free_reg_set_mem ();
06566
06567
06568 end_alias_analysis ();
06569 allocate_reg_info (max_reg_num (), FALSE, FALSE);
06570
06571 return changed;
06572 }
06573
06574
06575
06576
06577 static bool
06578 is_too_expensive (const char *pass)
06579 {
06580
06581
06582
06583
06584
06585
06586
06587
06588
06589 if (n_edges > 20000 + n_basic_blocks * 4)
06590 {
06591 warning (OPT_Wdisabled_optimization,
06592 "%s: %d basic blocks and %d edges/basic block",
06593 pass, n_basic_blocks, n_edges / n_basic_blocks);
06594
06595 return true;
06596 }
06597
06598
06599
06600 if ((n_basic_blocks
06601 * SBITMAP_SET_SIZE (max_reg_num ())
06602 * sizeof (SBITMAP_ELT_TYPE)) > MAX_GCSE_MEMORY)
06603 {
06604 warning (OPT_Wdisabled_optimization,
06605 "%s: %d basic blocks and %d registers",
06606 pass, n_basic_blocks, max_reg_num ());
06607
06608 return true;
06609 }
06610
06611 return false;
06612 }
06613
06614 static bool
06615 gate_handle_jump_bypass (void)
06616 {
06617 return optimize > 0 && flag_gcse;
06618 }
06619
06620
06621 static unsigned int
06622 rest_of_handle_jump_bypass (void)
06623 {
06624 cleanup_cfg (CLEANUP_EXPENSIVE);
06625 reg_scan (get_insns (), max_reg_num ());
06626
06627 if (bypass_jumps ())
06628 {
06629 rebuild_jump_labels (get_insns ());
06630 cleanup_cfg (CLEANUP_EXPENSIVE);
06631 delete_trivially_dead_insns (get_insns (), max_reg_num ());
06632 }
06633 return 0;
06634 }
06635
06636 struct tree_opt_pass pass_jump_bypass =
06637 {
06638 "bypass",
06639 gate_handle_jump_bypass,
06640 rest_of_handle_jump_bypass,
06641 NULL,
06642 NULL,
06643 0,
06644 TV_BYPASS,
06645 0,
06646 0,
06647 0,
06648 0,
06649 TODO_dump_func |
06650 TODO_ggc_collect | TODO_verify_flow,
06651 'G'
06652 };
06653
06654
06655 static bool
06656 gate_handle_gcse (void)
06657 {
06658 return optimize > 0 && flag_gcse;
06659 }
06660
06661
06662 static unsigned int
06663 rest_of_handle_gcse (void)
06664 {
06665 int save_csb, save_cfj;
06666 int tem2 = 0, tem;
06667
06668 tem = gcse_main (get_insns ());
06669 rebuild_jump_labels (get_insns ());
06670 delete_trivially_dead_insns (get_insns (), max_reg_num ());
06671
06672 save_csb = flag_cse_skip_blocks;
06673 save_cfj = flag_cse_follow_jumps;
06674 flag_cse_skip_blocks = flag_cse_follow_jumps = 0;
06675
06676
06677
06678 if (flag_expensive_optimizations)
06679 {
06680 timevar_push (TV_CSE);
06681 reg_scan (get_insns (), max_reg_num ());
06682 tem2 = cse_main (get_insns (), max_reg_num ());
06683 purge_all_dead_edges ();
06684 delete_trivially_dead_insns (get_insns (), max_reg_num ());
06685 timevar_pop (TV_CSE);
06686 cse_not_expected = !flag_rerun_cse_after_loop;
06687 }
06688
06689
06690
06691 if (tem || tem2)
06692 {
06693 timevar_push (TV_JUMP);
06694 rebuild_jump_labels (get_insns ());
06695 delete_dead_jumptables ();
06696 cleanup_cfg (CLEANUP_EXPENSIVE);
06697 timevar_pop (TV_JUMP);
06698 }
06699
06700 flag_cse_skip_blocks = save_csb;
06701 flag_cse_follow_jumps = save_cfj;
06702 return 0;
06703 }
06704
06705 struct tree_opt_pass pass_gcse =
06706 {
06707 "gcse1",
06708 gate_handle_gcse,
06709 rest_of_handle_gcse,
06710 NULL,
06711 NULL,
06712 0,
06713 TV_GCSE,
06714 0,
06715 0,
06716 0,
06717 0,
06718 TODO_dump_func |
06719 TODO_verify_flow | TODO_ggc_collect,
06720 'G'
06721 };
06722
06723
06724 #include "gt-gcse.h"