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