00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046 #include "config.h"
00047 #include "system.h"
00048 #include "coretypes.h"
00049 #include "tm.h"
00050 #include "rtl.h"
00051 #include "tm_p.h"
00052 #include "function.h"
00053 #include "expr.h"
00054 #include "hard-reg-set.h"
00055 #include "basic-block.h"
00056 #include "insn-config.h"
00057 #include "regs.h"
00058 #include "recog.h"
00059 #include "flags.h"
00060 #include "real.h"
00061 #include "cselib.h"
00062 #include "except.h"
00063 #include "toplev.h"
00064 #include "predict.h"
00065 #include "insn-flags.h"
00066 #include "optabs.h"
00067 #include "cfgloop.h"
00068 #include "ggc.h"
00069
00070
00071 #define LOOP_INFO(LOOP) ((struct loop_info *) (LOOP)->aux)
00072
00073
00074 #define LOOP_MOVABLES(LOOP) (&LOOP_INFO (LOOP)->movables)
00075
00076
00077 #define LOOP_REGS(LOOP) (&LOOP_INFO (LOOP)->regs)
00078
00079
00080 #define LOOP_IVS(LOOP) (&LOOP_INFO (LOOP)->ivs)
00081
00082
00083
00084
00085 #define INSN_LUID(INSN) \
00086 (INSN_UID (INSN) < max_uid_for_loop ? uid_luid[INSN_UID (INSN)] \
00087 : (abort (), -1))
00088
00089 #define REGNO_FIRST_LUID(REGNO) \
00090 (REGNO_FIRST_UID (REGNO) < max_uid_for_loop \
00091 ? uid_luid[REGNO_FIRST_UID (REGNO)] \
00092 : 0)
00093 #define REGNO_LAST_LUID(REGNO) \
00094 (REGNO_LAST_UID (REGNO) < max_uid_for_loop \
00095 ? uid_luid[REGNO_LAST_UID (REGNO)] \
00096 : INT_MAX)
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108 enum g_types
00109 {
00110 DEST_ADDR,
00111 DEST_REG
00112 };
00113
00114
00115
00116
00117
00118 struct induction
00119 {
00120 rtx insn;
00121 rtx new_reg;
00122
00123 rtx src_reg;
00124
00125 enum g_types giv_type;
00126 rtx dest_reg;
00127
00128
00129
00130 rtx *location;
00131
00132
00133
00134 enum machine_mode mode;
00135 rtx mem;
00136 rtx mult_val;
00137 rtx add_val;
00138 int benefit;
00139 rtx final_value;
00140
00141
00142
00143 unsigned combined_with;
00144
00145
00146 unsigned replaceable : 1;
00147
00148
00149
00150
00151 unsigned not_replaceable : 1;
00152
00153
00154
00155
00156
00157 unsigned ignore : 1;
00158 unsigned always_computable : 1;
00159
00160 unsigned always_executed : 1;
00161 unsigned maybe_multiple : 1;
00162
00163
00164 unsigned cant_derive : 1;
00165
00166
00167
00168 unsigned maybe_dead : 1;
00169
00170
00171 unsigned auto_inc_opt : 1;
00172
00173 unsigned shared : 1;
00174 unsigned no_const_addval : 1;
00175 int lifetime;
00176 rtx derive_adjustment;
00177
00178
00179
00180 rtx ext_dependent;
00181
00182 struct induction *next_iv;
00183
00184
00185
00186 struct induction *same;
00187
00188
00189
00190
00191
00192 struct induction *same_insn;
00193
00194
00195
00196 rtx last_use;
00197
00198 };
00199
00200
00201
00202
00203 struct iv_class
00204 {
00205 unsigned int regno;
00206 int biv_count;
00207 struct induction *biv;
00208 int giv_count;
00209
00210
00211 struct induction *giv;
00212
00213 int total_benefit;
00214 rtx initial_value;
00215 rtx initial_test;
00216 rtx final_value;
00217 struct iv_class *next;
00218 rtx init_insn;
00219 rtx init_set;
00220 unsigned incremented : 1;
00221 unsigned eliminable : 1;
00222
00223 unsigned nonneg : 1;
00224
00225 unsigned reversed : 1;
00226
00227 unsigned all_reduced : 1;
00228
00229 };
00230
00231
00232
00233 enum iv_mode
00234 {
00235 UNKNOWN_INDUCT,
00236 BASIC_INDUCT,
00237 NOT_BASIC_INDUCT,
00238 GENERAL_INDUCT
00239 };
00240
00241
00242
00243
00244 struct iv
00245 {
00246 enum iv_mode type;
00247 union
00248 {
00249 struct iv_class *class;
00250 struct induction *info;
00251 } iv;
00252 };
00253
00254
00255 #define REG_IV_TYPE(ivs, n) ivs->regs[n].type
00256 #define REG_IV_INFO(ivs, n) ivs->regs[n].iv.info
00257 #define REG_IV_CLASS(ivs, n) ivs->regs[n].iv.class
00258
00259
00260 struct loop_ivs
00261 {
00262
00263
00264 struct iv *regs;
00265
00266
00267 unsigned int n_regs;
00268
00269
00270
00271 struct iv_class *list;
00272 };
00273
00274
00275 typedef struct loop_mem_info
00276 {
00277 rtx mem;
00278 rtx reg;
00279 int optimize;
00280 } loop_mem_info;
00281
00282
00283
00284 struct loop_reg
00285 {
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296 int set_in_loop;
00297
00298
00299
00300
00301 int n_times_set;
00302
00303
00304
00305 rtx single_usage;
00306
00307
00308
00309 char may_not_optimize;
00310
00311
00312
00313 char moved_once;
00314 };
00315
00316
00317 struct loop_regs
00318 {
00319 int num;
00320 int size;
00321 struct loop_reg *array;
00322 int multiple_uses;
00323 };
00324
00325
00326
00327 struct loop_movables
00328 {
00329
00330 struct movable *head;
00331
00332 struct movable *last;
00333 };
00334
00335
00336
00337
00338 struct loop_info
00339 {
00340
00341 int has_call;
00342
00343 int has_libcall;
00344
00345 int has_nonconst_call;
00346
00347 int has_prefetch;
00348
00349
00350 int has_volatile;
00351
00352 int has_tablejump;
00353
00354
00355 int has_multiple_exit_targets;
00356
00357 int has_indirect_jump;
00358
00359 rtx initial_value;
00360
00361 rtx comparison_value;
00362
00363 rtx final_value;
00364
00365
00366 rtx initial_equiv_value;
00367
00368
00369 rtx final_equiv_value;
00370
00371 rtx iteration_var;
00372
00373 rtx increment;
00374 enum rtx_code comparison_code;
00375
00376
00377
00378
00379
00380 unsigned HOST_WIDE_INT n_iterations;
00381 int used_count_register;
00382
00383 struct iv_class *iv;
00384
00385 rtx store_mems;
00386
00387
00388
00389
00390
00391 loop_mem_info *mems;
00392
00393 int mems_idx;
00394
00395 int mems_allocated;
00396
00397
00398
00399
00400 int unknown_address_altered;
00401
00402
00403 int unknown_constant_address_altered;
00404
00405 int num_mem_sets;
00406
00407 rtx first_loop_store_insn;
00408
00409 struct loop_movables movables;
00410
00411 struct loop_regs regs;
00412
00413 struct loop_ivs ivs;
00414
00415 int pre_header_has_call;
00416 };
00417
00418
00419 #ifndef SIMULTANEOUS_PREFETCHES
00420 #define SIMULTANEOUS_PREFETCHES 3
00421 #endif
00422 #ifndef PREFETCH_BLOCK
00423 #define PREFETCH_BLOCK 32
00424 #endif
00425 #ifndef HAVE_prefetch
00426 #define HAVE_prefetch 0
00427 #define CODE_FOR_prefetch 0
00428 #define gen_prefetch(a,b,c) (abort(), NULL_RTX)
00429 #endif
00430
00431
00432
00433
00434 #define MAX_PREFETCHES 100
00435
00436
00437 #define PREFETCH_BLOCKS_BEFORE_LOOP_MAX 6
00438
00439
00440 #define PREFETCH_BLOCKS_BEFORE_LOOP_MIN 2
00441
00442
00443
00444
00445
00446
00447 #ifndef PREFETCH_ONLY_DENSE_MEM
00448 #define PREFETCH_ONLY_DENSE_MEM 1
00449 #endif
00450
00451
00452
00453 #ifndef PREFETCH_DENSE_MEM
00454 #define PREFETCH_DENSE_MEM 220
00455 #endif
00456
00457
00458 #ifndef PREFETCH_NO_LOW_LOOPCNT
00459 #define PREFETCH_NO_LOW_LOOPCNT 1
00460 #endif
00461
00462
00463 #ifndef PREFETCH_LOW_LOOPCNT
00464 #define PREFETCH_LOW_LOOPCNT 32
00465 #endif
00466
00467
00468
00469 #ifndef PREFETCH_NO_CALL
00470 #define PREFETCH_NO_CALL 1
00471 #endif
00472
00473
00474 #ifndef PREFETCH_NO_EXTREME_STRIDE
00475 #define PREFETCH_NO_EXTREME_STRIDE 1
00476 #endif
00477
00478
00479 #ifndef PREFETCH_EXTREME_STRIDE
00480 #define PREFETCH_EXTREME_STRIDE 4096
00481 #endif
00482
00483
00484
00485 #ifndef PREFETCH_EXTREME_DIFFERENCE
00486 #define PREFETCH_EXTREME_DIFFERENCE 4096
00487 #endif
00488
00489
00490
00491 #ifndef PREFETCH_BEFORE_LOOP
00492 #define PREFETCH_BEFORE_LOOP 1
00493 #endif
00494
00495
00496 #ifndef PREFETCH_NO_REVERSE_ORDER
00497 #define PREFETCH_NO_REVERSE_ORDER 1
00498 #endif
00499
00500
00501 #ifndef PREFETCH_CONDITIONAL
00502 #define PREFETCH_CONDITIONAL 1
00503 #endif
00504
00505 #define LOOP_REG_LIFETIME(LOOP, REGNO) \
00506 ((REGNO_LAST_LUID (REGNO) - REGNO_FIRST_LUID (REGNO)))
00507
00508 #define LOOP_REG_GLOBAL_P(LOOP, REGNO) \
00509 ((REGNO_LAST_LUID (REGNO) > INSN_LUID ((LOOP)->end) \
00510 || REGNO_FIRST_LUID (REGNO) < INSN_LUID ((LOOP)->start)))
00511
00512 #define LOOP_REGNO_NREGS(REGNO, SET_DEST) \
00513 ((REGNO) < FIRST_PSEUDO_REGISTER \
00514 ? (int) hard_regno_nregs[(REGNO)][GET_MODE (SET_DEST)] : 1)
00515
00516
00517
00518
00519
00520
00521 static int *uid_luid;
00522
00523
00524
00525
00526 static struct loop **uid_loop;
00527
00528
00529
00530 static int max_uid_for_loop;
00531
00532
00533
00534
00535 static int max_loop_num;
00536
00537
00538
00539 static unsigned int max_reg_before_loop;
00540
00541
00542 static int loop_max_reg;
00543
00544
00545
00546
00547
00548 struct movable
00549 {
00550 rtx insn;
00551 rtx set_src;
00552 rtx set_dest;
00553 rtx dependencies;
00554
00555 int consec;
00556
00557 unsigned int regno;
00558 short lifetime;
00559
00560
00561 short savings;
00562
00563
00564 ENUM_BITFIELD(machine_mode) savemode : 8;
00565
00566
00567 unsigned int cond : 1;
00568 unsigned int force : 1;
00569 unsigned int global : 1;
00570
00571
00572
00573 unsigned int done : 1;
00574
00575 unsigned int partial : 1;
00576
00577
00578 unsigned int move_insn : 1;
00579
00580 unsigned int move_insn_first:1;
00581
00582 unsigned int is_equiv : 1;
00583 unsigned int insert_temp : 1;
00584
00585
00586 struct movable *match;
00587 struct movable *forces;
00588 struct movable *next;
00589 };
00590
00591
00592 static FILE *loop_dump_stream;
00593
00594
00595
00596 static void invalidate_loops_containing_label (rtx);
00597 static void find_and_verify_loops (rtx, struct loops *);
00598 static void mark_loop_jump (rtx, struct loop *);
00599 static void prescan_loop (struct loop *);
00600 static int reg_in_basic_block_p (rtx, rtx);
00601 static int consec_sets_invariant_p (const struct loop *, rtx, int, rtx);
00602 static int labels_in_range_p (rtx, int);
00603 static void count_one_set (struct loop_regs *, rtx, rtx, rtx *);
00604 static void note_addr_stored (rtx, rtx, void *);
00605 static void note_set_pseudo_multiple_uses (rtx, rtx, void *);
00606 static int loop_reg_used_before_p (const struct loop *, rtx, rtx);
00607 static rtx find_regs_nested (rtx, rtx);
00608 static void scan_loop (struct loop*, int);
00609 #if 0
00610 static void replace_call_address (rtx, rtx, rtx);
00611 #endif
00612 static rtx skip_consec_insns (rtx, int);
00613 static int libcall_benefit (rtx);
00614 static rtx libcall_other_reg (rtx, rtx);
00615 static void record_excess_regs (rtx, rtx, rtx *);
00616 static void ignore_some_movables (struct loop_movables *);
00617 static void force_movables (struct loop_movables *);
00618 static void combine_movables (struct loop_movables *, struct loop_regs *);
00619 static int num_unmoved_movables (const struct loop *);
00620 static int regs_match_p (rtx, rtx, struct loop_movables *);
00621 static int rtx_equal_for_loop_p (rtx, rtx, struct loop_movables *,
00622 struct loop_regs *);
00623 static void add_label_notes (rtx, rtx);
00624 static void move_movables (struct loop *loop, struct loop_movables *, int,
00625 int);
00626 static void loop_movables_add (struct loop_movables *, struct movable *);
00627 static void loop_movables_free (struct loop_movables *);
00628 static int count_nonfixed_reads (const struct loop *, rtx);
00629 static void loop_bivs_find (struct loop *);
00630 static void loop_bivs_init_find (struct loop *);
00631 static void loop_bivs_check (struct loop *);
00632 static void loop_givs_find (struct loop *);
00633 static void loop_givs_check (struct loop *);
00634 static int loop_biv_eliminable_p (struct loop *, struct iv_class *, int, int);
00635 static int loop_giv_reduce_benefit (struct loop *, struct iv_class *,
00636 struct induction *, rtx);
00637 static void loop_givs_dead_check (struct loop *, struct iv_class *);
00638 static void loop_givs_reduce (struct loop *, struct iv_class *);
00639 static void loop_givs_rescan (struct loop *, struct iv_class *, rtx *);
00640 static void loop_ivs_free (struct loop *);
00641 static void strength_reduce (struct loop *, int);
00642 static void find_single_use_in_loop (struct loop_regs *, rtx, rtx);
00643 static int valid_initial_value_p (rtx, rtx, int, rtx);
00644 static void find_mem_givs (const struct loop *, rtx, rtx, int, int);
00645 static void record_biv (struct loop *, struct induction *, rtx, rtx, rtx,
00646 rtx, rtx *, int, int);
00647 static void check_final_value (const struct loop *, struct induction *);
00648 static void loop_ivs_dump (const struct loop *, FILE *, int);
00649 static void loop_iv_class_dump (const struct iv_class *, FILE *, int);
00650 static void loop_biv_dump (const struct induction *, FILE *, int);
00651 static void loop_giv_dump (const struct induction *, FILE *, int);
00652 static void record_giv (const struct loop *, struct induction *, rtx, rtx,
00653 rtx, rtx, rtx, rtx, int, enum g_types, int, int,
00654 rtx *);
00655 static void update_giv_derive (const struct loop *, rtx);
00656 static HOST_WIDE_INT get_monotonic_increment (struct iv_class *);
00657 static bool biased_biv_fits_mode_p (const struct loop *, struct iv_class *,
00658 HOST_WIDE_INT, enum machine_mode,
00659 unsigned HOST_WIDE_INT);
00660 static bool biv_fits_mode_p (const struct loop *, struct iv_class *,
00661 HOST_WIDE_INT, enum machine_mode, bool);
00662 static bool extension_within_bounds_p (const struct loop *, struct iv_class *,
00663 HOST_WIDE_INT, rtx);
00664 static void check_ext_dependent_givs (const struct loop *, struct iv_class *);
00665 static int basic_induction_var (const struct loop *, rtx, enum machine_mode,
00666 rtx, rtx, rtx *, rtx *, rtx **);
00667 static rtx simplify_giv_expr (const struct loop *, rtx, rtx *, int *);
00668 static int general_induction_var (const struct loop *loop, rtx, rtx *, rtx *,
00669 rtx *, rtx *, int, int *, enum machine_mode);
00670 static int consec_sets_giv (const struct loop *, int, rtx, rtx, rtx, rtx *,
00671 rtx *, rtx *, rtx *);
00672 static int check_dbra_loop (struct loop *, int);
00673 static rtx express_from_1 (rtx, rtx, rtx);
00674 static rtx combine_givs_p (struct induction *, struct induction *);
00675 static int cmp_combine_givs_stats (const void *, const void *);
00676 static void combine_givs (struct loop_regs *, struct iv_class *);
00677 static int product_cheap_p (rtx, rtx);
00678 static int maybe_eliminate_biv (const struct loop *, struct iv_class *, int,
00679 int, int);
00680 static int maybe_eliminate_biv_1 (const struct loop *, rtx, rtx,
00681 struct iv_class *, int, basic_block, rtx);
00682 static int last_use_this_basic_block (rtx, rtx);
00683 static void record_initial (rtx, rtx, void *);
00684 static void update_reg_last_use (rtx, rtx);
00685 static rtx next_insn_in_loop (const struct loop *, rtx);
00686 static void loop_regs_scan (const struct loop *, int);
00687 static int count_insns_in_loop (const struct loop *);
00688 static int find_mem_in_note_1 (rtx *, void *);
00689 static rtx find_mem_in_note (rtx);
00690 static void load_mems (const struct loop *);
00691 static int insert_loop_mem (rtx *, void *);
00692 static int replace_loop_mem (rtx *, void *);
00693 static void replace_loop_mems (rtx, rtx, rtx, int);
00694 static int replace_loop_reg (rtx *, void *);
00695 static void replace_loop_regs (rtx insn, rtx, rtx);
00696 static void note_reg_stored (rtx, rtx, void *);
00697 static void try_copy_prop (const struct loop *, rtx, unsigned int);
00698 static void try_swap_copy_prop (const struct loop *, rtx, unsigned int);
00699 static rtx check_insn_for_givs (struct loop *, rtx, int, int);
00700 static rtx check_insn_for_bivs (struct loop *, rtx, int, int);
00701 static rtx gen_add_mult (rtx, rtx, rtx, rtx);
00702 static void loop_regs_update (const struct loop *, rtx);
00703 static int iv_add_mult_cost (rtx, rtx, rtx, rtx);
00704 static int loop_invariant_p (const struct loop *, rtx);
00705 static rtx loop_insn_hoist (const struct loop *, rtx);
00706 static void loop_iv_add_mult_emit_before (const struct loop *, rtx, rtx, rtx,
00707 rtx, basic_block, rtx);
00708 static rtx loop_insn_emit_before (const struct loop *, basic_block,
00709 rtx, rtx);
00710 static int loop_insn_first_p (rtx, rtx);
00711 static rtx get_condition_for_loop (const struct loop *, rtx);
00712 static void loop_iv_add_mult_sink (const struct loop *, rtx, rtx, rtx, rtx);
00713 static void loop_iv_add_mult_hoist (const struct loop *, rtx, rtx, rtx, rtx);
00714 static rtx extend_value_for_giv (struct induction *, rtx);
00715 static rtx loop_insn_sink (const struct loop *, rtx);
00716
00717 static rtx loop_insn_emit_after (const struct loop *, basic_block, rtx, rtx);
00718 static rtx loop_call_insn_emit_before (const struct loop *, basic_block,
00719 rtx, rtx);
00720 static rtx loop_call_insn_hoist (const struct loop *, rtx);
00721 static rtx loop_insn_sink_or_swim (const struct loop *, rtx);
00722
00723 static void loop_dump_aux (const struct loop *, FILE *, int);
00724 static void loop_delete_insns (rtx, rtx);
00725 static HOST_WIDE_INT remove_constant_addition (rtx *);
00726 static rtx gen_load_of_final_value (rtx, rtx);
00727 void debug_ivs (const struct loop *);
00728 void debug_iv_class (const struct iv_class *);
00729 void debug_biv (const struct induction *);
00730 void debug_giv (const struct induction *);
00731 void debug_loop (const struct loop *);
00732 void debug_loops (const struct loops *);
00733
00734 typedef struct loop_replace_args
00735 {
00736 rtx match;
00737 rtx replacement;
00738 rtx insn;
00739 } loop_replace_args;
00740
00741
00742 #define INSN_IN_RANGE_P(INSN, START, END) \
00743 (INSN_UID (INSN) < max_uid_for_loop \
00744 && INSN_LUID (INSN) >= INSN_LUID (START) \
00745 && INSN_LUID (INSN) <= INSN_LUID (END))
00746
00747
00748 static int indirect_jump_in_function;
00749 static int indirect_jump_in_function_p (rtx);
00750
00751 static int compute_luids (rtx, rtx, int);
00752
00753 static int biv_elimination_giv_has_0_offset (struct induction *,
00754 struct induction *, rtx);
00755
00756
00757
00758 static int copy_cost;
00759
00760
00761 static int reg_address_cost;
00762
00763 void
00764 init_loop (void)
00765 {
00766 rtx reg = gen_rtx_REG (word_mode, LAST_VIRTUAL_REGISTER + 1);
00767
00768 reg_address_cost = address_cost (reg, SImode);
00769
00770 copy_cost = COSTS_N_INSNS (1);
00771 }
00772
00773
00774
00775
00776
00777
00778 static int
00779 compute_luids (rtx start, rtx end, int prev_luid)
00780 {
00781 int i;
00782 rtx insn;
00783
00784 for (insn = start, i = prev_luid; insn != end; insn = NEXT_INSN (insn))
00785 {
00786 if (INSN_UID (insn) >= max_uid_for_loop)
00787 continue;
00788
00789
00790 if (!NOTE_P (insn)
00791 || NOTE_LINE_NUMBER (insn) <= 0)
00792 uid_luid[INSN_UID (insn)] = ++i;
00793 else
00794
00795 uid_luid[INSN_UID (insn)] = i;
00796 }
00797 return i + 1;
00798 }
00799
00800
00801
00802
00803
00804
00805 void
00806 loop_optimize (rtx f, FILE *dumpfile, int flags)
00807 {
00808 rtx insn;
00809 int i;
00810 struct loops loops_data;
00811 struct loops *loops = &loops_data;
00812 struct loop_info *loops_info;
00813
00814 loop_dump_stream = dumpfile;
00815
00816 init_recog_no_volatile ();
00817
00818 max_reg_before_loop = max_reg_num ();
00819 loop_max_reg = max_reg_before_loop;
00820
00821 regs_may_share = 0;
00822
00823
00824
00825 max_loop_num = 0;
00826 for (insn = f; insn; insn = NEXT_INSN (insn))
00827 {
00828 if (NOTE_P (insn)
00829 && NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_BEG)
00830 max_loop_num++;
00831 }
00832
00833
00834 if (max_loop_num == 0)
00835 return;
00836
00837 loops->num = max_loop_num;
00838
00839
00840
00841 max_uid_for_loop = get_max_uid () + 1 + max_loop_num * 32;
00842
00843 uid_luid = xcalloc (max_uid_for_loop, sizeof (int));
00844 uid_loop = xcalloc (max_uid_for_loop, sizeof (struct loop *));
00845
00846
00847 loops->array = xcalloc (loops->num, sizeof (struct loop));
00848
00849
00850
00851 find_and_verify_loops (f, loops);
00852
00853
00854 loops_info = xcalloc (loops->num, sizeof (struct loop_info));
00855 for (i = 0; i < (int) loops->num; i++)
00856 loops->array[i].aux = loops_info + i;
00857
00858
00859
00860
00861 reg_scan (f, max_reg_before_loop);
00862
00863
00864
00865
00866
00867
00868 init_alias_analysis ();
00869
00870
00871
00872 if (get_max_uid () > max_uid_for_loop)
00873 abort ();
00874
00875 max_uid_for_loop = get_max_uid ();
00876
00877
00878
00879
00880 compute_luids (f, NULL_RTX, 0);
00881
00882
00883
00884
00885
00886
00887 for (i = 0; i < max_uid_for_loop; i++)
00888 {
00889 uid_luid[0] = uid_luid[i];
00890 if (uid_luid[0] != 0)
00891 break;
00892 }
00893 for (i = 0; i < max_uid_for_loop; i++)
00894 if (uid_luid[i] == 0)
00895 uid_luid[i] = uid_luid[i - 1];
00896
00897
00898
00899 indirect_jump_in_function = indirect_jump_in_function_p (f);
00900
00901
00902
00903 for (i = max_loop_num - 1; i >= 0; i--)
00904 {
00905 struct loop *loop = &loops->array[i];
00906
00907 if (! loop->invalid && loop->end)
00908 {
00909 scan_loop (loop, flags);
00910 ggc_collect ();
00911 }
00912 }
00913
00914 end_alias_analysis ();
00915
00916
00917 for (i = 0; i < (int) loops->num; i++)
00918 free (loops_info[i].mems);
00919
00920 free (uid_luid);
00921 free (uid_loop);
00922 free (loops_info);
00923 free (loops->array);
00924 }
00925
00926
00927
00928
00929
00930
00931
00932 static rtx
00933 next_insn_in_loop (const struct loop *loop, rtx insn)
00934 {
00935 insn = NEXT_INSN (insn);
00936
00937 if (insn == loop->end)
00938 {
00939 if (loop->top)
00940
00941 insn = loop->top;
00942 else
00943
00944 insn = NULL_RTX;
00945 }
00946
00947 if (insn == loop->scan_start)
00948
00949 insn = NULL_RTX;
00950
00951 return insn;
00952 }
00953
00954
00955
00956
00957
00958 static rtx
00959 find_regs_nested (rtx deps, rtx x)
00960 {
00961 enum rtx_code code = GET_CODE (x);
00962 if (code == REG)
00963 deps = gen_rtx_EXPR_LIST (VOIDmode, x, deps);
00964 else
00965 {
00966 const char *fmt = GET_RTX_FORMAT (code);
00967 int i, j;
00968 for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
00969 {
00970 if (fmt[i] == 'e')
00971 deps = find_regs_nested (deps, XEXP (x, i));
00972 else if (fmt[i] == 'E')
00973 for (j = 0; j < XVECLEN (x, i); j++)
00974 deps = find_regs_nested (deps, XVECEXP (x, i, j));
00975 }
00976 }
00977 return deps;
00978 }
00979
00980
00981
00982
00983
00984
00985
00986
00987
00988 static void
00989 scan_loop (struct loop *loop, int flags)
00990 {
00991 struct loop_info *loop_info = LOOP_INFO (loop);
00992 struct loop_regs *regs = LOOP_REGS (loop);
00993 int i;
00994 rtx loop_start = loop->start;
00995 rtx loop_end = loop->end;
00996 rtx p;
00997
00998 int maybe_never = 0;
00999
01000
01001 int call_passed = 0;
01002
01003 int insn_count;
01004 int tem;
01005 rtx temp, update_start, update_end;
01006
01007 rtx set, set1;
01008
01009 struct loop_movables *movables = LOOP_MOVABLES (loop);
01010
01011
01012
01013
01014 int threshold;
01015 int in_libcall;
01016
01017 loop->top = 0;
01018
01019 movables->head = 0;
01020 movables->last = 0;
01021
01022
01023
01024
01025
01026
01027
01028
01029
01030
01031
01032
01033
01034
01035
01036
01037
01038 for (p = NEXT_INSN (loop_start);
01039 p != loop_end
01040 && !LABEL_P (p) && ! INSN_P (p)
01041 && (!NOTE_P (p)
01042 || (NOTE_LINE_NUMBER (p) != NOTE_INSN_LOOP_BEG
01043 && NOTE_LINE_NUMBER (p) != NOTE_INSN_LOOP_END));
01044 p = NEXT_INSN (p))
01045 ;
01046
01047 loop->scan_start = p;
01048
01049
01050
01051
01052
01053 if (NEXT_INSN (loop->end) != 0)
01054 loop->sink = NEXT_INSN (loop->end);
01055 else
01056 loop->sink = emit_note_after (NOTE_INSN_DELETED, loop->end);
01057
01058
01059 prescan_loop (loop);
01060 threshold = (loop_info->has_call ? 1 : 2) * (1 + n_non_fixed_regs);
01061
01062
01063
01064
01065
01066
01067 if (JUMP_P (p)
01068
01069 && any_uncondjump_p (p)
01070 && JUMP_LABEL (p) != 0
01071
01072
01073
01074
01075
01076
01077 && INSN_IN_RANGE_P (JUMP_LABEL (p), loop_start, loop_end))
01078 {
01079 loop->top = next_label (loop->scan_start);
01080 loop->scan_start = JUMP_LABEL (p);
01081 }
01082
01083
01084
01085
01086
01087
01088
01089
01090
01091 if (INSN_UID (loop->scan_start) >= max_uid_for_loop
01092 || !LABEL_P (loop->scan_start))
01093 {
01094 if (loop_dump_stream)
01095 fprintf (loop_dump_stream, "\nLoop from %d to %d is phony.\n\n",
01096 INSN_UID (loop_start), INSN_UID (loop_end));
01097 return;
01098 }
01099
01100
01101
01102
01103 loop_regs_scan (loop, loop_info->mems_idx + 16);
01104 insn_count = count_insns_in_loop (loop);
01105
01106 if (loop_dump_stream)
01107 fprintf (loop_dump_stream, "\nLoop from %d to %d: %d real insns.\n",
01108 INSN_UID (loop_start), INSN_UID (loop_end), insn_count);
01109
01110
01111
01112
01113
01114
01115
01116
01117
01118
01119
01120
01121
01122
01123 for (in_libcall = 0, p = next_insn_in_loop (loop, loop->scan_start);
01124 p != NULL_RTX;
01125 p = next_insn_in_loop (loop, p))
01126 {
01127 if (in_libcall && INSN_P (p) && find_reg_note (p, REG_RETVAL, NULL_RTX))
01128 in_libcall--;
01129 if (NONJUMP_INSN_P (p))
01130 {
01131
01132 if (GET_CODE (PATTERN (p)) == ASM_INPUT)
01133 break;
01134 temp = find_reg_note (p, REG_LIBCALL, NULL_RTX);
01135 if (temp)
01136 in_libcall++;
01137 if (! in_libcall
01138 && (set = single_set (p))
01139 && REG_P (SET_DEST (set))
01140 #ifdef PIC_OFFSET_TABLE_REG_CALL_CLOBBERED
01141 && SET_DEST (set) != pic_offset_table_rtx
01142 #endif
01143 && ! regs->array[REGNO (SET_DEST (set))].may_not_optimize)
01144 {
01145 int tem1 = 0;
01146 int tem2 = 0;
01147 int move_insn = 0;
01148 int insert_temp = 0;
01149 rtx src = SET_SRC (set);
01150 rtx dependencies = 0;
01151
01152
01153
01154
01155
01156
01157
01158
01159
01160 temp = find_reg_note (p, REG_EQUIV, NULL_RTX);
01161 if (temp)
01162 src = XEXP (temp, 0), move_insn = 1;
01163 else
01164 {
01165 temp = find_reg_note (p, REG_EQUAL, NULL_RTX);
01166 if (temp && CONSTANT_P (XEXP (temp, 0)))
01167 src = XEXP (temp, 0), move_insn = 1;
01168 if (temp && find_reg_note (p, REG_RETVAL, NULL_RTX))
01169 {
01170 src = XEXP (temp, 0);
01171
01172
01173
01174 dependencies = libcall_other_reg (p, src);
01175 }
01176 }
01177
01178
01179
01180
01181
01182 if (GET_CODE (PATTERN (p)) == PARALLEL)
01183 {
01184 for (i = 0; i < XVECLEN (PATTERN (p), 0); i++)
01185 {
01186 rtx x = XVECEXP (PATTERN (p), 0, i);
01187 if (GET_CODE (x) == USE)
01188 dependencies
01189 = gen_rtx_EXPR_LIST (VOIDmode, XEXP (x, 0),
01190 dependencies);
01191 else if (GET_CODE (x) == CLOBBER
01192 && MEM_P (XEXP (x, 0)))
01193 dependencies = find_regs_nested (dependencies,
01194 XEXP (XEXP (x, 0), 0));
01195 }
01196 }
01197
01198 if (
01199
01200
01201
01202 ! reg_in_basic_block_p (p, SET_DEST (set))
01203
01204
01205
01206
01207
01208
01209
01210
01211
01212 && (maybe_never
01213 || loop_reg_used_before_p (loop, set, p)))
01214
01215
01216
01217
01218
01219
01220
01221
01222 insert_temp = 1;
01223
01224
01225
01226
01227 if (GET_MODE_CLASS (GET_MODE (SET_DEST (set))) == MODE_CC
01228 && CONSTANT_P (src))
01229 ;
01230
01231
01232
01233
01234 else if (REGNO (SET_DEST (set)) >= max_reg_before_loop)
01235 ;
01236
01237
01238
01239
01240
01241 else if (insert_temp
01242 && (optimize_size
01243 || ! can_copy_p (GET_MODE (SET_SRC (set)))
01244 || REG_P (SET_SRC (set))
01245 || (CONSTANT_P (SET_SRC (set))
01246 && LEGITIMATE_CONSTANT_P (SET_SRC (set)))))
01247 ;
01248 else if ((tem = loop_invariant_p (loop, src))
01249 && (dependencies == 0
01250 || (tem2
01251 = loop_invariant_p (loop, dependencies)) != 0)
01252 && (regs->array[REGNO (SET_DEST (set))].set_in_loop == 1
01253 || (tem1
01254 = consec_sets_invariant_p
01255 (loop, SET_DEST (set),
01256 regs->array[REGNO (SET_DEST (set))].set_in_loop,
01257 p)))
01258
01259
01260
01261
01262
01263 && ! ((maybe_never || call_passed)
01264 && may_trap_p (src)))
01265 {
01266 struct movable *m;
01267 int regno = REGNO (SET_DEST (set));
01268
01269
01270
01271
01272
01273
01274
01275
01276
01277
01278
01279
01280
01281
01282
01283
01284 if (loop_info->has_call
01285 && regs->array[regno].single_usage != 0
01286 && regs->array[regno].single_usage != const0_rtx
01287 && REGNO_FIRST_UID (regno) == INSN_UID (p)
01288 && (REGNO_LAST_UID (regno)
01289 == INSN_UID (regs->array[regno].single_usage))
01290 && regs->array[regno].set_in_loop == 1
01291 && GET_CODE (SET_SRC (set)) != ASM_OPERANDS
01292 && ! side_effects_p (SET_SRC (set))
01293 && ! find_reg_note (p, REG_RETVAL, NULL_RTX)
01294 && (! SMALL_REGISTER_CLASSES
01295 || (! (REG_P (SET_SRC (set))
01296 && (REGNO (SET_SRC (set))
01297 < FIRST_PSEUDO_REGISTER))))
01298 && regno >= FIRST_PSEUDO_REGISTER
01299
01300
01301
01302 && ! modified_between_p (SET_SRC (set), p,
01303 regs->array[regno].single_usage)
01304 && no_labels_between_p (p,
01305 regs->array[regno].single_usage)
01306 && validate_replace_rtx (SET_DEST (set), SET_SRC (set),
01307 regs->array[regno].single_usage))
01308 {
01309
01310
01311
01312 REG_NOTES (regs->array[regno].single_usage)
01313 = (replace_rtx
01314 (REG_NOTES (regs->array[regno].single_usage),
01315 SET_DEST (set), copy_rtx (SET_SRC (set))));
01316
01317 delete_insn (p);
01318 for (i = 0; i < LOOP_REGNO_NREGS (regno, SET_DEST (set));
01319 i++)
01320 regs->array[regno+i].set_in_loop = 0;
01321 continue;
01322 }
01323
01324 m = xmalloc (sizeof (struct movable));
01325 m->next = 0;
01326 m->insn = p;
01327 m->set_src = src;
01328 m->dependencies = dependencies;
01329 m->set_dest = SET_DEST (set);
01330 m->force = 0;
01331 m->consec
01332 = regs->array[REGNO (SET_DEST (set))].set_in_loop - 1;
01333 m->done = 0;
01334 m->forces = 0;
01335 m->partial = 0;
01336 m->move_insn = move_insn;
01337 m->move_insn_first = 0;
01338 m->insert_temp = insert_temp;
01339 m->is_equiv = (find_reg_note (p, REG_EQUIV, NULL_RTX) != 0);
01340 m->savemode = VOIDmode;
01341 m->regno = regno;
01342
01343
01344
01345 m->cond = ((tem | tem1 | tem2) > 1);
01346 m->global = LOOP_REG_GLOBAL_P (loop, regno);
01347 m->match = 0;
01348 m->lifetime = LOOP_REG_LIFETIME (loop, regno);
01349 m->savings = regs->array[regno].n_times_set;
01350 if (find_reg_note (p, REG_RETVAL, NULL_RTX))
01351 m->savings += libcall_benefit (p);
01352 for (i = 0; i < LOOP_REGNO_NREGS (regno, SET_DEST (set)); i++)
01353 regs->array[regno+i].set_in_loop = move_insn ? -2 : -1;
01354
01355 loop_movables_add (movables, m);
01356
01357 if (m->consec > 0)
01358 {
01359
01360
01361
01362
01363 m->move_insn_first = m->move_insn;
01364
01365
01366 p = next_nonnote_insn (p);
01367
01368 p = skip_consec_insns (p, m->consec);
01369
01370 p = prev_nonnote_insn (p);
01371
01372
01373
01374
01375 temp = find_reg_note (p, REG_EQUIV, NULL_RTX);
01376 if (temp)
01377 m->set_src = XEXP (temp, 0), m->move_insn = 1;
01378 else
01379 {
01380 temp = find_reg_note (p, REG_EQUAL, NULL_RTX);
01381 if (temp && CONSTANT_P (XEXP (temp, 0)))
01382 m->set_src = XEXP (temp, 0), m->move_insn = 1;
01383 else
01384 m->move_insn = 0;
01385
01386 }
01387 m->is_equiv
01388 = (find_reg_note (p, REG_EQUIV, NULL_RTX) != 0);
01389 }
01390 }
01391
01392
01393
01394
01395
01396
01397
01398 else if (SET_SRC (set) == const0_rtx
01399 && NONJUMP_INSN_P (NEXT_INSN (p))
01400 && (set1 = single_set (NEXT_INSN (p)))
01401 && GET_CODE (set1) == SET
01402 && (GET_CODE (SET_DEST (set1)) == STRICT_LOW_PART)
01403 && (GET_CODE (XEXP (SET_DEST (set1), 0)) == SUBREG)
01404 && (SUBREG_REG (XEXP (SET_DEST (set1), 0))
01405 == SET_DEST (set))
01406 && !reg_mentioned_p (SET_DEST (set), SET_SRC (set1)))
01407 {
01408 int regno = REGNO (SET_DEST (set));
01409 if (regs->array[regno].set_in_loop == 2)
01410 {
01411 struct movable *m;
01412 m = xmalloc (sizeof (struct movable));
01413 m->next = 0;
01414 m->insn = p;
01415 m->set_dest = SET_DEST (set);
01416 m->dependencies = 0;
01417 m->force = 0;
01418 m->consec = 0;
01419 m->done = 0;
01420 m->forces = 0;
01421 m->move_insn = 0;
01422 m->move_insn_first = 0;
01423 m->insert_temp = insert_temp;
01424 m->partial = 1;
01425
01426
01427
01428
01429
01430
01431
01432
01433
01434
01435
01436
01437
01438
01439
01440
01441
01442
01443 m->global = (INSN_UID (p) >= max_uid_for_loop
01444 || LOOP_REG_GLOBAL_P (loop, regno)
01445 || (labels_in_range_p
01446 (p, REGNO_FIRST_LUID (regno))));
01447 if (maybe_never && m->global)
01448 m->savemode = GET_MODE (SET_SRC (set1));
01449 else
01450 m->savemode = VOIDmode;
01451 m->regno = regno;
01452 m->cond = 0;
01453 m->match = 0;
01454 m->lifetime = LOOP_REG_LIFETIME (loop, regno);
01455 m->savings = 1;
01456 for (i = 0;
01457 i < LOOP_REGNO_NREGS (regno, SET_DEST (set));
01458 i++)
01459 regs->array[regno+i].set_in_loop = -1;
01460
01461 loop_movables_add (movables, m);
01462 }
01463 }
01464 }
01465 }
01466
01467
01468
01469 else if (CALL_P (p) && ! CONST_OR_PURE_CALL_P (p))
01470 call_passed = 1;
01471
01472
01473
01474
01475
01476
01477 else if ((LABEL_P (p) || JUMP_P (p))
01478
01479
01480
01481
01482
01483 && ! (JUMP_P (p) && JUMP_LABEL (p) == loop->top
01484 && NEXT_INSN (NEXT_INSN (p)) == loop_end
01485 && any_uncondjump_p (p)))
01486 maybe_never = 1;
01487 }
01488
01489
01490
01491 ignore_some_movables (movables);
01492
01493
01494
01495
01496
01497
01498 force_movables (movables);
01499
01500
01501
01502
01503
01504
01505 combine_movables (movables, regs);
01506
01507
01508
01509
01510
01511
01512
01513
01514 if (!optimize_size
01515 || (reg_class_size[GENERAL_REGS] > 18 && !loop_info->has_call))
01516 {
01517 move_movables (loop, movables, threshold, insn_count);
01518
01519
01520
01521 if (max_reg_num () > regs->num)
01522 {
01523 loop_regs_scan (loop, 0);
01524 for (update_start = loop_start;
01525 PREV_INSN (update_start)
01526 && !LABEL_P (PREV_INSN (update_start));
01527 update_start = PREV_INSN (update_start))
01528 ;
01529 update_end = NEXT_INSN (loop_end);
01530
01531 reg_scan_update (update_start, update_end, loop_max_reg);
01532 loop_max_reg = max_reg_num ();
01533 }
01534 }
01535
01536
01537
01538
01539 for (i = 0; i < regs->num; i++)
01540 if (regs->array[i].set_in_loop < 0)
01541 regs->array[i].set_in_loop = regs->array[i].n_times_set;
01542
01543
01544
01545 load_mems (loop);
01546
01547
01548 if (max_reg_num () > regs->num)
01549 loop_regs_scan (loop, 0);
01550
01551 for (update_start = loop_start;
01552 PREV_INSN (update_start)
01553 && !LABEL_P (PREV_INSN (update_start));
01554 update_start = PREV_INSN (update_start))
01555 ;
01556 update_end = NEXT_INSN (loop_end);
01557
01558 reg_scan_update (update_start, update_end, loop_max_reg);
01559 loop_max_reg = max_reg_num ();
01560
01561 if (flag_strength_reduce)
01562 {
01563 if (update_end && LABEL_P (update_end))
01564
01565 LABEL_NUSES (update_end)++;
01566
01567 strength_reduce (loop, flags);
01568
01569 reg_scan_update (update_start, update_end, loop_max_reg);
01570 loop_max_reg = max_reg_num ();
01571
01572 if (update_end && LABEL_P (update_end)
01573 && --LABEL_NUSES (update_end) == 0)
01574 delete_related_insns (update_end);
01575 }
01576
01577
01578
01579 loop_movables_free (movables);
01580
01581 free (regs->array);
01582 regs->array = 0;
01583 regs->num = 0;
01584 }
01585
01586
01587
01588
01589 static void
01590 record_excess_regs (rtx in_this, rtx not_in_this, rtx *output)
01591 {
01592 enum rtx_code code;
01593 const char *fmt;
01594 int i;
01595
01596 code = GET_CODE (in_this);
01597
01598 switch (code)
01599 {
01600 case PC:
01601 case CC0:
01602 case CONST_INT:
01603 case CONST_DOUBLE:
01604 case CONST:
01605 case SYMBOL_REF:
01606 case LABEL_REF:
01607 return;
01608
01609 case REG:
01610 if (REGNO (in_this) >= FIRST_PSEUDO_REGISTER
01611 && ! reg_mentioned_p (in_this, not_in_this))
01612 *output = gen_rtx_EXPR_LIST (VOIDmode, in_this, *output);
01613 return;
01614
01615 default:
01616 break;
01617 }
01618
01619 fmt = GET_RTX_FORMAT (code);
01620 for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
01621 {
01622 int j;
01623
01624 switch (fmt[i])
01625 {
01626 case 'E':
01627 for (j = 0; j < XVECLEN (in_this, i); j++)
01628 record_excess_regs (XVECEXP (in_this, i, j), not_in_this, output);
01629 break;
01630
01631 case 'e':
01632 record_excess_regs (XEXP (in_this, i), not_in_this, output);
01633 break;
01634 }
01635 }
01636 }
01637
01638
01639
01640
01641
01642
01643 static rtx
01644 libcall_other_reg (rtx insn, rtx equiv)
01645 {
01646 rtx note = find_reg_note (insn, REG_RETVAL, NULL_RTX);
01647 rtx p = XEXP (note, 0);
01648 rtx output = 0;
01649
01650
01651
01652
01653 while (p != insn)
01654 {
01655 if (INSN_P (p))
01656 record_excess_regs (PATTERN (p), equiv, &output);
01657 p = NEXT_INSN (p);
01658 }
01659
01660 return output;
01661 }
01662
01663
01664
01665
01666 static int
01667 reg_in_basic_block_p (rtx insn, rtx reg)
01668 {
01669 int regno = REGNO (reg);
01670 rtx p;
01671
01672 if (REGNO_FIRST_UID (regno) != INSN_UID (insn))
01673 return 0;
01674
01675
01676 for (p = insn; p; p = NEXT_INSN (p))
01677 {
01678 switch (GET_CODE (p))
01679 {
01680 case NOTE:
01681 break;
01682
01683 case INSN:
01684 case CALL_INSN:
01685
01686 if (REGNO_LAST_UID (regno) == INSN_UID (p))
01687 return 1;
01688 break;
01689
01690 case JUMP_INSN:
01691
01692 if (REGNO_LAST_UID (regno) == INSN_UID (p))
01693 return 1;
01694
01695 return 0;
01696
01697 case CODE_LABEL:
01698 case BARRIER:
01699
01700 return 0;
01701
01702 default:
01703 break;
01704 }
01705 }
01706
01707
01708
01709
01710
01711
01712 return 1;
01713 }
01714
01715
01716
01717
01718
01719 static int
01720 libcall_benefit (rtx last)
01721 {
01722 rtx insn;
01723 int benefit = 0;
01724
01725 for (insn = XEXP (find_reg_note (last, REG_RETVAL, NULL_RTX), 0);
01726 insn != last; insn = NEXT_INSN (insn))
01727 {
01728 if (CALL_P (insn))
01729 benefit += 10;
01730
01731 else if (NONJUMP_INSN_P (insn)
01732 && GET_CODE (PATTERN (insn)) != USE
01733 && GET_CODE (PATTERN (insn)) != CLOBBER)
01734 benefit++;
01735 }
01736
01737 return benefit;
01738 }
01739
01740
01741
01742 static rtx
01743 skip_consec_insns (rtx insn, int count)
01744 {
01745 for (; count > 0; count--)
01746 {
01747 rtx temp;
01748
01749
01750
01751
01752 if (!NOTE_P (insn)
01753 && (temp = find_reg_note (insn, REG_LIBCALL, NULL_RTX)))
01754 insn = XEXP (temp, 0);
01755
01756 do
01757 insn = NEXT_INSN (insn);
01758 while (NOTE_P (insn));
01759 }
01760
01761 return insn;
01762 }
01763
01764
01765
01766
01767
01768
01769 static void
01770 ignore_some_movables (struct loop_movables *movables)
01771 {
01772 struct movable *m, *m1;
01773
01774 for (m = movables->head; m; m = m->next)
01775 {
01776
01777 rtx note = find_reg_note (m->insn, REG_RETVAL, NULL_RTX);
01778 if (note)
01779 {
01780 rtx insn;
01781
01782
01783
01784
01785
01786
01787 for (insn = XEXP (note, 0); insn != m->insn; insn = NEXT_INSN (insn))
01788 for (m1 = movables->head; m1 != m; m1 = m1->next)
01789 if (m1->insn == insn)
01790 m1->done = 1;
01791 }
01792 }
01793 }
01794
01795
01796
01797
01798
01799
01800 static void
01801 force_movables (struct loop_movables *movables)
01802 {
01803 struct movable *m, *m1;
01804
01805 for (m1 = movables->head; m1; m1 = m1->next)
01806
01807 if (!m1->partial && !m1->done)
01808 {
01809 int regno = m1->regno;
01810 for (m = m1->next; m; m = m->next)
01811
01812
01813
01814
01815
01816
01817 if (INSN_UID (m->insn) == REGNO_LAST_UID (regno)
01818 && !m->done)
01819 break;
01820 if (m != 0 && m->set_src == m1->set_dest
01821
01822 && m->consec == 0)
01823 m = 0;
01824
01825
01826
01827
01828 if (m != 0)
01829 {
01830 struct movable *m2;
01831
01832 m->forces = m1;
01833 for (m2 = m1; m2; m2 = m2->forces)
01834 {
01835 m2->lifetime += m->lifetime;
01836 m2->savings += m->savings;
01837 }
01838 }
01839 }
01840 }
01841
01842
01843
01844
01845 static void
01846 combine_movables (struct loop_movables *movables, struct loop_regs *regs)
01847 {
01848 struct movable *m;
01849 char *matched_regs = xmalloc (regs->num);
01850 enum machine_mode mode;
01851
01852
01853
01854
01855
01856
01857
01858 for (m = movables->head; m; m = m->next)
01859 if (m->match == 0 && regs->array[m->regno].n_times_set == 1
01860 && m->regno >= FIRST_PSEUDO_REGISTER
01861 && !m->insert_temp
01862 && !m->partial)
01863 {
01864 struct movable *m1;
01865 int regno = m->regno;
01866
01867 memset (matched_regs, 0, regs->num);
01868 matched_regs[regno] = 1;
01869
01870
01871
01872 for (m1 = m->next; m1; m1 = m1->next)
01873 if (m != m1 && m1->match == 0
01874 && !m1->insert_temp
01875 && regs->array[m1->regno].n_times_set == 1
01876 && m1->regno >= FIRST_PSEUDO_REGISTER
01877
01878 && !m1->global
01879
01880 && !m1->partial
01881 && (matched_regs[m1->regno]
01882 ||
01883 (
01884
01885
01886
01887
01888
01889
01890
01891 (GET_MODE (m->set_dest) == GET_MODE (m1->set_dest)
01892 || (GET_MODE_CLASS (GET_MODE (m->set_dest)) == MODE_INT
01893 && GET_MODE_CLASS (GET_MODE (m1->set_dest)) == MODE_INT
01894 && (GET_MODE_BITSIZE (GET_MODE (m->set_dest))
01895 >= GET_MODE_BITSIZE (GET_MODE (m1->set_dest)))))
01896
01897 && ((REG_P (m1->set_src)
01898 && matched_regs[REGNO (m1->set_src)])
01899 || rtx_equal_for_loop_p (m->set_src, m1->set_src,
01900 movables, regs))))
01901 && ((m->dependencies == m1->dependencies)
01902 || rtx_equal_p (m->dependencies, m1->dependencies)))
01903 {
01904 m->lifetime += m1->lifetime;
01905 m->savings += m1->savings;
01906 m1->done = 1;
01907 m1->match = m;
01908 matched_regs[m1->regno] = 1;
01909 }
01910 }
01911
01912
01913
01914
01915
01916 for (mode = GET_CLASS_NARROWEST_MODE (MODE_INT); mode != VOIDmode;
01917 mode = GET_MODE_WIDER_MODE (mode))
01918 {
01919 struct movable *m0 = 0;
01920
01921
01922
01923 for (m = movables->head; m; m = m->next)
01924 if (m->partial && ! m->global
01925 && mode == GET_MODE (SET_SRC (PATTERN (NEXT_INSN (m->insn)))))
01926 {
01927 struct movable *m1;
01928
01929 int first = REGNO_FIRST_LUID (m->regno);
01930 int last = REGNO_LAST_LUID (m->regno);
01931
01932 if (m0 == 0)
01933 {
01934
01935 m0 = m;
01936 continue;
01937 }
01938
01939
01940
01941 if (GET_MODE (m->set_dest) != GET_MODE (m0->set_dest))
01942 continue;
01943
01944
01945
01946 for (m1 = movables->head; m1 != m; m1 = m1->next)
01947 if (m1 == m0 || (m1->partial && m1->match == m0))
01948 if (! (REGNO_FIRST_LUID (m1->regno) > last
01949 || REGNO_LAST_LUID (m1->regno) < first))
01950 goto overlap;
01951
01952
01953 m0->lifetime += m->lifetime;
01954 m0->savings += m->savings;
01955 m->done = 1;
01956 m->match = m0;
01957
01958 overlap:
01959 ;
01960 }
01961 }
01962
01963
01964 free (matched_regs);
01965 }
01966
01967
01968
01969
01970 static int
01971 num_unmoved_movables (const struct loop *loop)
01972 {
01973 int num = 0;
01974 struct movable *m;
01975
01976 for (m = LOOP_MOVABLES (loop)->head; m; m = m->next)
01977 if (!m->done)
01978 ++num;
01979
01980 return num;
01981 }
01982
01983
01984
01985
01986 static int
01987 regs_match_p (rtx x, rtx y, struct loop_movables *movables)
01988 {
01989 unsigned int xn = REGNO (x);
01990 unsigned int yn = REGNO (y);
01991 struct movable *mx, *my;
01992
01993 for (mx = movables->head; mx; mx = mx->next)
01994 if (mx->regno == xn)
01995 break;
01996
01997 for (my = movables->head; my; my = my->next)
01998 if (my->regno == yn)
01999 break;
02000
02001 return (mx && my
02002 && ((mx->match == my->match && mx->match != 0)
02003 || mx->match == my
02004 || mx == my->match));
02005 }
02006
02007
02008
02009
02010
02011
02012
02013 static int
02014 rtx_equal_for_loop_p (rtx x, rtx y, struct loop_movables *movables,
02015 struct loop_regs *regs)
02016 {
02017 int i;
02018 int j;
02019 struct movable *m;
02020 enum rtx_code code;
02021 const char *fmt;
02022
02023 if (x == y)
02024 return 1;
02025 if (x == 0 || y == 0)
02026 return 0;
02027
02028 code = GET_CODE (x);
02029
02030
02031
02032 if (REG_P (x) && regs->array[REGNO (x)].set_in_loop == -2
02033 && CONSTANT_P (y))
02034 {
02035 for (m = movables->head; m; m = m->next)
02036 if (m->move_insn && m->regno == REGNO (x)
02037 && rtx_equal_p (m->set_src, y))
02038 return 1;
02039 }
02040 else if (REG_P (y) && regs->array[REGNO (y)].set_in_loop == -2
02041 && CONSTANT_P (x))
02042 {
02043 for (m = movables->head; m; m = m->next)
02044 if (m->move_insn && m->regno == REGNO (y)
02045 && rtx_equal_p (m->set_src, x))
02046 return 1;
02047 }
02048
02049
02050 if (code != GET_CODE (y))
02051 return 0;
02052
02053
02054
02055
02056 if (GET_MODE (x) != GET_MODE (y))
02057 return 0;
02058
02059
02060 if (code == REG)
02061 return (REGNO (x) == REGNO (y) || regs_match_p (x, y, movables));
02062
02063 if (code == LABEL_REF)
02064 return XEXP (x, 0) == XEXP (y, 0);
02065 if (code == SYMBOL_REF)
02066 return XSTR (x, 0) == XSTR (y, 0);
02067
02068
02069
02070
02071 fmt = GET_RTX_FORMAT (code);
02072 for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
02073 {
02074 switch (fmt[i])
02075 {
02076 case 'w':
02077 if (XWINT (x, i) != XWINT (y, i))
02078 return 0;
02079 break;
02080
02081 case 'i':
02082 if (XINT (x, i) != XINT (y, i))
02083 return 0;
02084 break;
02085
02086 case 'E':
02087
02088 if (XVECLEN (x, i) != XVECLEN (y, i))
02089 return 0;
02090
02091
02092 for (j = 0; j < XVECLEN (x, i); j++)
02093 if (rtx_equal_for_loop_p (XVECEXP (x, i, j), XVECEXP (y, i, j),
02094 movables, regs) == 0)
02095 return 0;
02096 break;
02097
02098 case 'e':
02099 if (rtx_equal_for_loop_p (XEXP (x, i), XEXP (y, i), movables, regs)
02100 == 0)
02101 return 0;
02102 break;
02103
02104 case 's':
02105 if (strcmp (XSTR (x, i), XSTR (y, i)))
02106 return 0;
02107 break;
02108
02109 case 'u':
02110
02111 break;
02112
02113 case '0':
02114 break;
02115
02116
02117
02118
02119 default:
02120 abort ();
02121 }
02122 }
02123 return 1;
02124 }
02125
02126
02127
02128
02129
02130 static void
02131 add_label_notes (rtx x, rtx insns)
02132 {
02133 enum rtx_code code = GET_CODE (x);
02134 int i, j;
02135 const char *fmt;
02136 rtx insn;
02137
02138 if (code == LABEL_REF && !LABEL_REF_NONLOCAL_P (x))
02139 {
02140
02141
02142
02143
02144
02145 for (insn = insns; insn; insn = NEXT_INSN (insn))
02146 if (reg_mentioned_p (XEXP (x, 0), insn))
02147 {
02148 REG_NOTES (insn) = gen_rtx_INSN_LIST (REG_LABEL, XEXP (x, 0),
02149 REG_NOTES (insn));
02150 if (LABEL_P (XEXP (x, 0)))
02151 LABEL_NUSES (XEXP (x, 0))++;
02152 }
02153 }
02154
02155 fmt = GET_RTX_FORMAT (code);
02156 for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
02157 {
02158 if (fmt[i] == 'e')
02159 add_label_notes (XEXP (x, i), insns);
02160 else if (fmt[i] == 'E')
02161 for (j = XVECLEN (x, i) - 1; j >= 0; j--)
02162 add_label_notes (XVECEXP (x, i, j), insns);
02163 }
02164 }
02165
02166
02167
02168
02169
02170 static void
02171 move_movables (struct loop *loop, struct loop_movables *movables,
02172 int threshold, int insn_count)
02173 {
02174 struct loop_regs *regs = LOOP_REGS (loop);
02175 int nregs = regs->num;
02176 rtx new_start = 0;
02177 struct movable *m;
02178 rtx p;
02179 rtx loop_start = loop->start;
02180 rtx loop_end = loop->end;
02181
02182
02183
02184 rtx *reg_map = xcalloc (nregs, sizeof (rtx));
02185 char *already_moved = xcalloc (nregs, sizeof (char));
02186
02187 for (m = movables->head; m; m = m->next)
02188 {
02189
02190
02191 if (loop_dump_stream)
02192 {
02193 fprintf (loop_dump_stream, "Insn %d: regno %d (life %d), ",
02194 INSN_UID (m->insn), m->regno, m->lifetime);
02195 if (m->consec > 0)
02196 fprintf (loop_dump_stream, "consec %d, ", m->consec);
02197 if (m->cond)
02198 fprintf (loop_dump_stream, "cond ");
02199 if (m->force)
02200 fprintf (loop_dump_stream, "force ");
02201 if (m->global)
02202 fprintf (loop_dump_stream, "global ");
02203 if (m->done)
02204 fprintf (loop_dump_stream, "done ");
02205 if (m->move_insn)
02206 fprintf (loop_dump_stream, "move-insn ");
02207 if (m->match)
02208 fprintf (loop_dump_stream, "matches %d ",
02209 INSN_UID (m->match->insn));
02210 if (m->forces)
02211 fprintf (loop_dump_stream, "forces %d ",
02212 INSN_UID (m->forces->insn));
02213 }
02214
02215
02216
02217
02218 if (!m->done
02219 && (! m->cond
02220 || (1 == loop_invariant_p (loop, m->set_src)
02221 && (m->dependencies == 0
02222 || 1 == loop_invariant_p (loop, m->dependencies))
02223 && (m->consec == 0
02224 || 1 == consec_sets_invariant_p (loop, m->set_dest,
02225 m->consec + 1,
02226 m->insn))))
02227 && (! m->forces || m->forces->done))
02228 {
02229 int regno;
02230 rtx p;
02231 int savings = m->savings;
02232
02233
02234
02235
02236 p = m->insn;
02237 regno = m->regno;
02238
02239 if (loop_dump_stream)
02240 fprintf (loop_dump_stream, "savings %d ", savings);
02241
02242 if (regs->array[regno].moved_once && loop_dump_stream)
02243 fprintf (loop_dump_stream, "halved since already moved ");
02244
02245
02246
02247
02248
02249
02250
02251
02252
02253
02254
02255
02256
02257
02258 if (already_moved[regno]
02259 || (threshold * savings * m->lifetime) >=
02260 (regs->array[regno].moved_once ? insn_count * 2 : insn_count)
02261 || (m->forces && m->forces->done
02262 && regs->array[m->forces->regno].n_times_set == 1))
02263 {
02264 int count;
02265 struct movable *m1;
02266 rtx first = NULL_RTX;
02267 rtx newreg = NULL_RTX;
02268
02269 if (m->insert_temp)
02270 newreg = gen_reg_rtx (GET_MODE (m->set_dest));
02271
02272
02273
02274 if (m->partial && m->match)
02275 {
02276 rtx newpat, i1;
02277 rtx r1, r2;
02278
02279
02280
02281
02282 for (m1 = m; m1->match; m1 = m1->match);
02283 newpat = gen_move_insn (SET_DEST (PATTERN (m->insn)),
02284 SET_DEST (PATTERN (m1->insn)));
02285 i1 = loop_insn_hoist (loop, newpat);
02286
02287
02288
02289 REG_NOTES (i1) = REG_NOTES (m->insn);
02290 r1 = SET_DEST (PATTERN (m->insn));
02291 r2 = SET_DEST (PATTERN (m1->insn));
02292 regs_may_share
02293 = gen_rtx_EXPR_LIST (VOIDmode, r1,
02294 gen_rtx_EXPR_LIST (VOIDmode, r2,
02295 regs_may_share));
02296 delete_insn (m->insn);
02297
02298 if (new_start == 0)
02299 new_start = i1;
02300
02301 if (loop_dump_stream)
02302 fprintf (loop_dump_stream, " moved to %d", INSN_UID (i1));
02303 }
02304
02305
02306
02307 else if (m->move_insn)
02308 {
02309 rtx i1, temp, seq;
02310
02311 for (count = m->consec; count >= 0; count--)
02312 {
02313
02314
02315 if (!NOTE_P (p)
02316 && (temp = find_reg_note (p, REG_LIBCALL, NULL_RTX)))
02317 abort ();
02318
02319
02320
02321
02322 if (!NOTE_P (p)
02323 && (temp = find_reg_note (p, REG_RETVAL, NULL_RTX)))
02324 {
02325 temp = XEXP (temp, 0);
02326 while (temp != p)
02327 temp = delete_insn (temp);
02328 }
02329
02330 temp = p;
02331 p = delete_insn (p);
02332
02333
02334
02335
02336
02337
02338
02339 while (p && NOTE_P (p))
02340 p = NEXT_INSN (temp) = NEXT_INSN (p);
02341
02342 if (m->insert_temp)
02343 {
02344
02345
02346 start_sequence ();
02347 emit_move_insn (m->set_dest, newreg);
02348 seq = get_insns ();
02349 end_sequence ();
02350 emit_insn_before (seq, p);
02351 }
02352 }
02353
02354 start_sequence ();
02355 emit_move_insn (m->insert_temp ? newreg : m->set_dest,
02356 m->set_src);
02357 seq = get_insns ();
02358 end_sequence ();
02359
02360 add_label_notes (m->set_src, seq);
02361
02362 i1 = loop_insn_hoist (loop, seq);
02363 if (! find_reg_note (i1, REG_EQUAL, NULL_RTX))
02364 set_unique_reg_note (i1,
02365 m->is_equiv ? REG_EQUIV : REG_EQUAL,
02366 m->set_src);
02367
02368 if (loop_dump_stream)
02369 fprintf (loop_dump_stream, " moved to %d", INSN_UID (i1));
02370
02371
02372 threshold -= 3;
02373 }
02374 else
02375 {
02376 for (count = m->consec; count >= 0; count--)
02377 {
02378 rtx i1, temp;
02379
02380
02381
02382
02383 if (!NOTE_P (p)
02384 && (temp = find_reg_note (p, REG_LIBCALL, NULL_RTX)))
02385 p = XEXP (temp, 0);
02386
02387
02388
02389
02390 if (!NOTE_P (p)
02391 && (temp = find_reg_note (p, REG_RETVAL, NULL_RTX)))
02392 {
02393 rtx fn_address = 0;
02394 rtx fn_reg = 0;
02395 rtx fn_address_insn = 0;
02396
02397 first = 0;
02398 for (temp = XEXP (temp, 0); temp != p;
02399 temp = NEXT_INSN (temp))
02400 {
02401 rtx body;
02402 rtx n;
02403 rtx next;
02404
02405 if (NOTE_P (temp))
02406 continue;
02407
02408 body = PATTERN (temp);
02409
02410
02411
02412 for (next = NEXT_INSN (temp); next != p;
02413 next = NEXT_INSN (next))
02414 if (! (NONJUMP_INSN_P (next)
02415 && GET_CODE (PATTERN (next)) == USE)
02416 && !NOTE_P (next))
02417 break;
02418
02419
02420
02421
02422
02423
02424
02425
02426
02427
02428
02429
02430 if (CALL_P (next)
02431 && GET_CODE (body) == SET
02432 && REG_P (SET_DEST (body))
02433 && (n = find_reg_note (temp, REG_EQUAL,
02434 NULL_RTX)))
02435 {
02436 fn_reg = SET_SRC (body);
02437 if (!REG_P (fn_reg))
02438 fn_reg = SET_DEST (body);
02439 fn_address = XEXP (n, 0);
02440 fn_address_insn = temp;
02441 }
02442
02443
02444
02445 if (CALL_P (temp)
02446 && fn_address != 0
02447 && reg_referenced_p (fn_reg, body))
02448 loop_insn_emit_after (loop, 0, fn_address_insn,
02449 gen_move_insn
02450 (fn_reg, fn_address));
02451
02452 if (CALL_P (temp))
02453 {
02454 i1 = loop_call_insn_hoist (loop, body);
02455
02456
02457
02458 if (CALL_INSN_FUNCTION_USAGE (temp))
02459 CALL_INSN_FUNCTION_USAGE (i1)
02460 = copy_rtx (CALL_INSN_FUNCTION_USAGE (temp));
02461 }
02462 else
02463 i1 = loop_insn_hoist (loop, body);
02464 if (first == 0)
02465 first = i1;
02466 if (temp == fn_address_insn)
02467 fn_address_insn = i1;
02468 REG_NOTES (i1) = REG_NOTES (temp);
02469 REG_NOTES (temp) = NULL;
02470 delete_insn (temp);
02471 }
02472 if (new_start == 0)
02473 new_start = first;
02474 }
02475 if (m->savemode != VOIDmode)
02476 {
02477
02478
02479
02480 rtx reg = m->set_dest;
02481 rtx sequence;
02482 rtx tem;
02483
02484 start_sequence ();
02485 tem = expand_simple_binop
02486 (GET_MODE (reg), AND, reg,
02487 GEN_INT ((((HOST_WIDE_INT) 1
02488 << GET_MODE_BITSIZE (m->savemode)))
02489 - 1),
02490 reg, 1, OPTAB_LIB_WIDEN);
02491 if (tem == 0)
02492 abort ();
02493 if (tem != reg)
02494 emit_move_insn (reg, tem);
02495 sequence = get_insns ();
02496 end_sequence ();
02497 i1 = loop_insn_hoist (loop, sequence);
02498 }
02499 else if (CALL_P (p))
02500 {
02501 i1 = loop_call_insn_hoist (loop, PATTERN (p));
02502
02503
02504
02505 if (CALL_INSN_FUNCTION_USAGE (p))
02506 CALL_INSN_FUNCTION_USAGE (i1)
02507 = copy_rtx (CALL_INSN_FUNCTION_USAGE (p));
02508 }
02509 else if (count == m->consec && m->move_insn_first)
02510 {
02511 rtx seq;
02512
02513
02514 start_sequence ();
02515 emit_move_insn (m->insert_temp ? newreg : m->set_dest,
02516 m->set_src);
02517 seq = get_insns ();
02518 end_sequence ();
02519
02520 add_label_notes (m->set_src, seq);
02521
02522 i1 = loop_insn_hoist (loop, seq);
02523 if (! find_reg_note (i1, REG_EQUAL, NULL_RTX))
02524 set_unique_reg_note (i1, m->is_equiv ? REG_EQUIV
02525 : REG_EQUAL, m->set_src);
02526 }
02527 else if (m->insert_temp)
02528 {
02529 rtx *reg_map2 = xcalloc (REGNO (newreg),
02530 sizeof(rtx));
02531 reg_map2 [m->regno] = newreg;
02532
02533 i1 = loop_insn_hoist (loop, copy_rtx (PATTERN (p)));
02534 replace_regs (i1, reg_map2, REGNO (newreg), 1);
02535 free (reg_map2);
02536 }
02537 else
02538 i1 = loop_insn_hoist (loop, PATTERN (p));
02539
02540 if (REG_NOTES (i1) == 0)
02541 {
02542 REG_NOTES (i1) = REG_NOTES (p);
02543 REG_NOTES (p) = NULL;
02544
02545
02546
02547
02548
02549
02550
02551 if ((temp = find_reg_note (i1, REG_EQUAL, NULL_RTX))
02552 && ! loop_invariant_p (loop, XEXP (temp, 0)))
02553 remove_note (i1, temp);
02554 }
02555
02556 if (new_start == 0)
02557 new_start = i1;
02558
02559 if (loop_dump_stream)
02560 fprintf (loop_dump_stream, " moved to %d",
02561 INSN_UID (i1));
02562
02563
02564
02565
02566 if ((temp = find_reg_note (i1, REG_RETVAL, NULL_RTX)))
02567 {
02568 XEXP (temp, 0) = first;
02569 temp = find_reg_note (first, REG_LIBCALL, NULL_RTX);
02570 XEXP (temp, 0) = i1;
02571 }
02572
02573 temp = p;
02574 delete_insn (p);
02575 p = NEXT_INSN (p);
02576
02577
02578
02579
02580
02581
02582
02583 while (p && NOTE_P (p))
02584 p = NEXT_INSN (temp) = NEXT_INSN (p);
02585
02586 if (m->insert_temp)
02587 {
02588 rtx seq;
02589
02590
02591 start_sequence ();
02592 emit_move_insn (m->set_dest, newreg);
02593 seq = get_insns ();
02594 end_sequence ();
02595 emit_insn_before (seq, p);
02596 }
02597 }
02598
02599
02600 threshold -= 3;
02601 }
02602
02603 m->done = 1;
02604
02605 if (!m->insert_temp)
02606 {
02607
02608
02609 already_moved[regno] = 1;
02610
02611
02612 regs->array[regno].moved_once = 1;
02613
02614
02615 if (! m->partial)
02616 {
02617 int i;
02618 for (i = 0; i < LOOP_REGNO_NREGS (regno, m->set_dest); i++)
02619 regs->array[regno+i].set_in_loop = 0;
02620 }
02621
02622
02623
02624
02625
02626 if (REGNO_FIRST_LUID (regno) > INSN_LUID (loop_start))
02627
02628
02629
02630 REGNO_FIRST_UID (regno) = INSN_UID (loop_start);
02631 if (REGNO_LAST_LUID (regno) < INSN_LUID (loop_end))
02632 REGNO_LAST_UID (regno) = INSN_UID (loop_end);
02633 }
02634
02635
02636
02637 if (! m->partial)
02638 for (m1 = movables->head; m1; m1 = m1->next)
02639 if (m1->match == m)
02640 {
02641 rtx temp;
02642
02643
02644
02645
02646
02647
02648
02649
02650
02651
02652
02653
02654 if (GET_MODE (m->set_dest) == GET_MODE (m1->set_dest))
02655 reg_map[m1->regno] = m->set_dest;
02656 else
02657 reg_map[m1->regno]
02658 = gen_lowpart_common (GET_MODE (m1->set_dest),
02659 m->set_dest);
02660
02661
02662
02663 m1->done = 1;
02664
02665
02666 if ((temp = find_reg_note (m1->insn, REG_RETVAL,
02667 NULL_RTX)))
02668 delete_insn_chain (XEXP (temp, 0), m1->insn);
02669 else
02670 delete_insn (m1->insn);
02671
02672
02673
02674 already_moved[m1->regno] = 1;
02675
02676
02677
02678 if (! m->partial)
02679 {
02680 int i;
02681 for (i = 0;
02682 i < LOOP_REGNO_NREGS (regno, m1->set_dest);
02683 i++)
02684 regs->array[m1->regno+i].set_in_loop = 0;
02685 }
02686 }
02687 }
02688 else if (loop_dump_stream)
02689 fprintf (loop_dump_stream, "not desirable");
02690 }
02691 else if (loop_dump_stream && !m->match)
02692 fprintf (loop_dump_stream, "not safe");
02693
02694 if (loop_dump_stream)
02695 fprintf (loop_dump_stream, "\n");
02696 }
02697
02698 if (new_start == 0)
02699 new_start = loop_start;
02700
02701
02702
02703 for (p = new_start; p != loop_end; p = NEXT_INSN (p))
02704 if (INSN_P (p))
02705 {
02706 replace_regs (PATTERN (p), reg_map, nregs, 0);
02707 replace_regs (REG_NOTES (p), reg_map, nregs, 0);
02708 INSN_CODE (p) = -1;
02709 }
02710
02711
02712 free (reg_map);
02713 free (already_moved);
02714 }
02715
02716
02717 static void
02718 loop_movables_add (struct loop_movables *movables, struct movable *m)
02719 {
02720 if (movables->head == 0)
02721 movables->head = m;
02722 else
02723 movables->last->next = m;
02724 movables->last = m;
02725 }
02726
02727
02728 static void
02729 loop_movables_free (struct loop_movables *movables)
02730 {
02731 struct movable *m;
02732 struct movable *m_next;
02733
02734 for (m = movables->head; m; m = m_next)
02735 {
02736 m_next = m->next;
02737 free (m);
02738 }
02739 }
02740
02741 #if 0
02742
02743
02744
02745 static void
02746 replace_call_address (rtx x, rtx reg, rtx addr)
02747 {
02748 enum rtx_code code;
02749 int i;
02750 const char *fmt;
02751
02752 if (x == 0)
02753 return;
02754 code = GET_CODE (x);
02755 switch (code)
02756 {
02757 case PC:
02758 case CC0:
02759 case CONST_INT:
02760 case CONST_DOUBLE:
02761 case CONST:
02762 case SYMBOL_REF:
02763 case LABEL_REF:
02764 case REG:
02765 return;
02766
02767 case SET:
02768
02769 replace_call_address (XEXP (x, 1), reg, addr);
02770 return;
02771
02772 case CALL:
02773
02774 replace_call_address (XEXP (x, 0), reg, addr);
02775 return;
02776
02777 case MEM:
02778
02779
02780 if (XEXP (x, 0) != reg)
02781 abort ();
02782 XEXP (x, 0) = addr;
02783 return;
02784
02785 default:
02786 break;
02787 }
02788
02789 fmt = GET_RTX_FORMAT (code);
02790 for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
02791 {
02792 if (fmt[i] == 'e')
02793 replace_call_address (XEXP (x, i), reg, addr);
02794 else if (fmt[i] == 'E')
02795 {
02796 int j;
02797 for (j = 0; j < XVECLEN (x, i); j++)
02798 replace_call_address (XVECEXP (x, i, j), reg, addr);
02799 }
02800 }
02801 }
02802 #endif
02803
02804
02805
02806
02807 static int
02808 count_nonfixed_reads (const struct loop *loop, rtx x)
02809 {
02810 enum rtx_code code;
02811 int i;
02812 const char *fmt;
02813 int value;
02814
02815 if (x == 0)
02816 return 0;
02817
02818 code = GET_CODE (x);
02819 switch (code)
02820 {
02821 case PC:
02822 case CC0:
02823 case CONST_INT:
02824 case CONST_DOUBLE:
02825 case CONST:
02826 case SYMBOL_REF:
02827 case LABEL_REF:
02828 case REG:
02829 return 0;
02830
02831 case MEM:
02832 return ((loop_invariant_p (loop, XEXP (x, 0)) != 1)
02833 + count_nonfixed_reads (loop, XEXP (x, 0)));
02834
02835 default:
02836 break;
02837 }
02838
02839 value = 0;
02840 fmt = GET_RTX_FORMAT (code);
02841 for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
02842 {
02843 if (fmt[i] == 'e')
02844 value += count_nonfixed_reads (loop, XEXP (x, i));
02845 if (fmt[i] == 'E')
02846 {
02847 int j;
02848 for (j = 0; j < XVECLEN (x, i); j++)
02849 value += count_nonfixed_reads (loop, XVECEXP (x, i, j));
02850 }
02851 }
02852 return value;
02853 }
02854
02855
02856
02857
02858
02859
02860
02861 static void
02862 prescan_loop (struct loop *loop)
02863 {
02864 int level = 1;
02865 rtx insn;
02866 struct loop_info *loop_info = LOOP_INFO (loop);
02867 rtx start = loop->start;
02868 rtx end = loop->end;
02869
02870
02871
02872
02873 rtx exit_target = next_nonnote_insn (end);
02874
02875 loop_info->has_indirect_jump = indirect_jump_in_function;
02876 loop_info->pre_header_has_call = 0;
02877 loop_info->has_call = 0;
02878 loop_info->has_nonconst_call = 0;
02879 loop_info->has_prefetch = 0;
02880 loop_info->has_volatile = 0;
02881 loop_info->has_tablejump = 0;
02882 loop_info->has_multiple_exit_targets = 0;
02883 loop->level = 1;
02884
02885 loop_info->unknown_address_altered = 0;
02886 loop_info->unknown_constant_address_altered = 0;
02887 loop_info->store_mems = NULL_RTX;
02888 loop_info->first_loop_store_insn = NULL_RTX;
02889 loop_info->mems_idx = 0;
02890 loop_info->num_mem_sets = 0;
02891
02892 for (insn = start; insn && !LABEL_P (insn);
02893 insn = PREV_INSN (insn))
02894 {
02895 if (CALL_P (insn))
02896 {
02897 loop_info->pre_header_has_call = 1;
02898 break;
02899 }
02900 }
02901
02902 for (insn = NEXT_INSN (start); insn != NEXT_INSN (end);
02903 insn = NEXT_INSN (insn))
02904 {
02905 switch (GET_CODE (insn))
02906 {
02907 case NOTE:
02908 if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_BEG)
02909 {
02910 ++level;
02911
02912 loop->level++;
02913 }
02914 else if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_END)
02915 --level;
02916 break;
02917
02918 case CALL_INSN:
02919 if (! CONST_OR_PURE_CALL_P (insn))
02920 {
02921 loop_info->unknown_address_altered = 1;
02922 loop_info->has_nonconst_call = 1;
02923 }
02924 else if (pure_call_p (insn))
02925 loop_info->has_nonconst_call = 1;
02926 loop_info->has_call = 1;
02927 if (can_throw_internal (insn))
02928 loop_info->has_multiple_exit_targets = 1;
02929 break;
02930
02931 case JUMP_INSN:
02932 if (! loop_info->has_multiple_exit_targets)
02933 {
02934 rtx set = pc_set (insn);
02935
02936 if (set)
02937 {
02938 rtx src = SET_SRC (set);
02939 rtx label1, label2;
02940
02941 if (GET_CODE (src) == IF_THEN_ELSE)
02942 {
02943 label1 = XEXP (src, 1);
02944 label2 = XEXP (src, 2);
02945 }
02946 else
02947 {
02948 label1 = src;
02949 label2 = NULL_RTX;
02950 }
02951
02952 do
02953 {
02954 if (label1 && label1 != pc_rtx)
02955 {
02956 if (GET_CODE (label1) != LABEL_REF)
02957 {
02958
02959 loop_info->has_multiple_exit_targets = 1;
02960 break;
02961 }
02962 else if (XEXP (label1, 0) != exit_target
02963 && LABEL_OUTSIDE_LOOP_P (label1))
02964 {
02965
02966 loop_info->has_multiple_exit_targets = 1;
02967 break;
02968 }
02969 }
02970
02971 label1 = label2;
02972 label2 = NULL_RTX;
02973 }
02974 while (label1);
02975 }
02976 else
02977 {
02978
02979 loop_info->has_multiple_exit_targets = 1;
02980 }
02981 }
02982
02983
02984 case INSN:
02985 if (volatile_refs_p (PATTERN (insn)))
02986 loop_info->has_volatile = 1;
02987
02988 if (JUMP_P (insn)
02989 && (GET_CODE (PATTERN (insn)) == ADDR_DIFF_VEC
02990 || GET_CODE (PATTERN (insn)) == ADDR_VEC))
02991 loop_info->has_tablejump = 1;
02992
02993 note_stores (PATTERN (insn), note_addr_stored, loop_info);
02994 if (! loop_info->first_loop_store_insn && loop_info->store_mems)
02995 loop_info->first_loop_store_insn = insn;
02996
02997 if (flag_non_call_exceptions && can_throw_internal (insn))
02998 loop_info->has_multiple_exit_targets = 1;
02999 break;
03000
03001 default:
03002 break;
03003 }
03004 }
03005
03006
03007 if (
03008
03009 ! loop_info->has_nonconst_call
03010
03011
03012
03013
03014 && ! current_function_calls_alloca
03015
03016
03017 && ! loop_info->has_multiple_exit_targets)
03018 for (insn = NEXT_INSN (start); insn != NEXT_INSN (end);
03019 insn = NEXT_INSN (insn))
03020 for_each_rtx (&insn, insert_loop_mem, loop_info);
03021
03022
03023
03024
03025 if (loop_info->unknown_address_altered)
03026 {
03027 rtx mem = gen_rtx_MEM (BLKmode, const0_rtx);
03028
03029 loop_info->store_mems
03030 = gen_rtx_EXPR_LIST (VOIDmode, mem, loop_info->store_mems);
03031 }
03032 if (loop_info->unknown_constant_address_altered)
03033 {
03034 rtx mem = gen_rtx_MEM (BLKmode, const0_rtx);
03035 MEM_READONLY_P (mem) = 1;
03036 loop_info->store_mems
03037 = gen_rtx_EXPR_LIST (VOIDmode, mem, loop_info->store_mems);
03038 }
03039 }
03040
03041
03042
03043 static void
03044 invalidate_loops_containing_label (rtx label)
03045 {
03046 struct loop *loop;
03047 for (loop = uid_loop[INSN_UID (label)]; loop; loop = loop->outer)
03048 loop->invalid = 1;
03049 }
03050
03051
03052
03053
03054
03055 static void
03056 find_and_verify_loops (rtx f, struct loops *loops)
03057 {
03058 rtx insn;
03059 rtx label;
03060 int num_loops;
03061 struct loop *current_loop;
03062 struct loop *next_loop;
03063 struct loop *loop;
03064
03065 num_loops = loops->num;
03066
03067 compute_luids (f, NULL_RTX, 0);
03068
03069
03070
03071
03072 uid_loop[0] = NULL;
03073
03074
03075
03076
03077 num_loops = 0;
03078 current_loop = NULL;
03079 for (insn = f; insn; insn = NEXT_INSN (insn))
03080 {
03081 if (NOTE_P (insn))
03082 switch (NOTE_LINE_NUMBER (insn))
03083 {
03084 case NOTE_INSN_LOOP_BEG:
03085 next_loop = loops->array + num_loops;
03086 next_loop->num = num_loops;
03087 num_loops++;
03088 next_loop->start = insn;
03089 next_loop->outer = current_loop;
03090 current_loop = next_loop;
03091 break;
03092
03093 case NOTE_INSN_LOOP_END:
03094 if (! current_loop)
03095 abort ();
03096
03097 current_loop->end = insn;
03098 current_loop = current_loop->outer;
03099 break;
03100
03101 default:
03102 break;
03103 }
03104
03105 if (CALL_P (insn)
03106 && find_reg_note (insn, REG_SETJMP, NULL))
03107 {
03108
03109
03110 for (loop = current_loop; loop; loop = loop->outer)
03111 {
03112 loop->invalid = 1;
03113 if (loop_dump_stream)
03114 fprintf (loop_dump_stream,
03115 "\nLoop at %d ignored due to setjmp.\n",
03116 INSN_UID (loop->start));
03117 }
03118 }
03119
03120
03121
03122 uid_loop[INSN_UID (insn)] = current_loop;
03123 }
03124
03125
03126
03127 for (label = forced_labels; label; label = XEXP (label, 1))
03128 invalidate_loops_containing_label (XEXP (label, 0));
03129
03130
03131
03132 for_each_eh_label (invalidate_loops_containing_label);
03133
03134
03135
03136
03137
03138
03139
03140
03141
03142
03143
03144
03145
03146
03147 for (insn = f; insn; insn = NEXT_INSN (insn))
03148 if (INSN_P (insn))
03149 {
03150 struct loop *this_loop = uid_loop[INSN_UID (insn)];
03151
03152 if (NONJUMP_INSN_P (insn) || CALL_P (insn))
03153 {
03154 rtx note = find_reg_note (insn, REG_LABEL, NULL_RTX);
03155 if (note)
03156 invalidate_loops_containing_label (XEXP (note, 0));
03157 }
03158
03159 if (!JUMP_P (insn))
03160 continue;
03161
03162 mark_loop_jump (PATTERN (insn), this_loop);
03163
03164
03165 if (this_loop
03166 && (GET_CODE (PATTERN (insn)) == RETURN
03167 || (any_uncondjump_p (insn)
03168 && onlyjump_p (insn)
03169 && (uid_loop[INSN_UID (JUMP_LABEL (insn))]
03170 != this_loop)))
03171 && get_max_uid () < max_uid_for_loop)
03172 {
03173 rtx p;
03174 rtx our_next = next_real_insn (insn);
03175 rtx last_insn_to_move = NEXT_INSN (insn);
03176 struct loop *dest_loop;
03177 struct loop *outer_loop = NULL;
03178
03179
03180
03181 for (p = PREV_INSN (insn);
03182 !LABEL_P (p)
03183 && ! (NOTE_P (p)
03184 && NOTE_LINE_NUMBER (p) == NOTE_INSN_LOOP_BEG)
03185 && !JUMP_P (p);
03186 p = PREV_INSN (p))
03187 ;
03188
03189
03190
03191
03192 if (JUMP_LABEL (insn))
03193 {
03194 dest_loop = uid_loop[INSN_UID (JUMP_LABEL (insn))];
03195 if (dest_loop)
03196 {
03197 for (outer_loop = dest_loop; outer_loop;
03198 outer_loop = outer_loop->outer)
03199 if (outer_loop == this_loop)
03200 break;
03201 }
03202 }
03203
03204
03205
03206 if (JUMP_P (p) && JUMP_LABEL (p)
03207 && uid_loop[INSN_UID (JUMP_LABEL (p))] != this_loop)
03208 outer_loop = this_loop;
03209
03210
03211
03212
03213
03214
03215
03216
03217
03218
03219 if (! outer_loop
03220 && JUMP_P (p)
03221 && JUMP_LABEL (p) != 0
03222
03223
03224 && INSN_UID (JUMP_LABEL (p)) != 0
03225 && any_condjump_p (p) && onlyjump_p (p)
03226 && next_real_insn (JUMP_LABEL (p)) == our_next
03227
03228
03229 && insns_safe_to_move_p (p, NEXT_INSN (insn),
03230 &last_insn_to_move))
03231 {
03232 rtx target
03233 = JUMP_LABEL (insn) ? JUMP_LABEL (insn) : get_last_insn ();
03234 struct loop *target_loop = uid_loop[INSN_UID (target)];
03235 rtx loc, loc2;
03236 rtx tmp;
03237
03238
03239
03240 for (tmp = last_insn_to_move;
03241 tmp && !LABEL_P (tmp); tmp = NEXT_INSN (tmp))
03242 if (BARRIER_P (tmp))
03243 last_insn_to_move = tmp;
03244
03245 for (loc = target; loc; loc = PREV_INSN (loc))
03246 if (BARRIER_P (loc)
03247
03248 && ((loc2 = next_nonnote_insn (loc)) == 0
03249 || !LABEL_P (loc2)
03250 || (loc2 = next_nonnote_insn (loc2)) == 0
03251 || !JUMP_P (loc2)
03252 || (GET_CODE (PATTERN (loc2)) != ADDR_VEC
03253 && GET_CODE (PATTERN (loc2)) != ADDR_DIFF_VEC))
03254 && uid_loop[INSN_UID (loc)] == target_loop)
03255 break;
03256
03257 if (loc == 0)
03258 for (loc = target; loc; loc = NEXT_INSN (loc))
03259 if (BARRIER_P (loc)
03260
03261 && ((loc2 = next_nonnote_insn (loc)) == 0
03262 || !LABEL_P (loc2)
03263 || (loc2 = next_nonnote_insn (loc2)) == 0
03264 || !JUMP_P (loc2)
03265 || (GET_CODE (PATTERN (loc2)) != ADDR_VEC
03266 && GET_CODE (PATTERN (loc2)) != ADDR_DIFF_VEC))
03267 && uid_loop[INSN_UID (loc)] == target_loop)
03268 break;
03269
03270 if (loc)
03271 {
03272 rtx cond_label = JUMP_LABEL (p);
03273 rtx new_label = get_label_after (p);
03274
03275
03276 LABEL_NUSES (cond_label)++;
03277
03278
03279
03280 if (invert_jump (p, new_label, 1))
03281 {
03282 rtx q, r;
03283
03284
03285
03286
03287
03288
03289
03290
03291
03292
03293
03294 if (loc == 0)
03295 {
03296 rtx temp;
03297
03298 temp = gen_jump (JUMP_LABEL (insn));
03299 temp = emit_jump_insn_before (temp, target);
03300 JUMP_LABEL (temp) = JUMP_LABEL (insn);
03301 LABEL_NUSES (JUMP_LABEL (insn))++;
03302 loc = emit_barrier_before (target);
03303 }
03304
03305
03306
03307 if (squeeze_notes (&new_label, &last_insn_to_move))
03308 abort ();
03309 reorder_insns (new_label, last_insn_to_move, loc);
03310
03311
03312 for (q = new_label;
03313 q != NEXT_INSN (last_insn_to_move);
03314 q = NEXT_INSN (q))
03315 uid_loop[INSN_UID (q)] = target_loop;
03316
03317
03318
03319
03320
03321
03322 if (JUMP_LABEL (insn))
03323 {
03324 for (q = 0, r = this_loop->exit_labels;
03325 r;
03326 q = r, r = LABEL_NEXTREF (r))
03327 if (XEXP (r, 0) == JUMP_LABEL (insn))
03328 {
03329 LABEL_OUTSIDE_LOOP_P (r) = 0;
03330 if (q)
03331 LABEL_NEXTREF (q) = LABEL_NEXTREF (r);
03332 else
03333 this_loop->exit_labels = LABEL_NEXTREF (r);
03334 break;
03335 }
03336
03337 for (loop = this_loop; loop && loop != target_loop;
03338 loop = loop->outer)
03339 loop->exit_count--;
03340
03341
03342
03343 if (! r)
03344 abort ();
03345 }
03346
03347
03348
03349
03350
03351 mark_loop_jump (PATTERN (p), this_loop);
03352
03353
03354
03355 if (JUMP_LABEL (insn) != 0
03356 && (next_real_insn (JUMP_LABEL (insn))
03357 == next_real_insn (insn)))
03358 delete_related_insns (insn);
03359 }
03360
03361
03362
03363
03364
03365 insn = NEXT_INSN (cond_label);
03366
03367 if (--LABEL_NUSES (cond_label) == 0)
03368 delete_related_insns (cond_label);
03369
03370
03371 insn = PREV_INSN (insn);
03372 }
03373 }
03374 }
03375 }
03376 }
03377
03378
03379
03380
03381
03382
03383 static void
03384 mark_loop_jump (rtx x, struct loop *loop)
03385 {
03386 struct loop *dest_loop;
03387 struct loop *outer_loop;
03388 int i;
03389
03390 switch (GET_CODE (x))
03391 {
03392 case PC:
03393 case USE:
03394 case CLOBBER:
03395 case REG:
03396 case MEM:
03397 case CONST_INT:
03398 case CONST_DOUBLE:
03399 case RETURN:
03400 return;
03401
03402 case CONST:
03403
03404 mark_loop_jump (XEXP (x, 0), loop);
03405 return;
03406
03407 case PLUS:
03408 case MINUS:
03409 case MULT:
03410 mark_loop_jump (XEXP (x, 0), loop);
03411 mark_loop_jump (XEXP (x, 1), loop);
03412 return;
03413
03414 case LO_SUM:
03415
03416 mark_loop_jump (XEXP (x, 1), loop);
03417 return;
03418
03419 case SIGN_EXTEND:
03420 case ZERO_EXTEND:
03421 mark_loop_jump (XEXP (x, 0), loop);
03422 return;
03423
03424 case LABEL_REF:
03425 dest_loop = uid_loop[INSN_UID (XEXP (x, 0))];
03426
03427
03428
03429
03430
03431
03432
03433
03434 if (dest_loop)
03435 {
03436 for (outer_loop = dest_loop; outer_loop;
03437 outer_loop = outer_loop->outer)
03438 if (outer_loop == loop)
03439 break;
03440 }
03441 else
03442 outer_loop = NULL;
03443
03444 if (loop && ! outer_loop)
03445 {
03446 LABEL_OUTSIDE_LOOP_P (x) = 1;
03447 LABEL_NEXTREF (x) = loop->exit_labels;
03448 loop->exit_labels = x;
03449
03450 for (outer_loop = loop;
03451 outer_loop && outer_loop != dest_loop;
03452 outer_loop = outer_loop->outer)
03453 outer_loop->exit_count++;
03454 }
03455
03456
03457
03458
03459 if (! dest_loop)
03460 return;
03461
03462
03463
03464
03465 for (; dest_loop; dest_loop = dest_loop->outer)
03466 {
03467
03468 for (outer_loop = loop; outer_loop; outer_loop = outer_loop->outer)
03469 if (dest_loop == outer_loop)
03470 return;
03471
03472
03473 if (loop_dump_stream && ! dest_loop->invalid)
03474 fprintf (loop_dump_stream,
03475 "\nLoop at %d ignored due to multiple entry points.\n",
03476 INSN_UID (dest_loop->start));
03477
03478 dest_loop->invalid = 1;
03479 }
03480 return;
03481
03482 case SET:
03483
03484 if (SET_DEST (x) == pc_rtx)
03485 mark_loop_jump (SET_SRC (x), loop);
03486 return;
03487
03488 case IF_THEN_ELSE:
03489 mark_loop_jump (XEXP (x, 1), loop);
03490 mark_loop_jump (XEXP (x, 2), loop);
03491 return;
03492
03493 case PARALLEL:
03494 case ADDR_VEC:
03495 for (i = 0; i < XVECLEN (x, 0); i++)
03496 mark_loop_jump (XVECEXP (x, 0, i), loop);
03497 return;
03498
03499 case ADDR_DIFF_VEC:
03500 for (i = 0; i < XVECLEN (x, 1); i++)
03501 mark_loop_jump (XVECEXP (x, 1, i), loop);
03502 return;
03503
03504 default:
03505
03506
03507
03508
03509 if (loop)
03510 {
03511 for (outer_loop = loop; outer_loop; outer_loop = outer_loop->outer)
03512 {
03513 if (loop_dump_stream && ! outer_loop->invalid)
03514 fprintf (loop_dump_stream,
03515 "\nLoop at %d ignored due to unknown exit jump.\n",
03516 INSN_UID (outer_loop->start));
03517 outer_loop->invalid = 1;
03518 }
03519 }
03520 return;
03521 }
03522 }
03523
03524
03525
03526
03527
03528
03529 static int
03530 labels_in_range_p (rtx insn, int end)
03531 {
03532 while (insn && INSN_LUID (insn) <= end)
03533 {
03534 if (LABEL_P (insn))
03535 return 1;
03536 insn = NEXT_INSN (insn);
03537 }
03538
03539 return 0;
03540 }
03541
03542
03543
03544 static void
03545 note_addr_stored (rtx x, rtx y ATTRIBUTE_UNUSED,
03546 void *data ATTRIBUTE_UNUSED)
03547 {
03548 struct loop_info *loop_info = data;
03549
03550 if (x == 0 || !MEM_P (x))
03551 return;
03552
03553
03554
03555 loop_info->num_mem_sets++;
03556
03557
03558 if (GET_MODE (x) == BLKmode)
03559 {
03560 if (MEM_READONLY_P (x))
03561 loop_info->unknown_constant_address_altered = 1;
03562 else
03563 loop_info->unknown_address_altered = 1;
03564
03565 return;
03566 }
03567
03568 loop_info->store_mems = gen_rtx_EXPR_LIST (VOIDmode, x,
03569 loop_info->store_mems);
03570 }
03571
03572
03573
03574
03575
03576
03577 static void
03578 note_set_pseudo_multiple_uses (rtx x, rtx y ATTRIBUTE_UNUSED, void *data)
03579 {
03580 struct loop_regs *regs = (struct loop_regs *) data;
03581
03582 if (x == 0)
03583 return;
03584
03585 while (GET_CODE (x) == STRICT_LOW_PART
03586 || GET_CODE (x) == SIGN_EXTRACT
03587 || GET_CODE (x) == ZERO_EXTRACT
03588 || GET_CODE (x) == SUBREG)
03589 x = XEXP (x, 0);
03590
03591 if (!REG_P (x) || REGNO (x) < FIRST_PSEUDO_REGISTER)
03592 return;
03593
03594
03595
03596 if (REGNO (x) >= max_reg_before_loop
03597 || ! regs->array[REGNO (x)].single_usage
03598 || regs->array[REGNO (x)].single_usage == const0_rtx)
03599 regs->multiple_uses = 1;
03600 }
03601
03602
03603
03604
03605
03606
03607
03608
03609 static int
03610 loop_invariant_p (const struct loop *loop, rtx x)
03611 {
03612 struct loop_info *loop_info = LOOP_INFO (loop);
03613 struct loop_regs *regs = LOOP_REGS (loop);
03614 int i;
03615 enum rtx_code code;
03616 const char *fmt;
03617 int conditional = 0;
03618 rtx mem_list_entry;
03619
03620 if (x == 0)
03621 return 1;
03622 code = GET_CODE (x);
03623 switch (code)
03624 {
03625 case CONST_INT:
03626 case CONST_DOUBLE:
03627 case SYMBOL_REF:
03628 case CONST:
03629 return 1;
03630
03631 case LABEL_REF:
03632 return 1;
03633
03634 case PC:
03635 case CC0:
03636 case UNSPEC_VOLATILE:
03637 return 0;
03638
03639 case REG:
03640 if ((x == frame_pointer_rtx || x == hard_frame_pointer_rtx
03641 || x == arg_pointer_rtx || x == pic_offset_table_rtx)
03642 && ! current_function_has_nonlocal_goto)
03643 return 1;
03644
03645 if (LOOP_INFO (loop)->has_call
03646 && REGNO (x) < FIRST_PSEUDO_REGISTER && call_used_regs[REGNO (x)])
03647 return 0;
03648
03649
03650
03651
03652
03653
03654
03655
03656
03657
03658
03659 if (REGNO (x) >= (unsigned) regs->num)
03660 return 0;
03661
03662 if (regs->array[REGNO (x)].set_in_loop < 0)
03663 return 2;
03664
03665 return regs->array[REGNO (x)].set_in_loop == 0;
03666
03667 case MEM:
03668
03669
03670
03671 if (MEM_VOLATILE_P (x))
03672 return 0;
03673
03674
03675 mem_list_entry = loop_info->store_mems;
03676 while (mem_list_entry)
03677 {
03678 if (true_dependence (XEXP (mem_list_entry, 0), VOIDmode,
03679 x, rtx_varies_p))
03680 return 0;
03681
03682 mem_list_entry = XEXP (mem_list_entry, 1);
03683 }
03684
03685
03686
03687 break;
03688
03689 case ASM_OPERANDS:
03690
03691 if (MEM_VOLATILE_P (x))
03692 return 0;
03693 break;
03694
03695 default:
03696 break;
03697 }
03698
03699 fmt = GET_RTX_FORMAT (code);
03700 for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
03701 {
03702 if (fmt[i] == 'e')
03703 {
03704 int tem = loop_invariant_p (loop, XEXP (x, i));
03705 if (tem == 0)
03706 return 0;
03707 if (tem == 2)
03708 conditional = 1;
03709 }
03710 else if (fmt[i] == 'E')
03711 {
03712 int j;
03713 for (j = 0; j < XVECLEN (x, i); j++)
03714 {
03715 int tem = loop_invariant_p (loop, XVECEXP (x, i, j));
03716 if (tem == 0)
03717 return 0;
03718 if (tem == 2)
03719 conditional = 1;
03720 }
03721
03722 }
03723 }
03724
03725 return 1 + conditional;
03726 }
03727
03728
03729
03730
03731
03732
03733
03734
03735
03736
03737
03738 static int
03739 consec_sets_invariant_p (const struct loop *loop, rtx reg, int n_sets,
03740 rtx insn)
03741 {
03742 struct loop_regs *regs = LOOP_REGS (loop);
03743 rtx p = insn;
03744 unsigned int regno = REGNO (reg);
03745 rtx temp;
03746
03747 int count = n_sets - 1;
03748 int old = regs->array[regno].set_in_loop;
03749 int value = 0;
03750 int this;
03751
03752
03753 if (n_sets == 127)
03754 return 0;
03755
03756 regs->array[regno].set_in_loop = 0;
03757
03758 while (count > 0)
03759 {
03760 enum rtx_code code;
03761 rtx set;
03762
03763 p = NEXT_INSN (p);
03764 code = GET_CODE (p);
03765
03766
03767 if (code == INSN && (temp = find_reg_note (p, REG_LIBCALL, NULL_RTX)))
03768 p = XEXP (temp, 0);
03769
03770 this = 0;
03771 if (code == INSN
03772 && (set = single_set (p))
03773 && REG_P (SET_DEST (set))
03774 && REGNO (SET_DEST (set)) == regno)
03775 {
03776 this = loop_invariant_p (loop, SET_SRC (set));
03777 if (this != 0)
03778 value |= this;
03779 else if ((temp = find_reg_note (p, REG_EQUAL, NULL_RTX)))
03780 {
03781
03782
03783
03784 this = (CONSTANT_P (XEXP (temp, 0))
03785 || (find_reg_note (p, REG_RETVAL, NULL_RTX)
03786 && loop_invariant_p (loop, XEXP (temp, 0))));
03787 if (this != 0)
03788 value |= this;
03789 }
03790 }
03791 if (this != 0)
03792 count--;
03793 else if (code != NOTE)
03794 {
03795 regs->array[regno].set_in_loop = old;
03796 return 0;
03797 }
03798 }
03799
03800 regs->array[regno].set_in_loop = old;
03801
03802 return 1 + (value & 2);
03803 }
03804
03805
03806
03807
03808
03809 static void
03810 find_single_use_in_loop (struct loop_regs *regs, rtx insn, rtx x)
03811 {
03812 enum rtx_code code = GET_CODE (x);
03813 const char *fmt = GET_RTX_FORMAT (code);
03814 int i, j;
03815
03816 if (code == REG)
03817 regs->array[REGNO (x)].single_usage
03818 = (regs->array[REGNO (x)].single_usage != 0
03819 && regs->array[REGNO (x)].single_usage != insn)
03820 ? const0_rtx : insn;
03821
03822 else if (code == SET)
03823 {
03824
03825
03826
03827
03828 if (!REG_P (SET_DEST (x)))
03829 find_single_use_in_loop (regs, insn, SET_DEST (x));
03830 find_single_use_in_loop (regs, insn, SET_SRC (x));
03831 }
03832 else
03833 for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
03834 {
03835 if (fmt[i] == 'e' && XEXP (x, i) != 0)
03836 find_single_use_in_loop (regs, insn, XEXP (x, i));
03837 else if (fmt[i] == 'E')
03838 for (j = XVECLEN (x, i) - 1; j >= 0; j--)
03839 find_single_use_in_loop (regs, insn, XVECEXP (x, i, j));
03840 }
03841 }
03842
03843
03844
03845
03846
03847 static void
03848 count_one_set (struct loop_regs *regs, rtx insn, rtx x, rtx *last_set)
03849 {
03850 if (GET_CODE (x) == CLOBBER && REG_P (XEXP (x, 0)))
03851
03852
03853 regs->array[REGNO (XEXP (x, 0))].may_not_optimize = 1;
03854
03855 if (GET_CODE (x) == SET || GET_CODE (x) == CLOBBER)
03856 {
03857 rtx dest = SET_DEST (x);
03858 while (GET_CODE (dest) == SUBREG
03859 || GET_CODE (dest) == ZERO_EXTRACT
03860 || GET_CODE (dest) == STRICT_LOW_PART)
03861 dest = XEXP (dest, 0);
03862 if (REG_P (dest))
03863 {
03864 int i;
03865 int regno = REGNO (dest);
03866 for (i = 0; i < LOOP_REGNO_NREGS (regno, dest); i++)
03867 {
03868
03869
03870
03871
03872 if (regs->array[regno].set_in_loop > 0
03873 && last_set[regno] == 0)
03874 regs->array[regno+i].may_not_optimize = 1;
03875
03876
03877
03878 if (last_set[regno] != 0
03879 && reg_used_between_p (dest, last_set[regno], insn))
03880 regs->array[regno+i].may_not_optimize = 1;
03881 if (regs->array[regno+i].set_in_loop < 127)
03882 ++regs->array[regno+i].set_in_loop;
03883 last_set[regno+i] = insn;
03884 }
03885 }
03886 }
03887 }
03888
03889
03890
03891
03892
03893
03894
03895
03896
03897
03898 static int
03899 loop_reg_used_before_p (const struct loop *loop, rtx set, rtx insn)
03900 {
03901 rtx reg = SET_DEST (set);
03902 rtx p;
03903
03904
03905
03906 for (p = loop->scan_start; p != insn; p = NEXT_INSN (p))
03907 {
03908 if (INSN_P (p) && reg_overlap_mentioned_p (reg, PATTERN (p)))
03909 return 1;
03910
03911 if (p == loop->end)
03912 p = loop->start;
03913 }
03914
03915 return 0;
03916 }
03917
03918
03919
03920 struct prefetch_info
03921 {
03922 struct iv_class *class;
03923 struct induction *giv;
03924 rtx base_address;
03925
03926 HOST_WIDE_INT index;
03927 HOST_WIDE_INT stride;
03928
03929 unsigned int bytes_accessed;
03930
03931 unsigned int total_bytes;
03932
03933
03934
03935 int prefetch_in_loop;
03936 int prefetch_before_loop;
03937 unsigned int write : 1;
03938 };
03939
03940
03941 struct check_store_data
03942 {
03943 rtx mem_address;
03944 int mem_write;
03945 };
03946
03947 static void check_store (rtx, rtx, void *);
03948 static void emit_prefetch_instructions (struct loop *);
03949 static int rtx_equal_for_prefetch_p (rtx, rtx);
03950
03951
03952
03953 static void
03954 check_store (rtx x, rtx pat ATTRIBUTE_UNUSED, void *data)
03955 {
03956 struct check_store_data *d = (struct check_store_data *) data;
03957
03958 if ((MEM_P (x)) && rtx_equal_p (d->mem_address, XEXP (x, 0)))
03959 d->mem_write = 1;
03960 }
03961
03962
03963
03964
03965
03966
03967
03968
03969 static int
03970 rtx_equal_for_prefetch_p (rtx x, rtx y)
03971 {
03972 int i;
03973 int j;
03974 enum rtx_code code = GET_CODE (x);
03975 const char *fmt;
03976
03977 if (x == y)
03978 return 1;
03979 if (code != GET_CODE (y))
03980 return 0;
03981
03982 if (COMMUTATIVE_ARITH_P (x))
03983 {
03984 return ((rtx_equal_for_prefetch_p (XEXP (x, 0), XEXP (y, 0))
03985 && rtx_equal_for_prefetch_p (XEXP (x, 1), XEXP (y, 1)))
03986 || (rtx_equal_for_prefetch_p (XEXP (x, 0), XEXP (y, 1))
03987 && rtx_equal_for_prefetch_p (XEXP (x, 1), XEXP (y, 0))));
03988 }
03989
03990
03991
03992
03993 fmt = GET_RTX_FORMAT (code);
03994 for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
03995 {
03996 switch (fmt[i])
03997 {
03998 case 'w':
03999 if (XWINT (x, i) != XWINT (y, i))
04000 return 0;
04001 break;
04002
04003 case 'i':
04004 if (XINT (x, i) != XINT (y, i))
04005 return 0;
04006 break;
04007
04008 case 'E':
04009
04010 if (XVECLEN (x, i) != XVECLEN (y, i))
04011 return 0;
04012
04013
04014 for (j = 0; j < XVECLEN (x, i); j++)
04015 if (rtx_equal_for_prefetch_p (XVECEXP (x, i, j),
04016 XVECEXP (y, i, j)) == 0)
04017 return 0;
04018 break;
04019
04020 case 'e':
04021 if (rtx_equal_for_prefetch_p (XEXP (x, i), XEXP (y, i)) == 0)
04022 return 0;
04023 break;
04024
04025 case 's':
04026 if (strcmp (XSTR (x, i), XSTR (y, i)))
04027 return 0;
04028 break;
04029
04030 case 'u':
04031
04032 break;
04033
04034 case '0':
04035 break;
04036
04037
04038
04039
04040 default:
04041 abort ();
04042 }
04043 }
04044 return 1;
04045 }
04046
04047
04048
04049
04050 static HOST_WIDE_INT
04051 remove_constant_addition (rtx *x)
04052 {
04053 HOST_WIDE_INT addval = 0;
04054 rtx exp = *x;
04055
04056
04057 if (GET_CODE (exp) == CONST)
04058 {
04059 if (GET_CODE (XEXP (exp, 0)) == PLUS
04060 && GET_CODE (XEXP (XEXP (exp, 0), 0)) == SYMBOL_REF
04061 && GET_CODE (XEXP (XEXP (exp, 0), 1)) == CONST_INT)
04062 {
04063 *x = XEXP (XEXP (exp, 0), 0);
04064 return INTVAL (XEXP (XEXP (exp, 0), 1));
04065 }
04066 return 0;
04067 }
04068
04069 if (GET_CODE (exp) == CONST_INT)
04070 {
04071 addval = INTVAL (exp);
04072 *x = const0_rtx;
04073 }
04074
04075
04076 else if (GET_CODE (exp) == PLUS)
04077 {
04078 addval += remove_constant_addition (&XEXP (exp, 0));
04079 addval += remove_constant_addition (&XEXP (exp, 1));
04080
04081
04082
04083 if (XEXP (exp, 0) == const0_rtx)
04084 *x = XEXP (exp, 1);
04085 else if (XEXP (exp, 1) == const0_rtx)
04086 *x = XEXP (exp, 0);
04087 }
04088
04089 return addval;
04090 }
04091
04092
04093
04094
04095
04096
04097
04098
04099
04100
04101
04102
04103
04104
04105
04106
04107
04108
04109
04110
04111
04112 static void
04113 emit_prefetch_instructions (struct loop *loop)
04114 {
04115 int num_prefetches = 0;
04116 int num_real_prefetches = 0;
04117 int num_real_write_prefetches = 0;
04118 int num_prefetches_before = 0;
04119 int num_write_prefetches_before = 0;
04120 int ahead = 0;
04121 int i;
04122 struct iv_class *bl;
04123 struct induction *iv;
04124 struct prefetch_info info[MAX_PREFETCHES];
04125 struct loop_ivs *ivs = LOOP_IVS (loop);
04126
04127 if (!HAVE_prefetch || PREFETCH_BLOCK == 0)
04128 return;
04129
04130
04131
04132 if (PREFETCH_NO_CALL && LOOP_INFO (loop)->has_call)
04133 {
04134 if (loop_dump_stream)
04135 fprintf (loop_dump_stream, "Prefetch: ignoring loop: has call.\n");
04136
04137 return;
04138 }
04139
04140
04141 if (PREFETCH_NO_LOW_LOOPCNT
04142 && LOOP_INFO (loop)->n_iterations
04143 && LOOP_INFO (loop)->n_iterations <= PREFETCH_LOW_LOOPCNT)
04144 {
04145 if (loop_dump_stream)
04146 fprintf (loop_dump_stream,
04147 "Prefetch: ignoring loop: not enough iterations.\n");
04148 return;
04149 }
04150
04151
04152
04153 for (bl = ivs->list; bl; bl = bl->next)
04154 {
04155 struct induction *biv = bl->biv, *biv1;
04156 int basestride = 0;
04157
04158 biv1 = biv;
04159
04160
04161
04162 while (biv1)
04163 {
04164
04165
04166
04167
04168
04169 if (GET_CODE (biv->add_val) != CONST_INT)
04170 {
04171 if (loop_dump_stream)
04172 {
04173 fprintf (loop_dump_stream,
04174 "Prefetch: ignoring biv %d: non-constant addition at insn %d:",
04175 REGNO (biv->src_reg), INSN_UID (biv->insn));
04176 print_rtl (loop_dump_stream, biv->add_val);
04177 fprintf (loop_dump_stream, "\n");
04178 }
04179 break;
04180 }
04181
04182 if (biv->maybe_multiple)
04183 {
04184 if (loop_dump_stream)
04185 {
04186 fprintf (loop_dump_stream,
04187 "Prefetch: ignoring biv %d: maybe_multiple at insn %i:",
04188 REGNO (biv->src_reg), INSN_UID (biv->insn));
04189 print_rtl (loop_dump_stream, biv->add_val);
04190 fprintf (loop_dump_stream, "\n");
04191 }
04192 break;
04193 }
04194
04195 basestride += INTVAL (biv1->add_val);
04196 biv1 = biv1->next_iv;
04197 }
04198
04199 if (biv1 || !basestride)
04200 continue;
04201
04202 for (iv = bl->giv; iv; iv = iv->next_iv)
04203 {
04204 rtx address;
04205 rtx temp;
04206 HOST_WIDE_INT index = 0;
04207 int add = 1;
04208 HOST_WIDE_INT stride = 0;
04209 int stride_sign = 1;
04210 struct check_store_data d;
04211 const char *ignore_reason = NULL;
04212 int size = GET_MODE_SIZE (GET_MODE (iv));
04213
04214
04215
04216 if (iv->giv_type != DEST_ADDR)
04217 ignore_reason = "giv is not a destination address";
04218
04219
04220
04221 else if (GET_CODE (iv->mult_val) != CONST_INT)
04222 ignore_reason = "stride is not constant";
04223
04224 else
04225 {
04226 stride = INTVAL (iv->mult_val) * basestride;
04227 if (stride < 0)
04228 {
04229 stride = -stride;
04230 stride_sign = -1;
04231 }
04232
04233
04234
04235 if (PREFETCH_NO_REVERSE_ORDER && stride_sign < 0)
04236 ignore_reason = "reversed order stride";
04237
04238
04239
04240 else if (PREFETCH_NO_EXTREME_STRIDE
04241 && stride > PREFETCH_EXTREME_STRIDE)
04242 ignore_reason = "extreme stride";
04243
04244
04245
04246 else if (!loop_invariant_p (loop, iv->add_val))
04247 ignore_reason = "giv has varying add value";
04248
04249
04250
04251 else if (iv->maybe_multiple)
04252 ignore_reason = "giv is in nested loop";
04253 }
04254
04255 if (ignore_reason != NULL)
04256 {
04257 if (loop_dump_stream)
04258 fprintf (loop_dump_stream,
04259 "Prefetch: ignoring giv at %d: %s.\n",
04260 INSN_UID (iv->insn), ignore_reason);
04261 continue;
04262 }
04263
04264
04265
04266 address = copy_rtx (iv->add_val);
04267 temp = copy_rtx (bl->initial_value);
04268
04269 address = simplify_gen_binary (PLUS, Pmode, temp, address);
04270 index = remove_constant_addition (&address);
04271
04272 d.mem_write = 0;
04273 d.mem_address = *iv->location;
04274
04275
04276
04277 if (PREFETCH_CONDITIONAL || iv->always_executed)
04278 note_stores (PATTERN (iv->insn), check_store, &d);
04279 else
04280 {
04281 if (loop_dump_stream)
04282 fprintf (loop_dump_stream, "Prefetch: Ignoring giv at %d: %s\n",
04283 INSN_UID (iv->insn), "in conditional code.");
04284 continue;
04285 }
04286
04287
04288
04289 for (i = 0; i < num_prefetches; i++)
04290 if (rtx_equal_for_prefetch_p (address, info[i].base_address)
04291 && stride == info[i].stride)
04292 {
04293
04294
04295
04296
04297
04298
04299
04300 if (index >= info[i].index
04301 && index - info[i].index < PREFETCH_EXTREME_DIFFERENCE)
04302 {
04303 info[i].write |= d.mem_write;
04304 info[i].bytes_accessed += size;
04305 info[i].index = index;
04306 info[i].giv = iv;
04307 info[i].class = bl;
04308 info[num_prefetches].base_address = address;
04309 add = 0;
04310 break;
04311 }
04312
04313 if (index < info[i].index
04314 && info[i].index - index < PREFETCH_EXTREME_DIFFERENCE)
04315 {
04316 info[i].write |= d.mem_write;
04317 info[i].bytes_accessed += size;
04318 add = 0;
04319 break;
04320 }
04321 }
04322
04323
04324 if (add)
04325 {
04326 info[num_prefetches].giv = iv;
04327 info[num_prefetches].class = bl;
04328 info[num_prefetches].index = index;
04329 info[num_prefetches].stride = stride;
04330 info[num_prefetches].base_address = address;
04331 info[num_prefetches].write = d.mem_write;
04332 info[num_prefetches].bytes_accessed = size;
04333 num_prefetches++;
04334 if (num_prefetches >= MAX_PREFETCHES)
04335 {
04336 if (loop_dump_stream)
04337 fprintf (loop_dump_stream,
04338 "Maximal number of prefetches exceeded.\n");
04339 return;
04340 }
04341 }
04342 }
04343 }
04344
04345 for (i = 0; i < num_prefetches; i++)
04346 {
04347 int density;
04348
04349
04350
04351 if (LOOP_INFO (loop)->n_iterations
04352 && ((unsigned HOST_WIDE_INT) (0xffffffff / info[i].stride)
04353 >= LOOP_INFO (loop)->n_iterations))
04354 info[i].total_bytes = info[i].stride * LOOP_INFO (loop)->n_iterations;
04355 else
04356 info[i].total_bytes = 0xffffffff;
04357
04358 density = info[i].bytes_accessed * 100 / info[i].stride;
04359
04360
04361 if (PREFETCH_ONLY_DENSE_MEM)
04362 if (density * 256 > PREFETCH_DENSE_MEM * 100
04363 && (info[i].total_bytes / PREFETCH_BLOCK
04364 >= PREFETCH_BLOCKS_BEFORE_LOOP_MIN))
04365 {
04366 info[i].prefetch_before_loop = 1;
04367 info[i].prefetch_in_loop
04368 = (info[i].total_bytes / PREFETCH_BLOCK
04369 > PREFETCH_BLOCKS_BEFORE_LOOP_MAX);
04370 }
04371 else
04372 {
04373 info[i].prefetch_in_loop = 0, info[i].prefetch_before_loop = 0;
04374 if (loop_dump_stream)
04375 fprintf (loop_dump_stream,
04376 "Prefetch: ignoring giv at %d: %d%% density is too low.\n",
04377 INSN_UID (info[i].giv->insn), density);
04378 }
04379 else
04380 info[i].prefetch_in_loop = 1, info[i].prefetch_before_loop = 1;
04381
04382
04383 if (info[i].prefetch_in_loop != 0)
04384 {
04385 info[i].prefetch_in_loop = ((info[i].stride + PREFETCH_BLOCK - 1)
04386 / PREFETCH_BLOCK);
04387 num_real_prefetches += info[i].prefetch_in_loop;
04388 if (info[i].write)
04389 num_real_write_prefetches += info[i].prefetch_in_loop;
04390 }
04391 }
04392
04393
04394
04395 if (num_real_prefetches != 0)
04396 {
04397 if ((ahead = SIMULTANEOUS_PREFETCHES / num_real_prefetches) == 0)
04398 {
04399 if (loop_dump_stream)
04400 fprintf (loop_dump_stream,
04401 "Prefetch: ignoring prefetches within loop: ahead is zero; %d < %d\n",
04402 SIMULTANEOUS_PREFETCHES, num_real_prefetches);
04403 num_real_prefetches = 0, num_real_write_prefetches = 0;
04404 }
04405 }
04406
04407
04408 if (ahead == 0)
04409 ahead = PREFETCH_BLOCKS_BEFORE_LOOP_MAX;
04410
04411 for (i = 0; i < num_prefetches; i++)
04412 {
04413
04414 if (num_real_prefetches == 0)
04415 info[i].prefetch_in_loop = 0;
04416
04417
04418 if (info[i].prefetch_before_loop != 0)
04419 {
04420 int n = info[i].total_bytes / PREFETCH_BLOCK;
04421 if (n > ahead)
04422 n = ahead;
04423 info[i].prefetch_before_loop = n;
04424 num_prefetches_before += n;
04425 if (info[i].write)
04426 num_write_prefetches_before += n;
04427 }
04428
04429 if (loop_dump_stream)
04430 {
04431 if (info[i].prefetch_in_loop == 0
04432 && info[i].prefetch_before_loop == 0)
04433 continue;
04434 fprintf (loop_dump_stream, "Prefetch insn: %d",
04435 INSN_UID (info[i].giv->insn));
04436 fprintf (loop_dump_stream,
04437 "; in loop: %d; before: %d; %s\n",
04438 info[i].prefetch_in_loop,
04439 info[i].prefetch_before_loop,
04440 info[i].write ? "read/write" : "read only");
04441 fprintf (loop_dump_stream,
04442 " density: %d%%; bytes_accessed: %u; total_bytes: %u\n",
04443 (int) (info[i].bytes_accessed * 100 / info[i].stride),
04444 info[i].bytes_accessed, info[i].total_bytes);
04445 fprintf (loop_dump_stream, " index: " HOST_WIDE_INT_PRINT_DEC
04446 "; stride: " HOST_WIDE_INT_PRINT_DEC "; address: ",
04447 info[i].index, info[i].stride);
04448 print_rtl (loop_dump_stream, info[i].base_address);
04449 fprintf (loop_dump_stream, "\n");
04450 }
04451 }
04452
04453 if (num_real_prefetches + num_prefetches_before > 0)
04454 {
04455
04456 LOOP_INFO (loop)->has_prefetch = 1;
04457
04458 if (loop_dump_stream)
04459 {
04460 fprintf (loop_dump_stream, "Real prefetches needed within loop: %d (write: %d)\n",
04461 num_real_prefetches, num_real_write_prefetches);
04462 fprintf (loop_dump_stream, "Real prefetches needed before loop: %d (write: %d)\n",
04463 num_prefetches_before, num_write_prefetches_before);
04464 }
04465 }
04466
04467 for (i = 0; i < num_prefetches; i++)
04468 {
04469 int y;
04470
04471 for (y = 0; y < info[i].prefetch_in_loop; y++)
04472 {
04473 rtx loc = copy_rtx (*info[i].giv->location);
04474 rtx insn;
04475 int bytes_ahead = PREFETCH_BLOCK * (ahead + y);
04476 rtx before_insn = info[i].giv->insn;
04477 rtx prev_insn = PREV_INSN (info[i].giv->insn);
04478 rtx seq;
04479
04480
04481
04482 if (offsettable_address_p (0, VOIDmode, loc))
04483 loc = plus_constant (loc, bytes_ahead);
04484 else
04485 {
04486 rtx reg = gen_reg_rtx (Pmode);
04487 loop_iv_add_mult_emit_before (loop, loc, const1_rtx,
04488 GEN_INT (bytes_ahead), reg,
04489 0, before_insn);
04490 loc = reg;
04491 }
04492
04493 start_sequence ();
04494
04495 if (! (*insn_data[(int)CODE_FOR_prefetch].operand[0].predicate)
04496 (loc, insn_data[(int)CODE_FOR_prefetch].operand[0].mode))
04497 loc = force_reg (Pmode, loc);
04498 emit_insn (gen_prefetch (loc, GEN_INT (info[i].write),
04499 GEN_INT (3)));
04500 seq = get_insns ();
04501 end_sequence ();
04502 emit_insn_before (seq, before_insn);
04503
04504
04505
04506 insn = NEXT_INSN (prev_insn);
04507 while (insn != before_insn)
04508 {
04509 insn = check_insn_for_givs (loop, insn,
04510 info[i].giv->always_executed,
04511 info[i].giv->maybe_multiple);
04512 insn = NEXT_INSN (insn);
04513 }
04514 }
04515
04516 if (PREFETCH_BEFORE_LOOP)
04517 {
04518
04519
04520
04521 for (y = 0; y < info[i].prefetch_before_loop; y++)
04522 {
04523 rtx reg = gen_reg_rtx (Pmode);
04524 rtx loop_start = loop->start;
04525 rtx init_val = info[i].class->initial_value;
04526 rtx add_val = simplify_gen_binary (PLUS, Pmode,
04527 info[i].giv->add_val,
04528 GEN_INT (y * PREFETCH_BLOCK));
04529
04530
04531
04532
04533 if (GET_MODE (init_val) != Pmode && !CONSTANT_P (init_val))
04534 {
04535 rtx seq;
04536
04537 start_sequence ();
04538 init_val = convert_to_mode (Pmode, init_val, 0);
04539 seq = get_insns ();
04540 end_sequence ();
04541 loop_insn_emit_before (loop, 0, loop_start, seq);
04542 }
04543 loop_iv_add_mult_emit_before (loop, init_val,
04544 info[i].giv->mult_val,
04545 add_val, reg, 0, loop_start);
04546 emit_insn_before (gen_prefetch (reg, GEN_INT (info[i].write),
04547 GEN_INT (3)),
04548 loop_start);
04549 }
04550 }
04551 }
04552
04553 return;
04554 }
04555
04556
04557
04558 static rtx note_insn;
04559
04560
04561
04562 static rtx addr_placeholder;
04563
04564
04565
04566
04567
04568
04569
04570
04571
04572
04573
04574
04575
04576
04577
04578
04579
04580
04581
04582
04583
04584
04585
04586
04587
04588
04589
04590
04591
04592
04593
04594
04595
04596
04597
04598
04599 static int
04600 back_branch_in_range_p (const struct loop *loop, rtx insn)
04601 {
04602 rtx p, q, target_insn;
04603 rtx loop_start = loop->start;
04604 rtx loop_end = loop->end;
04605 rtx orig_loop_end = loop->end;
04606
04607
04608 loop_end = prev_nonnote_insn (loop_end);
04609 if (BARRIER_P (loop_end))
04610 loop_end = PREV_INSN (loop_end);
04611
04612
04613
04614 while (INSN_DELETED_P (insn))
04615 insn = NEXT_INSN (insn);
04616
04617
04618
04619
04620 if (insn == loop_end || insn == orig_loop_end)
04621 return 0;
04622
04623 for (p = NEXT_INSN (insn); p != loop_end; p = NEXT_INSN (p))
04624 {
04625 if (JUMP_P (p))
04626 {
04627 target_insn = JUMP_LABEL (p);
04628
04629
04630
04631
04632 for (q = loop_start; q != insn; q = NEXT_INSN (q))
04633 if (q == target_insn)
04634 return 1;
04635 }
04636 }
04637
04638 return 0;
04639 }
04640
04641
04642
04643
04644
04645
04646
04647
04648
04649
04650
04651 typedef rtx (*loop_insn_callback) (struct loop *, rtx, int, int);
04652 static void
04653 for_each_insn_in_loop (struct loop *loop, loop_insn_callback fncall)
04654 {
04655 int not_every_iteration = 0;
04656 int maybe_multiple = 0;
04657 int past_loop_latch = 0;
04658 bool exit_test_is_entry = false;
04659 rtx p;
04660
04661
04662
04663
04664
04665 if (prev_nonnote_insn (loop->scan_start) != prev_nonnote_insn (loop->start))
04666 {
04667 exit_test_is_entry = true;
04668 maybe_multiple = back_branch_in_range_p (loop, loop->scan_start);
04669 }
04670
04671
04672 for (p = next_insn_in_loop (loop, loop->scan_start);
04673 p != NULL_RTX;
04674 p = next_insn_in_loop (loop, p))
04675 {
04676 p = fncall (loop, p, not_every_iteration, maybe_multiple);
04677
04678
04679
04680
04681
04682
04683
04684 if (LABEL_P (p))
04685 {
04686 rtx insn = p;
04687
04688 maybe_multiple = 0;
04689
04690 while (1)
04691 {
04692 insn = NEXT_INSN (insn);
04693 if (insn == loop->scan_start)
04694 break;
04695 if (insn == loop->end)
04696 {
04697 if (loop->top != 0)
04698 insn = loop->top;
04699 else
04700 break;
04701 if (insn == loop->scan_start)
04702 break;
04703 }
04704
04705 if (JUMP_P (insn)
04706 && GET_CODE (PATTERN (insn)) != RETURN
04707 && (!any_condjump_p (insn)
04708 || (JUMP_LABEL (insn) != 0
04709 && JUMP_LABEL (insn) != loop->scan_start
04710 && !loop_insn_first_p (p, JUMP_LABEL (insn)))))
04711 {
04712 maybe_multiple = 1;
04713 break;
04714 }
04715 }
04716 }
04717
04718
04719
04720
04721
04722 if (JUMP_P (p)
04723
04724
04725
04726
04727 && (exit_test_is_entry
04728 || !(JUMP_LABEL (p) == loop->top
04729 && ((NEXT_INSN (NEXT_INSN (p)) == loop->end
04730 && any_uncondjump_p (p))
04731 || (NEXT_INSN (p) == loop->end
04732 && any_condjump_p (p))))))
04733 {
04734 rtx label = 0;
04735
04736
04737
04738
04739
04740 for (label = loop->exit_labels; label; label = LABEL_NEXTREF (label))
04741 if (XEXP (label, 0) == JUMP_LABEL (p))
04742 break;
04743
04744 if (!label)
04745 not_every_iteration = 1;
04746 }
04747
04748
04749
04750
04751
04752
04753
04754
04755
04756 if (JUMP_P (p)
04757 && JUMP_LABEL (p) == NEXT_INSN (loop->start))
04758 past_loop_latch = 1;
04759
04760
04761
04762
04763
04764
04765
04766
04767
04768
04769
04770 if (not_every_iteration
04771 && !past_loop_latch
04772 && LABEL_P (p)
04773 && no_labels_between_p (p, loop->end))
04774 not_every_iteration = 0;
04775 }
04776 }
04777
04778 static void
04779 loop_bivs_find (struct loop *loop)
04780 {
04781 struct loop_regs *regs = LOOP_REGS (loop);
04782 struct loop_ivs *ivs = LOOP_IVS (loop);
04783
04784 struct iv_class *bl, **backbl;
04785
04786 ivs->list = 0;
04787
04788 for_each_insn_in_loop (loop, check_insn_for_bivs);
04789
04790
04791
04792 for (backbl = &ivs->list, bl = *backbl; bl; bl = bl->next)
04793 {
04794 if (REG_IV_TYPE (ivs, bl->regno) != BASIC_INDUCT
04795
04796
04797 || regs->array[bl->regno].n_times_set != bl->biv_count
04798
04799
04800 || ! bl->incremented)
04801 {
04802 if (loop_dump_stream)
04803 fprintf (loop_dump_stream, "Biv %d: discarded, %s\n",
04804 bl->regno,
04805 (REG_IV_TYPE (ivs, bl->regno) != BASIC_INDUCT
04806 ? "not induction variable"
04807 : (! bl->incremented ? "never incremented"
04808 : "count error")));
04809
04810 REG_IV_TYPE (ivs, bl->regno) = NOT_BASIC_INDUCT;
04811 *backbl = bl->next;
04812 }
04813 else
04814 {
04815 backbl = &bl->next;
04816
04817 if (loop_dump_stream)
04818 fprintf (loop_dump_stream, "Biv %d: verified\n", bl->regno);
04819 }
04820 }
04821 }
04822
04823
04824
04825
04826 static void
04827 loop_bivs_init_find (struct loop *loop)
04828 {
04829 struct loop_ivs *ivs = LOOP_IVS (loop);
04830
04831 struct iv_class *bl;
04832 int call_seen;
04833 rtx p;
04834
04835
04836
04837
04838 call_seen = 0;
04839 for (p = loop->start; p && !LABEL_P (p); p = PREV_INSN (p))
04840 {
04841 rtx test;
04842
04843 note_insn = p;
04844
04845 if (CALL_P (p))
04846 call_seen = 1;
04847
04848 if (INSN_P (p))
04849 note_stores (PATTERN (p), record_initial, ivs);
04850
04851
04852
04853
04854 if (JUMP_P (p)
04855 && JUMP_LABEL (p) != 0
04856 && next_real_insn (JUMP_LABEL (p)) == next_real_insn (loop->end)
04857 && (test = get_condition_for_loop (loop, p)) != 0
04858 && REG_P (XEXP (test, 0))
04859 && REGNO (XEXP (test, 0)) < max_reg_before_loop
04860 && (bl = REG_IV_CLASS (ivs, REGNO (XEXP (test, 0)))) != 0
04861 && valid_initial_value_p (XEXP (test, 1), p, call_seen, loop->start)
04862 && bl->init_insn == 0)
04863 {
04864
04865 if (GET_CODE (test) == NE)
04866 {
04867 bl->init_insn = p;
04868 bl->init_set = gen_rtx_SET (VOIDmode,
04869 XEXP (test, 0), XEXP (test, 1));
04870 }
04871 else
04872 bl->initial_test = test;
04873 }
04874 }
04875 }
04876
04877
04878
04879
04880
04881 static void
04882 loop_bivs_check (struct loop *loop)
04883 {
04884 struct loop_ivs *ivs = LOOP_IVS (loop);
04885
04886 struct iv_class *bl;
04887 struct iv_class **backbl;
04888
04889 for (backbl = &ivs->list; (bl = *backbl); backbl = &bl->next)
04890 {
04891 rtx src;
04892 rtx note;
04893
04894 if (! bl->init_insn)
04895 continue;
04896
04897
04898
04899 if (((note = find_reg_note (bl->init_insn, REG_EQUAL, 0)) != NULL
04900 && CONSTANT_P (XEXP (note, 0)))
04901 || ((note = find_reg_note (bl->init_insn, REG_EQUIV, 0)) != NULL
04902 && CONSTANT_P (XEXP (note, 0))))
04903 src = XEXP (note, 0);
04904 else
04905 src = SET_SRC (bl->init_set);
04906
04907 if (loop_dump_stream)
04908 fprintf (loop_dump_stream,
04909 "Biv %d: initialized at insn %d: initial value ",
04910 bl->regno, INSN_UID (bl->init_insn));
04911
04912 if ((GET_MODE (src) == GET_MODE (regno_reg_rtx[bl->regno])
04913 || GET_MODE (src) == VOIDmode)
04914 && valid_initial_value_p (src, bl->init_insn,
04915 LOOP_INFO (loop)->pre_header_has_call,
04916 loop->start))
04917 {
04918 bl->initial_value = src;
04919
04920 if (loop_dump_stream)
04921 {
04922 print_simple_rtl (loop_dump_stream, src);
04923 fputc ('\n', loop_dump_stream);
04924 }
04925 }
04926
04927
04928 else if (loop_dump_stream)
04929 fprintf (loop_dump_stream, "is complex\n");
04930 }
04931 }
04932
04933
04934
04935
04936 static void
04937 loop_givs_find (struct loop* loop)
04938 {
04939 for_each_insn_in_loop (loop, check_insn_for_givs);
04940 }
04941
04942
04943
04944
04945
04946
04947 static void
04948 loop_givs_check (struct loop *loop)
04949 {
04950 struct loop_ivs *ivs = LOOP_IVS (loop);
04951 struct iv_class *bl;
04952
04953 for (bl = ivs->list; bl; bl = bl->next)
04954 {
04955 struct induction *v;
04956
04957 for (v = bl->giv; v; v = v->next_iv)
04958 if (! v->replaceable && ! v->not_replaceable)
04959 check_final_value (loop, v);
04960 }
04961 }
04962
04963
04964
04965
04966
04967 static rtx
04968 fold_rtx_mult_add (rtx mult1, rtx mult2, rtx add1, enum machine_mode mode)
04969 {
04970 rtx temp, mult_res;
04971 rtx result;
04972
04973
04974
04975 if ((GET_MODE (mult1) != mode && GET_MODE (mult1) != VOIDmode)
04976 || (GET_MODE (mult2) != mode && GET_MODE (mult2) != VOIDmode)
04977 || (GET_MODE (add1) != mode && GET_MODE (add1) != VOIDmode))
04978 abort ();
04979
04980
04981
04982 if (GET_CODE (mult1) == CONST_INT)
04983 {
04984 temp = mult2;
04985 mult2 = mult1;
04986 mult1 = temp;
04987 }
04988
04989 mult_res = simplify_binary_operation (MULT, mode, mult1, mult2);
04990 if (! mult_res)
04991 mult_res = gen_rtx_MULT (mode, mult1, mult2);
04992
04993
04994 if (GET_CODE (add1) == CONST_INT)
04995 {
04996 temp = add1;
04997 add1 = mult_res;
04998 mult_res = temp;
04999 }
05000
05001 result = simplify_binary_operation (PLUS, mode, add1, mult_res);
05002 if (! result)
05003 result = gen_rtx_PLUS (mode, add1, mult_res);
05004
05005 return result;
05006 }
05007
05008
05009
05010
05011
05012
05013
05014 static rtx
05015 biv_total_increment (const struct iv_class *bl)
05016 {
05017 struct induction *v;
05018 rtx result;
05019
05020
05021
05022
05023
05024
05025
05026
05027 result = const0_rtx;
05028 for (v = bl->biv; v; v = v->next_iv)
05029 {
05030 if (v->always_computable && v->mult_val == const1_rtx
05031 && ! v->maybe_multiple
05032 && SCALAR_INT_MODE_P (v->mode))
05033 {
05034
05035 if (v->same)
05036 continue;
05037
05038 result = fold_rtx_mult_add (result, const1_rtx, v->add_val, v->mode);
05039 }
05040 else
05041 return 0;
05042 }
05043
05044 return result;
05045 }
05046
05047
05048
05049
05050
05051
05052
05053
05054
05055 static int
05056 reg_dead_after_loop (const struct loop *loop, rtx reg)
05057 {
05058 rtx insn, label;
05059 int jump_count = 0;
05060 int label_count = 0;
05061
05062
05063
05064
05065
05066
05067 for (label = loop->exit_labels; label; label = LABEL_NEXTREF (label))
05068 label_count++;
05069
05070 if (label_count != loop->exit_count)
05071 return 0;
05072
05073
05074
05075
05076 label = gen_rtx_LABEL_REF (VOIDmode, loop->end);
05077 LABEL_NEXTREF (label) = loop->exit_labels;
05078
05079 for (; label; label = LABEL_NEXTREF (label))
05080 {
05081
05082
05083
05084
05085 insn = NEXT_INSN (XEXP (label, 0));
05086 while (insn)
05087 {
05088 if (INSN_P (insn))
05089 {
05090 rtx set, note;
05091
05092 if (reg_referenced_p (reg, PATTERN (insn)))
05093 return 0;
05094
05095 note = find_reg_equal_equiv_note (insn);
05096 if (note && reg_overlap_mentioned_p (reg, XEXP (note, 0)))
05097 return 0;
05098
05099 set = single_set (insn);
05100 if (set && rtx_equal_p (SET_DEST (set), reg))
05101 break;
05102
05103 if (JUMP_P (insn))
05104 {
05105 if (GET_CODE (PATTERN (insn)) == RETURN)
05106 break;
05107 else if (!any_uncondjump_p (insn)
05108
05109 || jump_count++ > 20)
05110 return 0;
05111 else
05112 insn = JUMP_LABEL (insn);
05113 }
05114 }
05115
05116 insn = NEXT_INSN (insn);
05117 }
05118 }
05119
05120
05121 return 1;
05122 }
05123
05124
05125
05126
05127 static rtx
05128 final_biv_value (const struct loop *loop, struct iv_class *bl)
05129 {
05130 unsigned HOST_WIDE_INT n_iterations = LOOP_INFO (loop)->n_iterations;
05131 rtx increment, tem;
05132
05133
05134
05135 if (GET_MODE_CLASS (bl->biv->mode) != MODE_INT)
05136 return 0;
05137
05138
05139
05140
05141
05142 if (bl->reversed)
05143 {
05144 if (loop_dump_stream)
05145 fprintf (loop_dump_stream,
05146 "Final biv value for %d, reversed biv.\n", bl->regno);
05147
05148 return const0_rtx;
05149 }
05150
05151
05152
05153
05154
05155
05156
05157 if (n_iterations != 0
05158 && ! loop->exit_count
05159 && loop_invariant_p (loop, bl->initial_value))
05160 {
05161 increment = biv_total_increment (bl);
05162
05163 if (increment && loop_invariant_p (loop, increment))
05164 {
05165
05166
05167
05168
05169 tem = gen_reg_rtx (bl->biv->mode);
05170 record_base_value (REGNO (tem), bl->biv->add_val, 0);
05171 loop_iv_add_mult_sink (loop, increment, GEN_INT (n_iterations),
05172 bl->initial_value, tem);
05173
05174 if (loop_dump_stream)
05175 fprintf (loop_dump_stream,
05176 "Final biv value for %d, calculated.\n", bl->regno);
05177
05178 return tem;
05179 }
05180 }
05181
05182
05183 if (reg_dead_after_loop (loop, bl->biv->src_reg))
05184 {
05185 if (loop_dump_stream)
05186 fprintf (loop_dump_stream,
05187 "Final biv value for %d, biv dead after loop exit.\n",
05188 bl->regno);
05189
05190 return const0_rtx;
05191 }
05192
05193 return 0;
05194 }
05195
05196
05197
05198
05199
05200
05201 static int
05202 loop_biv_eliminable_p (struct loop *loop, struct iv_class *bl,
05203 int threshold, int insn_count)
05204 {
05205
05206
05207
05208
05209 #ifdef HAVE_decrement_and_branch_until_zero
05210 if (bl->nonneg)
05211 {
05212 if (loop_dump_stream)
05213 fprintf (loop_dump_stream,
05214 "Cannot eliminate nonneg biv %d.\n", bl->regno);
05215 return 0;
05216 }
05217 #endif
05218
05219
05220
05221
05222
05223
05224
05225
05226 if ((REGNO_LAST_LUID (bl->regno) < INSN_LUID (loop->end)
05227 && bl->init_insn
05228 && INSN_UID (bl->init_insn) < max_uid_for_loop
05229 && REGNO_FIRST_LUID (bl->regno) >= INSN_LUID (bl->init_insn)
05230 && ! reg_mentioned_p (bl->biv->dest_reg, SET_SRC (bl->init_set)))
05231 || (bl->final_value = final_biv_value (loop, bl)))
05232 return maybe_eliminate_biv (loop, bl, 0, threshold, insn_count);
05233
05234 if (loop_dump_stream)
05235 {
05236 fprintf (loop_dump_stream,
05237 "Cannot eliminate biv %d.\n",
05238 bl->regno);
05239 fprintf (loop_dump_stream,
05240 "First use: insn %d, last use: insn %d.\n",
05241 REGNO_FIRST_UID (bl->regno),
05242 REGNO_LAST_UID (bl->regno));
05243 }
05244 return 0;
05245 }
05246
05247
05248
05249
05250 static void
05251 loop_givs_reduce (struct loop *loop, struct iv_class *bl)
05252 {
05253 struct induction *v;
05254
05255 for (v = bl->giv; v; v = v->next_iv)
05256 {
05257 struct induction *tv;
05258 if (! v->ignore && v->same == 0)
05259 {
05260 int auto_inc_opt = 0;
05261
05262
05263
05264 if (! v->new_reg)
05265 v->new_reg = gen_reg_rtx (v->mode);
05266
05267 #ifdef AUTO_INC_DEC
05268
05269
05270
05271
05272
05273
05274
05275
05276
05277
05278
05279
05280
05281
05282 if (v->giv_type == DEST_ADDR && bl->biv_count == 1
05283 && bl->biv->always_executed && ! bl->biv->maybe_multiple
05284
05285
05286 && ! bl->reversed
05287 && v->always_executed && ! v->maybe_multiple
05288 && INSN_UID (v->insn) < max_uid_for_loop
05289 && !loop->top)
05290 {
05291
05292
05293
05294
05295
05296
05297
05298
05299
05300
05301
05302
05303 if (v->combined_with)
05304 {
05305 struct induction *other_giv = 0;
05306
05307 for (tv = bl->giv; tv; tv = tv->next_iv)
05308 if (tv->same == v)
05309 {
05310 if (other_giv)
05311 break;
05312 else
05313 other_giv = tv;
05314 }
05315 if (! tv && other_giv
05316 && REGNO (other_giv->dest_reg) < max_reg_before_loop
05317 && (REGNO_LAST_UID (REGNO (other_giv->dest_reg))
05318 == INSN_UID (v->insn))
05319 && INSN_LUID (v->insn) < INSN_LUID (bl->biv->insn))
05320 auto_inc_opt = 1;
05321 }
05322
05323
05324 else if ((INSN_LUID (v->insn) > INSN_LUID (bl->biv->insn)
05325 && (INSN_LUID (v->insn) < INSN_LUID (loop->scan_start)
05326 || (INSN_LUID (bl->biv->insn)
05327 > INSN_LUID (loop->scan_start))))
05328 || (INSN_LUID (v->insn) < INSN_LUID (loop->scan_start)
05329 && (INSN_LUID (loop->scan_start)
05330 < INSN_LUID (bl->biv->insn))))
05331 auto_inc_opt = -1;
05332 else
05333 auto_inc_opt = 1;
05334
05335 #ifdef HAVE_cc0
05336 {
05337 rtx prev;
05338
05339
05340
05341 if ((auto_inc_opt == 1 && sets_cc0_p (PATTERN (v->insn)))
05342 || (auto_inc_opt == -1
05343 && (prev = prev_nonnote_insn (v->insn)) != 0
05344 && INSN_P (prev)
05345 && sets_cc0_p (PATTERN (prev))))
05346 auto_inc_opt = 0;
05347 }
05348 #endif
05349
05350 if (auto_inc_opt)
05351 v->auto_inc_opt = 1;
05352 }
05353 #endif
05354
05355
05356
05357 for (tv = bl->biv; tv; tv = tv->next_iv)
05358 {
05359 rtx insert_before;
05360
05361
05362 if (tv->same)
05363 continue;
05364 if (! auto_inc_opt)
05365 insert_before = NEXT_INSN (tv->insn);
05366 else if (auto_inc_opt == 1)
05367 insert_before = NEXT_INSN (v->insn);
05368 else
05369 insert_before = v->insn;
05370
05371 if (tv->mult_val == const1_rtx)
05372 loop_iv_add_mult_emit_before (loop, tv->add_val, v->mult_val,
05373 v->new_reg, v->new_reg,
05374 0, insert_before);
05375 else
05376
05377
05378 loop_iv_add_mult_emit_before (loop, tv->add_val, v->mult_val,
05379 v->add_val, v->new_reg,
05380 0, insert_before);
05381 }
05382
05383
05384
05385 loop_iv_add_mult_hoist (loop,
05386 extend_value_for_giv (v, bl->initial_value),
05387 v->mult_val, v->add_val, v->new_reg);
05388 }
05389 }
05390 }
05391
05392
05393
05394
05395
05396
05397
05398 static void
05399 loop_givs_dead_check (struct loop *loop ATTRIBUTE_UNUSED, struct iv_class *bl)
05400 {
05401 struct induction *v;
05402
05403 for (v = bl->giv; v; v = v->next_iv)
05404 {
05405 if (v->ignore
05406 || (v->same && v->same->ignore))
05407 continue;
05408
05409 if (v->giv_type == DEST_REG
05410 && REGNO_FIRST_UID (REGNO (v->dest_reg)) == INSN_UID (v->insn))
05411 {
05412 struct induction *v1;
05413
05414 for (v1 = bl->giv; v1; v1 = v1->next_iv)
05415 if (REGNO_LAST_UID (REGNO (v->dest_reg)) == INSN_UID (v1->insn))
05416 v->maybe_dead = 1;
05417 }
05418 }
05419 }
05420
05421
05422 static void
05423 loop_givs_rescan (struct loop *loop, struct iv_class *bl, rtx *reg_map)
05424 {
05425 struct induction *v;
05426
05427 for (v = bl->giv; v; v = v->next_iv)
05428 {
05429 if (v->same && v->same->ignore)
05430 v->ignore = 1;
05431
05432 if (v->ignore)
05433 continue;
05434
05435
05436
05437 if (v->same)
05438 v->new_reg = replace_rtx (v->new_reg,
05439 v->same->dest_reg, v->same->new_reg);
05440
05441
05442
05443
05444
05445
05446
05447
05448 if (REG_P (v->new_reg)
05449 && v->giv_type == DEST_REG
05450 && REG_POINTER (v->dest_reg))
05451 mark_reg_pointer (v->new_reg,
05452 REGNO_POINTER_ALIGN (REGNO (v->dest_reg)));
05453 else if (REG_P (v->new_reg)
05454 && REG_POINTER (v->src_reg))
05455 {
05456 unsigned int align = REGNO_POINTER_ALIGN (REGNO (v->src_reg));
05457
05458 if (align == 0
05459 || GET_CODE (v->add_val) != CONST_INT
05460 || INTVAL (v->add_val) % (align / BITS_PER_UNIT) != 0)
05461 align = 0;
05462
05463 mark_reg_pointer (v->new_reg, align);
05464 }
05465 else if (REG_P (v->new_reg)
05466 && REG_P (v->add_val)
05467 && REG_POINTER (v->add_val))
05468 {
05469 unsigned int align = REGNO_POINTER_ALIGN (REGNO (v->add_val));
05470
05471 if (align == 0 || GET_CODE (v->mult_val) != CONST_INT
05472 || INTVAL (v->mult_val) % (align / BITS_PER_UNIT) != 0)
05473 align = 0;
05474
05475 mark_reg_pointer (v->new_reg, align);
05476 }
05477 else if (REG_P (v->new_reg) && v->giv_type == DEST_ADDR)
05478 mark_reg_pointer (v->new_reg, 0);
05479
05480 if (v->giv_type == DEST_ADDR)
05481 {
05482
05483
05484 if (!validate_change (v->insn, v->location, v->new_reg, 0))
05485 {
05486 if (loop_dump_stream)
05487 fprintf (loop_dump_stream,
05488 "unable to reduce iv to register in insn %d\n",
05489 INSN_UID (v->insn));
05490 bl->all_reduced = 0;
05491 v->ignore = 1;
05492 continue;
05493 }
05494 }
05495 else if (v->replaceable)
05496 {
05497 reg_map[REGNO (v->dest_reg)] = v->new_reg;
05498 }
05499 else
05500 {
05501 rtx original_insn = v->insn;
05502 rtx note;
05503
05504
05505
05506 v->insn = loop_insn_emit_after (loop, 0, original_insn,
05507 gen_move_insn (v->dest_reg,
05508 v->new_reg));
05509
05510
05511
05512
05513
05514 note = find_reg_note (original_insn, REG_EQUAL, NULL_RTX);
05515 if (note)
05516 remove_note (original_insn, note);
05517 }
05518
05519
05520
05521
05522
05523
05524 if (bl->reversed && ! v->replaceable)
05525 loop_iv_add_mult_sink (loop,
05526 extend_value_for_giv (v, bl->initial_value),
05527 v->mult_val, v->add_val, v->dest_reg);
05528 else if (v->final_value)
05529 loop_insn_sink_or_swim (loop,
05530 gen_load_of_final_value (v->dest_reg,
05531 v->final_value));
05532
05533 if (loop_dump_stream)
05534 {
05535 fprintf (loop_dump_stream, "giv at %d reduced to ",
05536 INSN_UID (v->insn));
05537 print_simple_rtl (loop_dump_stream, v->new_reg);
05538 fprintf (loop_dump_stream, "\n");
05539 }
05540 }
05541 }
05542
05543
05544 static int
05545 loop_giv_reduce_benefit (struct loop *loop ATTRIBUTE_UNUSED,
05546 struct iv_class *bl, struct induction *v,
05547 rtx test_reg)
05548 {
05549 int add_cost;
05550 int benefit;
05551
05552 benefit = v->benefit;
05553 PUT_MODE (test_reg, v->mode);
05554 add_cost = iv_add_mult_cost (bl->biv->add_val, v->mult_val,
05555 test_reg, test_reg);
05556
05557
05558
05559
05560
05561
05562
05563
05564
05565
05566
05567 if (! v->replaceable && ! bl->eliminable
05568 && REG_USERVAR_P (v->dest_reg))
05569 benefit -= copy_cost;
05570
05571
05572
05573
05574
05575
05576
05577
05578
05579 benefit -= add_cost * bl->biv_count;
05580
05581
05582
05583
05584
05585 #ifdef AUTO_INC_DEC
05586
05587
05588
05589 if (v->giv_type == DEST_ADDR
05590
05591
05592
05593 && benefit > 0
05594 && GET_CODE (v->mult_val) == CONST_INT)
05595 {
05596 int size = GET_MODE_SIZE (GET_MODE (v->mem));
05597
05598 if (HAVE_POST_INCREMENT
05599 && INTVAL (v->mult_val) == size)
05600 benefit += add_cost * bl->biv_count;
05601 else if (HAVE_PRE_INCREMENT
05602 && INTVAL (v->mult_val) == size)
05603 benefit += add_cost * bl->biv_count;
05604 else if (HAVE_POST_DECREMENT
05605 && -INTVAL (v->mult_val) == size)
05606 benefit += add_cost * bl->biv_count;
05607 else if (HAVE_PRE_DECREMENT
05608 && -INTVAL (v->mult_val) == size)
05609 benefit += add_cost * bl->biv_count;
05610 }
05611 #endif
05612
05613 return benefit;
05614 }
05615
05616
05617
05618
05619 static void
05620 loop_ivs_free (struct loop *loop)
05621 {
05622 struct loop_ivs *ivs = LOOP_IVS (loop);
05623 struct iv_class *iv = ivs->list;
05624
05625 free (ivs->regs);
05626
05627 while (iv)
05628 {
05629 struct iv_class *next = iv->next;
05630 struct induction *induction;
05631 struct induction *next_induction;
05632
05633 for (induction = iv->biv; induction; induction = next_induction)
05634 {
05635 next_induction = induction->next_iv;
05636 free (induction);
05637 }
05638 for (induction = iv->giv; induction; induction = next_induction)
05639 {
05640 next_induction = induction->next_iv;
05641 free (induction);
05642 }
05643
05644 free (iv);
05645 iv = next;
05646 }
05647 }
05648
05649
05650
05651
05652
05653 static rtx
05654 loop_find_equiv_value (const struct loop *loop, rtx reg)
05655 {
05656 rtx loop_start = loop->start;
05657 rtx insn, set;
05658 rtx ret;
05659
05660 ret = reg;
05661 for (insn = PREV_INSN (loop_start); insn; insn = PREV_INSN (insn))
05662 {
05663 if (LABEL_P (insn))
05664 break;
05665
05666 else if (INSN_P (insn) && reg_set_p (reg, insn))
05667 {
05668
05669
05670
05671 if ((set = single_set (insn))
05672 && (SET_DEST (set) == reg))
05673 {
05674 rtx note = find_reg_note (insn, REG_EQUAL, NULL_RTX);
05675
05676
05677
05678
05679 if (note && GET_CODE (XEXP (note, 0)) != EXPR_LIST
05680 && CONSTANT_P (XEXP (note, 0)))
05681 ret = XEXP (note, 0);
05682 else
05683 ret = SET_SRC (set);
05684
05685
05686
05687 if (modified_between_p (ret, insn, loop_start))
05688 ret = reg;
05689 }
05690 break;
05691 }
05692 }
05693 return ret;
05694 }
05695
05696
05697
05698
05699
05700 static rtx
05701 find_common_reg_term (rtx op0, rtx op1)
05702 {
05703 if ((REG_P (op0) || GET_CODE (op0) == PLUS)
05704 && (REG_P (op1) || GET_CODE (op1) == PLUS))
05705 {
05706 rtx op00;
05707 rtx op01;
05708 rtx op10;
05709 rtx op11;
05710
05711 if (GET_CODE (op0) == PLUS)
05712 op01 = XEXP (op0, 1), op00 = XEXP (op0, 0);
05713 else
05714 op01 = const0_rtx, op00 = op0;
05715
05716 if (GET_CODE (op1) == PLUS)
05717 op11 = XEXP (op1, 1), op10 = XEXP (op1, 0);
05718 else
05719 op11 = const0_rtx, op10 = op1;
05720
05721
05722 if (REG_P (op00) && (op00 == op10 || op00 == op11))
05723 return op00;
05724 else if (REG_P (op01) && (op01 == op10 || op01 == op11))
05725 return op01;
05726 }
05727
05728
05729 return NULL_RTX;
05730 }
05731
05732
05733
05734
05735
05736 static unsigned HOST_WIDE_INT
05737 loop_iterations (struct loop *loop)
05738 {
05739 struct loop_info *loop_info = LOOP_INFO (loop);
05740 struct loop_ivs *ivs = LOOP_IVS (loop);
05741 rtx comparison, comparison_value;
05742 rtx iteration_var, initial_value, increment, final_value;
05743 enum rtx_code comparison_code;
05744 HOST_WIDE_INT inc;
05745 unsigned HOST_WIDE_INT abs_inc;
05746 unsigned HOST_WIDE_INT abs_diff;
05747 int off_by_one;
05748 int increment_dir;
05749 int unsigned_p, compare_dir, final_larger;
05750 rtx last_loop_insn;
05751 struct iv_class *bl;
05752
05753 loop_info->n_iterations = 0;
05754 loop_info->initial_value = 0;
05755 loop_info->initial_equiv_value = 0;
05756 loop_info->comparison_value = 0;
05757 loop_info->final_value = 0;
05758 loop_info->final_equiv_value = 0;
05759 loop_info->increment = 0;
05760 loop_info->iteration_var = 0;
05761 loop_info->iv = 0;
05762
05763
05764
05765
05766
05767 last_loop_insn = PREV_INSN (loop->end);
05768
05769
05770
05771
05772 if (!JUMP_P (last_loop_insn))
05773 {
05774 if (loop_dump_stream)
05775 fprintf (loop_dump_stream,
05776 "Loop iterations: No final conditional branch found.\n");
05777 return 0;
05778 }
05779
05780
05781
05782 if (LABEL_NUSES (JUMP_LABEL (last_loop_insn)) > 1)
05783 {
05784 if (loop_dump_stream)
05785 fprintf (loop_dump_stream,
05786 "Loop iterations: Loop has multiple back edges.\n");
05787 return 0;
05788 }
05789
05790
05791
05792
05793
05794 comparison = get_condition_for_loop (loop, last_loop_insn);
05795 if (comparison == 0)
05796 {
05797 if (loop_dump_stream)
05798 fprintf (loop_dump_stream,
05799 "Loop iterations: No final comparison found.\n");
05800 return 0;
05801 }
05802
05803
05804
05805
05806 comparison_code = GET_CODE (comparison);
05807 iteration_var = XEXP (comparison, 0);
05808 comparison_value = XEXP (comparison, 1);
05809
05810 if (!REG_P (iteration_var))
05811 {
05812 if (loop_dump_stream)
05813 fprintf (loop_dump_stream,
05814 "Loop iterations: Comparison not against register.\n");
05815 return 0;
05816 }
05817
05818
05819
05820
05821
05822
05823
05824 if ((unsigned) REGNO (iteration_var) >= ivs->n_regs
05825 && ! REG_USERVAR_P (iteration_var))
05826 abort ();
05827
05828
05829
05830
05831
05832
05833 initial_value = 0;
05834 increment = 0;
05835
05836
05837
05838
05839
05840
05841
05842 if ((unsigned) REGNO (iteration_var) >= ivs->n_regs)
05843 {
05844 if (loop_dump_stream)
05845 fprintf (loop_dump_stream,
05846 "Loop iterations: No reg_iv_type entry for iteration var.\n");
05847 return 0;
05848 }
05849
05850
05851
05852
05853 else if ((GET_MODE_BITSIZE (GET_MODE (iteration_var))
05854 > HOST_BITS_PER_WIDE_INT))
05855 {
05856 if (loop_dump_stream)
05857 fprintf (loop_dump_stream,
05858 "Loop iterations: Iteration var rejected because mode too large.\n");
05859 return 0;
05860 }
05861 else if (GET_MODE_CLASS (GET_MODE (iteration_var)) != MODE_INT)
05862 {
05863 if (loop_dump_stream)
05864 fprintf (loop_dump_stream,
05865 "Loop iterations: Iteration var not an integer.\n");
05866 return 0;
05867 }
05868
05869
05870 if (REG_IV_TYPE (ivs, REGNO (iteration_var)) != BASIC_INDUCT
05871 && REG_IV_TYPE (ivs, REGNO (iteration_var)) != GENERAL_INDUCT
05872 && REG_P (comparison_value)
05873 && REGNO (comparison_value) < ivs->n_regs)
05874 {
05875 rtx temp = comparison_value;
05876 comparison_code = swap_condition (comparison_code);
05877 comparison_value = iteration_var;
05878 iteration_var = temp;
05879 }
05880
05881 if (REG_IV_TYPE (ivs, REGNO (iteration_var)) == BASIC_INDUCT)
05882 {
05883 if (REGNO (iteration_var) >= ivs->n_regs)
05884 abort ();
05885
05886
05887 bl = REG_IV_CLASS (ivs, REGNO (iteration_var));
05888 initial_value = bl->initial_value;
05889 if (!bl->biv->always_executed || bl->biv->maybe_multiple)
05890 {
05891 if (loop_dump_stream)
05892 fprintf (loop_dump_stream,
05893 "Loop iterations: Basic induction var not set once in each iteration.\n");
05894 return 0;
05895 }
05896
05897 increment = biv_total_increment (bl);
05898 }
05899 else if (REG_IV_TYPE (ivs, REGNO (iteration_var)) == GENERAL_INDUCT)
05900 {
05901 HOST_WIDE_INT offset = 0;
05902 struct induction *v = REG_IV_INFO (ivs, REGNO (iteration_var));
05903 rtx biv_initial_value;
05904
05905 if (REGNO (v->src_reg) >= ivs->n_regs)
05906 abort ();
05907
05908 if (!v->always_executed || v->maybe_multiple)
05909 {
05910 if (loop_dump_stream)
05911 fprintf (loop_dump_stream,
05912 "Loop iterations: General induction var not set once in each iteration.\n");
05913 return 0;
05914 }
05915
05916 bl = REG_IV_CLASS (ivs, REGNO (v->src_reg));
05917
05918
05919
05920 increment = biv_total_increment (bl);
05921 if (increment)
05922 {
05923 struct induction *biv_inc;
05924
05925 increment = fold_rtx_mult_add (v->mult_val,
05926 extend_value_for_giv (v, increment),
05927 const0_rtx, v->mode);
05928
05929
05930
05931
05932
05933
05934 for (biv_inc = bl->biv; biv_inc; biv_inc = biv_inc->next_iv)
05935 {
05936 if (loop_insn_first_p (v->insn, biv_inc->insn))
05937 {
05938 if (REG_P (biv_inc->add_val))
05939 {
05940 if (loop_dump_stream)
05941 fprintf (loop_dump_stream,
05942 "Loop iterations: Basic induction var add_val is REG %d.\n",
05943 REGNO (biv_inc->add_val));
05944 return 0;
05945 }
05946
05947
05948 if (biv_inc->same)
05949 continue;
05950
05951 offset -= INTVAL (biv_inc->add_val);
05952 }
05953 }
05954 }
05955 if (loop_dump_stream)
05956 fprintf (loop_dump_stream,
05957 "Loop iterations: Giv iterator, initial value bias %ld.\n",
05958 (long) offset);
05959
05960
05961
05962 biv_initial_value = extend_value_for_giv (v, bl->initial_value);
05963 initial_value
05964 = fold_rtx_mult_add (v->mult_val,
05965 plus_constant (biv_initial_value, offset),
05966 v->add_val, v->mode);
05967 }
05968 else
05969 {
05970 if (loop_dump_stream)
05971 fprintf (loop_dump_stream,
05972 "Loop iterations: Not basic or general induction var.\n");
05973 return 0;
05974 }
05975
05976 if (initial_value == 0)
05977 return 0;
05978
05979 unsigned_p = 0;
05980 off_by_one = 0;
05981 switch (comparison_code)
05982 {
05983 case LEU:
05984 unsigned_p = 1;
05985 case LE:
05986 compare_dir = 1;
05987 off_by_one = 1;
05988 break;
05989 case GEU:
05990 unsigned_p = 1;
05991 case GE:
05992 compare_dir = -1;
05993 off_by_one = -1;
05994 break;
05995 case EQ:
05996
05997 compare_dir = 0;
05998 break;
05999 case LTU:
06000 unsigned_p = 1;
06001 case LT:
06002 compare_dir = 1;
06003 break;
06004 case GTU:
06005 unsigned_p = 1;
06006 case GT:
06007 compare_dir = -1;
06008 break;
06009 case NE:
06010 compare_dir = 0;
06011 break;
06012 default:
06013 abort ();
06014 }
06015
06016
06017
06018
06019 final_value = comparison_value;
06020 if (REG_P (comparison_value)
06021 && loop_invariant_p (loop, comparison_value))
06022 {
06023 final_value = loop_find_equiv_value (loop, comparison_value);
06024
06025
06026
06027 if (! loop_invariant_p (loop, final_value))
06028 final_value = comparison_value;
06029 }
06030
06031
06032
06033
06034
06035
06036
06037
06038
06039
06040 if (off_by_one)
06041 final_value = plus_constant (final_value, off_by_one);
06042
06043
06044
06045
06046
06047
06048
06049
06050
06051
06052 loop_info->initial_value = initial_value;
06053 loop_info->comparison_value = comparison_value;
06054 loop_info->final_value = plus_constant (comparison_value, off_by_one);
06055 loop_info->increment = increment;
06056 loop_info->iteration_var = iteration_var;
06057 loop_info->comparison_code = comparison_code;
06058 loop_info->iv = bl;
06059
06060
06061
06062
06063
06064
06065 if (REG_P (initial_value))
06066 {
06067 rtx reg1;
06068 rtx reg2;
06069 rtx const2;
06070
06071 reg1 = initial_value;
06072 if (GET_CODE (final_value) == PLUS)
06073 reg2 = XEXP (final_value, 0), const2 = XEXP (final_value, 1);
06074 else
06075 reg2 = final_value, const2 = const0_rtx;
06076
06077
06078
06079 if (REG_P (reg2) && reg2 != reg1)
06080 {
06081 rtx temp;
06082
06083
06084
06085 temp = loop_find_equiv_value (loop, reg1);
06086
06087 if (find_common_reg_term (temp, reg2))
06088 initial_value = temp;
06089 else if (loop_invariant_p (loop, reg2))
06090 {
06091
06092
06093
06094 temp = loop_find_equiv_value (loop, reg2);
06095
06096 if (temp == loop_info->iteration_var)
06097 temp = initial_value;
06098 if (temp == reg1)
06099 final_value = (const2 == const0_rtx)
06100 ? reg1 : gen_rtx_PLUS (GET_MODE (reg1), reg1, const2);
06101 }
06102 }
06103 }
06104
06105 loop_info->initial_equiv_value = initial_value;
06106 loop_info->final_equiv_value = final_value;
06107
06108
06109
06110
06111 if (comparison_code == EQ)
06112 loop_info->final_equiv_value = loop_info->final_value = 0;
06113
06114 if (increment == 0)
06115 {
06116 if (loop_dump_stream)
06117 fprintf (loop_dump_stream,
06118 "Loop iterations: Increment value can't be calculated.\n");
06119 return 0;
06120 }
06121
06122 if (GET_CODE (increment) != CONST_INT)
06123 {
06124
06125
06126
06127 if (REG_P (increment) || GET_CODE (increment) == SUBREG)
06128 increment = loop_find_equiv_value (loop, increment);
06129
06130 if (GET_CODE (increment) != CONST_INT)
06131 {
06132 if (loop_dump_stream)
06133 {
06134 fprintf (loop_dump_stream,
06135 "Loop iterations: Increment value not constant ");
06136 print_simple_rtl (loop_dump_stream, increment);
06137 fprintf (loop_dump_stream, ".\n");
06138 }
06139 return 0;
06140 }
06141 loop_info->increment = increment;
06142 }
06143
06144 if (GET_CODE (initial_value) != CONST_INT)
06145 {
06146 if (loop_dump_stream)
06147 {
06148 fprintf (loop_dump_stream,
06149 "Loop iterations: Initial value not constant ");
06150 print_simple_rtl (loop_dump_stream, initial_value);
06151 fprintf (loop_dump_stream, ".\n");
06152 }
06153 return 0;
06154 }
06155 else if (GET_CODE (final_value) != CONST_INT)
06156 {
06157 if (loop_dump_stream)
06158 {
06159 fprintf (loop_dump_stream,
06160 "Loop iterations: Final value not constant ");
06161 print_simple_rtl (loop_dump_stream, final_value);
06162 fprintf (loop_dump_stream, ".\n");
06163 }
06164 return 0;
06165 }
06166 else if (comparison_code == EQ)
06167 {
06168 rtx inc_once;
06169
06170 if (loop_dump_stream)
06171 fprintf (loop_dump_stream, "Loop iterations: EQ comparison loop.\n");
06172
06173 inc_once = gen_int_mode (INTVAL (initial_value) + INTVAL (increment),
06174 GET_MODE (iteration_var));
06175
06176 if (inc_once == final_value)
06177 {
06178
06179
06180
06181 if (increment == const0_rtx)
06182 return 0;
06183 loop_info->n_iterations = 2;
06184 }
06185 else
06186 loop_info->n_iterations = 1;
06187
06188 if (GET_CODE (loop_info->initial_value) == CONST_INT)
06189 loop_info->final_value
06190 = gen_int_mode ((INTVAL (loop_info->initial_value)
06191 + loop_info->n_iterations * INTVAL (increment)),
06192 GET_MODE (iteration_var));
06193 else
06194 loop_info->final_value
06195 = plus_constant (loop_info->initial_value,
06196 loop_info->n_iterations * INTVAL (increment));
06197 loop_info->final_equiv_value
06198 = gen_int_mode ((INTVAL (initial_value)
06199 + loop_info->n_iterations * INTVAL (increment)),
06200 GET_MODE (iteration_var));
06201 return loop_info->n_iterations;
06202 }
06203
06204
06205 if (unsigned_p)
06206 final_larger
06207 = ((unsigned HOST_WIDE_INT) INTVAL (final_value)
06208 > (unsigned HOST_WIDE_INT) INTVAL (initial_value))
06209 - ((unsigned HOST_WIDE_INT) INTVAL (final_value)
06210 < (unsigned HOST_WIDE_INT) INTVAL (initial_value));
06211 else
06212 final_larger = (INTVAL (final_value) > INTVAL (initial_value))
06213 - (INTVAL (final_value) < INTVAL (initial_value));
06214
06215 if (INTVAL (increment) > 0)
06216 increment_dir = 1;
06217 else if (INTVAL (increment) == 0)
06218 increment_dir = 0;
06219 else
06220 increment_dir = -1;
06221
06222
06223
06224
06225
06226
06227
06228
06229
06230
06231
06232
06233
06234
06235
06236
06237
06238
06239
06240
06241
06242
06243
06244
06245
06246
06247
06248
06249 if (final_larger == increment_dir && final_larger != 0
06250 && (final_larger == compare_dir || compare_dir == 0))
06251
06252 ;
06253 else
06254 {
06255 if (loop_dump_stream)
06256 fprintf (loop_dump_stream, "Loop iterations: Not normal loop.\n");
06257 return 0;
06258 }
06259
06260
06261
06262
06263
06264 inc = INTVAL (increment);
06265 if (inc > 0)
06266 {
06267 abs_diff = INTVAL (final_value) - INTVAL (initial_value);
06268 abs_inc = inc;
06269 }
06270 else if (inc < 0)
06271 {
06272 abs_diff = INTVAL (initial_value) - INTVAL (final_value);
06273 abs_inc = -inc;
06274 }
06275 else
06276 abort ();
06277
06278
06279
06280
06281
06282 abs_diff &= ((unsigned HOST_WIDE_INT) 1
06283 << (GET_MODE_BITSIZE (GET_MODE (iteration_var)) - 1)
06284 << 1) - 1;
06285
06286
06287
06288
06289
06290 if (compare_dir == 0 && (abs_diff % abs_inc) != 0)
06291 return 0;
06292
06293
06294
06295
06296 loop_info->n_iterations = abs_diff / abs_inc + ((abs_diff % abs_inc) != 0);
06297 return loop_info->n_iterations;
06298 }
06299
06300
06301
06302
06303
06304
06305
06306
06307
06308
06309 static void
06310 strength_reduce (struct loop *loop, int flags)
06311 {
06312 struct loop_info *loop_info = LOOP_INFO (loop);
06313 struct loop_regs *regs = LOOP_REGS (loop);
06314 struct loop_ivs *ivs = LOOP_IVS (loop);
06315 rtx p;
06316
06317 struct iv_class *bl;
06318
06319
06320
06321
06322
06323 int threshold = (loop_info->has_call ? 1 : 2) * (3 + n_non_fixed_regs);
06324
06325 rtx *reg_map = NULL;
06326 int reg_map_size;
06327 rtx test_reg = gen_rtx_REG (word_mode, LAST_VIRTUAL_REGISTER + 1);
06328 int insn_count = count_insns_in_loop (loop);
06329
06330 addr_placeholder = gen_reg_rtx (Pmode);
06331
06332 ivs->n_regs = max_reg_before_loop;
06333 ivs->regs = xcalloc (ivs->n_regs, sizeof (struct iv));
06334
06335
06336 loop_bivs_find (loop);
06337
06338
06339 if (! ivs->list)
06340 {
06341 loop_ivs_free (loop);
06342 return;
06343 }
06344
06345
06346
06347 loop_bivs_init_find (loop);
06348
06349
06350
06351 loop_bivs_check (loop);
06352
06353
06354 loop_givs_find (loop);
06355
06356
06357
06358
06359
06360 loop_iterations (loop);
06361
06362 #ifdef HAVE_prefetch
06363 if (flags & LOOP_PREFETCH)
06364 emit_prefetch_instructions (loop);
06365 #endif
06366
06367
06368
06369
06370
06371 loop_givs_check (loop);
06372
06373
06374
06375
06376 check_dbra_loop (loop, insn_count);
06377
06378
06379
06380
06381 reg_map_size = ivs->n_regs;
06382 reg_map = xcalloc (reg_map_size, sizeof (rtx));
06383
06384
06385
06386
06387 for (bl = ivs->list; bl; bl = bl->next)
06388 {
06389 struct induction *v;
06390 int benefit;
06391
06392
06393
06394 bl->eliminable = loop_biv_eliminable_p (loop, bl, threshold, insn_count);
06395
06396
06397
06398
06399 bl->all_reduced = 1;
06400
06401
06402
06403 check_ext_dependent_givs (loop, bl);
06404
06405
06406 combine_givs (regs, bl);
06407
06408 for (v = bl->giv; v; v = v->next_iv)
06409 {
06410 struct induction *tv;
06411
06412 if (v->ignore || v->same)
06413 continue;
06414
06415 benefit = loop_giv_reduce_benefit (loop, bl, v, test_reg);
06416
06417
06418
06419
06420
06421
06422
06423
06424
06425
06426 if (v->lifetime * threshold * benefit < insn_count
06427 && ! bl->reversed)
06428 {
06429 if (loop_dump_stream)
06430 fprintf (loop_dump_stream,
06431 "giv of insn %d not worth while, %d vs %d.\n",
06432 INSN_UID (v->insn),
06433 v->lifetime * threshold * benefit, insn_count);
06434 v->ignore = 1;
06435 bl->all_reduced = 0;
06436 }
06437 else
06438 {
06439
06440
06441
06442 for (tv = bl->biv; tv; tv = tv->next_iv)
06443 if (tv->mult_val == const1_rtx
06444 && ! product_cheap_p (tv->add_val, v->mult_val))
06445 {
06446 if (loop_dump_stream)
06447 fprintf (loop_dump_stream,
06448 "giv of insn %d: would need a multiply.\n",
06449 INSN_UID (v->insn));
06450 v->ignore = 1;
06451 bl->all_reduced = 0;
06452 break;
06453 }
06454 }
06455 }
06456
06457
06458
06459
06460
06461 loop_givs_dead_check (loop, bl);
06462
06463
06464 loop_givs_reduce (loop, bl);
06465
06466
06467
06468
06469
06470
06471
06472 loop_givs_rescan (loop, bl, reg_map);
06473
06474
06475
06476
06477
06478
06479
06480
06481
06482
06483
06484
06485
06486
06487
06488 for (v = bl->giv; v; v = v->next_iv)
06489 if (! v->maybe_dead && v->same)
06490 v->same->maybe_dead = 0;
06491
06492
06493
06494
06495
06496
06497
06498
06499
06500
06501
06502
06503
06504
06505
06506
06507
06508
06509
06510 if (bl->all_reduced == 1 && bl->eliminable
06511 && maybe_eliminate_biv (loop, bl, 1, threshold, insn_count))
06512 {
06513
06514
06515
06516
06517
06518
06519
06520
06521
06522
06523
06524
06525 if (bl->final_value && ! bl->reversed)
06526 loop_insn_sink_or_swim (loop,
06527 gen_load_of_final_value (bl->biv->dest_reg,
06528 bl->final_value));
06529
06530 if (loop_dump_stream)
06531 fprintf (loop_dump_stream, "Reg %d: biv eliminated\n",
06532 bl->regno);
06533 }
06534
06535
06536 else if (bl->final_value && ! bl->reversed)
06537 loop_insn_sink (loop, gen_load_of_final_value (bl->biv->dest_reg,
06538 bl->final_value));
06539 }
06540
06541
06542
06543
06544 for (p = loop->start; p != loop->end; p = NEXT_INSN (p))
06545 if (INSN_P (p))
06546 {
06547 replace_regs (PATTERN (p), reg_map, reg_map_size, 0);
06548 replace_regs (REG_NOTES (p), reg_map, reg_map_size, 0);
06549 INSN_CODE (p) = -1;
06550 }
06551
06552 if (loop_dump_stream)
06553 fprintf (loop_dump_stream, "\n");
06554
06555 loop_ivs_free (loop);
06556 if (reg_map)
06557 free (reg_map);
06558 }
06559
06560
06561 static rtx
06562 check_insn_for_bivs (struct loop *loop, rtx p, int not_every_iteration,
06563 int maybe_multiple)
06564 {
06565 struct loop_ivs *ivs = LOOP_IVS (loop);
06566 rtx set;
06567 rtx dest_reg;
06568 rtx inc_val;
06569 rtx mult_val;
06570 rtx *location;
06571
06572 if (NONJUMP_INSN_P (p)
06573 && (set = single_set (p))
06574 && REG_P (SET_DEST (set)))
06575 {
06576 dest_reg = SET_DEST (set);
06577 if (REGNO (dest_reg) < max_reg_before_loop
06578 && REGNO (dest_reg) >= FIRST_PSEUDO_REGISTER
06579 && REG_IV_TYPE (ivs, REGNO (dest_reg)) != NOT_BASIC_INDUCT)
06580 {
06581 if (basic_induction_var (loop, SET_SRC (set),
06582 GET_MODE (SET_SRC (set)),
06583 dest_reg, p, &inc_val, &mult_val,
06584 &location))
06585 {
06586
06587
06588
06589 struct induction *v = xmalloc (sizeof (struct induction));
06590
06591 record_biv (loop, v, p, dest_reg, inc_val, mult_val, location,
06592 not_every_iteration, maybe_multiple);
06593 REG_IV_TYPE (ivs, REGNO (dest_reg)) = BASIC_INDUCT;
06594 }
06595 else if (REGNO (dest_reg) < ivs->n_regs)
06596 REG_IV_TYPE (ivs, REGNO (dest_reg)) = NOT_BASIC_INDUCT;
06597 }
06598 }
06599 return p;
06600 }
06601
06602
06603
06604
06605 static rtx
06606 check_insn_for_givs (struct loop *loop, rtx p, int not_every_iteration,
06607 int maybe_multiple)
06608 {
06609 struct loop_regs *regs = LOOP_REGS (loop);
06610
06611 rtx set;
06612
06613 if (NONJUMP_INSN_P (p)
06614 && (set = single_set (p))
06615 && REG_P (SET_DEST (set))
06616 && ! regs->array[REGNO (SET_DEST (set))].may_not_optimize)
06617 {
06618 rtx src_reg;
06619 rtx dest_reg;
06620 rtx add_val;
06621 rtx mult_val;
06622 rtx ext_val;
06623 int benefit;
06624 rtx regnote = 0;
06625 rtx last_consec_insn;
06626
06627 dest_reg = SET_DEST (set);
06628 if (REGNO (dest_reg) < FIRST_PSEUDO_REGISTER)
06629 return p;
06630
06631 if (
06632 (general_induction_var (loop, SET_SRC (set), &src_reg, &add_val,
06633 &mult_val, &ext_val, 0, &benefit, VOIDmode)
06634
06635 || ((regnote = find_reg_note (p, REG_EQUAL, NULL_RTX))
06636 && general_induction_var (loop, XEXP (regnote, 0), &src_reg,
06637 &add_val, &mult_val, &ext_val, 0,
06638 &benefit, VOIDmode)))
06639
06640
06641 && REGNO (dest_reg) < max_reg_before_loop
06642
06643 && dest_reg != src_reg
06644
06645 && (regs->array[REGNO (dest_reg)].n_times_set == 1
06646
06647 || (benefit = consec_sets_giv (loop, benefit, p,
06648 src_reg, dest_reg,
06649 &add_val, &mult_val, &ext_val,
06650 &last_consec_insn))))
06651 {
06652 struct induction *v = xmalloc (sizeof (struct induction));
06653
06654
06655 if (find_reg_note (p, REG_RETVAL, NULL_RTX))
06656 benefit += libcall_benefit (p);
06657
06658
06659 if (regs->array[REGNO (dest_reg)].n_times_set != 1)
06660 p = last_consec_insn;
06661
06662 record_giv (loop, v, p, src_reg, dest_reg, mult_val, add_val,
06663 ext_val, benefit, DEST_REG, not_every_iteration,
06664 maybe_multiple, (rtx*) 0);
06665
06666 }
06667 }
06668
06669
06670 if (NONJUMP_INSN_P (p))
06671 find_mem_givs (loop, PATTERN (p), p, not_every_iteration,
06672 maybe_multiple);
06673
06674
06675
06676 if (INSN_P (p) || LABEL_P (p))
06677 update_giv_derive (loop, p);
06678 return p;
06679 }
06680
06681
06682
06683
06684
06685
06686
06687
06688
06689 static int
06690 valid_initial_value_p (rtx x, rtx insn, int call_seen, rtx loop_start)
06691 {
06692 if (CONSTANT_P (x))
06693 return 1;
06694
06695
06696
06697 if (!REG_P (x)
06698 || REGNO (x) >= max_reg_before_loop)
06699 return 0;
06700
06701
06702
06703 if (REGNO (x) < FIRST_PSEUDO_REGISTER
06704 && (SMALL_REGISTER_CLASSES
06705 || (call_used_regs[REGNO (x)] && call_seen)))
06706 return 0;
06707
06708
06709
06710 if (reg_set_between_p (x, insn, loop_start))
06711 return 0;
06712
06713 return 1;
06714 }
06715
06716
06717
06718
06719
06720
06721
06722 static void
06723 find_mem_givs (const struct loop *loop, rtx x, rtx insn,
06724 int not_every_iteration, int maybe_multiple)
06725 {
06726 int i, j;
06727 enum rtx_code code;
06728 const char *fmt;
06729
06730 if (x == 0)
06731 return;
06732
06733 code = GET_CODE (x);
06734 switch (code)
06735 {
06736 case REG:
06737 case CONST_INT:
06738 case CONST:
06739 case CONST_DOUBLE:
06740 case SYMBOL_REF:
06741 case LABEL_REF:
06742 case PC:
06743 case CC0:
06744 case ADDR_VEC:
06745 case ADDR_DIFF_VEC:
06746 case USE:
06747 case CLOBBER:
06748 return;
06749
06750 case MEM:
06751 {
06752 rtx src_reg;
06753 rtx add_val;
06754 rtx mult_val;
06755 rtx ext_val;
06756 int benefit;
06757
06758
06759
06760
06761
06762
06763 if (general_induction_var (loop, XEXP (x, 0), &src_reg, &add_val,
06764 &mult_val, &ext_val, 1, &benefit,
06765 GET_MODE (x)))
06766 {
06767
06768 struct induction *v = xmalloc (sizeof (struct induction));
06769
06770 record_giv (loop, v, insn, src_reg, addr_placeholder, mult_val,
06771 add_val, ext_val, benefit, DEST_ADDR,
06772 not_every_iteration, maybe_multiple, &XEXP (x, 0));
06773
06774 v->mem = x;
06775 }
06776 }
06777 return;
06778
06779 default:
06780 break;
06781 }
06782
06783
06784
06785 fmt = GET_RTX_FORMAT (code);
06786 for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
06787 if (fmt[i] == 'e')
06788 find_mem_givs (loop, XEXP (x, i), insn, not_every_iteration,
06789 maybe_multiple);
06790 else if (fmt[i] == 'E')
06791 for (j = 0; j < XVECLEN (x, i); j++)
06792 find_mem_givs (loop, XVECEXP (x, i, j), insn, not_every_iteration,
06793 maybe_multiple);
06794 }
06795
06796
06797
06798
06799
06800
06801
06802
06803
06804
06805
06806
06807
06808
06809
06810
06811
06812 static void
06813 record_biv (struct loop *loop, struct induction *v, rtx insn, rtx dest_reg,
06814 rtx inc_val, rtx mult_val, rtx *location,
06815 int not_every_iteration, int maybe_multiple)
06816 {
06817 struct loop_ivs *ivs = LOOP_IVS (loop);
06818 struct iv_class *bl;
06819
06820 v->insn = insn;
06821 v->src_reg = dest_reg;
06822 v->dest_reg = dest_reg;
06823 v->mult_val = mult_val;
06824 v->add_val = inc_val;
06825 v->ext_dependent = NULL_RTX;
06826 v->location = location;
06827 v->mode = GET_MODE (dest_reg);
06828 v->always_computable = ! not_every_iteration;
06829 v->always_executed = ! not_every_iteration;
06830 v->maybe_multiple = maybe_multiple;
06831 v->same = 0;
06832
06833
06834
06835
06836 bl = REG_IV_CLASS (ivs, REGNO (dest_reg));
06837 if (bl == 0)
06838 {
06839
06840
06841 bl = xmalloc (sizeof (struct iv_class));
06842
06843 bl->regno = REGNO (dest_reg);
06844 bl->biv = 0;
06845 bl->giv = 0;
06846 bl->biv_count = 0;
06847 bl->giv_count = 0;
06848
06849
06850 bl->initial_value = dest_reg;
06851 bl->final_value = 0;
06852
06853 bl->init_insn = 0;
06854 bl->init_set = 0;
06855 bl->initial_test = 0;
06856 bl->incremented = 0;
06857 bl->eliminable = 0;
06858 bl->nonneg = 0;
06859 bl->reversed = 0;
06860 bl->total_benefit = 0;
06861
06862
06863 bl->next = ivs->list;
06864 ivs->list = bl;
06865
06866
06867 REG_IV_CLASS (ivs, REGNO (dest_reg)) = bl;
06868 }
06869 else
06870 {
06871
06872 struct induction *induction;
06873 for (induction = bl->biv; induction; induction = induction->next_iv)
06874 if (location == induction->location)
06875 {
06876 v->same = induction;
06877 break;
06878 }
06879 }
06880
06881
06882 v->next_iv = bl->biv;
06883 bl->biv = v;
06884 bl->biv_count++;
06885 if (mult_val == const1_rtx)
06886 bl->incremented = 1;
06887
06888 if (loop_dump_stream)
06889 loop_biv_dump (v, loop_dump_stream, 0);
06890 }
06891
06892
06893
06894
06895
06896
06897
06898
06899
06900
06901
06902
06903
06904
06905 static void
06906 record_giv (const struct loop *loop, struct induction *v, rtx insn,
06907 rtx src_reg, rtx dest_reg, rtx mult_val, rtx add_val,
06908 rtx ext_val, int benefit, enum g_types type,
06909 int not_every_iteration, int maybe_multiple, rtx *location)
06910 {
06911 struct loop_ivs *ivs = LOOP_IVS (loop);
06912 struct induction *b;
06913 struct iv_class *bl;
06914 rtx set = single_set (insn);
06915 rtx temp;
06916
06917
06918
06919 temp = simplify_rtx (add_val);
06920 if (temp
06921 && ! (GET_CODE (add_val) == MULT
06922 && GET_CODE (temp) == ASHIFT))
06923 add_val = temp;
06924
06925 v->insn = insn;
06926 v->src_reg = src_reg;
06927 v->giv_type = type;
06928 v->dest_reg = dest_reg;
06929 v->mult_val = mult_val;
06930 v->add_val = add_val;
06931 v->ext_dependent = ext_val;
06932 v->benefit = benefit;
06933 v->location = location;
06934 v->cant_derive = 0;
06935 v->combined_with = 0;
06936 v->maybe_multiple = maybe_multiple;
06937 v->maybe_dead = 0;
06938 v->derive_adjustment = 0;
06939 v->same = 0;
06940 v->ignore = 0;
06941 v->new_reg = 0;
06942 v->final_value = 0;
06943 v->same_insn = 0;
06944 v->auto_inc_opt = 0;
06945 v->shared = 0;
06946
06947
06948
06949
06950
06951
06952
06953
06954
06955 if (type == DEST_ADDR)
06956 v->always_computable = 1;
06957 else
06958 v->always_computable = ! not_every_iteration;
06959
06960 v->always_executed = ! not_every_iteration;
06961
06962 if (type == DEST_ADDR)
06963 {
06964 v->mode = GET_MODE (*location);
06965 v->lifetime = 1;
06966 }
06967 else
06968 {
06969 v->mode = GET_MODE (SET_DEST (set));
06970
06971 v->lifetime = LOOP_REG_LIFETIME (loop, REGNO (dest_reg));
06972
06973
06974
06975
06976 if (v->lifetime == 0)
06977 v->ignore = 1;
06978
06979 REG_IV_TYPE (ivs, REGNO (dest_reg)) = GENERAL_INDUCT;
06980 REG_IV_INFO (ivs, REGNO (dest_reg)) = v;
06981 }
06982
06983
06984
06985 bl = REG_IV_CLASS (ivs, REGNO (src_reg));
06986 if (bl)
06987 {
06988 v->next_iv = bl->giv;
06989 bl->giv = v;
06990
06991
06992 if (type == DEST_REG)
06993 bl->giv_count++;
06994 bl->total_benefit += benefit;
06995 }
06996 else
06997
06998 abort ();
06999
07000 if (type == DEST_ADDR)
07001 {
07002 v->replaceable = 1;
07003 v->not_replaceable = 0;
07004 }
07005 else
07006 {
07007
07008
07009
07010
07011
07012
07013
07014
07015
07016
07017 if (REGNO_FIRST_UID (REGNO (dest_reg)) == INSN_UID (insn)
07018
07019 && REGNO_LAST_LUID (REGNO (dest_reg))
07020 < INSN_LUID (loop->end)
07021 && (! not_every_iteration
07022 || last_use_this_basic_block (dest_reg, insn)))
07023 {
07024
07025
07026
07027
07028
07029
07030
07031
07032
07033
07034
07035
07036
07037
07038 v->replaceable = 1;
07039 v->not_replaceable = 0;
07040 for (b = bl->biv; b; b = b->next_iv)
07041 {
07042 if (INSN_UID (b->insn) >= max_uid_for_loop
07043 || ((INSN_LUID (b->insn)
07044 >= REGNO_FIRST_LUID (REGNO (dest_reg)))
07045 && (INSN_LUID (b->insn)
07046 <= REGNO_LAST_LUID (REGNO (dest_reg)))))
07047 {
07048 v->replaceable = 0;
07049 v->not_replaceable = 1;
07050 break;
07051 }
07052 }
07053
07054
07055
07056 if (v->replaceable)
07057 for (b = bl->biv; b; b = b->next_iv)
07058 if (back_branch_in_range_p (loop, b->insn))
07059 {
07060 v->replaceable = 0;
07061 v->not_replaceable = 1;
07062 break;
07063 }
07064 }
07065 else
07066 {
07067
07068
07069 v->replaceable = 0;
07070 v->not_replaceable = 0;
07071 }
07072 }
07073
07074
07075
07076 {
07077 rtx tem = add_val;
07078
07079 v->no_const_addval = 1;
07080 if (tem == const0_rtx)
07081 ;
07082 else if (CONSTANT_P (add_val))
07083 v->no_const_addval = 0;
07084 if (GET_CODE (tem) == PLUS)
07085 {
07086 while (1)
07087 {
07088 if (GET_CODE (XEXP (tem, 0)) == PLUS)
07089 tem = XEXP (tem, 0);
07090 else if (GET_CODE (XEXP (tem, 1)) == PLUS)
07091 tem = XEXP (tem, 1);
07092 else
07093 break;
07094 }
07095 if (CONSTANT_P (XEXP (tem, 1)))
07096 v->no_const_addval = 0;
07097 }
07098 }
07099
07100 if (loop_dump_stream)
07101 loop_giv_dump (v, loop_dump_stream, 0);
07102 }
07103
07104
07105
07106
07107 static rtx
07108 final_giv_value (const struct loop *loop, struct induction *v)
07109 {
07110 struct loop_ivs *ivs = LOOP_IVS (loop);
07111 struct iv_class *bl;
07112 rtx insn;
07113 rtx increment, tem;
07114 rtx seq;
07115 rtx loop_end = loop->end;
07116 unsigned HOST_WIDE_INT n_iterations = LOOP_INFO (loop)->n_iterations;
07117
07118 bl = REG_IV_CLASS (ivs, REGNO (v->src_reg));
07119
07120
07121
07122
07123
07124 if (bl->reversed)
07125 {
07126 if (loop_dump_stream)
07127 fprintf (loop_dump_stream,
07128 "Final giv value for %d, depends on reversed biv\n",
07129 REGNO (v->dest_reg));
07130 return const0_rtx;
07131 }
07132
07133
07134
07135
07136
07137
07138
07139
07140
07141
07142
07143 if (n_iterations != 0
07144 && ! loop->exit_count
07145 && v->always_executed)
07146 {
07147
07148
07149
07150
07151
07152
07153
07154
07155
07156
07157
07158 increment = biv_total_increment (bl);
07159
07160 if (increment && loop_invariant_p (loop, increment)
07161 && loop_invariant_p (loop, bl->initial_value))
07162 {
07163
07164
07165
07166
07167
07168
07169
07170
07171
07172
07173
07174 tem = gen_reg_rtx (v->mode);
07175 record_base_value (REGNO (tem), bl->biv->add_val, 0);
07176 loop_iv_add_mult_sink (loop, extend_value_for_giv (v, increment),
07177 GEN_INT (n_iterations),
07178 extend_value_for_giv (v, bl->initial_value),
07179 tem);
07180
07181
07182 for (insn = NEXT_INSN (v->insn); insn != loop_end;
07183 insn = NEXT_INSN (insn))
07184 {
07185 struct induction *biv;
07186
07187 for (biv = bl->biv; biv; biv = biv->next_iv)
07188 if (biv->insn == insn)
07189 {
07190 start_sequence ();
07191 tem = expand_simple_binop (GET_MODE (tem), MINUS, tem,
07192 biv->add_val, NULL_RTX, 0,
07193 OPTAB_LIB_WIDEN);
07194 seq = get_insns ();
07195 end_sequence ();
07196 loop_insn_sink (loop, seq);
07197 }
07198 }
07199
07200
07201 loop_iv_add_mult_sink (loop, tem, v->mult_val, v->add_val, tem);
07202
07203 if (loop_dump_stream)
07204 fprintf (loop_dump_stream,
07205 "Final giv value for %d, calc from biv's value.\n",
07206 REGNO (v->dest_reg));
07207
07208 return tem;
07209 }
07210 }
07211
07212
07213 if (v->replaceable)
07214 abort ();
07215
07216
07217 if (reg_dead_after_loop (loop, v->dest_reg))
07218 {
07219 if (loop_dump_stream)
07220 fprintf (loop_dump_stream,
07221 "Final giv value for %d, giv dead after loop exit.\n",
07222 REGNO (v->dest_reg));
07223
07224 return const0_rtx;
07225 }
07226
07227 return 0;
07228 }
07229
07230
07231
07232
07233
07234
07235
07236 static void
07237 check_final_value (const struct loop *loop, struct induction *v)
07238 {
07239 rtx final_value = 0;
07240
07241
07242
07243
07244
07245
07246
07247
07248
07249
07250
07251
07252
07253
07254
07255
07256 #if 0
07257
07258
07259 v->replaceable = 0;
07260 #endif
07261
07262 if ((final_value = final_giv_value (loop, v))
07263 && (v->always_executed
07264 || last_use_this_basic_block (v->dest_reg, v->insn)))
07265 {
07266 int biv_increment_seen = 0, before_giv_insn = 0;
07267 rtx p = v->insn;
07268 rtx last_giv_use;
07269
07270 v->replaceable = 1;
07271 v->not_replaceable = 0;
07272
07273
07274
07275
07276
07277
07278
07279
07280
07281
07282
07283
07284
07285
07286
07287
07288
07289
07290
07291 last_giv_use = v->insn;
07292
07293 while (1)
07294 {
07295 p = NEXT_INSN (p);
07296 if (p == loop->end)
07297 {
07298 before_giv_insn = 1;
07299 p = NEXT_INSN (loop->start);
07300 }
07301 if (p == v->insn)
07302 break;
07303
07304 if (INSN_P (p))
07305 {
07306
07307
07308
07309
07310
07311 if (! biv_increment_seen
07312 && reg_set_p (v->src_reg, PATTERN (p)))
07313 biv_increment_seen = 1;
07314
07315 if (reg_mentioned_p (v->dest_reg, PATTERN (p)))
07316 {
07317 if (biv_increment_seen || before_giv_insn)
07318 {
07319 v->replaceable = 0;
07320 v->not_replaceable = 1;
07321 break;
07322 }
07323 last_giv_use = p;
07324 }
07325 }
07326 }
07327
07328
07329
07330
07331
07332 if (v->replaceable)
07333 {
07334 p = v->insn;
07335 while (1)
07336 {
07337 p = NEXT_INSN (p);
07338 if (p == loop->end)
07339 p = NEXT_INSN (loop->start);
07340 if (p == last_giv_use)
07341 break;
07342
07343 if (JUMP_P (p) && JUMP_LABEL (p)
07344 && LABEL_NAME (JUMP_LABEL (p))
07345 && ((loop_insn_first_p (JUMP_LABEL (p), v->insn)
07346 && loop_insn_first_p (loop->start, JUMP_LABEL (p)))
07347 || (loop_insn_first_p (last_giv_use, JUMP_LABEL (p))
07348 && loop_insn_first_p (JUMP_LABEL (p), loop->end))))
07349 {
07350 v->replaceable = 0;
07351 v->not_replaceable = 1;
07352
07353 if (loop_dump_stream)
07354 fprintf (loop_dump_stream,
07355 "Found branch outside giv lifetime.\n");
07356
07357 break;
07358 }
07359 }
07360 }
07361
07362
07363 if (v->replaceable)
07364 v->final_value = final_value;
07365 }
07366
07367 if (loop_dump_stream && v->replaceable)
07368 fprintf (loop_dump_stream, "Insn %d: giv reg %d final_value replaceable\n",
07369 INSN_UID (v->insn), REGNO (v->dest_reg));
07370 }
07371
07372
07373
07374
07375
07376
07377
07378
07379
07380
07381
07382
07383 static void
07384 update_giv_derive (const struct loop *loop, rtx p)
07385 {
07386 struct loop_ivs *ivs = LOOP_IVS (loop);
07387 struct iv_class *bl;
07388 struct induction *biv, *giv;
07389 rtx tem;
07390 int dummy;
07391
07392
07393
07394
07395
07396
07397
07398
07399
07400
07401
07402
07403
07404
07405
07406
07407
07408
07409
07410
07411
07412
07413
07414
07415
07416
07417
07418
07419 for (bl = ivs->list; bl; bl = bl->next)
07420 for (biv = bl->biv; biv; biv = biv->next_iv)
07421 if (LABEL_P (p) || JUMP_P (p)
07422 || biv->insn == p)
07423 {
07424
07425 if (biv->same)
07426 continue;
07427
07428 for (giv = bl->giv; giv; giv = giv->next_iv)
07429 {
07430
07431
07432 if (giv->cant_derive)
07433 continue;
07434
07435
07436
07437 if (LABEL_P (p) && ! giv->always_computable)
07438 giv->cant_derive = 1;
07439
07440
07441
07442
07443
07444 else if (giv->mult_val == const0_rtx || giv->replaceable)
07445 continue;
07446
07447
07448
07449
07450
07451 else if (biv->insn == p)
07452 {
07453 rtx ext_val_dummy;
07454
07455 tem = 0;
07456 if (biv->mult_val == const1_rtx)
07457 tem = simplify_giv_expr (loop,
07458 gen_rtx_MULT (giv->mode,
07459 biv->add_val,
07460 giv->mult_val),
07461 &ext_val_dummy, &dummy);
07462
07463 if (tem && giv->derive_adjustment)
07464 tem = simplify_giv_expr
07465 (loop,
07466 gen_rtx_PLUS (giv->mode, tem, giv->derive_adjustment),
07467 &ext_val_dummy, &dummy);
07468
07469 if (tem)
07470 giv->derive_adjustment = tem;
07471 else
07472 giv->cant_derive = 1;
07473 }
07474 else if ((LABEL_P (p) && ! biv->always_computable)
07475 || (JUMP_P (p) && biv->maybe_multiple))
07476 giv->cant_derive = 1;
07477 }
07478 }
07479 }
07480
07481
07482
07483
07484
07485
07486
07487
07488
07489
07490
07491
07492
07493
07494
07495
07496
07497
07498
07499
07500
07501
07502
07503
07504
07505
07506
07507
07508
07509
07510
07511
07512
07513
07514
07515
07516
07517
07518 static int
07519 basic_induction_var (const struct loop *loop, rtx x, enum machine_mode mode,
07520 rtx dest_reg, rtx p, rtx *inc_val, rtx *mult_val,
07521 rtx **location)
07522 {
07523 enum rtx_code code;
07524 rtx *argp, arg;
07525 rtx insn, set = 0, last, inc;
07526
07527 code = GET_CODE (x);
07528 *location = NULL;
07529 switch (code)
07530 {
07531 case PLUS:
07532 if (rtx_equal_p (XEXP (x, 0), dest_reg)
07533 || (GET_CODE (XEXP (x, 0)) == SUBREG
07534 && SUBREG_PROMOTED_VAR_P (XEXP (x, 0))
07535 && SUBREG_REG (XEXP (x, 0)) == dest_reg))
07536 {
07537 argp = &XEXP (x, 1);
07538 }
07539 else if (rtx_equal_p (XEXP (x, 1), dest_reg)
07540 || (GET_CODE (XEXP (x, 1)) == SUBREG
07541 && SUBREG_PROMOTED_VAR_P (XEXP (x, 1))
07542 && SUBREG_REG (XEXP (x, 1)) == dest_reg))
07543 {
07544 argp = &XEXP (x, 0);
07545 }
07546 else
07547 return 0;
07548
07549 arg = *argp;
07550 if (loop_invariant_p (loop, arg) != 1)
07551 return 0;
07552
07553
07554
07555
07556
07557
07558
07559
07560
07561
07562
07563
07564 last = get_last_insn ();
07565 inc = convert_modes (GET_MODE (dest_reg), GET_MODE (x), arg, 0);
07566 if (get_last_insn () != last)
07567 {
07568 delete_insns_since (last);
07569 return 0;
07570 }
07571
07572 *inc_val = inc;
07573 *mult_val = const1_rtx;
07574 *location = argp;
07575 return 1;
07576
07577 case SUBREG:
07578
07579
07580
07581
07582 return basic_induction_var (loop, SUBREG_REG (x),
07583 GET_MODE (SUBREG_REG (x)),
07584 dest_reg, p, inc_val, mult_val, location);
07585
07586 case REG:
07587
07588
07589
07590
07591
07592 if (rtx_equal_p (dest_reg, x))
07593 return 0;
07594
07595 insn = p;
07596 while (1)
07597 {
07598 rtx dest;
07599 do
07600 {
07601 insn = PREV_INSN (insn);
07602 }
07603 while (insn && NOTE_P (insn)
07604 && NOTE_LINE_NUMBER (insn) != NOTE_INSN_LOOP_BEG);
07605
07606 if (!insn)
07607 break;
07608 set = single_set (insn);
07609 if (set == 0)
07610 break;
07611 dest = SET_DEST (set);
07612 if (dest == x
07613 || (GET_CODE (dest) == SUBREG
07614 && (GET_MODE_SIZE (GET_MODE (dest)) <= UNITS_PER_WORD)
07615 && (GET_MODE_CLASS (GET_MODE (dest)) == MODE_INT)
07616 && SUBREG_REG (dest) == x))
07617 return basic_induction_var (loop, SET_SRC (set),
07618 (GET_MODE (SET_SRC (set)) == VOIDmode
07619 ? GET_MODE (x)
07620 : GET_MODE (SET_SRC (set))),
07621 dest_reg, insn,
07622 inc_val, mult_val, location);
07623
07624 while (GET_CODE (dest) == SUBREG
07625 || GET_CODE (dest) == ZERO_EXTRACT
07626 || GET_CODE (dest) == STRICT_LOW_PART)
07627 dest = XEXP (dest, 0);
07628 if (dest == x)
07629 break;
07630 }
07631
07632
07633
07634
07635
07636
07637 case MEM:
07638 if (loop_invariant_p (loop, x) != 1)
07639 return 0;
07640 case CONST_INT:
07641 case SYMBOL_REF:
07642 case CONST:
07643
07644
07645
07646
07647 if (loop->level == 1
07648 && GET_MODE_CLASS (mode) == GET_MODE_CLASS (GET_MODE (dest_reg))
07649 && GET_MODE_CLASS (mode) != MODE_CC)
07650 {
07651
07652 last = get_last_insn ();
07653 inc = convert_modes (GET_MODE (dest_reg), mode, x, 0);
07654 if (get_last_insn () != last)
07655 {
07656 delete_insns_since (last);
07657 return 0;
07658 }
07659
07660 *inc_val = inc;
07661 *mult_val = const0_rtx;
07662 return 1;
07663 }
07664 else
07665 return 0;
07666
07667 case SIGN_EXTEND:
07668
07669 if (flag_wrapv)
07670 return 0;
07671 return basic_induction_var (loop, XEXP (x, 0), GET_MODE (XEXP (x, 0)),
07672 dest_reg, p, inc_val, mult_val, location);
07673
07674 case ASHIFTRT:
07675
07676 for (insn = PREV_INSN (p);
07677 (insn && NOTE_P (insn)
07678 && NOTE_LINE_NUMBER (insn) != NOTE_INSN_LOOP_BEG);
07679 insn = PREV_INSN (insn))
07680 ;
07681
07682 if (insn)
07683 set = single_set (insn);
07684
07685 if (! rtx_equal_p (dest_reg, XEXP (x, 0))
07686 && set && SET_DEST (set) == XEXP (x, 0)
07687 && GET_CODE (XEXP (x, 1)) == CONST_INT
07688 && INTVAL (XEXP (x, 1)) >= 0
07689 && GET_CODE (SET_SRC (set)) == ASHIFT
07690 && XEXP (x, 1) == XEXP (SET_SRC (set), 1))
07691 return basic_induction_var (loop, XEXP (SET_SRC (set), 0),
07692 GET_MODE (XEXP (x, 0)),
07693 dest_reg, insn, inc_val, mult_val,
07694 location);
07695 return 0;
07696
07697 default:
07698 return 0;
07699 }
07700 }
07701
07702
07703
07704
07705
07706
07707
07708
07709
07710
07711
07712
07713
07714
07715
07716 static int
07717 general_induction_var (const struct loop *loop, rtx x, rtx *src_reg,
07718 rtx *add_val, rtx *mult_val, rtx *ext_val,
07719 int is_addr, int *pbenefit,
07720 enum machine_mode addr_mode)
07721 {
07722 struct loop_ivs *ivs = LOOP_IVS (loop);
07723 rtx orig_x = x;
07724
07725
07726 if (loop_invariant_p (loop, x) == 1)
07727 return 0;
07728
07729 *pbenefit = 0;
07730 *ext_val = NULL_RTX;
07731 x = simplify_giv_expr (loop, x, ext_val, pbenefit);
07732 if (x == 0)
07733 return 0;
07734
07735 switch (GET_CODE (x))
07736 {
07737 case USE:
07738 case CONST_INT:
07739
07740
07741
07742 *src_reg = ivs->list->biv->dest_reg;
07743 *mult_val = const0_rtx;
07744 *add_val = x;
07745 break;
07746
07747 case REG:
07748
07749 *src_reg = x;
07750 *mult_val = const1_rtx;
07751 *add_val = const0_rtx;
07752 break;
07753
07754 case PLUS:
07755
07756
07757 if (GET_CODE (XEXP (x, 0)) == MULT)
07758 {
07759 *src_reg = XEXP (XEXP (x, 0), 0);
07760 *mult_val = XEXP (XEXP (x, 0), 1);
07761 }
07762 else
07763 {
07764 *src_reg = XEXP (x, 0);
07765 *mult_val = const1_rtx;
07766 }
07767 *add_val = XEXP (x, 1);
07768 break;
07769
07770 case MULT:
07771
07772 *src_reg = XEXP (x, 0);
07773 *mult_val = XEXP (x, 1);
07774 *add_val = const0_rtx;
07775 break;
07776
07777 default:
07778 abort ();
07779 }
07780
07781
07782
07783 if (GET_CODE (*add_val) == USE)
07784 *add_val = XEXP (*add_val, 0);
07785 if (GET_CODE (*mult_val) == USE)
07786 *mult_val = XEXP (*mult_val, 0);
07787
07788 if (is_addr)
07789 *pbenefit += address_cost (orig_x, addr_mode) - reg_address_cost;
07790 else
07791 *pbenefit += rtx_cost (orig_x, SET);
07792
07793
07794
07795
07796 return 1;
07797 }
07798
07799
07800
07801
07802
07803
07804
07805
07806
07807
07808
07809
07810
07811
07812
07813
07814
07815
07816
07817
07818
07819 static rtx sge_plus (enum machine_mode, rtx, rtx);
07820 static rtx sge_plus_constant (rtx, rtx);
07821
07822 static rtx
07823 simplify_giv_expr (const struct loop *loop, rtx x, rtx *ext_val, int *benefit)
07824 {
07825 struct loop_ivs *ivs = LOOP_IVS (loop);
07826 struct loop_regs *regs = LOOP_REGS (loop);
07827 enum machine_mode mode = GET_MODE (x);
07828 rtx arg0, arg1;
07829 rtx tem;
07830
07831
07832
07833 if (mode != VOIDmode
07834 && (GET_MODE_CLASS (mode) != MODE_INT
07835 || GET_MODE_BITSIZE (mode) > HOST_BITS_PER_WIDE_INT))
07836 return NULL_RTX;
07837
07838 switch (GET_CODE (x))
07839 {
07840 case PLUS:
07841 arg0 = simplify_giv_expr (loop, XEXP (x, 0), ext_val, benefit);
07842 arg1 = simplify_giv_expr (loop, XEXP (x, 1), ext_val, benefit);
07843 if (arg0 == 0 || arg1 == 0)
07844 return NULL_RTX;
07845
07846
07847 if ((GET_CODE (arg0) == USE
07848 || GET_CODE (arg0) == CONST_INT)
07849 && ! ((GET_CODE (arg0) == USE
07850 && GET_CODE (arg1) == USE)
07851 || GET_CODE (arg1) == CONST_INT))
07852 tem = arg0, arg0 = arg1, arg1 = tem;
07853
07854
07855 if (arg1 == const0_rtx)
07856 return arg0;
07857 else if (GET_CODE (arg1) == CONST_INT || GET_CODE (arg1) == USE)
07858 switch (GET_CODE (arg0))
07859 {
07860 case CONST_INT:
07861 case USE:
07862
07863
07864 if (GET_CODE (arg0) == USE)
07865 arg0 = XEXP (arg0, 0);
07866 if (GET_CODE (arg1) == USE)
07867 arg1 = XEXP (arg1, 0);
07868
07869 if (GET_CODE (arg0) == CONST_INT)
07870 tem = arg0, arg0 = arg1, arg1 = tem;
07871 if (GET_CODE (arg1) == CONST_INT)
07872 tem = sge_plus_constant (arg0, arg1);
07873 else
07874 tem = sge_plus (mode, arg0, arg1);
07875
07876 if (GET_CODE (tem) != CONST_INT)
07877 tem = gen_rtx_USE (mode, tem);
07878 return tem;
07879
07880 case REG:
07881 case MULT:
07882
07883 return gen_rtx_PLUS (mode, arg0, arg1);
07884
07885 case PLUS:
07886
07887 return
07888 simplify_giv_expr (loop,
07889 gen_rtx_PLUS (mode,
07890 XEXP (arg0, 0),
07891 gen_rtx_PLUS (mode,
07892 XEXP (arg0, 1),
07893 arg1)),
07894 ext_val, benefit);
07895
07896 default:
07897 abort ();
07898 }
07899
07900
07901
07902 if (REG_P (arg0))
07903 arg0 = gen_rtx_MULT (mode, arg0, const1_rtx);
07904 if (REG_P (arg1))
07905 arg1 = gen_rtx_MULT (mode, arg1, const1_rtx);
07906
07907
07908
07909
07910 if (GET_CODE (arg1) == MULT)
07911 tem = arg0, arg0 = arg1, arg1 = tem;
07912
07913 if (GET_CODE (arg1) == PLUS)
07914 return
07915 simplify_giv_expr (loop,
07916 gen_rtx_PLUS (mode,
07917 gen_rtx_PLUS (mode, arg0,
07918 XEXP (arg1, 0)),
07919 XEXP (arg1, 1)),
07920 ext_val, benefit);
07921
07922
07923 if (GET_CODE (arg0) != MULT || GET_CODE (arg1) != MULT)
07924 return NULL_RTX;
07925
07926 if (!rtx_equal_p (arg0, arg1))
07927 return NULL_RTX;
07928
07929 return simplify_giv_expr (loop,
07930 gen_rtx_MULT (mode,
07931 XEXP (arg0, 0),
07932 gen_rtx_PLUS (mode,
07933 XEXP (arg0, 1),
07934 XEXP (arg1, 1))),
07935 ext_val, benefit);
07936
07937 case MINUS:
07938
07939 return simplify_giv_expr (loop,
07940 gen_rtx_PLUS (mode,
07941 XEXP (x, 0),
07942 gen_rtx_MULT (mode,
07943 XEXP (x, 1),
07944 constm1_rtx)),
07945 ext_val, benefit);
07946
07947 case MULT:
07948 arg0 = simplify_giv_expr (loop, XEXP (x, 0), ext_val, benefit);
07949 arg1 = simplify_giv_expr (loop, XEXP (x, 1), ext_val, benefit);
07950 if (arg0 == 0 || arg1 == 0)
07951 return NULL_RTX;
07952
07953
07954 if ((GET_CODE (arg0) == USE || GET_CODE (arg0) == CONST_INT)
07955 && GET_CODE (arg1) != CONST_INT)
07956 tem = arg0, arg0 = arg1, arg1 = tem;
07957
07958
07959 if (GET_CODE (arg1) != USE && GET_CODE (arg1) != CONST_INT)
07960 return NULL_RTX;
07961
07962
07963 if (arg1 == const0_rtx)
07964 return const0_rtx;
07965
07966 else if (arg1 == const1_rtx)
07967 return arg0;
07968
07969 switch (GET_CODE (arg0))
07970 {
07971 case REG:
07972
07973 return gen_rtx_MULT (mode, arg0, arg1);
07974
07975 case CONST_INT:
07976
07977 return GEN_INT (INTVAL (arg0) * INTVAL (arg1));
07978
07979 case USE:
07980
07981 if (GET_CODE (arg1) != CONST_INT)
07982 return NULL_RTX;
07983
07984 arg0 = XEXP (arg0, 0);
07985 if (GET_CODE (arg0) == MULT)
07986 {
07987
07988 return simplify_giv_expr (loop,
07989 gen_rtx_MULT (mode,
07990 XEXP (arg0, 0),
07991 gen_rtx_MULT (mode,
07992 XEXP (arg0,
07993 1),
07994 arg1)),
07995 ext_val, benefit);
07996 }
07997
07998 else if (GET_CODE (arg0) == PLUS)
07999 {
08000
08001 return simplify_giv_expr (loop,
08002 gen_rtx_PLUS (mode,
08003 gen_rtx_MULT (mode,
08004 XEXP (arg0,
08005 0),
08006 arg1),
08007 gen_rtx_MULT (mode,
08008 XEXP (arg0,
08009 1),
08010 arg1)),
08011 ext_val, benefit);
08012 }
08013 return gen_rtx_USE (mode, gen_rtx_MULT (mode, arg0, arg1));
08014
08015 case MULT:
08016
08017 return simplify_giv_expr (loop,
08018 gen_rtx_MULT (mode,
08019 XEXP (arg0, 0),
08020 gen_rtx_MULT (mode,
08021 XEXP (arg0, 1),
08022 arg1)),
08023 ext_val, benefit);
08024
08025 case PLUS:
08026
08027 return simplify_giv_expr (loop,
08028 gen_rtx_PLUS (mode,
08029 gen_rtx_MULT (mode,
08030 XEXP (arg0, 0),
08031 arg1),
08032 gen_rtx_MULT (mode,
08033 XEXP (arg0, 1),
08034 arg1)),
08035 ext_val, benefit);
08036
08037 default:
08038 abort ();
08039 }
08040
08041 case ASHIFT:
08042
08043 if (GET_CODE (XEXP (x, 1)) != CONST_INT)
08044 return 0;
08045
08046 return
08047 simplify_giv_expr (loop,
08048 gen_rtx_MULT (mode,
08049 XEXP (x, 0),
08050 GEN_INT ((HOST_WIDE_INT) 1
08051 << INTVAL (XEXP (x, 1)))),
08052 ext_val, benefit);
08053
08054 case NEG:
08055
08056 return simplify_giv_expr (loop,
08057 gen_rtx_MULT (mode, XEXP (x, 0), constm1_rtx),
08058 ext_val, benefit);
08059
08060 case NOT:
08061
08062 return simplify_giv_expr (loop,
08063 gen_rtx_MINUS (mode,
08064 gen_rtx_NEG (mode, XEXP (x, 0)),
08065 const1_rtx),
08066 ext_val, benefit);
08067
08068 case USE:
08069
08070 return x;
08071
08072 case SIGN_EXTEND:
08073 case ZERO_EXTEND:
08074 case TRUNCATE:
08075
08076
08077
08078 if (*ext_val == NULL_RTX)
08079 {
08080 arg0 = simplify_giv_expr (loop, XEXP (x, 0), ext_val, benefit);
08081 if (arg0 && *ext_val == NULL_RTX && REG_P (arg0))
08082 {
08083 *ext_val = gen_rtx_fmt_e (GET_CODE (x), mode, arg0);
08084 return arg0;
08085 }
08086 }
08087 goto do_default;
08088
08089 case REG:
08090
08091 if (REGNO (x) >= max_reg_before_loop)
08092 return 0;
08093
08094
08095 switch (REG_IV_TYPE (ivs, REGNO (x)))
08096 {
08097 case BASIC_INDUCT:
08098 return x;
08099 case GENERAL_INDUCT:
08100 {
08101 struct induction *v = REG_IV_INFO (ivs, REGNO (x));
08102
08103
08104
08105
08106
08107
08108
08109
08110
08111
08112
08113 {
08114 rtx single_use = regs->array[REGNO (x)].single_usage;
08115 if (single_use && single_use != const0_rtx)
08116 *benefit += v->benefit;
08117 }
08118
08119 if (v->cant_derive)
08120 return 0;
08121
08122 tem = gen_rtx_PLUS (mode, gen_rtx_MULT (mode,
08123 v->src_reg, v->mult_val),
08124 v->add_val);
08125
08126 if (v->derive_adjustment)
08127 tem = gen_rtx_MINUS (mode, tem, v->derive_adjustment);
08128 arg0 = simplify_giv_expr (loop, tem, ext_val, benefit);
08129 if (*ext_val)
08130 {
08131 if (!v->ext_dependent)
08132 return arg0;
08133 }
08134 else
08135 {
08136 *ext_val = v->ext_dependent;
08137 return arg0;
08138 }
08139 return 0;
08140 }
08141
08142 default:
08143 do_default:
08144
08145
08146
08147 if (loop_invariant_p (loop, x) == 1)
08148 {
08149 struct movable *m;
08150 struct loop_movables *movables = LOOP_MOVABLES (loop);
08151
08152 for (m = movables->head; m; m = m->next)
08153 if (rtx_equal_p (x, m->set_dest))
08154 {
08155
08156
08157
08158
08159 if (m->match)
08160 return simplify_giv_expr (loop, m->match->set_dest,
08161 ext_val, benefit);
08162
08163
08164
08165
08166
08167 if (m->consec != 0)
08168 {
08169 int i = m->consec;
08170 tem = m->insn;
08171 do
08172 {
08173 tem = NEXT_INSN (tem);
08174 }
08175 while (--i > 0);
08176
08177 tem = find_reg_note (tem, REG_EQUAL, NULL_RTX);
08178 if (tem)
08179 tem = XEXP (tem, 0);
08180 }
08181 else
08182 {
08183 tem = single_set (m->insn);
08184 if (tem)
08185 tem = SET_SRC (tem);
08186 }
08187
08188 if (tem)
08189 {
08190
08191
08192
08193 if (GET_CODE (tem) == PLUS
08194 || GET_CODE (tem) == MULT
08195 || GET_CODE (tem) == ASHIFT
08196 || GET_CODE (tem) == CONST_INT
08197 || GET_CODE (tem) == SYMBOL_REF)
08198 {
08199 tem = simplify_giv_expr (loop, tem, ext_val,
08200 benefit);
08201 if (tem)
08202 return tem;
08203 }
08204 else if (GET_CODE (tem) == CONST
08205 && GET_CODE (XEXP (tem, 0)) == PLUS
08206 && GET_CODE (XEXP (XEXP (tem, 0), 0)) == SYMBOL_REF
08207 && GET_CODE (XEXP (XEXP (tem, 0), 1)) == CONST_INT)
08208 {
08209 tem = simplify_giv_expr (loop, XEXP (tem, 0),
08210 ext_val, benefit);
08211 if (tem)
08212 return tem;
08213 }
08214 }
08215 break;
08216 }
08217 }
08218 break;
08219 }
08220
08221
08222 default:
08223
08224
08225 if (GET_CODE (x) == USE)
08226 x = XEXP (x, 0);
08227
08228 if (loop_invariant_p (loop, x) == 1)
08229 {
08230 if (GET_CODE (x) == CONST_INT)
08231 return x;
08232 if (GET_CODE (x) == CONST
08233 && GET_CODE (XEXP (x, 0)) == PLUS
08234 && GET_CODE (XEXP (XEXP (x, 0), 0)) == SYMBOL_REF
08235 && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT)
08236 x = XEXP (x, 0);
08237 return gen_rtx_USE (mode, x);
08238 }
08239 else
08240 return 0;
08241 }
08242 }
08243
08244
08245
08246
08247 static rtx
08248 sge_plus_constant (rtx x, rtx c)
08249 {
08250 if (GET_CODE (x) == CONST_INT)
08251 return GEN_INT (INTVAL (x) + INTVAL (c));
08252 else if (GET_CODE (x) != PLUS)
08253 return gen_rtx_PLUS (GET_MODE (x), x, c);
08254 else if (GET_CODE (XEXP (x, 1)) == CONST_INT)
08255 {
08256 return gen_rtx_PLUS (GET_MODE (x), XEXP (x, 0),
08257 GEN_INT (INTVAL (XEXP (x, 1)) + INTVAL (c)));
08258 }
08259 else if (GET_CODE (XEXP (x, 0)) == PLUS
08260 || GET_CODE (XEXP (x, 1)) != PLUS)
08261 {
08262 return gen_rtx_PLUS (GET_MODE (x),
08263 sge_plus_constant (XEXP (x, 0), c), XEXP (x, 1));
08264 }
08265 else
08266 {
08267 return gen_rtx_PLUS (GET_MODE (x),
08268 sge_plus_constant (XEXP (x, 1), c), XEXP (x, 0));
08269 }
08270 }
08271
08272 static rtx
08273 sge_plus (enum machine_mode mode, rtx x, rtx y)
08274 {
08275 while (GET_CODE (y) == PLUS)
08276 {
08277 rtx a = XEXP (y, 0);
08278 if (GET_CODE (a) == CONST_INT)
08279 x = sge_plus_constant (x, a);
08280 else
08281 x = gen_rtx_PLUS (mode, x, a);
08282 y = XEXP (y, 1);
08283 }
08284 if (GET_CODE (y) == CONST_INT)
08285 x = sge_plus_constant (x, y);
08286 else
08287 x = gen_rtx_PLUS (mode, x, y);
08288 return x;
08289 }
08290
08291
08292
08293
08294
08295
08296
08297
08298
08299
08300
08301
08302
08303
08304
08305
08306
08307
08308
08309
08310 static int
08311 consec_sets_giv (const struct loop *loop, int first_benefit, rtx p,
08312 rtx src_reg, rtx dest_reg, rtx *add_val, rtx *mult_val,
08313 rtx *ext_val, rtx *last_consec_insn)
08314 {
08315 struct loop_ivs *ivs = LOOP_IVS (loop);
08316 struct loop_regs *regs = LOOP_REGS (loop);
08317 int count;
08318 enum rtx_code code;
08319 int benefit;
08320 rtx temp;
08321 rtx set;
08322
08323
08324
08325
08326
08327
08328
08329
08330 struct induction *v;
08331
08332 if (REG_IV_TYPE (ivs, REGNO (dest_reg)) != UNKNOWN_INDUCT)
08333 return 0;
08334
08335 v = alloca (sizeof (struct induction));
08336 v->src_reg = src_reg;
08337 v->mult_val = *mult_val;
08338 v->add_val = *add_val;
08339 v->benefit = first_benefit;
08340 v->cant_derive = 0;
08341 v->derive_adjustment = 0;
08342 v->ext_dependent = NULL_RTX;
08343
08344 REG_IV_TYPE (ivs, REGNO (dest_reg)) = GENERAL_INDUCT;
08345 REG_IV_INFO (ivs, REGNO (dest_reg)) = v;
08346
08347 count = regs->array[REGNO (dest_reg)].n_times_set - 1;
08348
08349 while (count > 0)
08350 {
08351 p = NEXT_INSN (p);
08352 code = GET_CODE (p);
08353
08354
08355 if (code == INSN && (temp = find_reg_note (p, REG_LIBCALL, NULL_RTX)))
08356 p = XEXP (temp, 0);
08357
08358 if (code == INSN
08359 && (set = single_set (p))
08360 && REG_P (SET_DEST (set))
08361 && SET_DEST (set) == dest_reg
08362 && (general_induction_var (loop, SET_SRC (set), &src_reg,
08363 add_val, mult_val, ext_val, 0,
08364 &benefit, VOIDmode)
08365
08366 || ((temp = find_reg_note (p, REG_EQUAL, NULL_RTX))
08367 && general_induction_var (loop, XEXP (temp, 0), &src_reg,
08368 add_val, mult_val, ext_val, 0,
08369 &benefit, VOIDmode)))
08370 && src_reg == v->src_reg)
08371 {
08372 if (find_reg_note (p, REG_RETVAL, NULL_RTX))
08373 benefit += libcall_benefit (p);
08374
08375 count--;
08376 v->mult_val = *mult_val;
08377 v->add_val = *add_val;
08378 v->benefit += benefit;
08379 }
08380 else if (code != NOTE)
08381 {
08382
08383
08384
08385 if (code == INSN
08386 && (set = single_set (p))
08387 && SET_DEST (set) != dest_reg
08388 && CONSTANT_P (SET_SRC (set)))
08389 continue;
08390
08391 REG_IV_TYPE (ivs, REGNO (dest_reg)) = UNKNOWN_INDUCT;
08392 return 0;
08393 }
08394 }
08395
08396 REG_IV_TYPE (ivs, REGNO (dest_reg)) = UNKNOWN_INDUCT;
08397 *last_consec_insn = p;
08398 return v->benefit;
08399 }
08400
08401
08402
08403
08404
08405
08406
08407
08408
08409
08410
08411
08412
08413
08414
08415
08416
08417
08418 static rtx
08419 express_from_1 (rtx a, rtx b, rtx mult)
08420 {
08421
08422
08423 if (mult == const0_rtx)
08424 return b;
08425
08426
08427
08428
08429
08430
08431 if (mult != const1_rtx && GET_CODE (a) != CONST_INT)
08432 return NULL_RTX;
08433
08434
08435
08436
08437
08438
08439
08440 while (GET_CODE (a) == PLUS && GET_CODE (b) == PLUS)
08441 {
08442 rtx ra, rb, oa, ob, tmp;
08443
08444 ra = XEXP (a, 0), oa = XEXP (a, 1);
08445 if (GET_CODE (ra) == PLUS)
08446 tmp = ra, ra = oa, oa = tmp;
08447
08448 rb = XEXP (b, 0), ob = XEXP (b, 1);
08449 if (GET_CODE (rb) == PLUS)
08450 tmp = rb, rb = ob, ob = tmp;
08451
08452 if (rtx_equal_p (ra, rb))
08453
08454 a = oa, b = ob;
08455 else if (GET_CODE (ob) != PLUS && rtx_equal_p (ra, ob))
08456
08457 a = oa, b = rb;
08458 else if (GET_CODE (oa) != PLUS && rtx_equal_p (oa, rb))
08459
08460 a = ra, b = ob;
08461 else
08462 {
08463
08464
08465 ob = express_from_1 (a, ob, mult);
08466 if (ob == NULL_RTX)
08467 return NULL_RTX;
08468 return gen_rtx_PLUS (GET_MODE (b), rb, ob);
08469 }
08470 }
08471
08472
08473
08474
08475 if (GET_CODE (a) == PLUS)
08476 {
08477 rtx ra, oa;
08478
08479 ra = XEXP (a, 0), oa = XEXP (a, 1);
08480 if (rtx_equal_p (oa, b))
08481 oa = ra;
08482 else if (!rtx_equal_p (ra, b))
08483 return NULL_RTX;
08484
08485 if (GET_CODE (oa) != CONST_INT)
08486 return NULL_RTX;
08487
08488 return GEN_INT (-INTVAL (oa) * INTVAL (mult));
08489 }
08490 else if (GET_CODE (a) == CONST_INT)
08491 {
08492 return plus_constant (b, -INTVAL (a) * INTVAL (mult));
08493 }
08494 else if (CONSTANT_P (a))
08495 {
08496 enum machine_mode mode_a = GET_MODE (a);
08497 enum machine_mode mode_b = GET_MODE (b);
08498 enum machine_mode mode = mode_b == VOIDmode ? mode_a : mode_b;
08499 return simplify_gen_binary (MINUS, mode, b, a);
08500 }
08501 else if (GET_CODE (b) == PLUS)
08502 {
08503 if (rtx_equal_p (a, XEXP (b, 0)))
08504 return XEXP (b, 1);
08505 else if (rtx_equal_p (a, XEXP (b, 1)))
08506 return XEXP (b, 0);
08507 else
08508 return NULL_RTX;
08509 }
08510 else if (rtx_equal_p (a, b))
08511 return const0_rtx;
08512
08513 return NULL_RTX;
08514 }
08515
08516 static rtx
08517 express_from (struct induction *g1, struct induction *g2)
08518 {
08519 rtx mult, add;
08520
08521
08522
08523
08524 if (GET_CODE (g1->mult_val) == CONST_INT
08525 && GET_CODE (g2->mult_val) == CONST_INT)
08526 {
08527 if (g1->mult_val == const0_rtx
08528 || (g1->mult_val == constm1_rtx
08529 && INTVAL (g2->mult_val)
08530 == (HOST_WIDE_INT) 1 << (HOST_BITS_PER_WIDE_INT - 1))
08531 || INTVAL (g2->mult_val) % INTVAL (g1->mult_val) != 0)
08532 return NULL_RTX;
08533 mult = GEN_INT (INTVAL (g2->mult_val) / INTVAL (g1->mult_val));
08534 }
08535 else if (rtx_equal_p (g1->mult_val, g2->mult_val))
08536 mult = const1_rtx;
08537 else
08538 {
08539
08540 return NULL_RTX;
08541 }
08542
08543 add = express_from_1 (g1->add_val, g2->add_val, mult);
08544 if (add == NULL_RTX)
08545 {
08546
08547
08548 if (INTVAL (mult) > 1)
08549 {
08550 rtx g1_add_val = g1->add_val;
08551 if (GET_CODE (g1_add_val) == MULT
08552 && GET_CODE (XEXP (g1_add_val, 1)) == CONST_INT)
08553 {
08554 HOST_WIDE_INT m;
08555 m = INTVAL (mult) * INTVAL (XEXP (g1_add_val, 1));
08556 g1_add_val = gen_rtx_MULT (GET_MODE (g1_add_val),
08557 XEXP (g1_add_val, 0), GEN_INT (m));
08558 }
08559 else
08560 {
08561 g1_add_val = gen_rtx_MULT (GET_MODE (g1_add_val), g1_add_val,
08562 mult);
08563 }
08564
08565 add = express_from_1 (g1_add_val, g2->add_val, const1_rtx);
08566 }
08567 }
08568 if (add == NULL_RTX)
08569 return NULL_RTX;
08570
08571
08572 if (mult == const0_rtx)
08573 return add;
08574 else if (mult == const1_rtx)
08575 mult = g1->dest_reg;
08576 else
08577 mult = gen_rtx_MULT (g2->mode, g1->dest_reg, mult);
08578
08579 if (add == const0_rtx)
08580 return mult;
08581 else
08582 {
08583 if (GET_CODE (add) == PLUS
08584 && CONSTANT_P (XEXP (add, 1)))
08585 {
08586 rtx tem = XEXP (add, 1);
08587 mult = gen_rtx_PLUS (g2->mode, mult, XEXP (add, 0));
08588 add = tem;
08589 }
08590
08591 return gen_rtx_PLUS (g2->mode, mult, add);
08592 }
08593 }
08594
08595
08596
08597
08598
08599
08600 static rtx
08601 combine_givs_p (struct induction *g1, struct induction *g2)
08602 {
08603 rtx comb, ret;
08604
08605
08606
08607 if (GET_MODE_SIZE (g1->mode) < GET_MODE_SIZE (g2->mode))
08608 return NULL_RTX;
08609
08610 ret = comb = express_from (g1, g2);
08611 if (comb == NULL_RTX)
08612 return NULL_RTX;
08613 if (g1->mode != g2->mode)
08614 ret = gen_lowpart (g2->mode, comb);
08615
08616
08617
08618
08619
08620
08621 if (comb == g1->dest_reg
08622 && (g1->giv_type == DEST_REG || g2->giv_type == DEST_ADDR))
08623 {
08624 return ret;
08625 }
08626
08627
08628
08629
08630 if (ret != NULL_RTX
08631 && g2->giv_type == DEST_ADDR
08632 && memory_address_p (GET_MODE (g2->mem), ret))
08633 return ret;
08634
08635 return NULL_RTX;
08636 }
08637
08638
08639
08640
08641 static HOST_WIDE_INT
08642 get_monotonic_increment (struct iv_class *bl)
08643 {
08644 struct induction *v;
08645 rtx incr;
08646
08647
08648 incr = biv_total_increment (bl);
08649 if (incr == 0 || GET_CODE (incr) != CONST_INT)
08650 return 0;
08651
08652 for (v = bl->biv; v != 0; v = v->next_iv)
08653 {
08654 if (GET_CODE (v->add_val) != CONST_INT)
08655 return 0;
08656
08657 if (INTVAL (v->add_val) < 0 && INTVAL (incr) >= 0)
08658 return 0;
08659
08660 if (INTVAL (v->add_val) > 0 && INTVAL (incr) <= 0)
08661 return 0;
08662 }
08663 return INTVAL (incr);
08664 }
08665
08666
08667
08668
08669
08670
08671 static bool
08672 biased_biv_fits_mode_p (const struct loop *loop, struct iv_class *bl,
08673 HOST_WIDE_INT incr, enum machine_mode mode,
08674 unsigned HOST_WIDE_INT bias)
08675 {
08676 unsigned HOST_WIDE_INT initial, maximum, span, delta;
08677
08678
08679 if (HOST_BITS_PER_WIDE_INT < GET_MODE_BITSIZE (mode))
08680 return false;
08681
08682
08683 if (LOOP_INFO (loop)->n_iterations == 0)
08684 return false;
08685
08686
08687 if (bl->initial_value == 0 || GET_CODE (bl->initial_value) != CONST_INT)
08688 return false;
08689
08690 initial = bias + INTVAL (bl->initial_value);
08691 maximum = GET_MODE_MASK (mode);
08692
08693
08694 if (initial > maximum)
08695 return false;
08696
08697
08698
08699 if (incr < 0)
08700 {
08701 delta = -incr;
08702 span = initial;
08703 }
08704 else
08705 {
08706 delta = incr;
08707
08708
08709 if (maximum + 1 == initial)
08710 span = LOOP_INFO (loop)->n_iterations * delta;
08711 else
08712 span = maximum + 1 - initial;
08713 }
08714 return (span / LOOP_INFO (loop)->n_iterations >= delta);
08715 }
08716
08717
08718
08719
08720
08721
08722 static bool
08723 biv_fits_mode_p (const struct loop *loop, struct iv_class *bl,
08724 HOST_WIDE_INT incr, enum machine_mode mode, bool unsignedp)
08725 {
08726 struct loop_info *loop_info;
08727 unsigned HOST_WIDE_INT bias;
08728
08729
08730
08731 if (GET_MODE_SIZE (mode) > GET_MODE_SIZE (GET_MODE (bl->biv->src_reg)))
08732 mode = GET_MODE (bl->biv->src_reg);
08733
08734 loop_info = LOOP_INFO (loop);
08735
08736 bias = (unsignedp ? 0 : (GET_MODE_MASK (mode) >> 1) + 1);
08737 if (biased_biv_fits_mode_p (loop, bl, incr, mode, bias))
08738 return true;
08739
08740 if (mode == GET_MODE (bl->biv->src_reg)
08741 && bl->biv->src_reg == loop_info->iteration_var
08742 && loop_info->comparison_value
08743 && loop_invariant_p (loop, loop_info->comparison_value))
08744 {
08745
08746
08747
08748 if (incr == 1)
08749 {
08750 if (loop_info->comparison_code == LT)
08751 return true;
08752 if (loop_info->comparison_code == LTU && unsignedp)
08753 return true;
08754 }
08755
08756
08757 if (incr == -1)
08758 {
08759 if (loop_info->comparison_code == GT)
08760 return true;
08761 if (loop_info->comparison_code == GTU && unsignedp)
08762 return true;
08763 }
08764 }
08765 return false;
08766 }
08767
08768
08769
08770
08771
08772
08773
08774 static bool
08775 biased_biv_may_wrap_p (const struct loop *loop, struct iv_class *bl,
08776 unsigned HOST_WIDE_INT bias)
08777 {
08778 HOST_WIDE_INT incr;
08779 bool check_signed, check_unsigned;
08780 enum machine_mode mode;
08781
08782
08783
08784 incr = get_monotonic_increment (bl);
08785 if (incr == 0)
08786 return true;
08787
08788
08789
08790
08791
08792
08793 check_signed = check_unsigned = true;
08794 if (bl->biv->src_reg == LOOP_INFO (loop)->iteration_var)
08795 {
08796 switch (LOOP_INFO (loop)->comparison_code)
08797 {
08798 case GTU: case GEU: case LTU: case LEU:
08799 check_signed = false;
08800 break;
08801 case GT: case GE: case LT: case LE:
08802 check_unsigned = false;
08803 break;
08804 default:
08805 break;
08806 }
08807 }
08808
08809 mode = GET_MODE (bl->biv->src_reg);
08810
08811 if (check_unsigned
08812 && !biased_biv_fits_mode_p (loop, bl, incr, mode, bias))
08813 return true;
08814
08815 if (check_signed)
08816 {
08817 bias += (GET_MODE_MASK (mode) >> 1) + 1;
08818 if (!biased_biv_fits_mode_p (loop, bl, incr, mode, bias))
08819 return true;
08820 }
08821
08822 return false;
08823 }
08824
08825
08826
08827
08828
08829
08830 static bool
08831 extension_within_bounds_p (const struct loop *loop, struct iv_class *bl,
08832 HOST_WIDE_INT incr, rtx x)
08833 {
08834 enum machine_mode mode;
08835 bool signedp, unsignedp;
08836
08837 switch (GET_CODE (x))
08838 {
08839 case SIGN_EXTEND:
08840 case ZERO_EXTEND:
08841 mode = GET_MODE (XEXP (x, 0));
08842 signedp = (GET_CODE (x) == SIGN_EXTEND);
08843 unsignedp = (GET_CODE (x) == ZERO_EXTEND);
08844 break;
08845
08846 case TRUNCATE:
08847
08848
08849 mode = GET_MODE (x);
08850 signedp = unsignedp = true;
08851 break;
08852
08853 default:
08854 abort ();
08855 }
08856
08857 return ((!signedp || biv_fits_mode_p (loop, bl, incr, mode, false))
08858 && (!unsignedp || biv_fits_mode_p (loop, bl, incr, mode, true)));
08859 }
08860
08861
08862
08863
08864
08865
08866 static void
08867 check_ext_dependent_givs (const struct loop *loop, struct iv_class *bl)
08868 {
08869 struct induction *v;
08870 HOST_WIDE_INT incr;
08871
08872 incr = get_monotonic_increment (bl);
08873
08874
08875 for (v = bl->giv; v; v = v->next_iv)
08876 if (v->ext_dependent)
08877 {
08878 if (incr != 0
08879 && extension_within_bounds_p (loop, bl, incr, v->ext_dependent))
08880 {
08881 if (loop_dump_stream)
08882 fprintf (loop_dump_stream,
08883 "Verified ext dependent giv at %d of reg %d\n",
08884 INSN_UID (v->insn), bl->regno);
08885 }
08886 else
08887 {
08888 if (loop_dump_stream)
08889 fprintf (loop_dump_stream,
08890 "Failed ext dependent giv at %d\n",
08891 INSN_UID (v->insn));
08892
08893 v->ignore = 1;
08894 bl->all_reduced = 0;
08895 }
08896 }
08897 }
08898
08899
08900
08901 static rtx
08902 extend_value_for_giv (struct induction *v, rtx value)
08903 {
08904 rtx ext_dep = v->ext_dependent;
08905
08906 if (! ext_dep)
08907 return value;
08908
08909
08910
08911
08912 if (CONSTANT_P (value) && GET_MODE (value) == VOIDmode)
08913 return value;
08914
08915
08916
08917 return gen_rtx_fmt_e (GET_CODE (ext_dep), GET_MODE (ext_dep), value);
08918 }
08919
08920 struct combine_givs_stats
08921 {
08922 int giv_number;
08923 int total_benefit;
08924 };
08925
08926 static int
08927 cmp_combine_givs_stats (const void *xp, const void *yp)
08928 {
08929 const struct combine_givs_stats * const x =
08930 (const struct combine_givs_stats *) xp;
08931 const struct combine_givs_stats * const y =
08932 (const struct combine_givs_stats *) yp;
08933 int d;
08934 d = y->total_benefit - x->total_benefit;
08935
08936 if (!d)
08937 d = x->giv_number - y->giv_number;
08938 return d;
08939 }
08940
08941
08942
08943
08944
08945
08946 static void
08947 combine_givs (struct loop_regs *regs, struct iv_class *bl)
08948 {
08949
08950 const int extra_benefit = 3;
08951
08952 struct induction *g1, *g2, **giv_array;
08953 int i, j, k, giv_count;
08954 struct combine_givs_stats *stats;
08955 rtx *can_combine;
08956
08957
08958 giv_count = 0;
08959 for (g1 = bl->giv; g1; g1 = g1->next_iv)
08960 if (!g1->ignore)
08961 giv_count++;
08962
08963 giv_array = alloca (giv_count * sizeof (struct induction *));
08964 i = 0;
08965 for (g1 = bl->giv; g1; g1 = g1->next_iv)
08966 if (!g1->ignore)
08967 giv_array[i++] = g1;
08968
08969 stats = xcalloc (giv_count, sizeof (*stats));
08970 can_combine = xcalloc (giv_count, giv_count * sizeof (rtx));
08971
08972 for (i = 0; i < giv_count; i++)
08973 {
08974 int this_benefit;
08975 rtx single_use;
08976
08977 g1 = giv_array[i];
08978 stats[i].giv_number = i;
08979
08980
08981
08982
08983
08984
08985
08986 if (g1->giv_type == DEST_REG
08987 && (single_use = regs->array[REGNO (g1->dest_reg)].single_usage)
08988 && single_use != const0_rtx)
08989 continue;
08990
08991 this_benefit = g1->benefit;
08992
08993 if (g1->no_const_addval)
08994 this_benefit += 1;
08995
08996 for (j = 0; j < giv_count; j++)
08997 {
08998 rtx this_combine;
08999
09000 g2 = giv_array[j];
09001 if (g1 != g2
09002 && (this_combine = combine_givs_p (g1, g2)) != NULL_RTX)
09003 {
09004 can_combine[i * giv_count + j] = this_combine;
09005 this_benefit += g2->benefit + extra_benefit;
09006 }
09007 }
09008 stats[i].total_benefit = this_benefit;
09009 }
09010
09011
09012 restart:
09013 qsort (stats, giv_count, sizeof (*stats), cmp_combine_givs_stats);
09014
09015 if (loop_dump_stream)
09016 {
09017 fprintf (loop_dump_stream, "Sorted combine statistics:\n");
09018 for (k = 0; k < giv_count; k++)
09019 {
09020 g1 = giv_array[stats[k].giv_number];
09021 if (!g1->combined_with && !g1->same)
09022 fprintf (loop_dump_stream, " {%d, %d}",
09023 INSN_UID (giv_array[stats[k].giv_number]->insn),
09024 stats[k].total_benefit);
09025 }
09026 putc ('\n', loop_dump_stream);
09027 }
09028
09029 for (k = 0; k < giv_count; k++)
09030 {
09031 int g1_add_benefit = 0;
09032
09033 i = stats[k].giv_number;
09034 g1 = giv_array[i];
09035
09036
09037 if (g1->combined_with || g1->same)
09038 continue;
09039
09040 for (j = 0; j < giv_count; j++)
09041 {
09042 g2 = giv_array[j];
09043 if (g1 != g2 && can_combine[i * giv_count + j]
09044
09045 && ! g2->same && ! g2->combined_with)
09046 {
09047 int l;
09048
09049 g2->new_reg = can_combine[i * giv_count + j];
09050 g2->same = g1;
09051
09052
09053
09054 if (g2->giv_type == DEST_ADDR)
09055 g2->benefit = (g2->benefit + reg_address_cost
09056 - address_cost (g2->new_reg,
09057 GET_MODE (g2->mem)));
09058 g1->combined_with++;
09059 g1->lifetime += g2->lifetime;
09060
09061 g1_add_benefit += g2->benefit;
09062
09063
09064
09065
09066 if (! g2->replaceable && REG_USERVAR_P (g2->dest_reg))
09067 g1_add_benefit -= copy_cost;
09068
09069
09070
09071 for (l = 0; l < giv_count; ++l)
09072 {
09073 int m = stats[l].giv_number;
09074 if (can_combine[m * giv_count + j])
09075 stats[l].total_benefit -= g2->benefit + extra_benefit;
09076 }
09077
09078 if (loop_dump_stream)
09079 fprintf (loop_dump_stream,
09080 "giv at %d combined with giv at %d; new benefit %d + %d, lifetime %d\n",
09081 INSN_UID (g2->insn), INSN_UID (g1->insn),
09082 g1->benefit, g1_add_benefit, g1->lifetime);
09083 }
09084 }
09085
09086
09087
09088 if (g1->combined_with)
09089 {
09090 for (j = 0; j < giv_count; ++j)
09091 {
09092 int m = stats[j].giv_number;
09093 if (can_combine[m * giv_count + i])
09094 stats[j].total_benefit -= g1->benefit + extra_benefit;
09095 }
09096
09097 g1->benefit += g1_add_benefit;
09098
09099
09100
09101
09102
09103
09104
09105 goto restart;
09106 }
09107 }
09108
09109
09110 free (stats);
09111 free (can_combine);
09112 }
09113
09114
09115
09116
09117
09118 static rtx
09119 gen_add_mult (rtx b, rtx m, rtx a, rtx reg)
09120 {
09121 rtx seq;
09122 rtx result;
09123
09124 start_sequence ();
09125
09126 result = expand_mult_add (b, reg, m, a, GET_MODE (reg), 1);
09127 if (reg != result)
09128 emit_move_insn (reg, result);
09129 seq = get_insns ();
09130 end_sequence ();
09131
09132 return seq;
09133 }
09134
09135
09136
09137
09138 static void
09139 loop_regs_update (const struct loop *loop ATTRIBUTE_UNUSED, rtx seq)
09140 {
09141 rtx insn;
09142
09143
09144
09145 insn = seq;
09146 while (insn != NULL_RTX)
09147 {
09148 rtx set = single_set (insn);
09149
09150 if (set && REG_P (SET_DEST (set)))
09151 record_base_value (REGNO (SET_DEST (set)), SET_SRC (set), 0);
09152
09153 insn = NEXT_INSN (insn);
09154 }
09155 }
09156
09157
09158
09159
09160
09161
09162
09163 static void
09164 loop_iv_add_mult_emit_before (const struct loop *loop, rtx b, rtx m, rtx a,
09165 rtx reg, basic_block before_bb, rtx before_insn)
09166 {
09167 rtx seq;
09168
09169 if (! before_insn)
09170 {
09171 loop_iv_add_mult_hoist (loop, b, m, a, reg);
09172 return;
09173 }
09174
09175
09176 seq = gen_add_mult (copy_rtx (b), copy_rtx (m), copy_rtx (a), reg);
09177
09178
09179 update_reg_last_use (a, before_insn);
09180 update_reg_last_use (b, before_insn);
09181 update_reg_last_use (m, before_insn);
09182
09183
09184
09185
09186 loop_regs_update (loop, seq);
09187
09188 loop_insn_emit_before (loop, before_bb, before_insn, seq);
09189 }
09190
09191
09192
09193
09194
09195
09196
09197 static void
09198 loop_iv_add_mult_sink (const struct loop *loop, rtx b, rtx m, rtx a, rtx reg)
09199 {
09200 rtx seq;
09201
09202
09203 seq = gen_add_mult (copy_rtx (b), copy_rtx (m), copy_rtx (a), reg);
09204
09205
09206
09207 update_reg_last_use (a, loop->sink);
09208 update_reg_last_use (b, loop->sink);
09209 update_reg_last_use (m, loop->sink);
09210
09211
09212
09213
09214 loop_regs_update (loop, seq);
09215
09216 loop_insn_sink (loop, seq);
09217 }
09218
09219
09220
09221
09222
09223
09224 static void
09225 loop_iv_add_mult_hoist (const struct loop *loop, rtx b, rtx m, rtx a, rtx reg)
09226 {
09227 rtx seq;
09228
09229
09230 seq = gen_add_mult (copy_rtx (b), copy_rtx (m), copy_rtx (a), reg);
09231
09232
09233
09234
09235 loop_regs_update (loop, seq);
09236
09237 loop_insn_hoist (loop, seq);
09238 }
09239
09240
09241
09242
09243
09244
09245 static int
09246 iv_add_mult_cost (rtx b, rtx m, rtx a, rtx reg)
09247 {
09248 int cost = 0;
09249 rtx last, result;
09250
09251 start_sequence ();
09252 result = expand_mult_add (b, reg, m, a, GET_MODE (reg), 1);
09253 if (reg != result)
09254 emit_move_insn (reg, result);
09255 last = get_last_insn ();
09256 while (last)
09257 {
09258 rtx t = single_set (last);
09259 if (t)
09260 cost += rtx_cost (SET_SRC (t), SET);
09261 last = PREV_INSN (last);
09262 }
09263 end_sequence ();
09264 return cost;
09265 }
09266
09267
09268
09269
09270
09271
09272
09273
09274
09275 static int
09276 product_cheap_p (rtx a, rtx b)
09277 {
09278 rtx tmp;
09279 int win, n_insns;
09280
09281
09282 if (GET_CODE (a) == CONST_INT)
09283 tmp = a, a = b, b = tmp;
09284
09285
09286 if (GET_CODE (a) == CONST_INT)
09287 return 1;
09288
09289
09290 if (GET_CODE (b) != CONST_INT)
09291 return 0;
09292
09293
09294
09295
09296
09297 start_sequence ();
09298 expand_mult (GET_MODE (a), a, b, NULL_RTX, 1);
09299 tmp = get_insns ();
09300 end_sequence ();
09301
09302 win = 1;
09303 if (tmp == NULL_RTX)
09304 ;
09305 else if (INSN_P (tmp))
09306 {
09307 n_insns = 0;
09308 while (tmp != NULL_RTX)
09309 {
09310 rtx next = NEXT_INSN (tmp);
09311
09312 if (++n_insns > 3
09313 || !NONJUMP_INSN_P (tmp)
09314 || (GET_CODE (PATTERN (tmp)) == SET
09315 && GET_CODE (SET_SRC (PATTERN (tmp))) == MULT)
09316 || (GET_CODE (PATTERN (tmp)) == PARALLEL
09317 && GET_CODE (XVECEXP (PATTERN (tmp), 0, 0)) == SET
09318 && GET_CODE (SET_SRC (XVECEXP (PATTERN (tmp), 0, 0))) == MULT))
09319 {
09320 win = 0;
09321 break;
09322 }
09323
09324 tmp = next;
09325 }
09326 }
09327 else if (GET_CODE (tmp) == SET
09328 && GET_CODE (SET_SRC (tmp)) == MULT)
09329 win = 0;
09330 else if (GET_CODE (tmp) == PARALLEL
09331 && GET_CODE (XVECEXP (tmp, 0, 0)) == SET
09332 && GET_CODE (SET_SRC (XVECEXP (tmp, 0, 0))) == MULT)
09333 win = 0;
09334
09335 return win;
09336 }
09337
09338
09339
09340
09341
09342
09343
09344
09345
09346
09347
09348
09349
09350
09351
09352
09353 static int
09354 check_dbra_loop (struct loop *loop, int insn_count)
09355 {
09356 struct loop_info *loop_info = LOOP_INFO (loop);
09357 struct loop_regs *regs = LOOP_REGS (loop);
09358 struct loop_ivs *ivs = LOOP_IVS (loop);
09359 struct iv_class *bl;
09360 rtx reg;
09361 enum machine_mode mode;
09362 rtx jump_label;
09363 rtx final_value;
09364 rtx start_value;
09365 rtx new_add_val;
09366 rtx comparison;
09367 rtx before_comparison;
09368 rtx p;
09369 rtx jump;
09370 rtx first_compare;
09371 int compare_and_branch;
09372 rtx loop_start = loop->start;
09373 rtx loop_end = loop->end;
09374
09375
09376
09377
09378 jump = PREV_INSN (loop_end);
09379 comparison = get_condition_for_loop (loop, jump);
09380 if (comparison == 0)
09381 return 0;
09382 if (!onlyjump_p (jump))
09383 return 0;
09384
09385
09386
09387 get_condition (jump, &first_compare, false, true);
09388 if (first_compare == jump)
09389 compare_and_branch = 1;
09390 else if (first_compare == prev_nonnote_insn (jump))
09391 compare_and_branch = 2;
09392 else
09393 return 0;
09394
09395 {
09396
09397
09398
09399
09400
09401
09402
09403 rtx jump1;
09404 if ((jump1 = prev_nonnote_insn (first_compare))
09405 && JUMP_P (jump1))
09406 return 0;
09407 }
09408
09409
09410
09411
09412
09413
09414 for (bl = ivs->list; bl; bl = bl->next)
09415 {
09416 if (bl->biv_count == 1
09417 && ! bl->biv->maybe_multiple
09418 && bl->biv->dest_reg == XEXP (comparison, 0)
09419 && ! reg_used_between_p (regno_reg_rtx[bl->regno], bl->biv->insn,
09420 first_compare))
09421 break;
09422 }
09423
09424
09425 if (!bl)
09426 for (bl = ivs->list; bl; bl = bl->next)
09427 if (bl->biv_count == 1
09428 && ! bl->biv->maybe_multiple
09429 && bl->biv->dest_reg == XEXP (comparison, 1)
09430 && ! reg_used_between_p (regno_reg_rtx[bl->regno], bl->biv->insn,
09431 first_compare))
09432 {
09433 comparison = gen_rtx_fmt_ee (swap_condition (GET_CODE (comparison)),
09434 VOIDmode,
09435 XEXP (comparison, 1),
09436 XEXP (comparison, 0));
09437 break;
09438 }
09439
09440 if (! bl)
09441 return 0;
09442
09443
09444
09445
09446
09447
09448 if (((GET_CODE (comparison) == GT && XEXP (comparison, 1) == constm1_rtx)
09449 || (GET_CODE (comparison) == NE && XEXP (comparison, 1) == const0_rtx))
09450 && GET_CODE (bl->biv->add_val) == CONST_INT
09451 && INTVAL (bl->biv->add_val) < 0)
09452 {
09453
09454
09455
09456
09457 if (GET_CODE (bl->initial_value) == CONST_INT
09458 && INTVAL (bl->initial_value) > 0
09459 && (INTVAL (bl->initial_value)
09460 % (-INTVAL (bl->biv->add_val))) == 0)
09461 {
09462
09463 if (! find_reg_note (jump, REG_NONNEG, NULL_RTX))
09464 REG_NOTES (jump)
09465 = gen_rtx_EXPR_LIST (REG_NONNEG, bl->biv->dest_reg,
09466 REG_NOTES (jump));
09467 bl->nonneg = 1;
09468
09469 return 1;
09470 }
09471
09472
09473
09474 for (p = loop_start; p; p = PREV_INSN (p))
09475 {
09476 if (LABEL_P (p))
09477 break;
09478 if (!JUMP_P (p))
09479 continue;
09480
09481 before_comparison = get_condition_for_loop (loop, p);
09482 if (before_comparison
09483 && XEXP (before_comparison, 0) == bl->biv->dest_reg
09484 && (GET_CODE (before_comparison) == LT
09485 || GET_CODE (before_comparison) == LTU)
09486 && XEXP (before_comparison, 1) == const0_rtx
09487 && ! reg_set_between_p (bl->biv->dest_reg, p, loop_start)
09488 && INTVAL (bl->biv->add_val) == -1)
09489 {
09490 if (! find_reg_note (jump, REG_NONNEG, NULL_RTX))
09491 REG_NOTES (jump)
09492 = gen_rtx_EXPR_LIST (REG_NONNEG, bl->biv->dest_reg,
09493 REG_NOTES (jump));
09494 bl->nonneg = 1;
09495
09496 return 1;
09497 }
09498 }
09499 }
09500 else if (GET_CODE (bl->biv->add_val) == CONST_INT
09501 && INTVAL (bl->biv->add_val) > 0)
09502 {
09503
09504
09505
09506
09507
09508
09509
09510
09511
09512
09513
09514 int num_nonfixed_reads = 0;
09515
09516 int no_use_except_counting = 0;
09517
09518
09519 int reversible_mem_store = 1;
09520
09521 if (bl->giv_count == 0
09522 && !loop->exit_count
09523 && !loop_info->has_multiple_exit_targets)
09524 {
09525 rtx bivreg = regno_reg_rtx[bl->regno];
09526 struct iv_class *blt;
09527
09528
09529
09530
09531 no_use_except_counting = 1;
09532 for (p = loop_start; p != loop_end; p = NEXT_INSN (p))
09533 if (INSN_P (p))
09534 {
09535 rtx set = single_set (p);
09536
09537 if (set && REG_P (SET_DEST (set))
09538 && REGNO (SET_DEST (set)) == bl->regno)
09539
09540 ;
09541 else if (!reg_mentioned_p (bivreg, PATTERN (p)))
09542
09543 ;
09544 else if (p == prev_nonnote_insn (prev_nonnote_insn (loop_end))
09545 || p == prev_nonnote_insn (loop_end))
09546 {
09547
09548
09549
09550
09551 note_stores (PATTERN (p), note_set_pseudo_multiple_uses,
09552 regs);
09553 if (regs->multiple_uses)
09554 {
09555 no_use_except_counting = 0;
09556 break;
09557 }
09558 }
09559 else
09560 {
09561 no_use_except_counting = 0;
09562 break;
09563 }
09564 }
09565
09566
09567
09568 for (blt = ivs->list; blt; blt = blt->next)
09569 if (blt->init_set
09570 && reg_mentioned_p (bivreg, SET_SRC (blt->init_set)))
09571 {
09572 no_use_except_counting = 0;
09573 break;
09574 }
09575 }
09576
09577 if (no_use_except_counting)
09578
09579 ;
09580 else if (loop_info->num_mem_sets <= 1)
09581 {
09582 for (p = loop_start; p != loop_end; p = NEXT_INSN (p))
09583 if (INSN_P (p))
09584 num_nonfixed_reads += count_nonfixed_reads (loop, PATTERN (p));
09585
09586
09587
09588
09589
09590
09591
09592 if (loop_info->num_mem_sets == 1)
09593 {
09594 struct induction *v;
09595
09596
09597
09598
09599
09600 reversible_mem_store = 0;
09601
09602
09603
09604
09605 for (v = bl->giv; reversible_mem_store && v; v = v->next_iv)
09606 {
09607 if (v->giv_type == DEST_REG
09608 && reg_mentioned_p (v->dest_reg,
09609 PATTERN (loop_info->first_loop_store_insn))
09610 && loop_insn_first_p (loop_info->first_loop_store_insn,
09611 v->insn))
09612 reversible_mem_store = 0;
09613 }
09614 }
09615 }
09616 else
09617 return 0;
09618
09619
09620
09621
09622
09623
09624
09625
09626
09627 if ((num_nonfixed_reads <= 1
09628 && ! loop_info->has_nonconst_call
09629 && ! loop_info->has_prefetch
09630 && ! loop_info->has_volatile
09631 && reversible_mem_store
09632 && (bl->giv_count + bl->biv_count + loop_info->num_mem_sets
09633 + num_unmoved_movables (loop) + compare_and_branch == insn_count)
09634 && (bl == ivs->list && bl->next == 0))
09635 || (no_use_except_counting && ! loop_info->has_prefetch))
09636 {
09637 rtx tem;
09638
09639
09640 if (loop_dump_stream)
09641 fprintf (loop_dump_stream, "Can reverse loop\n");
09642
09643
09644
09645
09646
09647
09648
09649
09650
09651
09652 if (comparison
09653
09654 && (GET_CODE (comparison) == LT
09655 || (GET_CODE (comparison) == LE
09656 && no_use_except_counting)
09657 || GET_CODE (comparison) == LTU))
09658 {
09659 HOST_WIDE_INT add_val, add_adjust, comparison_val = 0;
09660 rtx initial_value, comparison_value;
09661 int nonneg = 0;
09662 enum rtx_code cmp_code;
09663 int comparison_const_width;
09664 unsigned HOST_WIDE_INT comparison_sign_mask;
09665 bool keep_first_compare;
09666
09667 add_val = INTVAL (bl->biv->add_val);
09668 comparison_value = XEXP (comparison, 1);
09669 if (GET_MODE (comparison_value) == VOIDmode)
09670 comparison_const_width
09671 = GET_MODE_BITSIZE (GET_MODE (XEXP (comparison, 0)));
09672 else
09673 comparison_const_width
09674 = GET_MODE_BITSIZE (GET_MODE (comparison_value));
09675 if (comparison_const_width > HOST_BITS_PER_WIDE_INT)
09676 comparison_const_width = HOST_BITS_PER_WIDE_INT;
09677 comparison_sign_mask
09678 = (unsigned HOST_WIDE_INT) 1 << (comparison_const_width - 1);
09679
09680
09681
09682
09683
09684
09685
09686 if (! loop_invariant_p (loop, comparison_value))
09687 return 0;
09688
09689 if (GET_CODE (comparison_value) == CONST_INT)
09690 comparison_val = INTVAL (comparison_value);
09691 initial_value = bl->initial_value;
09692
09693
09694
09695
09696 if (no_use_except_counting
09697 && GET_CODE (comparison_value) == CONST_INT
09698 && GET_CODE (initial_value) == CONST_INT)
09699 {
09700 comparison_val = comparison_val - INTVAL (bl->initial_value);
09701
09702
09703
09704
09705
09706 comparison_val = comparison_val + add_val - 1;
09707 comparison_val
09708 -= (unsigned HOST_WIDE_INT) comparison_val % add_val;
09709
09710
09711
09712
09713 initial_value = const0_rtx;
09714 }
09715
09716
09717 if (initial_value == const0_rtx
09718 && GET_CODE (comparison_value) == CONST_INT
09719
09720 && ! (((comparison_val - add_val) ^ INTVAL (comparison_value))
09721 & comparison_sign_mask))
09722 {
09723
09724
09725 add_adjust = add_val;
09726 nonneg = 1;
09727 cmp_code = GE;
09728 }
09729 else
09730 return 0;
09731
09732 if (GET_CODE (comparison) == LE)
09733 add_adjust -= add_val;
09734
09735
09736
09737
09738 if (initial_value == const0_rtx
09739 && GET_CODE (comparison_value) == CONST_INT)
09740 {
09741 if (((unsigned HOST_WIDE_INT) comparison_val % add_val) != 0)
09742 return 0;
09743 }
09744 else
09745 {
09746 if (! no_use_except_counting || add_val != 1)
09747 return 0;
09748 }
09749
09750 final_value = comparison_value;
09751
09752
09753
09754 if (GET_CODE (comparison_value) == CONST_INT
09755 && GET_CODE (initial_value) == CONST_INT)
09756 {
09757 comparison_value = GEN_INT (comparison_val);
09758 final_value
09759 = GEN_INT (comparison_val + INTVAL (bl->initial_value));
09760 }
09761 bl->initial_value = initial_value;
09762
09763
09764 reg = bl->biv->dest_reg;
09765 mode = GET_MODE (reg);
09766 jump_label = condjump_label (PREV_INSN (loop_end));
09767 new_add_val = GEN_INT (-INTVAL (bl->biv->add_val));
09768
09769
09770
09771
09772
09773
09774 if (initial_value == const0_rtx
09775 && GET_CODE (comparison_value) == CONST_INT)
09776 {
09777 start_value
09778 = gen_int_mode (comparison_val - add_adjust, mode);
09779 loop_insn_hoist (loop, gen_move_insn (reg, start_value));
09780 }
09781 else if (GET_CODE (initial_value) == CONST_INT)
09782 {
09783 rtx offset = GEN_INT (-INTVAL (initial_value) - add_adjust);
09784 rtx add_insn = gen_add3_insn (reg, comparison_value, offset);
09785
09786 if (add_insn == 0)
09787 return 0;
09788
09789 start_value
09790 = gen_rtx_PLUS (mode, comparison_value, offset);
09791 loop_insn_hoist (loop, add_insn);
09792 if (GET_CODE (comparison) == LE)
09793 final_value = gen_rtx_PLUS (mode, comparison_value,
09794 GEN_INT (add_val));
09795 }
09796 else if (! add_adjust)
09797 {
09798 rtx sub_insn = gen_sub3_insn (reg, comparison_value,
09799 initial_value);
09800
09801 if (sub_insn == 0)
09802 return 0;
09803 start_value
09804 = gen_rtx_MINUS (mode, comparison_value, initial_value);
09805 loop_insn_hoist (loop, sub_insn);
09806 }
09807 else
09808
09809
09810 return 0;
09811
09812
09813
09814 start_sequence ();
09815 expand_inc (reg, new_add_val);
09816 tem = get_insns ();
09817 end_sequence ();
09818
09819 p = loop_insn_emit_before (loop, 0, bl->biv->insn, tem);
09820 delete_insn (bl->biv->insn);
09821
09822
09823 bl->biv->insn = p;
09824 bl->initial_value = start_value;
09825 bl->biv->add_val = new_add_val;
09826
09827
09828 loop_info->initial_value = reg;
09829 loop_info->initial_equiv_value = reg;
09830 loop_info->final_value = const0_rtx;
09831 loop_info->final_equiv_value = const0_rtx;
09832 loop_info->comparison_value = const0_rtx;
09833 loop_info->comparison_code = cmp_code;
09834 loop_info->increment = new_add_val;
09835
09836
09837
09838 LABEL_NUSES (XEXP (jump_label, 0))++;
09839
09840
09841
09842
09843 keep_first_compare = (compare_and_branch == 2
09844 #ifdef HAVE_CC0
09845 && sets_cc0_p (first_compare) <= 0
09846 #endif
09847 );
09848
09849
09850
09851 if (keep_first_compare
09852 || (REGNO_LAST_UID (bl->regno) != INSN_UID (first_compare))
09853 || ! bl->init_insn
09854 || REGNO_FIRST_UID (bl->regno) != INSN_UID (bl->init_insn))
09855 loop_insn_sink (loop, gen_load_of_final_value (reg, final_value));
09856
09857 if (keep_first_compare)
09858 loop_insn_sink (loop, PATTERN (first_compare));
09859
09860
09861 delete_related_insns (PREV_INSN (loop_end));
09862 if (compare_and_branch == 2)
09863 delete_related_insns (first_compare);
09864
09865
09866 start_sequence ();
09867 emit_cmp_and_jump_insns (reg, const0_rtx, cmp_code, NULL_RTX,
09868 mode, 0,
09869 XEXP (jump_label, 0));
09870 tem = get_insns ();
09871 end_sequence ();
09872 emit_jump_insn_before (tem, loop_end);
09873
09874 for (tem = PREV_INSN (loop_end);
09875 tem && !JUMP_P (tem);
09876 tem = PREV_INSN (tem))
09877 ;
09878
09879 if (tem)
09880 JUMP_LABEL (tem) = XEXP (jump_label, 0);
09881
09882 if (nonneg)
09883 {
09884 if (tem)
09885 {
09886
09887
09888
09889 REG_NOTES (tem) = gen_rtx_EXPR_LIST (REG_NONNEG, reg,
09890 REG_NOTES (tem));
09891 }
09892 bl->nonneg = 1;
09893 }
09894
09895
09896
09897
09898
09899
09900
09901
09902
09903
09904
09905
09906 for (p = loop_start; p != loop_end; p = NEXT_INSN (p))
09907 if (INSN_P (p))
09908 {
09909 rtx *pnote;
09910 rtx set = single_set (p);
09911
09912
09913 if (! set
09914 || !REG_P (SET_DEST (set))
09915 || (size_t) REGNO (SET_DEST (set)) >= ivs->n_regs
09916 || REG_IV_TYPE (ivs, REGNO (SET_DEST (set))) != GENERAL_INDUCT
09917 || REG_IV_INFO (ivs, REGNO (SET_DEST (set)))->src_reg != bl->biv->src_reg)
09918 for (pnote = ®_NOTES (p); *pnote;)
09919 {
09920 if (REG_NOTE_KIND (*pnote) == REG_EQUAL
09921 && reg_mentioned_p (regno_reg_rtx[bl->regno],
09922 XEXP (*pnote, 0)))
09923 *pnote = XEXP (*pnote, 1);
09924 else
09925 pnote = &XEXP (*pnote, 1);
09926 }
09927 }
09928
09929
09930
09931
09932
09933 bl->reversed = 1;
09934
09935 if (loop_dump_stream)
09936 {
09937 fprintf (loop_dump_stream, "Reversed loop");
09938 if (bl->nonneg)
09939 fprintf (loop_dump_stream, " and added reg_nonneg\n");
09940 else
09941 fprintf (loop_dump_stream, "\n");
09942 }
09943
09944 return 1;
09945 }
09946 }
09947 }
09948
09949 return 0;
09950 }
09951
09952
09953
09954
09955
09956
09957
09958
09959
09960
09961 static int
09962 maybe_eliminate_biv (const struct loop *loop, struct iv_class *bl,
09963 int eliminate_p, int threshold, int insn_count)
09964 {
09965 struct loop_ivs *ivs = LOOP_IVS (loop);
09966 rtx reg = bl->biv->dest_reg;
09967 rtx p;
09968
09969
09970
09971
09972 for (p = loop->start; p != loop->end; p = NEXT_INSN (p))
09973 {
09974 enum rtx_code code = GET_CODE (p);
09975 basic_block where_bb = 0;
09976 rtx where_insn = threshold >= insn_count ? 0 : p;
09977 rtx note;
09978
09979
09980 if (INSN_P (p))
09981 {
09982 note = find_reg_note (p, REG_LIBCALL, NULL_RTX);
09983
09984 if (note)
09985 {
09986 rtx last = XEXP (note, 0);
09987 rtx set = single_set (last);
09988
09989 if (set && REG_P (SET_DEST (set)))
09990 {
09991 unsigned int regno = REGNO (SET_DEST (set));
09992
09993 if (regno < ivs->n_regs
09994 && REG_IV_TYPE (ivs, regno) == GENERAL_INDUCT
09995 && REG_IV_INFO (ivs, regno)->src_reg == bl->biv->src_reg)
09996 p = last;
09997 }
09998 }
09999 }
10000
10001
10002 if ((code == INSN || code == JUMP_INSN || code == CALL_INSN)
10003 && reg_mentioned_p (reg, PATTERN (p))
10004 && ! maybe_eliminate_biv_1 (loop, PATTERN (p), p, bl,
10005 eliminate_p, where_bb, where_insn))
10006 {
10007 if (loop_dump_stream)
10008 fprintf (loop_dump_stream,
10009 "Cannot eliminate biv %d: biv used in insn %d.\n",
10010 bl->regno, INSN_UID (p));
10011 break;
10012 }
10013
10014
10015 if (eliminate_p
10016 && (note = find_reg_note (p, REG_EQUAL, NULL_RTX)) != NULL_RTX
10017 && reg_mentioned_p (reg, XEXP (note, 0)))
10018 remove_note (p, note);
10019 }
10020
10021 if (p == loop->end)
10022 {
10023 if (loop_dump_stream)
10024 fprintf (loop_dump_stream, "biv %d %s eliminated.\n",
10025 bl->regno, eliminate_p ? "was" : "can be");
10026 return 1;
10027 }
10028
10029 return 0;
10030 }
10031
10032
10033
10034
10035 static int
10036 loop_insn_first_p (rtx insn, rtx reference)
10037 {
10038 rtx p, q;
10039
10040 for (p = insn, q = reference;;)
10041 {
10042
10043
10044 if (q == insn || ! p)
10045 return 0;
10046 if (p == reference || ! q)
10047 return 1;
10048
10049
10050
10051
10052 if (INSN_UID (p) < max_uid_for_loop
10053 && INSN_UID (q) < max_uid_for_loop
10054 && !NOTE_P (p))
10055 return INSN_LUID (p) <= INSN_LUID (q);
10056
10057 if (INSN_UID (p) >= max_uid_for_loop
10058 || NOTE_P (p))
10059 p = NEXT_INSN (p);
10060 if (INSN_UID (q) >= max_uid_for_loop)
10061 q = NEXT_INSN (q);
10062 }
10063 }
10064
10065
10066
10067
10068 static int
10069 biv_elimination_giv_has_0_offset (struct induction *biv,
10070 struct induction *giv, rtx insn)
10071 {
10072
10073
10074
10075
10076 if (giv->auto_inc_opt
10077 && ((loop_insn_first_p (giv->insn, insn)
10078 && loop_insn_first_p (insn, biv->insn))
10079 || (loop_insn_first_p (biv->insn, insn)
10080 && loop_insn_first_p (insn, giv->insn))))
10081 return 0;
10082
10083 return 1;
10084 }
10085
10086
10087
10088
10089
10090
10091
10092
10093
10094
10095
10096
10097 static int
10098 maybe_eliminate_biv_1 (const struct loop *loop, rtx x, rtx insn,
10099 struct iv_class *bl, int eliminate_p,
10100 basic_block where_bb, rtx where_insn)
10101 {
10102 enum rtx_code code = GET_CODE (x);
10103 rtx reg = bl->biv->dest_reg;
10104 enum machine_mode mode = GET_MODE (reg);
10105 struct induction *v;
10106 rtx arg, tem;
10107 #ifdef HAVE_cc0
10108 rtx new;
10109 #endif
10110 int arg_operand;
10111 const char *fmt;
10112 int i, j;
10113
10114 switch (code)
10115 {
10116 case REG:
10117
10118
10119 if (x == reg)
10120 return 0;
10121 return 1;
10122
10123 case SET:
10124
10125 if (SET_DEST (x) == reg)
10126 return 1;
10127
10128
10129
10130 for (v = bl->giv; v; v = v->next_iv)
10131 if (v->giv_type == DEST_REG && SET_DEST (x) == v->dest_reg)
10132 return 1;
10133
10134 #ifdef HAVE_cc0
10135 if (SET_DEST (x) == cc0_rtx && SET_SRC (x) == reg)
10136 {
10137
10138
10139
10140
10141
10142
10143 for (v = bl->giv; v; v = v->next_iv)
10144 if (GET_CODE (v->mult_val) == CONST_INT && v->mult_val != const0_rtx
10145 && v->add_val == const0_rtx
10146 && ! v->ignore && ! v->maybe_dead && v->always_computable
10147 && v->mode == mode
10148 && 0)
10149 {
10150 if (! biv_elimination_giv_has_0_offset (bl->biv, v, insn))
10151 continue;
10152
10153 if (! eliminate_p)
10154 return 1;
10155
10156
10157
10158 if (INTVAL (v->mult_val) < 0)
10159 new = gen_rtx_COMPARE (GET_MODE (v->new_reg),
10160 const0_rtx, v->new_reg);
10161 else
10162 new = v->new_reg;
10163
10164
10165 if (validate_change (insn, &SET_SRC (x), new, 0))
10166 return 1;
10167 }
10168
10169
10170
10171
10172
10173
10174
10175 for (v = bl->giv; v; v = v->next_iv)
10176 if (GET_CODE (v->mult_val) == CONST_INT
10177 && v->mult_val != const0_rtx
10178 && ! v->ignore && ! v->maybe_dead && v->always_computable
10179 && v->mode == mode
10180 && (GET_CODE (v->add_val) == SYMBOL_REF
10181 || GET_CODE (v->add_val) == LABEL_REF
10182 || GET_CODE (v->add_val) == CONST
10183 || (REG_P (v->add_val)
10184 && REG_POINTER (v->add_val))))
10185 {
10186 if (! biv_elimination_giv_has_0_offset (bl->biv, v, insn))
10187 continue;
10188
10189 if (! eliminate_p)
10190 return 1;
10191
10192
10193
10194 if (INTVAL (v->mult_val) < 0)
10195 new = gen_rtx_COMPARE (VOIDmode, copy_rtx (v->add_val),
10196 v->new_reg);
10197 else
10198 new = gen_rtx_COMPARE (VOIDmode, v->new_reg,
10199 copy_rtx (v->add_val));
10200
10201
10202 update_reg_last_use (v->add_val, insn);
10203 if (validate_change (insn, &SET_SRC (PATTERN (insn)), new, 0))
10204 return 1;
10205
10206
10207
10208 tem = gen_reg_rtx (GET_MODE (v->new_reg));
10209
10210 loop_insn_emit_before (loop, 0, where_insn,
10211 gen_move_insn (tem,
10212 copy_rtx (v->add_val)));
10213
10214
10215
10216 XEXP (new, (INTVAL (v->mult_val) < 0) ? 0 : 1) = tem;
10217 if (validate_change (insn, &SET_SRC (PATTERN (insn)), new, 0))
10218 return 1;
10219 }
10220 }
10221 #endif
10222 break;
10223
10224 case COMPARE:
10225 case EQ: case NE:
10226 case GT: case GE: case GTU: case GEU:
10227 case LT: case LE: case LTU: case LEU:
10228
10229 if (XEXP (x, 0) == reg)
10230 arg = XEXP (x, 1), arg_operand = 1;
10231 else if (XEXP (x, 1) == reg)
10232 arg = XEXP (x, 0), arg_operand = 0;
10233 else
10234 break;
10235
10236 if (GET_CODE (arg) != CONST_INT)
10237 return 0;
10238
10239
10240
10241
10242
10243
10244
10245
10246
10247
10248
10249
10250
10251 if (code != EQ && code != NE
10252 && biased_biv_may_wrap_p (loop, bl, INTVAL (arg)))
10253 return 0;
10254
10255
10256
10257 for (v = bl->giv; v; v = v->next_iv)
10258 if (GET_CODE (v->mult_val) == CONST_INT
10259 && INTVAL (v->mult_val) > 0
10260 && (GET_CODE (v->add_val) == SYMBOL_REF
10261 || GET_CODE (v->add_val) == LABEL_REF
10262 || GET_CODE (v->add_val) == CONST
10263 || (REG_P (v->add_val) && REG_POINTER (v->add_val)))
10264 && ! v->ignore && ! v->maybe_dead && v->always_computable
10265 && v->mode == mode)
10266 {
10267 if (! biv_elimination_giv_has_0_offset (bl->biv, v, insn))
10268 continue;
10269
10270 if (! eliminate_p)
10271 return 1;
10272
10273
10274 validate_change (insn, &XEXP (x, 1 - arg_operand), v->new_reg, 1);
10275
10276
10277 tem = gen_reg_rtx (mode);
10278 loop_iv_add_mult_emit_before (loop, arg, v->mult_val, v->add_val,
10279 tem, where_bb, where_insn);
10280
10281 validate_change (insn, &XEXP (x, arg_operand), tem, 1);
10282
10283 if (apply_change_group ())
10284 return 1;
10285 }
10286
10287
10288 return 0;
10289
10290 case MEM:
10291
10292
10293 for (v = bl->giv; v; v = v->next_iv)
10294 if (v->giv_type == DEST_ADDR && v->location == &XEXP (x, 0))
10295 return 1;
10296 break;
10297
10298 default:
10299 break;
10300 }
10301
10302
10303 fmt = GET_RTX_FORMAT (code);
10304 for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
10305 {
10306 switch (fmt[i])
10307 {
10308 case 'e':
10309 if (! maybe_eliminate_biv_1 (loop, XEXP (x, i), insn, bl,
10310 eliminate_p, where_bb, where_insn))
10311 return 0;
10312 break;
10313
10314 case 'E':
10315 for (j = XVECLEN (x, i) - 1; j >= 0; j--)
10316 if (! maybe_eliminate_biv_1 (loop, XVECEXP (x, i, j), insn, bl,
10317 eliminate_p, where_bb, where_insn))
10318 return 0;
10319 break;
10320 }
10321 }
10322
10323 return 1;
10324 }
10325
10326
10327
10328
10329 static int
10330 last_use_this_basic_block (rtx reg, rtx insn)
10331 {
10332 rtx n;
10333 for (n = insn;
10334 n && !LABEL_P (n) && !JUMP_P (n);
10335 n = NEXT_INSN (n))
10336 {
10337 if (REGNO_LAST_UID (REGNO (reg)) == INSN_UID (n))
10338 return 1;
10339 }
10340 return 0;
10341 }
10342
10343
10344
10345
10346 static void
10347 record_initial (rtx dest, rtx set, void *data ATTRIBUTE_UNUSED)
10348 {
10349 struct loop_ivs *ivs = (struct loop_ivs *) data;
10350 struct iv_class *bl;
10351
10352 if (!REG_P (dest)
10353 || REGNO (dest) >= ivs->n_regs
10354 || REG_IV_TYPE (ivs, REGNO (dest)) != BASIC_INDUCT)
10355 return;
10356
10357 bl = REG_IV_CLASS (ivs, REGNO (dest));
10358
10359
10360 if (bl->init_insn == 0)
10361 {
10362 bl->init_insn = note_insn;
10363 bl->init_set = set;
10364 }
10365 }
10366
10367
10368
10369
10370
10371
10372 static void
10373 update_reg_last_use (rtx x, rtx insn)
10374 {
10375
10376
10377
10378
10379
10380
10381 if (REG_P (x) && REGNO (x) < max_reg_before_loop
10382 && INSN_UID (insn) < max_uid_for_loop
10383 && REGNO_LAST_LUID (REGNO (x)) < INSN_LUID (insn))
10384 {
10385 REGNO_LAST_UID (REGNO (x)) = INSN_UID (insn);
10386 }
10387 else
10388 {
10389 int i, j;
10390 const char *fmt = GET_RTX_FORMAT (GET_CODE (x));
10391 for (i = GET_RTX_LENGTH (GET_CODE (x)) - 1; i >= 0; i--)
10392 {
10393 if (fmt[i] == 'e')
10394 update_reg_last_use (XEXP (x, i), insn);
10395 else if (fmt[i] == 'E')
10396 for (j = XVECLEN (x, i) - 1; j >= 0; j--)
10397 update_reg_last_use (XVECEXP (x, i, j), insn);
10398 }
10399 }
10400 }
10401
10402
10403
10404
10405 static rtx
10406 get_condition_for_loop (const struct loop *loop, rtx x)
10407 {
10408 rtx comparison = get_condition (x, (rtx*) 0, false, true);
10409
10410 if (comparison == 0
10411 || ! loop_invariant_p (loop, XEXP (comparison, 0))
10412 || loop_invariant_p (loop, XEXP (comparison, 1)))
10413 return comparison;
10414
10415 return gen_rtx_fmt_ee (swap_condition (GET_CODE (comparison)), VOIDmode,
10416 XEXP (comparison, 1), XEXP (comparison, 0));
10417 }
10418
10419
10420
10421
10422
10423 static int
10424 indirect_jump_in_function_p (rtx start)
10425 {
10426 rtx insn;
10427
10428 for (insn = start; insn; insn = NEXT_INSN (insn))
10429 if (computed_jump_p (insn))
10430 return 1;
10431
10432 return 0;
10433 }
10434
10435
10436
10437
10438
10439 static int
10440 insert_loop_mem (rtx *mem, void *data ATTRIBUTE_UNUSED)
10441 {
10442 struct loop_info *loop_info = data;
10443 int i;
10444 rtx m = *mem;
10445
10446 if (m == NULL_RTX)
10447 return 0;
10448
10449 switch (GET_CODE (m))
10450 {
10451 case MEM:
10452 break;
10453
10454 case CLOBBER:
10455
10456 return -1;
10457
10458 case CONST_DOUBLE:
10459
10460
10461 return -1;
10462
10463 case EXPR_LIST:
10464
10465 return -1;
10466
10467 default:
10468
10469 return 0;
10470 }
10471
10472
10473 for (i = 0; i < loop_info->mems_idx; ++i)
10474 if (rtx_equal_p (m, loop_info->mems[i].mem))
10475 {
10476 if (MEM_VOLATILE_P (m) && !MEM_VOLATILE_P (loop_info->mems[i].mem))
10477 loop_info->mems[i].mem = m;
10478 if (GET_MODE (m) != GET_MODE (loop_info->mems[i].mem))
10479
10480
10481
10482 loop_info->mems[i].optimize = 0;
10483
10484 return 0;
10485 }
10486
10487
10488 if (loop_info->mems_idx == loop_info->mems_allocated)
10489 {
10490 if (loop_info->mems_allocated != 0)
10491 loop_info->mems_allocated *= 2;
10492 else
10493 loop_info->mems_allocated = 32;
10494
10495 loop_info->mems = xrealloc (loop_info->mems,
10496 loop_info->mems_allocated * sizeof (loop_mem_info));
10497 }
10498
10499
10500 loop_info->mems[loop_info->mems_idx].mem = m;
10501
10502
10503
10504
10505 loop_info->mems[loop_info->mems_idx].optimize = (GET_MODE (m) != BLKmode);
10506 loop_info->mems[loop_info->mems_idx].reg = NULL_RTX;
10507 ++loop_info->mems_idx;
10508
10509 return 0;
10510 }
10511
10512
10513
10514
10515
10516
10517
10518
10519
10520
10521
10522
10523
10524
10525
10526
10527
10528 static void
10529 loop_regs_scan (const struct loop *loop, int extra_size)
10530 {
10531 struct loop_regs *regs = LOOP_REGS (loop);
10532 int old_nregs;
10533
10534
10535 rtx *last_set;
10536 rtx insn;
10537 int i;
10538
10539 old_nregs = regs->num;
10540 regs->num = max_reg_num ();
10541
10542
10543 if (regs->num >= regs->size)
10544 {
10545 regs->size = regs->num + extra_size;
10546
10547 regs->array = xrealloc (regs->array, regs->size * sizeof (*regs->array));
10548
10549
10550 memset (regs->array + old_nregs, 0,
10551 (regs->size - old_nregs) * sizeof (*regs->array));
10552 }
10553
10554
10555 for (i = 0; i < old_nregs; i++)
10556 {
10557 regs->array[i].set_in_loop = 0;
10558 regs->array[i].may_not_optimize = 0;
10559 regs->array[i].single_usage = NULL_RTX;
10560 }
10561
10562 last_set = xcalloc (regs->num, sizeof (rtx));
10563
10564
10565 for (insn = loop->top ? loop->top : loop->start; insn != loop->end;
10566 insn = NEXT_INSN (insn))
10567 {
10568 if (INSN_P (insn))
10569 {
10570
10571 find_single_use_in_loop (regs, insn, PATTERN (insn));
10572
10573
10574 if (REG_NOTES (insn))
10575 find_single_use_in_loop (regs, insn, REG_NOTES (insn));
10576
10577 if (GET_CODE (PATTERN (insn)) == SET
10578 || GET_CODE (PATTERN (insn)) == CLOBBER)
10579 count_one_set (regs, insn, PATTERN (insn), last_set);
10580 else if (GET_CODE (PATTERN (insn)) == PARALLEL)
10581 {
10582 int i;
10583 for (i = XVECLEN (PATTERN (insn), 0) - 1; i >= 0; i--)
10584 count_one_set (regs, insn, XVECEXP (PATTERN (insn), 0, i),
10585 last_set);
10586 }
10587 }
10588
10589 if (LABEL_P (insn) || JUMP_P (insn))
10590 memset (last_set, 0, regs->num * sizeof (rtx));
10591
10592
10593
10594
10595 if (CALL_P (insn))
10596 {
10597 rtx link;
10598 for (link = CALL_INSN_FUNCTION_USAGE (insn);
10599 link;
10600 link = XEXP (link, 1))
10601 {
10602 rtx op, reg;
10603
10604 if (GET_CODE (op = XEXP (link, 0)) == USE
10605 && REG_P (reg = XEXP (op, 0))
10606 && rtx_varies_p (reg, 1))
10607 regs->array[REGNO (reg)].may_not_optimize = 1;
10608 }
10609 }
10610 }
10611
10612
10613
10614
10615
10616 if (LOOP_INFO (loop)->has_call)
10617 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
10618 if (TEST_HARD_REG_BIT (regs_invalidated_by_call, i)
10619 && rtx_varies_p (regno_reg_rtx[i], 1))
10620 {
10621 regs->array[i].may_not_optimize = 1;
10622 regs->array[i].set_in_loop = 1;
10623 }
10624
10625 #ifdef AVOID_CCMODE_COPIES
10626
10627
10628 for (i = regs->num - 1; i >= FIRST_PSEUDO_REGISTER; i--)
10629 if (GET_MODE_CLASS (GET_MODE (regno_reg_rtx[i])) == MODE_CC)
10630 regs->array[i].may_not_optimize = 1;
10631 #endif
10632
10633
10634 for (i = old_nregs; i < regs->num; i++)
10635 regs->array[i].n_times_set = regs->array[i].set_in_loop;
10636
10637 free (last_set);
10638 }
10639
10640
10641
10642 static int
10643 count_insns_in_loop (const struct loop *loop)
10644 {
10645 int count = 0;
10646 rtx insn;
10647
10648 for (insn = loop->top ? loop->top : loop->start; insn != loop->end;
10649 insn = NEXT_INSN (insn))
10650 if (INSN_P (insn))
10651 ++count;
10652
10653 return count;
10654 }
10655
10656
10657
10658 static void
10659 load_mems (const struct loop *loop)
10660 {
10661 struct loop_info *loop_info = LOOP_INFO (loop);
10662 struct loop_regs *regs = LOOP_REGS (loop);
10663 int maybe_never = 0;
10664 int i;
10665 rtx p, prev_ebb_head;
10666 rtx label = NULL_RTX;
10667 rtx end_label;
10668
10669 int next_maybe_never = 0;
10670 unsigned int last_max_reg = max_reg_num ();
10671
10672 if (loop_info->mems_idx == 0)
10673 return;
10674
10675
10676 end_label = next_nonnote_insn (loop->end);
10677 if (end_label && !LABEL_P (end_label))
10678 end_label = NULL_RTX;
10679
10680
10681
10682
10683 for (p = next_insn_in_loop (loop, loop->scan_start);
10684 p != NULL_RTX;
10685 p = next_insn_in_loop (loop, p))
10686 {
10687 if (LABEL_P (p))
10688 maybe_never = 1;
10689 else if (JUMP_P (p)
10690
10691
10692
10693
10694
10695
10696 && ! (JUMP_P (p)
10697 && JUMP_LABEL (p) == loop->top
10698 && NEXT_INSN (NEXT_INSN (p)) == loop->end
10699 && any_uncondjump_p (p)))
10700 {
10701
10702
10703
10704 if (
10705
10706 !JUMP_LABEL (p)
10707 || (JUMP_LABEL (p) != end_label
10708 && (INSN_UID (JUMP_LABEL (p)) >= max_uid_for_loop
10709 || INSN_LUID (JUMP_LABEL (p)) < INSN_LUID (loop->start)
10710 || INSN_LUID (JUMP_LABEL (p)) > INSN_LUID (loop->end))))
10711 return;
10712
10713 if (!any_condjump_p (p))
10714
10715 maybe_never = 1;
10716 else
10717
10718
10719 next_maybe_never = 1;
10720 }
10721 else if (next_maybe_never)
10722 maybe_never = 1;
10723 }
10724
10725
10726 for (p = loop->start;
10727 PREV_INSN (p) && !LABEL_P (p);
10728 p = PREV_INSN (p))
10729 ;
10730 prev_ebb_head = p;
10731
10732 cselib_init (true);
10733
10734
10735
10736 for (; p != loop->start; p = NEXT_INSN (p))
10737 cselib_process_insn (p);
10738
10739
10740 for (i = 0; i < loop_info->mems_idx; ++i)
10741 {
10742 regset_head load_copies;
10743 regset_head store_copies;
10744 int written = 0;
10745 rtx reg;
10746 rtx mem = loop_info->mems[i].mem;
10747 rtx mem_list_entry;
10748
10749 if (MEM_VOLATILE_P (mem)
10750 || loop_invariant_p (loop, XEXP (mem, 0)) != 1)
10751
10752 loop_info->mems[i].optimize = 0;
10753
10754
10755
10756 mem_list_entry = loop_info->store_mems;
10757 while (mem_list_entry)
10758 {
10759 if (rtx_equal_p (mem, XEXP (mem_list_entry, 0)))
10760 written = 1;
10761 else if (true_dependence (XEXP (mem_list_entry, 0), VOIDmode,
10762 mem, rtx_varies_p))
10763 {
10764
10765 loop_info->mems[i].optimize = 0;
10766 break;
10767 }
10768 mem_list_entry = XEXP (mem_list_entry, 1);
10769 }
10770
10771 if (flag_float_store && written
10772 && GET_MODE_CLASS (GET_MODE (mem)) == MODE_FLOAT)
10773 loop_info->mems[i].optimize = 0;
10774
10775
10776
10777 if (loop_info->mems[i].optimize && written)
10778 {
10779 int j;
10780
10781 for (j = 0; j < loop_info->mems_idx; ++j)
10782 {
10783 if (j == i)
10784 continue;
10785 else if (true_dependence (mem,
10786 VOIDmode,
10787 loop_info->mems[j].mem,
10788 rtx_varies_p))
10789 {
10790
10791
10792
10793 loop_info->mems[i].optimize = 0;
10794 break;
10795 }
10796 }
10797 }
10798
10799 if (maybe_never && may_trap_p (mem))
10800
10801
10802 loop_info->mems[i].optimize = 0;
10803
10804 if (!loop_info->mems[i].optimize)
10805
10806
10807 continue;
10808
10809 INIT_REG_SET (&load_copies);
10810 INIT_REG_SET (&store_copies);
10811
10812
10813
10814
10815
10816 reg = gen_reg_rtx (GET_MODE (mem));
10817 REG_USERVAR_P (reg) = 1;
10818 loop_info->mems[i].reg = reg;
10819
10820
10821
10822 maybe_never = 0;
10823 for (p = next_insn_in_loop (loop, loop->scan_start);
10824 p != NULL_RTX;
10825 p = next_insn_in_loop (loop, p))
10826 {
10827 if (INSN_P (p))
10828 {
10829 rtx set;
10830
10831 set = single_set (p);
10832
10833
10834
10835
10836 if (set
10837
10838 && ! maybe_never
10839 && REG_P (SET_DEST (set))
10840 && REGNO (SET_DEST (set)) >= FIRST_PSEUDO_REGISTER
10841 && REGNO (SET_DEST (set)) < last_max_reg
10842 && regs->array[REGNO (SET_DEST (set))].n_times_set == 1
10843 && rtx_equal_p (SET_SRC (set), mem))
10844 SET_REGNO_REG_SET (&load_copies, REGNO (SET_DEST (set)));
10845
10846
10847
10848
10849
10850
10851 if (set
10852 && ! maybe_never
10853 && REG_P (SET_SRC (set))
10854 && REGNO (SET_SRC (set)) >= FIRST_PSEUDO_REGISTER
10855 && REGNO (SET_SRC (set)) < last_max_reg
10856 && regs->array[REGNO (SET_SRC (set))].n_times_set == 1
10857 && rtx_equal_p (SET_DEST (set), mem))
10858 SET_REGNO_REG_SET (&store_copies, REGNO (SET_SRC (set)));
10859
10860
10861
10862 if (CALL_P (p)
10863 && reg_mentioned_p (loop_info->mems[i].mem,
10864 CALL_INSN_FUNCTION_USAGE (p)))
10865 {
10866 cancel_changes (0);
10867 loop_info->mems[i].optimize = 0;
10868 break;
10869 }
10870 else
10871
10872 replace_loop_mems (p, loop_info->mems[i].mem,
10873 loop_info->mems[i].reg, written);
10874 }
10875
10876 if (LABEL_P (p)
10877 || JUMP_P (p))
10878 maybe_never = 1;
10879 }
10880
10881 if (! loop_info->mems[i].optimize)
10882 ;
10883 else if (! apply_change_group ())
10884
10885 loop_info->mems[i].optimize = 0;
10886 else
10887 {
10888
10889
10890 cselib_val *e = cselib_lookup (mem, VOIDmode, 0);
10891 rtx set;
10892 rtx best = mem;
10893 unsigned j;
10894 struct elt_loc_list *const_equiv = 0;
10895 reg_set_iterator rsi;
10896
10897 if (e)
10898 {
10899 struct elt_loc_list *equiv;
10900 struct elt_loc_list *best_equiv = 0;
10901 for (equiv = e->locs; equiv; equiv = equiv->next)
10902 {
10903 if (CONSTANT_P (equiv->loc))
10904 const_equiv = equiv;
10905 else if (REG_P (equiv->loc)
10906
10907
10908
10909
10910
10911 && REGNO (equiv->loc) >= FIRST_PSEUDO_REGISTER)
10912 best_equiv = equiv;
10913 }
10914
10915 if (! best_equiv)
10916 best_equiv = const_equiv;
10917 else if (const_equiv
10918 && (rtx_cost (const_equiv->loc, SET)
10919 <= rtx_cost (best_equiv->loc, SET)))
10920 {
10921 best_equiv = const_equiv;
10922 const_equiv = 0;
10923 }
10924
10925
10926
10927
10928
10929 if (best_equiv)
10930 best = copy_rtx (best_equiv->loc);
10931 }
10932
10933 set = gen_move_insn (reg, best);
10934 set = loop_insn_hoist (loop, set);
10935 if (REG_P (best))
10936 {
10937 for (p = prev_ebb_head; p != loop->start; p = NEXT_INSN (p))
10938 if (REGNO_LAST_UID (REGNO (best)) == INSN_UID (p))
10939 {
10940 REGNO_LAST_UID (REGNO (best)) = INSN_UID (set);
10941 break;
10942 }
10943 }
10944
10945 if (const_equiv)
10946 set_unique_reg_note (set, REG_EQUAL, copy_rtx (const_equiv->loc));
10947
10948 if (written)
10949 {
10950 if (label == NULL_RTX)
10951 {
10952 label = gen_label_rtx ();
10953 emit_label_after (label, loop->end);
10954 }
10955
10956
10957
10958 set = gen_move_insn (copy_rtx (mem), reg);
10959 loop_insn_emit_after (loop, 0, label, set);
10960 }
10961
10962 if (loop_dump_stream)
10963 {
10964 fprintf (loop_dump_stream, "Hoisted regno %d %s from ",
10965 REGNO (reg), (written ? "r/w" : "r/o"));
10966 print_rtl (loop_dump_stream, mem);
10967 fputc ('\n', loop_dump_stream);
10968 }
10969
10970
10971
10972
10973 EXECUTE_IF_SET_IN_REG_SET
10974 (&load_copies, FIRST_PSEUDO_REGISTER, j, rsi)
10975 {
10976 try_copy_prop (loop, reg, j);
10977 }
10978 CLEAR_REG_SET (&load_copies);
10979
10980 EXECUTE_IF_SET_IN_REG_SET
10981 (&store_copies, FIRST_PSEUDO_REGISTER, j, rsi)
10982 {
10983 try_swap_copy_prop (loop, reg, j);
10984 }
10985 CLEAR_REG_SET (&store_copies);
10986 }
10987 }
10988
10989
10990
10991 if (label != NULL_RTX && end_label != NULL_RTX)
10992 for (p = loop->start; p != loop->end; p = NEXT_INSN (p))
10993 if (JUMP_P (p) && JUMP_LABEL (p) == end_label)
10994 redirect_jump (p, label, false);
10995
10996 cselib_finish ();
10997 }
10998
10999
11000 struct note_reg_stored_arg
11001 {
11002 int set_seen;
11003 rtx reg;
11004 };
11005
11006
11007
11008 static void
11009 note_reg_stored (rtx x, rtx setter ATTRIBUTE_UNUSED, void *arg)
11010 {
11011 struct note_reg_stored_arg *t = (struct note_reg_stored_arg *) arg;
11012 if (t->reg == x)
11013 t->set_seen = 1;
11014 }
11015
11016
11017
11018
11019
11020
11021 static void
11022 try_copy_prop (const struct loop *loop, rtx replacement, unsigned int regno)
11023 {
11024
11025 rtx reg_rtx = regno_reg_rtx[regno];
11026 rtx init_insn = 0;
11027 rtx insn;
11028
11029 int replaced_last = 0;
11030 int store_is_first = 0;
11031
11032 for (insn = next_insn_in_loop (loop, loop->scan_start);
11033 insn != NULL_RTX;
11034 insn = next_insn_in_loop (loop, insn))
11035 {
11036 rtx set;
11037
11038
11039
11040 if (LABEL_P (insn) && init_insn)
11041 break;
11042
11043 if (! INSN_P (insn))
11044 continue;
11045
11046
11047 set = single_set (insn);
11048 if (set
11049 && REG_P (SET_DEST (set))
11050 && REGNO (SET_DEST (set)) == regno)
11051 {
11052 if (init_insn)
11053 abort ();
11054
11055 init_insn = insn;
11056 if (REGNO_FIRST_UID (regno) == INSN_UID (insn))
11057 store_is_first = 1;
11058 }
11059
11060
11061 if (init_insn && insn != init_insn)
11062 {
11063 struct note_reg_stored_arg arg;
11064
11065 replace_loop_regs (insn, reg_rtx, replacement);
11066 if (REGNO_LAST_UID (regno) == INSN_UID (insn))
11067 replaced_last = 1;
11068
11069
11070 arg.reg = replacement;
11071 arg.set_seen = 0;
11072 note_stores (PATTERN (insn), note_reg_stored, &arg);
11073 if (arg.set_seen)
11074 {
11075 rtx note = find_reg_note (insn, REG_EQUAL, NULL);
11076
11077
11078
11079
11080 if (note && reg_mentioned_p (replacement, XEXP (note, 0)))
11081 remove_note (insn, note);
11082 break;
11083 }
11084 }
11085 }
11086 if (! init_insn)
11087 abort ();
11088 if (apply_change_group ())
11089 {
11090 if (loop_dump_stream)
11091 fprintf (loop_dump_stream, " Replaced reg %d", regno);
11092 if (store_is_first && replaced_last)
11093 {
11094 rtx first;
11095 rtx retval_note;
11096
11097
11098 first = init_insn;
11099
11100
11101 retval_note = find_reg_note (init_insn, REG_RETVAL, NULL_RTX);
11102
11103
11104 if (retval_note)
11105 first = XEXP (retval_note, 0);
11106
11107
11108 loop_delete_insns (first, init_insn);
11109 }
11110 if (loop_dump_stream)
11111 fprintf (loop_dump_stream, ".\n");
11112 }
11113 }
11114
11115
11116
11117
11118 static void
11119 loop_delete_insns (rtx first, rtx last)
11120 {
11121 while (1)
11122 {
11123 if (loop_dump_stream)
11124 fprintf (loop_dump_stream, ", deleting init_insn (%d)",
11125 INSN_UID (first));
11126 delete_insn (first);
11127
11128
11129
11130 if (first == last)
11131 break;
11132
11133 first = NEXT_INSN (first);
11134 }
11135 }
11136
11137
11138
11139
11140
11141
11142 static void
11143 try_swap_copy_prop (const struct loop *loop, rtx replacement,
11144 unsigned int regno)
11145 {
11146 rtx insn;
11147 rtx set = NULL_RTX;
11148 unsigned int new_regno;
11149
11150 new_regno = REGNO (replacement);
11151
11152 for (insn = next_insn_in_loop (loop, loop->scan_start);
11153 insn != NULL_RTX;
11154 insn = next_insn_in_loop (loop, insn))
11155 {
11156
11157 if (INSN_P (insn)
11158 && (set = single_set (insn))
11159 && REG_P (SET_DEST (set))
11160 && REGNO (SET_DEST (set)) == new_regno
11161 && REG_P (SET_SRC (set))
11162 && REGNO (SET_SRC (set)) == regno)
11163 break;
11164 }
11165
11166 if (insn != NULL_RTX)
11167 {
11168 rtx prev_insn;
11169 rtx prev_set;
11170
11171
11172
11173
11174
11175 prev_insn = PREV_INSN (insn);
11176
11177 if (INSN_P (insn)
11178 && (prev_set = single_set (prev_insn))
11179 && REG_P (SET_DEST (prev_set))
11180 && REGNO (SET_DEST (prev_set)) == regno)
11181 {
11182
11183
11184
11185
11186
11187
11188
11189
11190
11191
11192
11193
11194
11195 validate_change (prev_insn, &SET_DEST (prev_set),
11196 replacement, 1);
11197 validate_change (insn, &SET_DEST (set),
11198 SET_SRC (set), 1);
11199 validate_change (insn, &SET_SRC (set),
11200 replacement, 1);
11201
11202 if (apply_change_group ())
11203 {
11204 if (loop_dump_stream)
11205 fprintf (loop_dump_stream,
11206 " Swapped set of reg %d at %d with reg %d at %d.\n",
11207 regno, INSN_UID (insn),
11208 new_regno, INSN_UID (prev_insn));
11209
11210
11211 if (REGNO_FIRST_UID (regno) == INSN_UID (prev_insn))
11212 REGNO_FIRST_UID (regno) = INSN_UID (insn);
11213
11214
11215
11216 try_copy_prop (loop, replacement, regno);
11217 }
11218 }
11219 }
11220 }
11221
11222
11223
11224 static int
11225 find_mem_in_note_1 (rtx *x, void *data)
11226 {
11227 if (*x != NULL_RTX && MEM_P (*x))
11228 {
11229 rtx *res = (rtx *) data;
11230 *res = *x;
11231 return 1;
11232 }
11233 return 0;
11234 }
11235
11236
11237
11238 static rtx
11239 find_mem_in_note (rtx note)
11240 {
11241 if (note && for_each_rtx (¬e, find_mem_in_note_1, ¬e))
11242 return note;
11243 return NULL_RTX;
11244 }
11245
11246
11247
11248
11249
11250
11251 static int
11252 replace_loop_mem (rtx *mem, void *data)
11253 {
11254 loop_replace_args *args = (loop_replace_args *) data;
11255 rtx m = *mem;
11256
11257 if (m == NULL_RTX)
11258 return 0;
11259
11260 switch (GET_CODE (m))
11261 {
11262 case MEM:
11263 break;
11264
11265 case CONST_DOUBLE:
11266
11267
11268 return -1;
11269
11270 default:
11271
11272 return 0;
11273 }
11274
11275 if (!rtx_equal_p (args->match, m))
11276
11277 return 0;
11278
11279
11280 validate_change (args->insn, mem, args->replacement, 1);
11281
11282 return 0;
11283 }
11284
11285 static void
11286 replace_loop_mems (rtx insn, rtx mem, rtx reg, int written)
11287 {
11288 loop_replace_args args;
11289
11290 args.insn = insn;
11291 args.match = mem;
11292 args.replacement = reg;
11293
11294 for_each_rtx (&insn, replace_loop_mem, &args);
11295
11296
11297
11298 if (written)
11299 {
11300 rtx note, sub;
11301 rtx *link;
11302
11303 for (link = ®_NOTES (insn); (note = *link); link = &XEXP (note, 1))
11304 {
11305 if (REG_NOTE_KIND (note) == REG_EQUAL
11306 && (sub = find_mem_in_note (note))
11307 && true_dependence (mem, VOIDmode, sub, rtx_varies_p))
11308 {
11309
11310 validate_change (NULL_RTX, link, XEXP (note, 1), 1);
11311 break;
11312 }
11313 }
11314 }
11315 }
11316
11317
11318
11319
11320
11321 static int
11322 replace_loop_reg (rtx *px, void *data)
11323 {
11324 rtx x = *px;
11325 loop_replace_args *args = (loop_replace_args *) data;
11326
11327 if (x == NULL_RTX)
11328 return 0;
11329
11330 if (x == args->match)
11331 validate_change (args->insn, px, args->replacement, 1);
11332
11333 return 0;
11334 }
11335
11336 static void
11337 replace_loop_regs (rtx insn, rtx reg, rtx replacement)
11338 {
11339 loop_replace_args args;
11340
11341 args.insn = insn;
11342 args.match = reg;
11343 args.replacement = replacement;
11344
11345 for_each_rtx (&insn, replace_loop_reg, &args);
11346 }
11347
11348
11349
11350
11351 static rtx
11352 loop_insn_emit_after (const struct loop *loop ATTRIBUTE_UNUSED,
11353 basic_block where_bb ATTRIBUTE_UNUSED, rtx where_insn,
11354 rtx pattern)
11355 {
11356 return emit_insn_after (pattern, where_insn);
11357 }
11358
11359
11360
11361
11362
11363
11364 static rtx
11365 loop_insn_emit_before (const struct loop *loop,
11366 basic_block where_bb ATTRIBUTE_UNUSED,
11367 rtx where_insn, rtx pattern)
11368 {
11369 if (! where_insn)
11370 return loop_insn_hoist (loop, pattern);
11371 return emit_insn_before (pattern, where_insn);
11372 }
11373
11374
11375
11376
11377
11378 static rtx
11379 loop_call_insn_emit_before (const struct loop *loop ATTRIBUTE_UNUSED,
11380 basic_block where_bb ATTRIBUTE_UNUSED,
11381 rtx where_insn, rtx pattern)
11382 {
11383 return emit_call_insn_before (pattern, where_insn);
11384 }
11385
11386
11387
11388
11389 static rtx
11390 loop_insn_hoist (const struct loop *loop, rtx pattern)
11391 {
11392 return loop_insn_emit_before (loop, 0, loop->start, pattern);
11393 }
11394
11395
11396
11397
11398 static rtx
11399 loop_call_insn_hoist (const struct loop *loop, rtx pattern)
11400 {
11401 return loop_call_insn_emit_before (loop, 0, loop->start, pattern);
11402 }
11403
11404
11405
11406
11407 static rtx
11408 loop_insn_sink (const struct loop *loop, rtx pattern)
11409 {
11410 return loop_insn_emit_before (loop, 0, loop->sink, pattern);
11411 }
11412
11413
11414
11415 static rtx
11416 gen_load_of_final_value (rtx reg, rtx final_value)
11417 {
11418 rtx seq;
11419 start_sequence ();
11420 final_value = force_operand (final_value, reg);
11421 if (final_value != reg)
11422 emit_move_insn (reg, final_value);
11423 seq = get_insns ();
11424 end_sequence ();
11425 return seq;
11426 }
11427
11428
11429
11430
11431
11432
11433 static rtx
11434 loop_insn_sink_or_swim (const struct loop *loop, rtx pattern)
11435 {
11436 if (loop->exit_count)
11437 return loop_insn_hoist (loop, pattern);
11438 else
11439 return loop_insn_sink (loop, pattern);
11440 }
11441
11442 static void
11443 loop_ivs_dump (const struct loop *loop, FILE *file, int verbose)
11444 {
11445 struct iv_class *bl;
11446 int iv_num = 0;
11447
11448 if (! loop || ! file)
11449 return;
11450
11451 for (bl = LOOP_IVS (loop)->list; bl; bl = bl->next)
11452 iv_num++;
11453
11454 fprintf (file, "Loop %d: %d IV classes\n", loop->num, iv_num);
11455
11456 for (bl = LOOP_IVS (loop)->list; bl; bl = bl->next)
11457 {
11458 loop_iv_class_dump (bl, file, verbose);
11459 fputc ('\n', file);
11460 }
11461 }
11462
11463
11464 static void
11465 loop_iv_class_dump (const struct iv_class *bl, FILE *file,
11466 int verbose ATTRIBUTE_UNUSED)
11467 {
11468 struct induction *v;
11469 rtx incr;
11470 int i;
11471
11472 if (! bl || ! file)
11473 return;
11474
11475 fprintf (file, "IV class for reg %d, benefit %d\n",
11476 bl->regno, bl->total_benefit);
11477
11478 fprintf (file, " Init insn %d", INSN_UID (bl->init_insn));
11479 if (bl->initial_value)
11480 {
11481 fprintf (file, ", init val: ");
11482 print_simple_rtl (file, bl->initial_value);
11483 }
11484 if (bl->initial_test)
11485 {
11486 fprintf (file, ", init test: ");
11487 print_simple_rtl (file, bl->initial_test);
11488 }
11489 fputc ('\n', file);
11490
11491 if (bl->final_value)
11492 {
11493 fprintf (file, " Final val: ");
11494 print_simple_rtl (file, bl->final_value);
11495 fputc ('\n', file);
11496 }
11497
11498 if ((incr = biv_total_increment (bl)))
11499 {
11500 fprintf (file, " Total increment: ");
11501 print_simple_rtl (file, incr);
11502 fputc ('\n', file);
11503 }
11504
11505
11506 for (i = 0, v = bl->biv; v; v = v->next_iv, i++)
11507 {
11508 fprintf (file, " Inc%d: insn %d, incr: ", i, INSN_UID (v->insn));
11509 print_simple_rtl (file, v->add_val);
11510 fputc ('\n', file);
11511 }
11512
11513
11514 for (i = 0, v = bl->giv; v; v = v->next_iv, i++)
11515 {
11516 fprintf (file, " Giv%d: insn %d, benefit %d, ",
11517 i, INSN_UID (v->insn), v->benefit);
11518 if (v->giv_type == DEST_ADDR)
11519 print_simple_rtl (file, v->mem);
11520 else
11521 print_simple_rtl (file, single_set (v->insn));
11522 fputc ('\n', file);
11523 }
11524 }
11525
11526
11527 static void
11528 loop_biv_dump (const struct induction *v, FILE *file, int verbose)
11529 {
11530 if (! v || ! file)
11531 return;
11532
11533 fprintf (file,
11534 "Biv %d: insn %d",
11535 REGNO (v->dest_reg), INSN_UID (v->insn));
11536 fprintf (file, " const ");
11537 print_simple_rtl (file, v->add_val);
11538
11539 if (verbose && v->final_value)
11540 {
11541 fputc ('\n', file);
11542 fprintf (file, " final ");
11543 print_simple_rtl (file, v->final_value);
11544 }
11545
11546 fputc ('\n', file);
11547 }
11548
11549
11550 static void
11551 loop_giv_dump (const struct induction *v, FILE *file, int verbose)
11552 {
11553 if (! v || ! file)
11554 return;
11555
11556 if (v->giv_type == DEST_REG)
11557 fprintf (file, "Giv %d: insn %d",
11558 REGNO (v->dest_reg), INSN_UID (v->insn));
11559 else
11560 fprintf (file, "Dest address: insn %d",
11561 INSN_UID (v->insn));
11562
11563 fprintf (file, " src reg %d benefit %d",
11564 REGNO (v->src_reg), v->benefit);
11565 fprintf (file, " lifetime %d",
11566 v->lifetime);
11567
11568 if (v->replaceable)
11569 fprintf (file, " replaceable");
11570
11571 if (v->no_const_addval)
11572 fprintf (file, " ncav");
11573
11574 if (v->ext_dependent)
11575 {
11576 switch (GET_CODE (v->ext_dependent))
11577 {
11578 case SIGN_EXTEND:
11579 fprintf (file, " ext se");
11580 break;
11581 case ZERO_EXTEND:
11582 fprintf (file, " ext ze");
11583 break;
11584 case TRUNCATE:
11585 fprintf (file, " ext tr");
11586 break;
11587 default:
11588 abort ();
11589 }
11590 }
11591
11592 fputc ('\n', file);
11593 fprintf (file, " mult ");
11594 print_simple_rtl (file, v->mult_val);
11595
11596 fputc ('\n', file);
11597 fprintf (file, " add ");
11598 print_simple_rtl (file, v->add_val);
11599
11600 if (verbose && v->final_value)
11601 {
11602 fputc ('\n', file);
11603 fprintf (file, " final ");
11604 print_simple_rtl (file, v->final_value);
11605 }
11606
11607 fputc ('\n', file);
11608 }
11609
11610
11611 void
11612 debug_ivs (const struct loop *loop)
11613 {
11614 loop_ivs_dump (loop, stderr, 1);
11615 }
11616
11617
11618 void
11619 debug_iv_class (const struct iv_class *bl)
11620 {
11621 loop_iv_class_dump (bl, stderr, 1);
11622 }
11623
11624
11625 void
11626 debug_biv (const struct induction *v)
11627 {
11628 loop_biv_dump (v, stderr, 1);
11629 }
11630
11631
11632 void
11633 debug_giv (const struct induction *v)
11634 {
11635 loop_giv_dump (v, stderr, 1);
11636 }
11637
11638
11639 #define LOOP_BLOCK_NUM_1(INSN) \
11640 ((INSN) ? (BLOCK_FOR_INSN (INSN) ? BLOCK_NUM (INSN) : - 1) : -1)
11641
11642
11643 #define LOOP_BLOCK_NUM(INSN) \
11644 ((INSN) ? (NOTE_P (INSN) \
11645 ? LOOP_BLOCK_NUM_1 (next_nonnote_insn (INSN)) \
11646 : LOOP_BLOCK_NUM_1 (INSN)) \
11647 : -1)
11648
11649 #define LOOP_INSN_UID(INSN) ((INSN) ? INSN_UID (INSN) : -1)
11650
11651 static void
11652 loop_dump_aux (const struct loop *loop, FILE *file,
11653 int verbose ATTRIBUTE_UNUSED)
11654 {
11655 rtx label;
11656
11657 if (! loop || ! file || !BB_HEAD (loop->first))
11658 return;
11659
11660
11661
11662 if (! PREV_INSN (BB_HEAD (loop->first))
11663 || !NOTE_P (PREV_INSN (BB_HEAD (loop->first)))
11664 || NOTE_LINE_NUMBER (PREV_INSN (BB_HEAD (loop->first)))
11665 != NOTE_INSN_LOOP_BEG)
11666 fprintf (file, ";; No NOTE_INSN_LOOP_BEG at %d\n",
11667 INSN_UID (PREV_INSN (BB_HEAD (loop->first))));
11668 if (! NEXT_INSN (BB_END (loop->last))
11669 || !NOTE_P (NEXT_INSN (BB_END (loop->last)))
11670 || NOTE_LINE_NUMBER (NEXT_INSN (BB_END (loop->last)))
11671 != NOTE_INSN_LOOP_END)
11672 fprintf (file, ";; No NOTE_INSN_LOOP_END at %d\n",
11673 INSN_UID (NEXT_INSN (BB_END (loop->last))));
11674
11675 if (loop->start)
11676 {
11677 fprintf (file,
11678 ";; start %d (%d), end %d (%d)\n",
11679 LOOP_BLOCK_NUM (loop->start),
11680 LOOP_INSN_UID (loop->start),
11681 LOOP_BLOCK_NUM (loop->end),
11682 LOOP_INSN_UID (loop->end));
11683 fprintf (file, ";; top %d (%d), scan start %d (%d)\n",
11684 LOOP_BLOCK_NUM (loop->top),
11685 LOOP_INSN_UID (loop->top),
11686 LOOP_BLOCK_NUM (loop->scan_start),
11687 LOOP_INSN_UID (loop->scan_start));
11688 fprintf (file, ";; exit_count %d", loop->exit_count);
11689 if (loop->exit_count)
11690 {
11691 fputs (", labels:", file);
11692 for (label = loop->exit_labels; label; label = LABEL_NEXTREF (label))
11693 {
11694 fprintf (file, " %d ",
11695 LOOP_INSN_UID (XEXP (label, 0)));
11696 }
11697 }
11698 fputs ("\n", file);
11699 }
11700 }
11701
11702
11703
11704 void
11705 debug_loop (const struct loop *loop)
11706 {
11707 flow_loop_dump (loop, stderr, loop_dump_aux, 1);
11708 }
11709
11710
11711
11712 void
11713 debug_loops (const struct loops *loops)
11714 {
11715 flow_loops_dump (loops, stderr, loop_dump_aux, 1);
11716 }