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