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