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