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