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) ==