00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134 #include "config.h"
00135 #include "system.h"
00136 #include "rtl.h"
00137 #include "tm_p.h"
00138 #include "insn-config.h"
00139 #include "integrate.h"
00140 #include "regs.h"
00141 #include "recog.h"
00142 #include "flags.h"
00143 #include "function.h"
00144 #include "expr.h"
00145 #include "loop.h"
00146 #include "toplev.h"
00147 #include "hard-reg-set.h"
00148 #include "basic-block.h"
00149 #include "predict.h"
00150 #include "params.h"
00151
00152
00153
00154
00155
00156
00157
00158
00159 #define NUM_FACTORS 4
00160
00161 static struct _factor { const int factor; int count; }
00162 factors[NUM_FACTORS] = { {2, 0}, {3, 0}, {5, 0}, {7, 0}};
00163
00164
00165
00166 enum unroll_types
00167 {
00168 UNROLL_COMPLETELY,
00169 UNROLL_MODULO,
00170 UNROLL_NAIVE
00171 };
00172
00173
00174
00175
00176
00177
00178
00179 static struct induction **addr_combined_regs;
00180
00181
00182
00183
00184
00185 static rtx *splittable_regs;
00186
00187
00188
00189
00190
00191
00192 static int *splittable_regs_updates;
00193
00194
00195
00196 static rtx simplify_cmp_and_jump_insns PARAMS ((enum rtx_code,
00197 enum machine_mode,
00198 rtx, rtx, rtx));
00199 static void init_reg_map PARAMS ((struct inline_remap *, int));
00200 static rtx calculate_giv_inc PARAMS ((rtx, rtx, unsigned int));
00201 static rtx initial_reg_note_copy PARAMS ((rtx, struct inline_remap *));
00202 static void final_reg_note_copy PARAMS ((rtx *, struct inline_remap *));
00203 static void copy_loop_body PARAMS ((struct loop *, rtx, rtx,
00204 struct inline_remap *, rtx, int,
00205 enum unroll_types, rtx, rtx, rtx, rtx));
00206 static int find_splittable_regs PARAMS ((const struct loop *,
00207 enum unroll_types, int));
00208 static int find_splittable_givs PARAMS ((const struct loop *,
00209 struct iv_class *, enum unroll_types,
00210 rtx, int));
00211 static int reg_dead_after_loop PARAMS ((const struct loop *, rtx));
00212 static rtx fold_rtx_mult_add PARAMS ((rtx, rtx, rtx, enum machine_mode));
00213 static rtx remap_split_bivs PARAMS ((struct loop *, rtx));
00214 static rtx find_common_reg_term PARAMS ((rtx, rtx));
00215 static rtx subtract_reg_term PARAMS ((rtx, rtx));
00216 static rtx loop_find_equiv_value PARAMS ((const struct loop *, rtx));
00217 static rtx ujump_to_loop_cont PARAMS ((rtx, rtx));
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228 void
00229 unroll_loop (loop, insn_count, strength_reduce_p)
00230 struct loop *loop;
00231 int insn_count;
00232 int strength_reduce_p;
00233 {
00234 struct loop_info *loop_info = LOOP_INFO (loop);
00235 struct loop_ivs *ivs = LOOP_IVS (loop);
00236 int i, j;
00237 unsigned int r;
00238 unsigned HOST_WIDE_INT temp;
00239 int unroll_number = 1;
00240 rtx copy_start, copy_end;
00241 rtx insn, sequence, pattern, tem;
00242 int max_labelno, max_insnno;
00243 rtx insert_before;
00244 struct inline_remap *map;
00245 char *local_label = NULL;
00246 char *local_regno;
00247 unsigned int max_local_regnum;
00248 unsigned int maxregnum;
00249 rtx exit_label = 0;
00250 rtx start_label;
00251 struct iv_class *bl;
00252 int splitting_not_safe = 0;
00253 enum unroll_types unroll_type = UNROLL_NAIVE;
00254 int loop_preconditioned = 0;
00255 rtx safety_label;
00256
00257
00258
00259 rtx last_loop_insn;
00260 rtx loop_start = loop->start;
00261 rtx loop_end = loop->end;
00262
00263
00264
00265
00266 if (insn_count > MAX_UNROLLED_INSNS / 2)
00267 {
00268 if (loop_dump_stream)
00269 fprintf (loop_dump_stream, "Unrolling failure: Loop too big.\n");
00270 return;
00271 }
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281 if (! strength_reduce_p)
00282 loop_info->n_iterations = 0;
00283
00284 if (loop_dump_stream && loop_info->n_iterations > 0)
00285 {
00286 fputs ("Loop unrolling: ", loop_dump_stream);
00287 fprintf (loop_dump_stream, HOST_WIDE_INT_PRINT_DEC,
00288 loop_info->n_iterations);
00289 fputs (" iterations.\n", loop_dump_stream);
00290 }
00291
00292
00293
00294 last_loop_insn = prev_nonnote_insn (loop_end);
00295
00296
00297
00298
00299 if (loop_info->n_iterations == 1)
00300 {
00301
00302
00303
00304
00305
00306
00307
00308
00309 rtx ujump = ujump_to_loop_cont (loop->start, loop->cont);
00310
00311
00312
00313
00314
00315
00316
00317
00318 if (GET_CODE (last_loop_insn) == BARRIER)
00319 {
00320
00321 last_loop_insn = PREV_INSN (last_loop_insn);
00322 }
00323
00324 if (ujump && GET_CODE (last_loop_insn) == JUMP_INSN)
00325 {
00326 #ifdef HAVE_cc0
00327 rtx prev = PREV_INSN (last_loop_insn);
00328 #endif
00329 delete_related_insns (last_loop_insn);
00330 #ifdef HAVE_cc0
00331
00332
00333 if (only_sets_cc0_p (prev))
00334 delete_related_insns (prev);
00335 #endif
00336
00337 delete_related_insns (ujump);
00338
00339
00340 if (loop->vtop)
00341 delete_related_insns (loop->vtop);
00342 if (loop->cont)
00343 delete_related_insns (loop->cont);
00344 if (loop_start)
00345 delete_related_insns (loop_start);
00346 if (loop_end)
00347 delete_related_insns (loop_end);
00348
00349 return;
00350 }
00351 }
00352
00353 if (loop_info->n_iterations > 0
00354
00355 && loop_info->n_iterations < (unsigned) MAX_UNROLLED_INSNS
00356 && loop_info->n_iterations * insn_count < (unsigned) MAX_UNROLLED_INSNS)
00357 {
00358 unroll_number = loop_info->n_iterations;
00359 unroll_type = UNROLL_COMPLETELY;
00360 }
00361 else if (loop_info->n_iterations > 0)
00362 {
00363
00364
00365
00366
00367 for (i = 0; i < NUM_FACTORS; i++)
00368 factors[i].count = 0;
00369
00370 temp = loop_info->n_iterations;
00371 for (i = NUM_FACTORS - 1; i >= 0; i--)
00372 while (temp % factors[i].factor == 0)
00373 {
00374 factors[i].count++;
00375 temp = temp / factors[i].factor;
00376 }
00377
00378
00379
00380
00381 unroll_number = 1;
00382 temp = insn_count;
00383 for (i = 3; i >= 0; i--)
00384 while (factors[i].count--)
00385 {
00386 if (temp * factors[i].factor < (unsigned) MAX_UNROLLED_INSNS)
00387 {
00388 unroll_number *= factors[i].factor;
00389 temp *= factors[i].factor;
00390 }
00391 else
00392 break;
00393 }
00394
00395
00396
00397 if (unroll_number == 1)
00398 {
00399 if (loop_dump_stream)
00400 fprintf (loop_dump_stream, "Loop unrolling: No factors found.\n");
00401 }
00402 else
00403 unroll_type = UNROLL_MODULO;
00404 }
00405
00406
00407
00408 if (unroll_type == UNROLL_NAIVE)
00409 {
00410 if (8 * insn_count < MAX_UNROLLED_INSNS)
00411 unroll_number = 8;
00412 else if (4 * insn_count < MAX_UNROLLED_INSNS)
00413 unroll_number = 4;
00414 else
00415 unroll_number = 2;
00416 }
00417
00418
00419
00420 if (loop_dump_stream)
00421 fprintf (loop_dump_stream, "Unrolling loop %d times.\n", unroll_number);
00422
00423 if (unroll_type == UNROLL_COMPLETELY || unroll_type == UNROLL_MODULO)
00424 {
00425
00426
00427
00428
00429
00430
00431
00432
00433
00434
00435
00436
00437
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448 insn = loop_start;
00449 while (GET_CODE (insn) != CODE_LABEL && GET_CODE (insn) != JUMP_INSN)
00450 insn = NEXT_INSN (insn);
00451 if (GET_CODE (insn) == JUMP_INSN)
00452 return;
00453 }
00454
00455 if (unroll_type == UNROLL_COMPLETELY)
00456 {
00457
00458
00459
00460
00461
00462
00463
00464 copy_start = loop_start;
00465
00466
00467
00468
00469 insert_before = NEXT_INSN (last_loop_insn);
00470
00471
00472 if (GET_CODE (last_loop_insn) == BARRIER)
00473 copy_end = PREV_INSN (PREV_INSN (last_loop_insn));
00474 else if (GET_CODE (last_loop_insn) == JUMP_INSN)
00475 {
00476 copy_end = PREV_INSN (last_loop_insn);
00477 #ifdef HAVE_cc0
00478
00479
00480 if (sets_cc0_p (PREV_INSN (copy_end)))
00481 copy_end = PREV_INSN (copy_end);
00482 #endif
00483 }
00484 else
00485 {
00486
00487
00488
00489
00490 if (loop_dump_stream)
00491 fprintf (loop_dump_stream,
00492 "Unrolling failure: loop does not end with a JUMP_INSN.\n");
00493 return;
00494 }
00495 }
00496 else if (unroll_type == UNROLL_MODULO)
00497 {
00498
00499
00500
00501
00502
00503
00504 copy_start = loop_start;
00505
00506
00507
00508 if (GET_CODE (last_loop_insn) == BARRIER)
00509 {
00510 insert_before = PREV_INSN (last_loop_insn);
00511 copy_end = PREV_INSN (insert_before);
00512 }
00513 else if (GET_CODE (last_loop_insn) == JUMP_INSN)
00514 {
00515 insert_before = last_loop_insn;
00516 #ifdef HAVE_cc0
00517
00518
00519 if (sets_cc0_p (PREV_INSN (insert_before)))
00520 insert_before = PREV_INSN (insert_before);
00521 #endif
00522 copy_end = PREV_INSN (insert_before);
00523 }
00524 else
00525 {
00526
00527
00528
00529
00530 if (loop_dump_stream)
00531 fprintf (loop_dump_stream,
00532 "Unrolling failure: loop does not end with a JUMP_INSN.\n");
00533 return;
00534 }
00535 }
00536 else
00537 {
00538
00539
00540
00541 if (GET_CODE (last_loop_insn) == BARRIER)
00542 {
00543
00544
00545
00546
00547
00548
00549
00550
00551 insert_before = PREV_INSN (last_loop_insn);
00552 copy_end = PREV_INSN (insert_before);
00553 }
00554 else if (GET_CODE (last_loop_insn) == JUMP_INSN)
00555 {
00556
00557
00558
00559 insert_before = NEXT_INSN (last_loop_insn);
00560 copy_end = last_loop_insn;
00561 }
00562 else
00563 {
00564
00565
00566
00567
00568 if (loop_dump_stream)
00569 fprintf (loop_dump_stream,
00570 "Unrolling failure: loop does not end with a JUMP_INSN.\n");
00571 return;
00572 }
00573
00574
00575
00576
00577
00578
00579
00580
00581 exit_label = gen_label_rtx ();
00582
00583 insn = loop_start;
00584 while (GET_CODE (insn) != CODE_LABEL && GET_CODE (insn) != JUMP_INSN)
00585 insn = NEXT_INSN (insn);
00586
00587 if (GET_CODE (insn) == JUMP_INSN)
00588 {
00589
00590
00591
00592 copy_start = NEXT_INSN (insn);
00593
00594
00595
00596
00597
00598
00599 splitting_not_safe = 1;
00600 if (loop_dump_stream)
00601 fprintf (loop_dump_stream,
00602 "Splitting not safe, because loop not entered at top.\n");
00603 }
00604 else
00605 copy_start = loop_start;
00606 }
00607
00608
00609 start_label = NEXT_INSN (copy_start);
00610
00611 while (GET_CODE (start_label) == NOTE)
00612 start_label = NEXT_INSN (start_label);
00613 if (GET_CODE (start_label) != CODE_LABEL)
00614 {
00615
00616
00617
00618
00619
00620
00621
00622 if (loop_dump_stream)
00623 fprintf (loop_dump_stream,
00624 "Unrolling failure: unknown insns between BEG note and loop label.\n");
00625 return;
00626 }
00627 if (LABEL_NAME (start_label))
00628 {
00629
00630
00631
00632
00633
00634 if (loop_dump_stream)
00635 fprintf (loop_dump_stream,
00636 "Unrolling failure: loop start label is gone\n");
00637 return;
00638 }
00639
00640 if (unroll_type == UNROLL_NAIVE
00641 && GET_CODE (last_loop_insn) == BARRIER
00642 && GET_CODE (PREV_INSN (last_loop_insn)) == JUMP_INSN
00643 && start_label != JUMP_LABEL (PREV_INSN (last_loop_insn)))
00644 {
00645
00646
00647
00648 insert_before = NEXT_INSN (last_loop_insn);
00649 copy_end = last_loop_insn;
00650 }
00651
00652 if (unroll_type == UNROLL_NAIVE
00653 && GET_CODE (last_loop_insn) == JUMP_INSN
00654 && start_label != JUMP_LABEL (last_loop_insn))
00655 {
00656
00657
00658
00659
00660
00661
00662
00663 if (loop_dump_stream)
00664 fprintf (loop_dump_stream,
00665 "Unrolling failure: final conditional branch not to loop start\n");
00666 return;
00667 }
00668
00669
00670
00671
00672 max_labelno = max_label_num ();
00673 max_insnno = get_max_uid ();
00674
00675
00676
00677
00678
00679 map = (struct inline_remap *) xcalloc (1, sizeof (struct inline_remap));
00680
00681
00682
00683 if (max_labelno > 0)
00684 {
00685 map->label_map = (rtx *) xcalloc (max_labelno, sizeof (rtx));
00686 local_label = (char *) xcalloc (max_labelno, sizeof (char));
00687 }
00688
00689
00690
00691
00692
00693
00694
00695
00696 for (insn = copy_start; insn != loop_end; insn = NEXT_INSN (insn))
00697 {
00698 rtx note;
00699
00700 if (GET_CODE (insn) == CODE_LABEL)
00701 local_label[CODE_LABEL_NUMBER (insn)] = 1;
00702 else if (GET_CODE (insn) == JUMP_INSN)
00703 {
00704 if (JUMP_LABEL (insn))
00705 set_label_in_map (map,
00706 CODE_LABEL_NUMBER (JUMP_LABEL (insn)),
00707 JUMP_LABEL (insn));
00708 else if (GET_CODE (PATTERN (insn)) == ADDR_VEC
00709 || GET_CODE (PATTERN (insn)) == ADDR_DIFF_VEC)
00710 {
00711 rtx pat = PATTERN (insn);
00712 int diff_vec_p = GET_CODE (PATTERN (insn)) == ADDR_DIFF_VEC;
00713 int len = XVECLEN (pat, diff_vec_p);
00714 rtx label;
00715
00716 for (i = 0; i < len; i++)
00717 {
00718 label = XEXP (XVECEXP (pat, diff_vec_p, i), 0);
00719 set_label_in_map (map, CODE_LABEL_NUMBER (label), label);
00720 }
00721 }
00722 }
00723 if ((note = find_reg_note (insn, REG_LABEL, NULL_RTX)))
00724 set_label_in_map (map, CODE_LABEL_NUMBER (XEXP (note, 0)),
00725 XEXP (note, 0));
00726 }
00727
00728
00729
00730 map->insn_map = (rtx *) xmalloc (max_insnno * sizeof (rtx));
00731
00732
00733
00734 map->inline_target = 0;
00735
00736
00737
00738
00739
00740
00741
00742
00743 maxregnum = max_reg_num ();
00744
00745
00746 max_local_regnum = maxregnum;
00747
00748
00749
00750
00751
00752
00753
00754
00755
00756 splittable_regs = (rtx *) xcalloc (maxregnum, sizeof (rtx));
00757 splittable_regs_updates = (int *) xcalloc (maxregnum, sizeof (int));
00758 addr_combined_regs
00759 = (struct induction **) xcalloc (maxregnum, sizeof (struct induction *));
00760 local_regno = (char *) xcalloc (maxregnum, sizeof (char));
00761
00762
00763
00764 if (INSN_UID (copy_end) < max_uid_for_loop)
00765 {
00766 int copy_start_luid = INSN_LUID (copy_start);
00767 int copy_end_luid = INSN_LUID (copy_end);
00768
00769
00770
00771 if (GET_CODE (copy_end) == JUMP_INSN)
00772 copy_end_luid--;
00773
00774
00775
00776 #ifdef HAVE_cc0
00777 if (GET_CODE (copy_end) == JUMP_INSN
00778 && sets_cc0_p (PREV_INSN (copy_end)))
00779 copy_end_luid--;
00780 #endif
00781
00782
00783
00784
00785
00786 if (copy_start == loop_start)
00787 copy_start_luid++;
00788
00789
00790
00791
00792
00793
00794 for (r = FIRST_PSEUDO_REGISTER; r < max_reg_before_loop; ++r)
00795 if (REGNO_FIRST_UID (r) > 0 && REGNO_FIRST_UID (r) < max_uid_for_loop
00796 && REGNO_FIRST_LUID (r) >= copy_start_luid
00797 && REGNO_LAST_UID (r) > 0 && REGNO_LAST_UID (r) < max_uid_for_loop
00798 && REGNO_LAST_LUID (r) <= copy_end_luid)
00799 {
00800
00801
00802
00803
00804
00805
00806
00807
00808
00809 if (set_dominates_use (r, REGNO_FIRST_UID (r), REGNO_LAST_UID (r),
00810 copy_start, copy_end))
00811 local_regno[r] = 1;
00812
00813 if (loop_dump_stream)
00814 {
00815 if (local_regno[r])
00816 fprintf (loop_dump_stream, "Marked reg %d as local\n", r);
00817 else
00818 fprintf (loop_dump_stream, "Did not mark reg %d as local\n",
00819 r);
00820 }
00821 }
00822 }
00823
00824
00825
00826
00827
00828
00829
00830
00831
00832
00833
00834
00835
00836
00837
00838
00839
00840
00841
00842
00843
00844
00845
00846 if (unroll_type == UNROLL_NAIVE && ! splitting_not_safe && strength_reduce_p)
00847 {
00848 rtx initial_value, final_value, increment;
00849 enum machine_mode mode;
00850
00851 if (precondition_loop_p (loop,
00852 &initial_value, &final_value, &increment,
00853 &mode))
00854 {
00855 rtx diff, insn;
00856 rtx *labels;
00857 int abs_inc, neg_inc;
00858 enum rtx_code cc = loop_info->comparison_code;
00859 int less_p = (cc == LE || cc == LEU || cc == LT || cc == LTU);
00860 int unsigned_p = (cc == LEU || cc == GEU || cc == LTU || cc == GTU);
00861
00862 map->reg_map = (rtx *) xmalloc (maxregnum * sizeof (rtx));
00863
00864 VARRAY_CONST_EQUIV_INIT (map->const_equiv_varray, maxregnum,
00865 "unroll_loop_precondition");
00866 global_const_equiv_varray = map->const_equiv_varray;
00867
00868 init_reg_map (map, maxregnum);
00869
00870
00871
00872 if (unroll_number > 4)
00873 unroll_number = 4;
00874
00875
00876
00877 neg_inc = 0;
00878 abs_inc = INTVAL (increment);
00879 if (abs_inc < 0)
00880 {
00881 abs_inc = -abs_inc;
00882 neg_inc = 1;
00883 }
00884
00885 start_sequence ();
00886
00887
00888
00889 final_value = copy_rtx (final_value);
00890 initial_value = copy_rtx (initial_value);
00891
00892
00893
00894
00895 final_value = force_operand (final_value, NULL_RTX);
00896 if (!nonmemory_operand (final_value, VOIDmode))
00897 final_value = force_reg (mode, final_value);
00898
00899
00900
00901
00902
00903
00904
00905
00906
00907
00908
00909
00910
00911
00912 if (cc == NE || less_p != neg_inc)
00913 diff = simplify_gen_binary (MINUS, mode, final_value,
00914 initial_value);
00915 else
00916 diff = simplify_gen_unary (neg_inc ? NOT : NEG, mode,
00917 initial_value, mode);
00918 diff = force_operand (diff, NULL_RTX);
00919
00920
00921
00922 diff = simplify_gen_binary (AND, mode, diff,
00923 GEN_INT (unroll_number*abs_inc - 1));
00924 diff = force_operand (diff, NULL_RTX);
00925
00926
00927
00928
00929 labels = (rtx *) xmalloc (sizeof (rtx) * unroll_number);
00930 for (i = 0; i < unroll_number; i++)
00931 labels[i] = gen_label_rtx ();
00932
00933
00934
00935
00936
00937
00938
00939 if (cc != NE)
00940 {
00941 rtx incremented_initval;
00942 enum rtx_code cmp_code;
00943
00944 incremented_initval
00945 = simplify_gen_binary (PLUS, mode, initial_value, increment);
00946 incremented_initval
00947 = force_operand (incremented_initval, NULL_RTX);
00948
00949 cmp_code = (less_p
00950 ? (unsigned_p ? GEU : GE)
00951 : (unsigned_p ? LEU : LE));
00952
00953 insn = simplify_cmp_and_jump_insns (cmp_code, mode,
00954 incremented_initval,
00955 final_value, labels[1]);
00956 if (insn)
00957 predict_insn_def (insn, PRED_LOOP_CONDITION, TAKEN);
00958 }
00959
00960
00961
00962
00963
00964
00965
00966
00967
00968
00969
00970
00971
00972
00973 for (i = 0; i < unroll_number - 1; i++)
00974 {
00975 int cmp_const;
00976 enum rtx_code cmp_code;
00977
00978
00979
00980 if (i == 0)
00981 {
00982 cmp_const = 0;
00983 cmp_code = EQ;
00984 }
00985 else if (neg_inc)
00986 {
00987 cmp_const = unroll_number - i;
00988 cmp_code = GE;
00989 }
00990 else
00991 {
00992 cmp_const = i;
00993 cmp_code = LE;
00994 }
00995
00996 insn = simplify_cmp_and_jump_insns (cmp_code, mode, diff,
00997 GEN_INT (abs_inc*cmp_const),
00998 labels[i]);
00999 if (insn)
01000 predict_insn (insn, PRED_LOOP_PRECONDITIONING,
01001 REG_BR_PROB_BASE / (unroll_number - i));
01002 }
01003
01004
01005
01006
01007
01008
01009
01010
01011
01012
01013 if (abs_inc != 1)
01014 {
01015 int cmp_const;
01016 enum rtx_code cmp_code;
01017
01018 if (neg_inc)
01019 {
01020 cmp_const = abs_inc - 1;
01021 cmp_code = LE;
01022 }
01023 else
01024 {
01025 cmp_const = abs_inc * (unroll_number - 1) + 1;
01026 cmp_code = GE;
01027 }
01028
01029 simplify_cmp_and_jump_insns (cmp_code, mode, diff,
01030 GEN_INT (cmp_const), labels[0]);
01031 }
01032
01033 sequence = get_insns ();
01034 end_sequence ();
01035 loop_insn_hoist (loop, sequence);
01036
01037
01038
01039
01040
01041
01042 if (GET_CODE (last_loop_insn) == BARRIER)
01043 copy_end = PREV_INSN (PREV_INSN (last_loop_insn));
01044 else if (GET_CODE (last_loop_insn) == JUMP_INSN)
01045 {
01046 copy_end = PREV_INSN (last_loop_insn);
01047 #ifdef HAVE_cc0
01048
01049
01050 if (sets_cc0_p (PREV_INSN (copy_end)))
01051 copy_end = PREV_INSN (copy_end);
01052 #endif
01053 }
01054 else
01055 abort ();
01056
01057 for (i = 1; i < unroll_number; i++)
01058 {
01059 emit_label_after (labels[unroll_number - i],
01060 PREV_INSN (loop_start));
01061
01062 memset ((char *) map->insn_map, 0, max_insnno * sizeof (rtx));
01063 memset ((char *) &VARRAY_CONST_EQUIV (map->const_equiv_varray, 0),
01064 0, (VARRAY_SIZE (map->const_equiv_varray)
01065 * sizeof (struct const_equiv_data)));
01066 map->const_age = 0;
01067
01068 for (j = 0; j < max_labelno; j++)
01069 if (local_label[j])
01070 set_label_in_map (map, j, gen_label_rtx ());
01071
01072 for (r = FIRST_PSEUDO_REGISTER; r < max_local_regnum; r++)
01073 if (local_regno[r])
01074 {
01075 map->reg_map[r]
01076 = gen_reg_rtx (GET_MODE (regno_reg_rtx[r]));
01077 record_base_value (REGNO (map->reg_map[r]),
01078 regno_reg_rtx[r], 0);
01079 }
01080
01081
01082
01083
01084 if (i == unroll_number - 1)
01085 {
01086 if (GET_CODE (last_loop_insn) == BARRIER)
01087 copy_end = PREV_INSN (PREV_INSN (last_loop_insn));
01088 else
01089 copy_end = last_loop_insn;
01090 }
01091
01092
01093
01094 copy_loop_body (loop, copy_start, copy_end, map, exit_label, 0,
01095 unroll_type, start_label, loop_end,
01096 loop_start, copy_end);
01097 }
01098 emit_label_after (labels[0], PREV_INSN (loop_start));
01099
01100 if (GET_CODE (last_loop_insn) == BARRIER)
01101 {
01102 insert_before = PREV_INSN (last_loop_insn);
01103 copy_end = PREV_INSN (insert_before);
01104 }
01105 else
01106 {
01107 insert_before = last_loop_insn;
01108 #ifdef HAVE_cc0
01109
01110
01111
01112 if (sets_cc0_p (PREV_INSN (insert_before)))
01113 insert_before = PREV_INSN (insert_before);
01114 #endif
01115 copy_end = PREV_INSN (insert_before);
01116 }
01117
01118
01119 unroll_type = UNROLL_MODULO;
01120 loop_preconditioned = 1;
01121
01122
01123 free (labels);
01124 }
01125 }
01126
01127
01128
01129 if (unroll_type == UNROLL_NAIVE && ! flag_unroll_all_loops)
01130 {
01131 if (loop_dump_stream)
01132 fprintf (loop_dump_stream,
01133 "Unrolling failure: Naive unrolling not being done.\n");
01134 goto egress;
01135 }
01136
01137
01138
01139
01140 loop_info->unroll_number = unroll_number;
01141
01142
01143 loop_info->preconditioned = loop_preconditioned;
01144
01145
01146 NOTE_PRECONDITIONED (loop->end) = loop_preconditioned;
01147
01148
01149
01150
01151
01152
01153
01154
01155
01156 if (splitting_not_safe)
01157 temp = 0;
01158 else
01159 temp = find_splittable_regs (loop, unroll_type, unroll_number);
01160
01161
01162
01163
01164
01165 maxregnum = max_reg_num ();
01166 map->reg_map = (rtx *) xmalloc (maxregnum * sizeof (rtx));
01167
01168 init_reg_map (map, maxregnum);
01169
01170 if (map->const_equiv_varray == 0)
01171 VARRAY_CONST_EQUIV_INIT (map->const_equiv_varray,
01172 maxregnum + temp * unroll_number * 2,
01173 "unroll_loop");
01174 global_const_equiv_varray = map->const_equiv_varray;
01175
01176
01177
01178
01179 for (bl = ivs->list; bl; bl = bl->next)
01180 {
01181 if (REGNO (bl->biv->src_reg) != bl->regno)
01182 map->reg_map[bl->regno] = bl->biv->src_reg;
01183 #if 0
01184
01185 for (v = bl->giv; v; v = v->next_iv)
01186 if (REGNO (v->src_reg) != bl->regno)
01187 map->reg_map[REGNO (v->dest_reg)] = v->src_reg;
01188 #endif
01189 }
01190
01191
01192 map->regno_pointer_align = cfun->emit->regno_pointer_align;
01193 map->x_regno_reg_rtx = cfun->emit->x_regno_reg_rtx;
01194
01195
01196
01197
01198
01199
01200
01201 if (unroll_type == UNROLL_MODULO)
01202 {
01203 insn = NEXT_INSN (copy_end);
01204 if (GET_CODE (insn) == INSN || GET_CODE (insn) == JUMP_INSN)
01205 PATTERN (insn) = remap_split_bivs (loop, PATTERN (insn));
01206 }
01207
01208
01209
01210
01211
01212 for (i = 0; i < unroll_number; i++)
01213 {
01214 memset ((char *) map->insn_map, 0, max_insnno * sizeof (rtx));
01215 memset ((char *) &VARRAY_CONST_EQUIV (map->const_equiv_varray, 0), 0,
01216 VARRAY_SIZE (map->const_equiv_varray) * sizeof (struct const_equiv_data));
01217 map->const_age = 0;
01218
01219 for (j = 0; j < max_labelno; j++)
01220 if (local_label[j])
01221 set_label_in_map (map, j, gen_label_rtx ());
01222
01223 for (r = FIRST_PSEUDO_REGISTER; r < max_local_regnum; r++)
01224 if (local_regno[r])
01225 {
01226 map->reg_map[r] = gen_reg_rtx (GET_MODE (regno_reg_rtx[r]));
01227 record_base_value (REGNO (map->reg_map[r]),
01228 regno_reg_rtx[r], 0);
01229 }
01230
01231
01232
01233 if (i == 0 && loop_start != copy_start)
01234 {
01235 insn = PREV_INSN (copy_start);
01236 pattern = PATTERN (insn);
01237
01238 tem = get_label_from_map (map,
01239 CODE_LABEL_NUMBER
01240 (XEXP (SET_SRC (pattern), 0)));
01241 SET_SRC (pattern) = gen_rtx_LABEL_REF (VOIDmode, tem);
01242
01243
01244
01245 JUMP_LABEL (insn) = tem;
01246 LABEL_NUSES (tem)++;
01247 }
01248
01249 copy_loop_body (loop, copy_start, copy_end, map, exit_label,
01250 i == unroll_number - 1, unroll_type, start_label,
01251 loop_end, insert_before, insert_before);
01252 }
01253
01254
01255
01256
01257
01258
01259
01260
01261
01262
01263 if (unroll_type == UNROLL_COMPLETELY)
01264 safety_label = emit_label_after (gen_label_rtx (), last_loop_insn);
01265 else
01266 safety_label = emit_label_after (gen_label_rtx (), copy_end);
01267
01268
01269
01270
01271 insn = NEXT_INSN (copy_start);
01272 while (insn != safety_label)
01273 {
01274
01275
01276
01277
01278
01279
01280
01281
01282 if (insn != start_label
01283 && ! (GET_CODE (insn) == CODE_LABEL && LABEL_NAME (insn))
01284 && ! (GET_CODE (insn) == NOTE
01285 && NOTE_LINE_NUMBER (insn) == NOTE_INSN_DELETED_LABEL))
01286 insn = delete_related_insns (insn);
01287 else
01288 insn = NEXT_INSN (insn);
01289 }
01290
01291
01292
01293 if (INSN_DELETED_P (safety_label))
01294 abort ();
01295 delete_related_insns (safety_label);
01296
01297
01298
01299
01300
01301
01302 if (exit_label)
01303 emit_label_after (exit_label, loop_end);
01304
01305 egress:
01306 if (unroll_type == UNROLL_COMPLETELY)
01307 {
01308
01309 if (loop->vtop)
01310 delete_related_insns (loop->vtop);
01311 if (loop->cont)
01312 delete_related_insns (loop->cont);
01313 if (loop_start)
01314 delete_related_insns (loop_start);
01315 if (loop_end)
01316 delete_related_insns (loop_end);
01317 }
01318
01319 if (map->const_equiv_varray)
01320 VARRAY_FREE (map->const_equiv_varray);
01321 if (map->label_map)
01322 {
01323 free (map->label_map);
01324 free (local_label);
01325 }
01326 free (map->insn_map);
01327 free (splittable_regs);
01328 free (splittable_regs_updates);
01329 free (addr_combined_regs);
01330 free (local_regno);
01331 if (map->reg_map)
01332 free (map->reg_map);
01333 free (map);
01334 }
01335
01336
01337
01338
01339
01340
01341 static rtx
01342 simplify_cmp_and_jump_insns (code, mode, op0, op1, label)
01343 enum rtx_code code;
01344 enum machine_mode mode;
01345 rtx op0, op1, label;
01346 {
01347 rtx t, insn;
01348
01349 t = simplify_relational_operation (code, mode, op0, op1);
01350 if (!t)
01351 {
01352 enum rtx_code scode = signed_condition (code);
01353 emit_cmp_and_jump_insns (op0, op1, scode, NULL_RTX, mode,
01354 code != scode, label);
01355 insn = get_last_insn ();
01356
01357 JUMP_LABEL (insn) = label;
01358 LABEL_NUSES (label) += 1;
01359
01360 return insn;
01361 }
01362 else if (t == const_true_rtx)
01363 {
01364 insn = emit_jump_insn (gen_jump (label));
01365 emit_barrier ();
01366 JUMP_LABEL (insn) = label;
01367 LABEL_NUSES (label) += 1;
01368 }
01369
01370 return NULL_RTX;
01371 }
01372
01373
01374
01375
01376
01377
01378
01379
01380
01381
01382
01383
01384
01385
01386
01387
01388
01389
01390 int
01391 precondition_loop_p (loop, initial_value, final_value, increment, mode)
01392 const struct loop *loop;
01393 rtx *initial_value, *final_value, *increment;
01394 enum machine_mode *mode;
01395 {
01396 rtx loop_start = loop->start;
01397 struct loop_info *loop_info = LOOP_INFO (loop);
01398
01399 if (loop_info->n_iterations > 0)
01400 {
01401 if (INTVAL (loop_info->increment) > 0)
01402 {
01403 *initial_value = const0_rtx;
01404 *increment = const1_rtx;
01405 *final_value = GEN_INT (loop_info->n_iterations);
01406 }
01407 else
01408 {
01409 *initial_value = GEN_INT (loop_info->n_iterations);
01410 *increment = constm1_rtx;
01411 *final_value = const0_rtx;
01412 }
01413 *mode = word_mode;
01414
01415 if (loop_dump_stream)
01416 {
01417 fputs ("Preconditioning: Success, number of iterations known, ",
01418 loop_dump_stream);
01419 fprintf (loop_dump_stream, HOST_WIDE_INT_PRINT_DEC,
01420 loop_info->n_iterations);
01421 fputs (".\n", loop_dump_stream);
01422 }
01423 return 1;
01424 }
01425
01426 if (loop_info->iteration_var == 0)
01427 {
01428 if (loop_dump_stream)
01429 fprintf (loop_dump_stream,
01430 "Preconditioning: Could not find iteration variable.\n");
01431 return 0;
01432 }
01433 else if (loop_info->initial_value == 0)
01434 {
01435 if (loop_dump_stream)
01436 fprintf (loop_dump_stream,
01437 "Preconditioning: Could not find initial value.\n");
01438 return 0;
01439 }
01440 else if (loop_info->increment == 0)
01441 {
01442 if (loop_dump_stream)
01443 fprintf (loop_dump_stream,
01444 "Preconditioning: Could not find increment value.\n");
01445 return 0;
01446 }
01447 else if (GET_CODE (loop_info->increment) != CONST_INT)
01448 {
01449 if (loop_dump_stream)
01450 fprintf (loop_dump_stream,
01451 "Preconditioning: Increment not a constant.\n");
01452 return 0;
01453 }
01454 else if ((exact_log2 (INTVAL (loop_info->increment)) < 0)
01455 && (exact_log2 (-INTVAL (loop_info->increment)) < 0))
01456 {
01457 if (loop_dump_stream)
01458 fprintf (loop_dump_stream,
01459 "Preconditioning: Increment not a constant power of 2.\n");
01460 return 0;
01461 }
01462
01463
01464
01465
01466 if (loop_info->final_value == 0)
01467 {
01468 if (loop_dump_stream)
01469 fprintf (loop_dump_stream,
01470 "Preconditioning: EQ comparison loop.\n");
01471 return 0;
01472 }
01473
01474
01475
01476
01477
01478
01479 if ((GET_CODE (loop_info->final_value) == REG
01480 && REGNO (loop_info->final_value) >= max_reg_before_loop)
01481 || (GET_CODE (loop_info->final_value) == PLUS
01482 && REGNO (XEXP (loop_info->final_value, 0)) >= max_reg_before_loop)
01483 || ! loop_invariant_p (loop, loop_info->final_value))
01484 {
01485 if (loop_dump_stream)
01486 fprintf (loop_dump_stream,
01487 "Preconditioning: Final value not invariant.\n");
01488 return 0;
01489 }
01490
01491
01492
01493 if (GET_MODE_CLASS (GET_MODE (loop_info->final_value)) == MODE_FLOAT
01494 || GET_MODE_CLASS (GET_MODE (loop_info->initial_value)) == MODE_FLOAT)
01495 {
01496 if (loop_dump_stream)
01497 fprintf (loop_dump_stream,
01498 "Preconditioning: Floating point final or initial value.\n");
01499 return 0;
01500 }
01501
01502
01503
01504
01505 if (REGNO_FIRST_LUID (REGNO (loop_info->iteration_var))
01506 > INSN_LUID (loop_start))
01507 {
01508 if (loop_dump_stream)
01509 fprintf (loop_dump_stream,
01510 "Preconditioning: Iteration var not live before loop start.\n");
01511 return 0;
01512 }
01513
01514
01515
01516
01517
01518
01519
01520
01521 *initial_value = loop_info->initial_value;
01522 *increment = loop_info->increment;
01523 *final_value = loop_info->final_value;
01524
01525
01526
01527
01528 *mode = GET_MODE (*final_value);
01529 if (*mode == VOIDmode)
01530 {
01531 *mode = GET_MODE (*initial_value);
01532 if (*mode == VOIDmode)
01533 *mode = word_mode;
01534 }
01535 else if (*mode != GET_MODE (*initial_value)
01536 && (GET_MODE_SIZE (*mode)
01537 < GET_MODE_SIZE (GET_MODE (*initial_value))))
01538 *mode = GET_MODE (*initial_value);
01539
01540
01541 if (loop_dump_stream)
01542 fprintf (loop_dump_stream, "Preconditioning: Successful.\n");
01543 return 1;
01544 }
01545
01546
01547
01548
01549
01550
01551
01552
01553 static void
01554 init_reg_map (map, maxregnum)
01555 struct inline_remap *map;
01556 int maxregnum;
01557 {
01558 int i;
01559
01560 for (i = maxregnum - 1; i > LAST_VIRTUAL_REGISTER; i--)
01561 map->reg_map[i] = regno_reg_rtx[i];
01562
01563 for (i = LAST_VIRTUAL_REGISTER; i >= 0; i--)
01564 map->reg_map[i] = 0;
01565
01566 map->reg_map[VIRTUAL_STACK_VARS_REGNUM]
01567 = regno_reg_rtx[VIRTUAL_STACK_VARS_REGNUM];
01568 map->reg_map[VIRTUAL_INCOMING_ARGS_REGNUM]
01569 = regno_reg_rtx[VIRTUAL_INCOMING_ARGS_REGNUM];
01570 }
01571
01572
01573
01574
01575
01576
01577
01578
01579
01580 static rtx
01581 calculate_giv_inc (pattern, src_insn, regno)
01582 rtx pattern, src_insn;
01583 unsigned int regno;
01584 {
01585 rtx increment;
01586 rtx increment_total = 0;
01587 int tries = 0;
01588
01589 retry:
01590
01591
01592 if (GET_CODE (SET_SRC (pattern)) != PLUS)
01593 {
01594
01595
01596 src_insn = PREV_INSN (src_insn);
01597 pattern = single_set (src_insn);
01598 if (GET_CODE (SET_SRC (pattern)) != PLUS)
01599 abort ();
01600
01601
01602
01603 delete_related_insns (get_last_insn ());
01604 }
01605
01606
01607 increment = XEXP (SET_SRC (pattern), 1);
01608 if (GET_CODE (increment) != CONST_INT)
01609 {
01610
01611
01612 increment = find_last_value (increment, &src_insn, NULL_RTX, 0);
01613
01614
01615
01616
01617 if (GET_CODE (increment) == LO_SUM)
01618 increment = XEXP (increment, 1);
01619
01620
01621
01622 else if (GET_CODE (increment) == MEM)
01623 {
01624 rtx note = find_reg_note (src_insn, REG_EQUAL, 0);
01625 if (note)
01626 increment = XEXP (note, 0);
01627 }
01628
01629 else if (GET_CODE (increment) == IOR
01630 || GET_CODE (increment) == PLUS
01631 || GET_CODE (increment) == ASHIFT
01632 || GET_CODE (increment) == LSHIFTRT)
01633 {
01634
01635
01636
01637 rtx second_part = XEXP (increment, 1);
01638 enum rtx_code code = GET_CODE (increment);
01639
01640 increment = find_last_value (XEXP (increment, 0),
01641 &src_insn, NULL_RTX, 0);
01642
01643 delete_related_insns (get_last_insn ());
01644
01645 if (GET_CODE (second_part) != CONST_INT
01646 || GET_CODE (increment) != CONST_INT)
01647 abort ();
01648
01649 if (code == IOR)
01650 increment = GEN_INT (INTVAL (increment) | INTVAL (second_part));
01651 else if (code == PLUS)
01652 increment = GEN_INT (INTVAL (increment) + INTVAL (second_part));
01653 else if (code == ASHIFT)
01654 increment = GEN_INT (INTVAL (increment) << INTVAL (second_part));
01655 else
01656 increment = GEN_INT ((unsigned HOST_WIDE_INT) INTVAL (increment) >> INTVAL (second_part));
01657 }
01658
01659 if (GET_CODE (increment) != CONST_INT)
01660 abort ();
01661
01662
01663
01664 delete_related_insns (get_last_insn ());
01665 }
01666
01667 if (increment_total)
01668 increment_total = GEN_INT (INTVAL (increment_total) + INTVAL (increment));
01669 else
01670 increment_total = increment;
01671
01672
01673
01674 if (GET_CODE (XEXP (SET_SRC (pattern), 0)) != REG
01675 || REGNO (XEXP (SET_SRC (pattern), 0)) != regno)
01676 {
01677
01678
01679
01680
01681 if (tries == 0)
01682 {
01683 tries++;
01684
01685 src_insn = PREV_INSN (src_insn);
01686 pattern = single_set (src_insn);
01687
01688 delete_related_insns (get_last_insn ());
01689
01690 goto retry;
01691 }
01692
01693 abort ();
01694 }
01695
01696 return increment_total;
01697 }
01698
01699
01700
01701
01702
01703 static rtx
01704 initial_reg_note_copy (notes, map)
01705 rtx notes;
01706 struct inline_remap *map;
01707 {
01708 rtx copy;
01709
01710 if (notes == 0)
01711 return 0;
01712
01713 copy = rtx_alloc (GET_CODE (notes));
01714 PUT_REG_NOTE_KIND (copy, REG_NOTE_KIND (notes));
01715
01716 if (GET_CODE (notes) == EXPR_LIST)
01717 XEXP (copy, 0) = copy_rtx_and_substitute (XEXP (notes, 0), map, 0);
01718 else if (GET_CODE (notes) == INSN_LIST)
01719
01720 XEXP (copy, 0) = copy_rtx (XEXP (notes, 0));
01721 else
01722 abort ();
01723
01724 XEXP (copy, 1) = initial_reg_note_copy (XEXP (notes, 1), map);
01725
01726 return copy;
01727 }
01728
01729
01730
01731 static void
01732 final_reg_note_copy (notesp, map)
01733 rtx *notesp;
01734 struct inline_remap *map;
01735 {
01736 while (*notesp)
01737 {
01738 rtx note = *notesp;
01739
01740 if (GET_CODE (note) == INSN_LIST)
01741 {
01742
01743
01744
01745 if (REG_NOTE_KIND (note) == REG_WAS_0)
01746 {
01747 *notesp = XEXP (note, 1);
01748 continue;
01749 }
01750 else
01751 {
01752 rtx insn = map->insn_map[INSN_UID (XEXP (note, 0))];
01753
01754
01755
01756
01757 if (!insn)
01758 {
01759 if (REG_NOTE_KIND (note) != REG_LABEL)
01760 abort ();
01761 }
01762 else
01763 XEXP (note, 0) = insn;
01764 }
01765 }
01766
01767 notesp = &XEXP (note, 1);
01768 }
01769 }
01770
01771
01772
01773
01774 static void
01775 copy_loop_body (loop, copy_start, copy_end, map, exit_label, last_iteration,
01776 unroll_type, start_label, loop_end, insert_before,
01777 copy_notes_from)
01778 struct loop *loop;
01779 rtx copy_start, copy_end;
01780 struct inline_remap *map;
01781 rtx exit_label;
01782 int last_iteration;
01783 enum unroll_types unroll_type;
01784 rtx start_label, loop_end, insert_before, copy_notes_from;
01785 {
01786 struct loop_ivs *ivs = LOOP_IVS (loop);
01787 rtx insn, pattern;
01788 rtx set, tem, copy = NULL_RTX;
01789 int dest_reg_was_split, i;
01790 #ifdef HAVE_cc0
01791 rtx cc0_insn = 0;
01792 #endif
01793 rtx final_label = 0;
01794 rtx giv_inc, giv_dest_reg, giv_src_reg;
01795
01796
01797
01798
01799
01800
01801
01802 if (! last_iteration)
01803 {
01804 final_label = gen_label_rtx ();
01805 set_label_in_map (map, CODE_LABEL_NUMBER (start_label), final_label);
01806 }
01807 else
01808 set_label_in_map (map, CODE_LABEL_NUMBER (start_label), start_label);
01809
01810 start_sequence ();
01811
01812 insn = copy_start;
01813 do
01814 {
01815 insn = NEXT_INSN (insn);
01816
01817 map->orig_asm_operands_vector = 0;
01818
01819 switch (GET_CODE (insn))
01820 {
01821 case INSN:
01822 pattern = PATTERN (insn);
01823 copy = 0;
01824 giv_inc = 0;
01825
01826
01827
01828
01829
01830
01831
01832
01833
01834 if ((set = single_set (insn))
01835 && GET_CODE (SET_DEST (set)) == REG
01836 && addr_combined_regs[REGNO (SET_DEST (set))])
01837 {
01838 struct iv_class *bl;
01839 struct induction *v, *tv;
01840 unsigned int regno = REGNO (SET_DEST (set));
01841
01842 v = addr_combined_regs[REGNO (SET_DEST (set))];
01843 bl = REG_IV_CLASS (ivs, REGNO (v->src_reg));
01844
01845
01846
01847
01848
01849
01850
01851 giv_inc = calculate_giv_inc (set, insn, regno);
01852
01853
01854
01855 for (tv = bl->giv; tv; tv = tv->next_iv)
01856 if (tv->giv_type == DEST_ADDR && tv->same == v)
01857 {
01858 int this_giv_inc;
01859
01860
01861 if (*tv->location != tv->dest_reg)
01862 continue;
01863
01864
01865
01866 this_giv_inc = INTVAL (giv_inc);
01867 if (tv->mult_val != v->mult_val)
01868 this_giv_inc = (this_giv_inc / INTVAL (v->mult_val)
01869 * INTVAL (tv->mult_val));
01870
01871 tv->dest_reg = plus_constant (tv->dest_reg, this_giv_inc);
01872 *tv->location = tv->dest_reg;
01873
01874 if (last_iteration && unroll_type != UNROLL_COMPLETELY)
01875 {
01876
01877
01878
01879 rtx value, dest_reg;
01880
01881
01882
01883 if (GET_CODE (tv->dest_reg) == REG)
01884 dest_reg = tv->dest_reg;
01885 else
01886 dest_reg = XEXP (tv->dest_reg, 0);
01887
01888
01889
01890
01891 if (! tv->same_insn && ! tv->shared)
01892 {
01893
01894
01895
01896
01897 value = plus_constant (tv->dest_reg,
01898 tv->const_adjust);
01899
01900 if (GET_CODE (value) == PLUS)
01901 {
01902
01903
01904
01905 emit_unrolled_add (dest_reg, XEXP (value, 0),
01906 XEXP (value, 1));
01907 }
01908 }
01909
01910
01911
01912
01913
01914 tv->dest_reg = plus_constant (dest_reg,
01915 -tv->const_adjust);
01916 *tv->location = tv->dest_reg;
01917 }
01918 }
01919 }
01920
01921
01922
01923
01924
01925
01926 dest_reg_was_split = 0;
01927
01928 if ((set = single_set (insn))
01929 && GET_CODE (SET_DEST (set)) == REG
01930 && splittable_regs[REGNO (SET_DEST (set))])
01931 {
01932 unsigned int regno = REGNO (SET_DEST (set));
01933 unsigned int src_regno;
01934
01935 dest_reg_was_split = 1;
01936
01937 giv_dest_reg = SET_DEST (set);
01938 giv_src_reg = giv_dest_reg;
01939
01940
01941 if (giv_inc == 0)
01942 giv_inc = calculate_giv_inc (set, insn, regno);
01943
01944 src_regno = REGNO (giv_src_reg);
01945
01946 if (unroll_type == UNROLL_COMPLETELY)
01947 {
01948
01949
01950
01951
01952
01953 splittable_regs[regno]
01954 = plus_constant (splittable_regs[src_regno],
01955 INTVAL (giv_inc));
01956
01957 if (GET_CODE (splittable_regs[regno]) == PLUS)
01958 {
01959 giv_src_reg = XEXP (splittable_regs[regno], 0);
01960 giv_inc = XEXP (splittable_regs[regno], 1);
01961 }
01962 else
01963 {
01964
01965
01966
01967 giv_src_reg = splittable_regs[regno];
01968 giv_inc = const0_rtx;
01969 }
01970 }
01971 else
01972 {
01973
01974
01975
01976
01977
01978
01979
01980
01981
01982
01983
01984
01985 if (regno < ivs->n_regs
01986 && REG_IV_TYPE (ivs, regno) == BASIC_INDUCT)
01987 {
01988 giv_src_reg = REG_IV_CLASS (ivs, regno)->biv->src_reg;
01989 giv_dest_reg = giv_src_reg;
01990 }
01991
01992 #if 0
01993
01994
01995
01996 #endif
01997
01998 splittable_regs[regno]
01999 = simplify_gen_binary (PLUS, GET_MODE (giv_src_reg),
02000 giv_inc,
02001 splittable_regs[src_regno]);
02002 giv_inc = splittable_regs[regno];
02003
02004
02005
02006
02007
02008
02009
02010
02011
02012
02013
02014
02015
02016
02017
02018 if (! last_iteration
02019 || (splittable_regs_updates[regno]-- != 1))
02020 {
02021 tem = gen_reg_rtx (GET_MODE (giv_src_reg));
02022 giv_dest_reg = tem;
02023 map->reg_map[regno] = tem;
02024 record_base_value (REGNO (tem),
02025 giv_inc == const0_rtx
02026 ? giv_src_reg
02027 : gen_rtx_PLUS (GET_MODE (giv_src_reg),
02028 giv_src_reg, giv_inc),
02029 1);
02030 }
02031 else
02032 map->reg_map[regno] = giv_src_reg;
02033 }
02034
02035
02036
02037 emit_unrolled_add (giv_dest_reg, giv_src_reg, giv_inc);
02038 copy = get_last_insn ();
02039 pattern = PATTERN (copy);
02040 }
02041 else
02042 {
02043 pattern = copy_rtx_and_substitute (pattern, map, 0);
02044 copy = emit_insn (pattern);
02045 }
02046 REG_NOTES (copy) = initial_reg_note_copy (REG_NOTES (insn), map);
02047 INSN_SCOPE (copy) = INSN_SCOPE (insn);
02048
02049
02050
02051
02052 if ((tem = find_reg_note (copy, REG_EQUAL, NULL_RTX))
02053 && !loop_invariant_p (loop, XEXP (tem, 0)))
02054 remove_note (copy, tem);
02055
02056 #ifdef HAVE_cc0
02057
02058
02059
02060
02061
02062
02063
02064
02065
02066
02067
02068
02069
02070 if (sets_cc0_p (PATTERN (copy)) != 0)
02071 cc0_insn = copy;
02072 else
02073 {
02074 if (cc0_insn)
02075 try_constants (cc0_insn, map);
02076 cc0_insn = 0;
02077 try_constants (copy, map);
02078 }
02079 #else
02080 try_constants (copy, map);
02081 #endif
02082
02083
02084
02085
02086 if (dest_reg_was_split)
02087 {
02088 int regno = REGNO (SET_DEST (set));
02089
02090 if ((size_t) regno < VARRAY_SIZE (map->const_equiv_varray)
02091 && (VARRAY_CONST_EQUIV (map->const_equiv_varray, regno).age
02092 == map->const_age))
02093 VARRAY_CONST_EQUIV (map->const_equiv_varray, regno).age = -1;
02094 }
02095 break;
02096
02097 case JUMP_INSN:
02098 pattern = copy_rtx_and_substitute (PATTERN (insn), map, 0);
02099 copy = emit_jump_insn (pattern);
02100 REG_NOTES (copy) = initial_reg_note_copy (REG_NOTES (insn), map);
02101 INSN_SCOPE (copy) = INSN_SCOPE (insn);
02102
02103 if (JUMP_LABEL (insn))
02104 {
02105 JUMP_LABEL (copy) = get_label_from_map (map,
02106 CODE_LABEL_NUMBER
02107 (JUMP_LABEL (insn)));
02108 LABEL_NUSES (JUMP_LABEL (copy))++;
02109 }
02110 if (JUMP_LABEL (insn) == start_label && insn == copy_end
02111 && ! last_iteration)
02112 {
02113
02114
02115
02116
02117
02118
02119
02120 if (!invert_jump (copy, exit_label, 0))
02121 {
02122 rtx jmp;
02123 rtx lab = gen_label_rtx ();
02124
02125
02126
02127
02128 jmp = emit_jump_insn_after (gen_jump (exit_label), copy);
02129 JUMP_LABEL (jmp) = exit_label;
02130 LABEL_NUSES (exit_label)++;
02131 jmp = emit_barrier_after (jmp);
02132 emit_label_after (lab, jmp);
02133 LABEL_NUSES (lab) = 0;
02134 if (!redirect_jump (copy, lab, 0))
02135 abort ();
02136 }
02137 }
02138
02139 #ifdef HAVE_cc0
02140 if (cc0_insn)
02141 try_constants (cc0_insn, map);
02142 cc0_insn = 0;
02143 #endif
02144 try_constants (copy, map);
02145
02146
02147
02148 if (JUMP_LABEL (insn))
02149 {
02150 rtx label = 0;
02151
02152
02153
02154 if ((set = single_set (copy)))
02155 {
02156 tem = SET_SRC (set);
02157 if (GET_CODE (tem) == LABEL_REF)
02158 label = XEXP (tem, 0);
02159 else if (GET_CODE (tem) == IF_THEN_ELSE)
02160 {
02161 if (XEXP (tem, 1) != pc_rtx)
02162 label = XEXP (XEXP (tem, 1), 0);
02163 else
02164 label = XEXP (XEXP (tem, 2), 0);
02165 }
02166 }
02167
02168 if (label && GET_CODE (label) == CODE_LABEL)
02169 JUMP_LABEL (copy) = label;
02170 else
02171 {
02172
02173
02174
02175 JUMP_LABEL (copy)
02176 = get_label_from_map (map,
02177 CODE_LABEL_NUMBER (JUMP_LABEL (insn)));
02178 }
02179
02180
02181
02182
02183 LABEL_NUSES (JUMP_LABEL (copy))++;
02184 }
02185 else if (GET_CODE (PATTERN (copy)) == ADDR_VEC
02186 || GET_CODE (PATTERN (copy)) == ADDR_DIFF_VEC)
02187 {
02188 rtx pat = PATTERN (copy);
02189 int diff_vec_p = GET_CODE (pat) == ADDR_DIFF_VEC;
02190 int len = XVECLEN (pat, diff_vec_p);
02191 int i;
02192
02193 for (i = 0; i < len; i++)
02194 LABEL_NUSES (XEXP (XVECEXP (pat, diff_vec_p, i), 0))++;
02195 }
02196
02197
02198
02199 if (any_condjump_p (insn) && onlyjump_p (insn) && map->last_pc_value)
02200 {
02201 #ifdef HAVE_cc0
02202
02203 if (only_sets_cc0_p (PREV_INSN (copy)))
02204 delete_related_insns (PREV_INSN (copy));
02205 #endif
02206
02207
02208 if (map->last_pc_value == pc_rtx)
02209 {
02210 delete_insn (copy);
02211 copy = 0;
02212 }
02213 else
02214
02215
02216
02217 emit_barrier ();
02218 }
02219 break;
02220
02221 case CALL_INSN:
02222 pattern = copy_rtx_and_substitute (PATTERN (insn), map, 0);
02223 copy = emit_call_insn (pattern);
02224 REG_NOTES (copy) = initial_reg_note_copy (REG_NOTES (insn), map);
02225 INSN_SCOPE (copy) = INSN_SCOPE (insn);
02226 SIBLING_CALL_P (copy) = SIBLING_CALL_P (insn);
02227 CONST_OR_PURE_CALL_P (copy) = CONST_OR_PURE_CALL_P (insn);
02228
02229
02230
02231 CALL_INSN_FUNCTION_USAGE (copy)
02232 = copy_rtx_and_substitute (CALL_INSN_FUNCTION_USAGE (insn),
02233 map, 0);
02234
02235 #ifdef HAVE_cc0
02236 if (cc0_insn)
02237 try_constants (cc0_insn, map);
02238 cc0_insn = 0;
02239 #endif
02240 try_constants (copy, map);
02241
02242
02243 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
02244 VARRAY_CONST_EQUIV (map->const_equiv_varray, i).rtx = 0;
02245 break;
02246
02247 case CODE_LABEL:
02248
02249
02250
02251 if (insn != start_label)
02252 {
02253 copy = emit_label (get_label_from_map (map,
02254 CODE_LABEL_NUMBER (insn)));
02255 map->const_age++;
02256 }
02257 break;
02258
02259 case BARRIER:
02260 copy = emit_barrier ();
02261 break;
02262
02263 case NOTE:
02264
02265
02266
02267
02268
02269
02270 if (NOTE_LINE_NUMBER (insn) != NOTE_INSN_DELETED
02271 && NOTE_LINE_NUMBER (insn) != NOTE_INSN_DELETED_LABEL
02272 && NOTE_LINE_NUMBER (insn) != NOTE_INSN_BASIC_BLOCK
02273 && ((NOTE_LINE_NUMBER (insn) != NOTE_INSN_LOOP_VTOP
02274 && NOTE_LINE_NUMBER (insn) != NOTE_INSN_LOOP_CONT)
02275 || (last_iteration && unroll_type != UNROLL_COMPLETELY)))
02276 copy = emit_note (NOTE_SOURCE_FILE (insn),
02277 NOTE_LINE_NUMBER (insn));
02278 else
02279 copy = 0;
02280 break;
02281
02282 default:
02283 abort ();
02284 }
02285
02286 map->insn_map[INSN_UID (insn)] = copy;
02287 }
02288 while (insn != copy_end);
02289
02290
02291 insn = copy_start;
02292 do
02293 {
02294 insn = NEXT_INSN (insn);
02295 if ((GET_CODE (insn) == INSN || GET_CODE (insn) == JUMP_INSN
02296 || GET_CODE (insn) == CALL_INSN)
02297 && map->insn_map[INSN_UID (insn)])
02298 final_reg_note_copy (®_NOTES (map->insn_map[INSN_UID (insn)]), map);
02299 }
02300 while (insn != copy_end);
02301
02302
02303
02304
02305
02306
02307
02308
02309
02310
02311
02312 if (! last_iteration)
02313 {
02314 for (insn = copy_notes_from; insn != loop_end; insn = NEXT_INSN (insn))
02315 {
02316
02317
02318
02319
02320
02321
02322 if (GET_CODE (insn) == NOTE
02323 && NOTE_LINE_NUMBER (insn) != NOTE_INSN_DELETED
02324 && NOTE_LINE_NUMBER (insn) != NOTE_INSN_BASIC_BLOCK
02325 && NOTE_LINE_NUMBER (insn) != NOTE_INSN_LOOP_VTOP
02326 && NOTE_LINE_NUMBER (insn) != NOTE_INSN_LOOP_CONT)
02327 emit_note (NOTE_SOURCE_FILE (insn), NOTE_LINE_NUMBER (insn));
02328 }
02329 }
02330
02331 if (final_label && LABEL_NUSES (final_label) > 0)
02332 emit_label (final_label);
02333
02334 tem = get_insns ();
02335 end_sequence ();
02336 loop_insn_emit_before (loop, 0, insert_before, tem);
02337 }
02338
02339
02340
02341
02342
02343 void
02344 emit_unrolled_add (dest_reg, src_reg, increment)
02345 rtx dest_reg, src_reg, increment;
02346 {
02347 rtx result;
02348
02349 result = expand_simple_binop (GET_MODE (dest_reg), PLUS, src_reg, increment,
02350 dest_reg, 0, OPTAB_LIB_WIDEN);
02351
02352 if (dest_reg != result)
02353 emit_move_insn (dest_reg, result);
02354 }
02355
02356
02357
02358
02359
02360
02361
02362
02363
02364 int
02365 back_branch_in_range_p (loop, insn)
02366 const struct loop *loop;
02367 rtx insn;
02368 {
02369 rtx p, q, target_insn;
02370 rtx loop_start = loop->start;
02371 rtx loop_end = loop->end;
02372 rtx orig_loop_end = loop->end;
02373
02374
02375 loop_end = prev_nonnote_insn (loop_end);
02376 if (GET_CODE (loop_end) == BARRIER)
02377 loop_end = PREV_INSN (loop_end);
02378
02379
02380
02381 while (INSN_DELETED_P (insn))
02382 insn = NEXT_INSN (insn);
02383
02384
02385
02386
02387 if (insn == loop_end || insn == orig_loop_end)
02388 return 0;
02389
02390 for (p = NEXT_INSN (insn); p != loop_end; p = NEXT_INSN (p))
02391 {
02392 if (GET_CODE (p) == JUMP_INSN)
02393 {
02394 target_insn = JUMP_LABEL (p);
02395
02396
02397
02398
02399 for (q = loop_start; q != insn; q = NEXT_INSN (q))
02400 if (q == target_insn)
02401 return 1;
02402 }
02403 }
02404
02405 return 0;
02406 }
02407
02408
02409
02410
02411
02412 static rtx
02413 fold_rtx_mult_add (mult1, mult2, add1, mode)
02414 rtx mult1, mult2, add1;
02415 enum machine_mode mode;
02416 {
02417 rtx temp, mult_res;
02418 rtx result;
02419
02420
02421
02422 if ((GET_MODE (mult1) != mode && GET_MODE (mult1) != VOIDmode)
02423 || (GET_MODE (mult2) != mode && GET_MODE (mult2) != VOIDmode)
02424 || (GET_MODE (add1) != mode && GET_MODE (add1) != VOIDmode))
02425 abort ();
02426
02427
02428
02429 if (GET_CODE (mult1) == CONST_INT)
02430 {
02431 temp = mult2;
02432 mult2 = mult1;
02433 mult1 = temp;
02434 }
02435
02436 mult_res = simplify_binary_operation (MULT, mode, mult1, mult2);
02437 if (! mult_res)
02438 mult_res = gen_rtx_MULT (mode, mult1, mult2);
02439
02440
02441 if (GET_CODE (add1) == CONST_INT)
02442 {
02443 temp = add1;
02444 add1 = mult_res;
02445 mult_res = temp;
02446 }
02447
02448 result = simplify_binary_operation (PLUS, mode, add1, mult_res);
02449 if (! result)
02450 result = gen_rtx_PLUS (mode, add1, mult_res);
02451
02452 return result;
02453 }
02454
02455
02456
02457
02458
02459
02460
02461 rtx
02462 biv_total_increment (bl)
02463 const struct iv_class *bl;
02464 {
02465 struct induction *v;
02466 rtx result;
02467
02468
02469
02470
02471
02472
02473
02474
02475 result = const0_rtx;
02476 for (v = bl->biv; v; v = v->next_iv)
02477 {
02478 if (v->always_computable && v->mult_val == const1_rtx
02479 && ! v->maybe_multiple
02480 && SCALAR_INT_MODE_P (v->mode))
02481 result = fold_rtx_mult_add (result, const1_rtx, v->add_val, v->mode);
02482 else
02483 return 0;
02484 }
02485
02486 return result;
02487 }
02488
02489
02490
02491
02492
02493
02494
02495
02496
02497
02498
02499
02500
02501
02502
02503
02504
02505
02506
02507
02508
02509
02510
02511
02512
02513 static int
02514 find_splittable_regs (loop, unroll_type, unroll_number)
02515 const struct loop *loop;
02516 enum unroll_types unroll_type;
02517 int unroll_number;
02518 {
02519 struct loop_ivs *ivs = LOOP_IVS (loop);
02520 struct iv_class *bl;
02521 struct induction *v;
02522 rtx increment, tem;
02523 rtx biv_final_value;
02524 int biv_splittable;
02525 int result = 0;
02526
02527 for (bl = ivs->list; bl; bl = bl->next)
02528 {
02529
02530
02531
02532 increment = biv_total_increment (bl);
02533 if (! increment || GET_CODE (increment) != CONST_INT)
02534 continue;
02535
02536
02537
02538
02539
02540
02541
02542
02543
02544
02545 biv_splittable = 1;
02546 biv_final_value = 0;
02547 if (unroll_type != UNROLL_COMPLETELY
02548 && (loop->exit_count || unroll_type == UNROLL_NAIVE)
02549 && (REGNO_LAST_LUID (bl->regno) >= INSN_LUID (loop->end)
02550 || ! bl->init_insn
02551 || INSN_UID (bl->init_insn) >= max_uid_for_loop
02552 || (REGNO_FIRST_LUID (bl->regno)
02553 < INSN_LUID (bl->init_insn))
02554 || reg_mentioned_p (bl->biv->dest_reg, SET_SRC (bl->init_set)))
02555 && ! (biv_final_value = final_biv_value (loop, bl)))
02556 biv_splittable = 0;
02557
02558
02559
02560 for (v = bl->biv; biv_splittable && v; v = v->next_iv)
02561 if ((tem = single_set (v->insn)) == 0
02562 || GET_CODE (SET_DEST (tem)) != REG
02563 || REGNO (SET_DEST (tem)) != bl->regno
02564 || GET_CODE (SET_SRC (tem)) != PLUS)
02565 biv_splittable = 0;
02566
02567
02568
02569
02570
02571
02572
02573
02574
02575 if (biv_splittable == 1)
02576 {
02577 if (unroll_type == UNROLL_COMPLETELY)
02578 {
02579
02580
02581
02582
02583
02584 if (GET_CODE (bl->initial_value) == REG
02585 && (REGNO (bl->initial_value) == bl->regno
02586 || REGNO (bl->initial_value) < FIRST_PSEUDO_REGISTER
02587 || ! loop_invariant_p (loop, bl->initial_value)))
02588 {
02589 rtx tem = gen_reg_rtx (bl->biv->mode);
02590
02591 record_base_value (REGNO (tem), bl->biv->add_val, 0);
02592 loop_insn_hoist (loop,
02593 gen_move_insn (tem, bl->biv->src_reg));
02594
02595 if (loop_dump_stream)
02596 fprintf (loop_dump_stream,
02597 "Biv %d initial value remapped to %d.\n",
02598 bl->regno, REGNO (tem));
02599
02600 splittable_regs[bl->regno] = tem;
02601 }
02602 else
02603 splittable_regs[bl->regno] = bl->initial_value;
02604 }
02605 else
02606 splittable_regs[bl->regno] = const0_rtx;
02607
02608
02609
02610
02611 splittable_regs_updates[bl->regno] = bl->biv_count;
02612 result += bl->biv_count;
02613
02614 if (loop_dump_stream)
02615 fprintf (loop_dump_stream,
02616 "Biv %d safe to split.\n", bl->regno);
02617 }
02618
02619
02620
02621
02622
02623
02624 result += find_splittable_givs (loop, bl, unroll_type, increment,
02625 unroll_number);
02626
02627
02628
02629
02630
02631 if (biv_final_value)
02632 {
02633
02634
02635
02636
02637 if (! loop->exit_count)
02638 loop_insn_sink (loop, gen_move_insn (bl->biv->src_reg,
02639 biv_final_value));
02640 else
02641 {
02642
02643
02644
02645
02646
02647 rtx tem = gen_reg_rtx (bl->biv->mode);
02648 record_base_value (REGNO (tem), bl->biv->add_val, 0);
02649
02650 loop_insn_hoist (loop, gen_move_insn (tem, bl->biv->src_reg));
02651 loop_insn_hoist (loop, gen_move_insn (bl->biv->src_reg,
02652 biv_final_value));
02653
02654 if (loop_dump_stream)
02655 fprintf (loop_dump_stream, "Biv %d mapped to %d for split.\n",
02656 REGNO (bl->biv->src_reg), REGNO (tem));
02657
02658
02659
02660 bl->biv->src_reg = tem;
02661 }
02662 }
02663 }
02664 return result;
02665 }
02666
02667
02668
02669
02670
02671
02672 static int
02673 find_splittable_givs (loop, bl, unroll_type, increment, unroll_number)
02674 const struct loop *loop;
02675 struct iv_class *bl;
02676 enum unroll_types unroll_type;
02677 rtx increment;
02678 int unroll_number ATTRIBUTE_UNUSED;
02679 {
02680 struct loop_ivs *ivs = LOOP_IVS (loop);
02681 struct induction *v, *v2;
02682 rtx final_value;
02683 rtx tem;
02684 int result = 0;
02685
02686
02687
02688 for (v = bl->giv; v; v = v->next_iv)
02689 for (v2 = v->next_iv; v2; v2 = v2->next_iv)
02690 if (v->insn == v2->insn && rtx_equal_p (v->new_reg, v2->new_reg)
02691 && ! v2->same_insn)
02692 v2->same_insn = v;
02693
02694 for (v = bl->giv; v; v = v->next_iv)
02695 {
02696 rtx giv_inc, value;
02697
02698
02699
02700 if (unroll_type != UNROLL_COMPLETELY && v->ignore)
02701 continue;
02702
02703
02704
02705
02706
02707
02708
02709 if (v->giv_type != DEST_ADDR
02710 && (! v->always_computable
02711 || back_branch_in_range_p (loop, v->insn)))
02712 continue;
02713
02714
02715 giv_inc = fold_rtx_mult_add (v->mult_val, increment, const0_rtx,
02716 v->mode);
02717 if (! giv_inc || GET_CODE (giv_inc) != CONST_INT)
02718 continue;
02719
02720
02721
02722
02723
02724
02725
02726
02727
02728
02729
02730 final_value = 0;
02731 if (unroll_type != UNROLL_COMPLETELY
02732 && (loop->exit_count || unroll_type == UNROLL_NAIVE)
02733 && v->giv_type != DEST_ADDR
02734
02735
02736
02737 && (REGNO (v->dest_reg) >= max_reg_before_loop
02738 || (REGNO_FIRST_UID (REGNO (v->dest_reg)) != INSN_UID (v->insn)
02739
02740
02741
02742 && (! (tem = find_reg_note (v->insn, REG_RETVAL, NULL_RTX))
02743 || (REGNO_FIRST_UID (REGNO (v->dest_reg))
02744 != INSN_UID (XEXP (tem, 0)))))
02745
02746 || (REGNO_LAST_LUID (REGNO (v->dest_reg))
02747 >= INSN_LUID (loop->end)))
02748 && ! (final_value = v->final_value))
02749 continue;
02750
02751 #if 0
02752
02753
02754
02755
02756
02757
02758 if (final_value && !v->new_reg)
02759 {
02760
02761
02762
02763
02764 tem = gen_reg_rtx (v->mode);
02765 loop_insn_hoist (loop, gen_move_insn (tem, v->dest_reg));
02766 loop_insn_hoist (loop, gen_move_insn (v->dest_reg, final_value));
02767
02768 if (loop_dump_stream)
02769 fprintf (loop_dump_stream, "Giv %d mapped to %d for split.\n",
02770 REGNO (v->dest_reg), REGNO (tem));
02771
02772 v->src_reg = tem;
02773 }
02774 #endif
02775
02776
02777
02778
02779 if (unroll_type == UNROLL_COMPLETELY)
02780 {
02781
02782
02783
02784
02785
02786 rtx biv_initial_value;
02787
02788 if (splittable_regs[bl->regno])
02789 biv_initial_value = splittable_regs[bl->regno];
02790 else if (GET_CODE (bl->initial_value) != REG
02791 || (REGNO (bl->initial_value) != bl->regno
02792 && REGNO (bl->initial_value) >= FIRST_PSEUDO_REGISTER))
02793 biv_initial_value = bl->initial_value;
02794 else
02795 {
02796 rtx tem = gen_reg_rtx (bl->biv->mode);
02797
02798 record_base_value (REGNO (tem), bl->biv->add_val, 0);
02799 loop_insn_hoist (loop, gen_move_insn (tem, bl->biv->src_reg));
02800 biv_initial_value = tem;
02801 }
02802 biv_initial_value = extend_value_for_giv (v, biv_initial_value);
02803 value = fold_rtx_mult_add (v->mult_val, biv_initial_value,
02804 v->add_val, v->mode);
02805 }
02806 else
02807 value = const0_rtx;
02808
02809 if (v->new_reg)
02810 {
02811
02812
02813
02814
02815 if (v->same && ! v->same->new_reg)
02816 {
02817 if (loop_dump_stream)
02818 fprintf (loop_dump_stream,
02819 "giv combined with unreduced giv not split.\n");
02820 continue;
02821 }
02822
02823
02824 else if (v->giv_type == DEST_REG)
02825 {
02826
02827
02828
02829
02830
02831
02832 if (unroll_type == UNROLL_COMPLETELY
02833 && GET_CODE (value) != CONST_INT
02834 && GET_CODE (value) != REG
02835 && (GET_CODE (value) != PLUS
02836 || GET_CODE (XEXP (value, 0)) != REG
02837 || GET_CODE (XEXP (value, 1)) != CONST_INT))
02838 {
02839 rtx tem = gen_reg_rtx (v->mode);
02840 record_base_value (REGNO (tem), v->add_val, 0);
02841 loop_iv_add_mult_hoist (loop, bl->initial_value, v->mult_val,
02842 v->add_val, tem);
02843 value = tem;
02844 }
02845
02846 splittable_regs[reg_or_subregno (v->new_reg)] = value;
02847 }
02848 else
02849 continue;
02850 }
02851 else
02852 {
02853 #if 0
02854
02855
02856
02857
02858
02859
02860
02861 splittable_regs[REGNO (v->dest_reg)] = value;
02862 fprintf (stderr, "Giv %d at insn %d not reduced\n",
02863 REGNO (v->dest_reg), INSN_UID (v->insn));
02864 #else
02865 continue;
02866 #endif
02867 }
02868
02869
02870
02871
02872
02873
02874 if (GET_CODE (v->new_reg) == REG)
02875 {
02876 int count = 1;
02877 if (! v->ignore)
02878 count = REG_IV_CLASS (ivs, REGNO (v->src_reg))->biv_count;
02879
02880 splittable_regs_updates[reg_or_subregno (v->new_reg)] = count;
02881 }
02882
02883 result++;
02884
02885 if (loop_dump_stream)
02886 {
02887 int regnum;
02888
02889 if (GET_CODE (v->dest_reg) == CONST_INT)
02890 regnum = -1;
02891 else if (GET_CODE (v->dest_reg) != REG)
02892 regnum = REGNO (XEXP (v->dest_reg, 0));
02893 else
02894 regnum = REGNO (v->dest_reg);
02895 fprintf (loop_dump_stream, "Giv %d at insn %d safe to split.\n",
02896 regnum, INSN_UID (v->insn));
02897 }
02898 }
02899
02900 return result;
02901 }
02902
02903
02904
02905
02906
02907
02908
02909
02910
02911 static int
02912 reg_dead_after_loop (loop, reg)
02913 const struct loop *loop;
02914 rtx reg;
02915 {
02916 rtx insn, label;
02917 enum rtx_code code;
02918 int jump_count = 0;
02919 int label_count = 0;
02920
02921
02922
02923
02924
02925
02926 for (label = loop->exit_labels; label; label = LABEL_NEXTREF (label))
02927 label_count++;
02928
02929 if (label_count != loop->exit_count)
02930 return 0;
02931
02932
02933
02934
02935 label = gen_rtx_LABEL_REF (VOIDmode, loop->end);
02936 LABEL_NEXTREF (label) = loop->exit_labels;
02937
02938 for (; label; label = LABEL_NEXTREF (label))
02939 {
02940
02941
02942
02943
02944 insn = NEXT_INSN (XEXP (label, 0));
02945 while (insn)
02946 {
02947 code = GET_CODE (insn);
02948 if (GET_RTX_CLASS (code) == 'i')
02949 {
02950 rtx set, note;
02951
02952 if (reg_referenced_p (reg, PATTERN (insn)))
02953 return 0;
02954
02955 note = find_reg_equal_equiv_note (insn);
02956 if (note && reg_overlap_mentioned_p (reg, XEXP (note, 0)))
02957 return 0;
02958
02959 set = single_set (insn);
02960 if (set && rtx_equal_p (SET_DEST (set), reg))
02961 break;
02962 }
02963
02964 if (code == JUMP_INSN)
02965 {
02966 if (GET_CODE (PATTERN (insn)) == RETURN)
02967 break;
02968 else if (!any_uncondjump_p (insn)
02969
02970 || jump_count++ > 20)
02971 return 0;
02972 else
02973 insn = JUMP_LABEL (insn);
02974 }
02975
02976 insn = NEXT_INSN (insn);
02977 }
02978 }
02979
02980
02981 return 1;
02982 }
02983
02984
02985
02986
02987 rtx
02988 final_biv_value (loop, bl)
02989 const struct loop *loop;
02990 struct iv_class *bl;
02991 {
02992 unsigned HOST_WIDE_INT n_iterations = LOOP_INFO (loop)->n_iterations;
02993 rtx increment, tem;
02994
02995
02996
02997 if (GET_MODE_CLASS (bl->biv->mode) != MODE_INT)
02998 return 0;
02999
03000
03001
03002
03003
03004 if (bl->reversed)
03005 {
03006 if (loop_dump_stream)
03007 fprintf (loop_dump_stream,
03008 "Final biv value for %d, reversed biv.\n", bl->regno);
03009
03010 return const0_rtx;
03011 }
03012
03013
03014
03015
03016
03017
03018
03019 if (n_iterations != 0
03020 && ! loop->exit_count
03021 && loop_invariant_p (loop, bl->initial_value))
03022 {
03023 increment = biv_total_increment (bl);
03024
03025 if (increment && loop_invariant_p (loop, increment))
03026 {
03027
03028
03029
03030
03031 tem = gen_reg_rtx (bl->biv->mode);
03032 record_base_value (REGNO (tem), bl->biv->add_val, 0);
03033 loop_iv_add_mult_sink (loop, increment, GEN_INT (n_iterations),
03034 bl->initial_value, tem);
03035
03036 if (loop_dump_stream)
03037 fprintf (loop_dump_stream,
03038 "Final biv value for %d, calculated.\n", bl->regno);
03039
03040 return tem;
03041 }
03042 }
03043
03044
03045 if (reg_dead_after_loop (loop, bl->biv->src_reg))
03046 {
03047 if (loop_dump_stream)
03048 fprintf (loop_dump_stream,
03049 "Final biv value for %d, biv dead after loop exit.\n",
03050 bl->regno);
03051
03052 return const0_rtx;
03053 }
03054
03055 return 0;
03056 }
03057
03058
03059
03060
03061 rtx
03062 final_giv_value (loop, v)
03063 const struct loop *loop;
03064 struct induction *v;
03065 {
03066 struct loop_ivs *ivs = LOOP_IVS (loop);
03067 struct iv_class *bl;
03068 rtx insn;
03069 rtx increment, tem;
03070 rtx seq;
03071 rtx loop_end = loop->end;
03072 unsigned HOST_WIDE_INT n_iterations = LOOP_INFO (loop)->n_iterations;
03073
03074 bl = REG_IV_CLASS (ivs, REGNO (v->src_reg));
03075
03076
03077
03078
03079
03080 if (bl->reversed)
03081 {
03082 if (loop_dump_stream)
03083 fprintf (loop_dump_stream,
03084 "Final giv value for %d, depends on reversed biv\n",
03085 REGNO (v->dest_reg));
03086 return const0_rtx;
03087 }
03088
03089
03090
03091
03092
03093
03094
03095
03096
03097
03098
03099 if (n_iterations != 0
03100 && ! loop->exit_count
03101 && v->always_executed)
03102 {
03103
03104
03105
03106
03107
03108
03109
03110
03111
03112
03113
03114 increment = biv_total_increment (bl);
03115
03116 if (increment && loop_invariant_p (loop, increment)
03117 && loop_invariant_p (loop, bl->initial_value))
03118 {
03119
03120
03121
03122
03123
03124
03125
03126
03127
03128
03129
03130 tem = gen_reg_rtx (v->mode);
03131 record_base_value (REGNO (tem), bl->biv->add_val, 0);
03132 loop_iv_add_mult_sink (loop, extend_value_for_giv (v, increment),
03133 GEN_INT (n_iterations),
03134 extend_value_for_giv (v, bl->initial_value),
03135 tem);
03136
03137
03138 for (insn = NEXT_INSN (v->insn); insn != loop_end;
03139 insn = NEXT_INSN (insn))
03140 {
03141 struct induction *biv;
03142
03143 for (biv = bl->biv; biv; biv = biv->next_iv)
03144 if (biv->insn == insn)
03145 {
03146 start_sequence ();
03147 tem = expand_simple_binop (GET_MODE (tem), MINUS, tem,
03148 biv->add_val, NULL_RTX, 0,
03149 OPTAB_LIB_WIDEN);
03150 seq = get_insns ();
03151 end_sequence ();
03152 loop_insn_sink (loop, seq);
03153 }
03154 }
03155
03156
03157 loop_iv_add_mult_sink (loop, tem, v->mult_val, v->add_val, tem);
03158
03159 if (loop_dump_stream)
03160 fprintf (loop_dump_stream,
03161 "Final giv value for %d, calc from biv's value.\n",
03162 REGNO (v->dest_reg));
03163
03164 return tem;
03165 }
03166 }
03167
03168
03169 if (v->replaceable)
03170 abort ();
03171
03172
03173 if (reg_dead_after_loop (loop, v->dest_reg))
03174 {
03175 if (loop_dump_stream)
03176 fprintf (loop_dump_stream,
03177 "Final giv value for %d, giv dead after loop exit.\n",
03178 REGNO (v->dest_reg));
03179
03180 return const0_rtx;
03181 }
03182
03183 return 0;
03184 }
03185
03186
03187
03188
03189
03190 static rtx
03191 loop_find_equiv_value (loop, reg)
03192 const struct loop *loop;
03193 rtx reg;
03194 {
03195 rtx loop_start = loop->start;
03196 rtx insn, set;
03197 rtx ret;
03198
03199 ret = reg;
03200 for (insn = PREV_INSN (loop_start); insn; insn = PREV_INSN (insn))
03201 {
03202 if (GET_CODE (insn) == CODE_LABEL)
03203 break;
03204
03205 else if (INSN_P (insn) && reg_set_p (reg, insn))
03206 {
03207
03208
03209
03210 if ((set = single_set (insn))
03211 && (SET_DEST (set) == reg))
03212 {
03213 rtx note = find_reg_note (insn, REG_EQUAL, NULL_RTX);
03214
03215
03216
03217
03218 if (note && GET_CODE (XEXP (note, 0)) != EXPR_LIST
03219 && CONSTANT_P (XEXP (note, 0)))
03220 ret = XEXP (note, 0);
03221 else
03222 ret = SET_SRC (set);
03223
03224
03225
03226 if (modified_between_p (ret, insn, loop_start))
03227 ret = reg;
03228 }
03229 break;
03230 }
03231 }
03232 return ret;
03233 }
03234
03235
03236
03237
03238
03239
03240
03241
03242
03243
03244
03245 static rtx
03246 subtract_reg_term (op, reg)
03247 rtx op, reg;
03248 {
03249 if (op == reg)
03250 return const0_rtx;
03251 if (GET_CODE (op) == PLUS)
03252 {
03253 if (XEXP (op, 0) == reg)
03254 return XEXP (op, 1);
03255 else if (XEXP (op, 1) == reg)
03256 return XEXP (op, 0);
03257 }
03258
03259 abort ();
03260 }
03261
03262
03263
03264
03265
03266 static rtx
03267 find_common_reg_term (op0, op1)
03268 rtx op0, op1;
03269 {
03270 if ((GET_CODE (op0) == REG || GET_CODE (op0) == PLUS)
03271 && (GET_CODE (op1) == REG || GET_CODE (op1) == PLUS))
03272 {
03273 rtx op00;
03274 rtx op01;
03275 rtx op10;
03276 rtx op11;
03277
03278 if (GET_CODE (op0) == PLUS)
03279 op01 = XEXP (op0, 1), op00 = XEXP (op0, 0);
03280 else
03281 op01 = const0_rtx, op00 = op0;
03282
03283 if (GET_CODE (op1) == PLUS)
03284 op11 = XEXP (op1, 1), op10 = XEXP (op1, 0);
03285 else
03286 op11 = const0_rtx, op10 = op1;
03287
03288
03289 if (REG_P (op00) && (op00 == op10 || op00 == op11))
03290 return op00;
03291 else if (REG_P (op01) && (op01 == op10 || op01 == op11))
03292 return op01;
03293 }
03294
03295
03296 return NULL_RTX;
03297 }
03298
03299
03300
03301
03302
03303 unsigned HOST_WIDE_INT
03304 loop_iterations (loop)
03305 struct loop *loop;
03306 {
03307 struct loop_info *loop_info = LOOP_INFO (loop);
03308 struct loop_ivs *ivs = LOOP_IVS (loop);
03309 rtx comparison, comparison_value;
03310 rtx iteration_var, initial_value, increment, final_value;
03311 enum rtx_code comparison_code;
03312 HOST_WIDE_INT inc;
03313 unsigned HOST_WIDE_INT abs_inc;
03314 unsigned HOST_WIDE_INT abs_diff;
03315 int off_by_one;
03316 int increment_dir;
03317 int unsigned_p, compare_dir, final_larger;
03318 rtx last_loop_insn;
03319 rtx reg_term;
03320 struct iv_class *bl;
03321
03322 loop_info->n_iterations = 0;
03323 loop_info->initial_value = 0;
03324 loop_info->initial_equiv_value = 0;
03325 loop_info->comparison_value = 0;
03326 loop_info->final_value = 0;
03327 loop_info->final_equiv_value = 0;
03328 loop_info->increment = 0;
03329 loop_info->iteration_var = 0;
03330 loop_info->unroll_number = 1;
03331 loop_info->iv = 0;
03332
03333
03334
03335
03336
03337 last_loop_insn = PREV_INSN (loop->end);
03338
03339
03340
03341
03342 if (GET_CODE (last_loop_insn) != JUMP_INSN)
03343 {
03344 if (loop_dump_stream)
03345 fprintf (loop_dump_stream,
03346 "Loop iterations: No final conditional branch found.\n");
03347 return 0;
03348 }
03349
03350
03351
03352 if (LABEL_NUSES (JUMP_LABEL (last_loop_insn)) > 1)
03353 {
03354 if (loop_dump_stream)
03355 fprintf (loop_dump_stream,
03356 "Loop iterations: Loop has multiple back edges.\n");
03357 return 0;
03358 }
03359
03360
03361
03362 if (loop->top && loop->cont)
03363 {
03364 rtx temp = PREV_INSN (last_loop_insn);
03365
03366 do
03367 {
03368 if (GET_CODE (temp) == JUMP_INSN)
03369 {
03370
03371 if (JUMP_LABEL (temp) == 0)
03372 {
03373 if (loop_dump_stream)
03374 fprintf
03375 (loop_dump_stream,
03376 "Loop iterations: Jump insn has null JUMP_LABEL.\n");
03377 return 0;
03378 }
03379
03380 if (
03381
03382 INSN_UID (JUMP_LABEL (temp)) < max_uid_for_loop
03383
03384 && INSN_LUID (JUMP_LABEL (temp)) > INSN_LUID (loop->top)
03385 && INSN_LUID (JUMP_LABEL (temp)) < INSN_LUID (loop->cont))
03386 {
03387 if (loop_dump_stream)
03388 fprintf
03389 (loop_dump_stream,
03390 "Loop iterations: Loop has multiple back edges.\n");
03391 return 0;
03392 }
03393 }
03394 }
03395 while ((temp = PREV_INSN (temp)) != loop->cont);
03396 }
03397
03398
03399
03400
03401
03402 comparison = get_condition_for_loop (loop, last_loop_insn);
03403 if (comparison == 0)
03404 {
03405 if (loop_dump_stream)
03406 fprintf (loop_dump_stream,
03407 "Loop iterations: No final comparison found.\n");
03408 return 0;
03409 }
03410
03411
03412
03413
03414 comparison_code = GET_CODE (comparison);
03415 iteration_var = XEXP (comparison, 0);
03416 comparison_value = XEXP (comparison, 1);
03417
03418 if (GET_CODE (iteration_var) != REG)
03419 {
03420 if (loop_dump_stream)
03421 fprintf (loop_dump_stream,
03422 "Loop iterations: Comparison not against register.\n");
03423 return 0;
03424 }
03425
03426
03427
03428
03429
03430
03431
03432 if ((unsigned) REGNO (iteration_var) >= ivs->n_regs
03433 && ! REG_USERVAR_P (iteration_var))
03434 abort ();
03435
03436
03437
03438
03439
03440
03441 initial_value = 0;
03442 increment = 0;
03443
03444
03445
03446
03447
03448
03449
03450 if ((unsigned) REGNO (iteration_var) >= ivs->n_regs)
03451 {
03452 if (loop_dump_stream)
03453 fprintf (loop_dump_stream,
03454 "Loop iterations: No reg_iv_type entry for iteration var.\n");
03455 return 0;
03456 }
03457
03458
03459
03460
03461 else if ((GET_MODE_BITSIZE (GET_MODE (iteration_var))
03462 > HOST_BITS_PER_WIDE_INT))
03463 {
03464 if (loop_dump_stream)
03465 fprintf (loop_dump_stream,
03466 "Loop iterations: Iteration var rejected because mode too large.\n");
03467 return 0;
03468 }
03469 else if (GET_MODE_CLASS (GET_MODE (iteration_var)) != MODE_INT)
03470 {
03471 if (loop_dump_stream)
03472 fprintf (loop_dump_stream,
03473 "Loop iterations: Iteration var not an integer.\n");
03474 return 0;
03475 }
03476 else if (REG_IV_TYPE (ivs, REGNO (iteration_var)) == BASIC_INDUCT)
03477 {
03478 if (REGNO (iteration_var) >= ivs->n_regs)
03479 abort ();
03480
03481
03482 bl = REG_IV_CLASS (ivs, REGNO (iteration_var));
03483 initial_value = bl->initial_value;
03484 if (!bl->biv->always_executed || bl->biv->maybe_multiple)
03485 {
03486 if (loop_dump_stream)
03487 fprintf (loop_dump_stream,
03488 "Loop iterations: Basic induction var not set once in each iteration.\n");
03489 return 0;
03490 }
03491
03492 increment = biv_total_increment (bl);
03493 }
03494 else if (REG_IV_TYPE (ivs, REGNO (iteration_var)) == GENERAL_INDUCT)
03495 {
03496 HOST_WIDE_INT offset = 0;
03497 struct induction *v = REG_IV_INFO (ivs, REGNO (iteration_var));
03498 rtx biv_initial_value;
03499
03500 if (REGNO (v->src_reg) >= ivs->n_regs)
03501 abort ();
03502
03503 if (!v->always_executed || v->maybe_multiple)
03504 {
03505 if (loop_dump_stream)
03506 fprintf (loop_dump_stream,
03507 "Loop iterations: General induction var not set once in each iteration.\n");
03508 return 0;
03509 }
03510
03511 bl = REG_IV_CLASS (ivs, REGNO (v->src_reg));
03512
03513
03514
03515 increment = biv_total_increment (bl);
03516 if (increment)
03517 {
03518 struct induction *biv_inc;
03519
03520 increment = fold_rtx_mult_add (v->mult_val,
03521 extend_value_for_giv (v, increment),
03522 const0_rtx, v->mode);
03523
03524
03525
03526
03527
03528
03529 for (biv_inc = bl->biv; biv_inc; biv_inc = biv_inc->next_iv)
03530 {
03531 if (loop_insn_first_p (v->insn, biv_inc->insn))
03532 {
03533 if (REG_P (biv_inc->add_val))
03534 {
03535 if (loop_dump_stream)
03536 fprintf (loop_dump_stream,
03537 "Loop iterations: Basic induction var add_val is REG %d.\n",
03538 REGNO (biv_inc->add_val));
03539 return 0;
03540 }
03541
03542 offset -= INTVAL (biv_inc->add_val);
03543 }
03544 }
03545 }
03546 if (loop_dump_stream)
03547 fprintf (loop_dump_stream,
03548 "Loop iterations: Giv iterator, initial value bias %ld.\n",
03549 (long) offset);
03550
03551
03552
03553 biv_initial_value = extend_value_for_giv (v, bl->initial_value);
03554 initial_value
03555 = fold_rtx_mult_add (v->mult_val,
03556 plus_constant (biv_initial_value, offset),
03557 v->add_val, v->mode);
03558 }
03559 else
03560 {
03561 if (loop_dump_stream)
03562 fprintf (loop_dump_stream,
03563 "Loop iterations: Not basic or general induction var.\n");
03564 return 0;
03565 }
03566
03567 if (initial_value == 0)
03568 return 0;
03569
03570 unsigned_p = 0;
03571 off_by_one = 0;
03572 switch (comparison_code)
03573 {
03574 case LEU:
03575 unsigned_p = 1;
03576 case LE:
03577 compare_dir = 1;
03578 off_by_one = 1;
03579 break;
03580 case GEU:
03581 unsigned_p = 1;
03582 case GE:
03583 compare_dir = -1;
03584 off_by_one = -1;
03585 break;
03586 case EQ:
03587
03588 compare_dir = 0;
03589 break;
03590 case LTU:
03591 unsigned_p = 1;
03592 case LT:
03593 compare_dir = 1;
03594 break;
03595 case GTU:
03596 unsigned_p = 1;
03597 case GT:
03598 compare_dir = -1;
03599 case NE:
03600 compare_dir = 0;
03601 break;
03602 default:
03603 abort ();
03604 }
03605
03606
03607
03608
03609 final_value = comparison_value;
03610 if (GET_CODE (comparison_value) == REG
03611 && loop_invariant_p (loop, comparison_value))
03612 {
03613 final_value = loop_find_equiv_value (loop, comparison_value);
03614
03615
03616
03617 if (! loop_invariant_p (loop, final_value))
03618 final_value = comparison_value;
03619 }
03620
03621
03622
03623
03624
03625
03626
03627
03628
03629
03630 if (off_by_one)
03631 final_value = plus_constant (final_value, off_by_one);
03632
03633
03634
03635
03636
03637
03638
03639
03640
03641
03642 loop_info->initial_value = initial_value;
03643 loop_info->comparison_value = comparison_value;
03644 loop_info->final_value = plus_constant (comparison_value, off_by_one);
03645 loop_info->increment = increment;
03646 loop_info->iteration_var = iteration_var;
03647 loop_info->comparison_code = comparison_code;
03648 loop_info->iv = bl;
03649
03650
03651
03652
03653
03654
03655 if (REG_P (initial_value))
03656 {
03657 rtx reg1;
03658 rtx reg2;
03659 rtx const2;
03660
03661 reg1 = initial_value;
03662 if (GET_CODE (final_value) == PLUS)
03663 reg2 = XEXP (final_value, 0), const2 = XEXP (final_value, 1);
03664 else
03665 reg2 = final_value, const2 = const0_rtx;
03666
03667
03668
03669 if (REG_P (reg2) && reg2 != reg1)
03670 {
03671 rtx temp;
03672
03673
03674
03675 temp = loop_find_equiv_value (loop, reg1);
03676
03677 if (find_common_reg_term (temp, reg2))
03678 initial_value = temp;
03679 else if (loop_invariant_p (loop, reg2))
03680 {
03681
03682
03683
03684 temp = loop_find_equiv_value (loop, reg2);
03685
03686 if (temp == loop_info->iteration_var)
03687 temp = initial_value;
03688 if (temp == reg1)
03689 final_value = (const2 == const0_rtx)
03690 ? reg1 : gen_rtx_PLUS (GET_MODE (reg1), reg1, const2);
03691 }
03692 }
03693 else if (loop->vtop && GET_CODE (reg2) == CONST_INT)
03694 {
03695 rtx temp;
03696
03697
03698
03699
03700
03701
03702
03703
03704 temp = loop_find_equiv_value (loop, reg1);
03705
03706 if (GET_CODE (temp) == MINUS && REG_P (XEXP (temp, 0)))
03707 {
03708 rtx temp2 = loop_find_equiv_value (loop, XEXP (temp, 0));
03709
03710 if (GET_CODE (temp2) == PLUS
03711 && XEXP (temp2, 0) == XEXP (temp, 1))
03712 initial_value = XEXP (temp2, 1);
03713 }
03714 }
03715 }
03716
03717
03718
03719
03720
03721
03722
03723
03724
03725
03726 if (loop->vtop
03727 && (reg_term = find_common_reg_term (initial_value, final_value)))
03728 {
03729 initial_value = subtract_reg_term (initial_value, reg_term);
03730 final_value = subtract_reg_term (final_value, reg_term);
03731 }
03732
03733 loop_info->initial_equiv_value = initial_value;
03734 loop_info->final_equiv_value = final_value;
03735
03736
03737
03738
03739 if (comparison_code == EQ)
03740 loop_info->final_equiv_value = loop_info->final_value = 0;
03741
03742 if (increment == 0)
03743 {
03744 if (loop_dump_stream)
03745 fprintf (loop_dump_stream,
03746 "Loop iterations: Increment value can't be calculated.\n");
03747 return 0;
03748 }
03749
03750 if (GET_CODE (increment) != CONST_INT)
03751 {
03752
03753
03754
03755 if (GET_CODE (increment) == REG || GET_CODE (increment) == SUBREG)
03756 increment = loop_find_equiv_value (loop, increment);
03757
03758 if (GET_CODE (increment) != CONST_INT)
03759 {
03760 if (loop_dump_stream)
03761 {
03762 fprintf (loop_dump_stream,
03763 "Loop iterations: Increment value not constant ");
03764 print_simple_rtl (loop_dump_stream, increment);
03765 fprintf (loop_dump_stream, ".\n");
03766 }
03767 return 0;
03768 }
03769 loop_info->increment = increment;
03770 }
03771
03772 if (GET_CODE (initial_value) != CONST_INT)
03773 {
03774 if (loop_dump_stream)
03775 {
03776 fprintf (loop_dump_stream,
03777 "Loop iterations: Initial value not constant ");
03778 print_simple_rtl (loop_dump_stream, initial_value);
03779 fprintf (loop_dump_stream, ".\n");
03780 }
03781 return 0;
03782 }
03783 else if (GET_CODE (final_value) != CONST_INT)
03784 {
03785 if (loop_dump_stream)
03786 {
03787 fprintf (loop_dump_stream,
03788 "Loop iterations: Final value not constant ");
03789 print_simple_rtl (loop_dump_stream, final_value);
03790 fprintf (loop_dump_stream, ".\n");
03791 }
03792 return 0;
03793 }
03794 else if (comparison_code == EQ)
03795 {
03796 rtx inc_once;
03797
03798 if (loop_dump_stream)
03799 fprintf (loop_dump_stream, "Loop iterations: EQ comparison loop.\n");
03800
03801 inc_once = gen_int_mode (INTVAL (initial_value) + INTVAL (increment),
03802 GET_MODE (iteration_var));
03803
03804 if (inc_once == final_value)
03805 {
03806
03807
03808
03809 if (increment == const0_rtx)
03810 return 0;
03811 loop_info->n_iterations = 2;
03812 }
03813 else
03814 loop_info->n_iterations = 1;
03815
03816 if (GET_CODE (loop_info->initial_value) == CONST_INT)
03817 loop_info->final_value
03818 = gen_int_mode ((INTVAL (loop_info->initial_value)
03819 + loop_info->n_iterations * INTVAL (increment)),
03820 GET_MODE (iteration_var));
03821 else
03822 loop_info->final_value
03823 = plus_constant (loop_info->initial_value,
03824 loop_info->n_iterations * INTVAL (increment));
03825 loop_info->final_equiv_value
03826 = gen_int_mode ((INTVAL (initial_value)
03827 + loop_info->n_iterations * INTVAL (increment)),
03828 GET_MODE (iteration_var));
03829 return loop_info->n_iterations;
03830 }
03831
03832
03833 if (unsigned_p)
03834 final_larger
03835 = ((unsigned HOST_WIDE_INT) INTVAL (final_value)
03836 > (unsigned HOST_WIDE_INT) INTVAL (initial_value))
03837 - ((unsigned HOST_WIDE_INT) INTVAL (final_value)
03838 < (unsigned HOST_WIDE_INT) INTVAL (initial_value));
03839 else
03840 final_larger = (INTVAL (final_value) > INTVAL (initial_value))
03841 - (INTVAL (final_value) < INTVAL (initial_value));
03842
03843 if (INTVAL (increment) > 0)
03844 increment_dir = 1;
03845 else if (INTVAL (increment) == 0)
03846 increment_dir = 0;
03847 else
03848 increment_dir = -1;
03849
03850
03851
03852
03853
03854
03855
03856
03857
03858
03859
03860
03861
03862
03863
03864
03865
03866
03867
03868
03869
03870
03871
03872
03873
03874
03875
03876
03877 if (final_larger == increment_dir && final_larger != 0
03878 && (final_larger == compare_dir || compare_dir == 0))
03879
03880 ;
03881 else
03882 {
03883 if (loop_dump_stream)
03884 fprintf (loop_dump_stream, "Loop iterations: Not normal loop.\n");
03885 return 0;
03886 }
03887
03888
03889
03890
03891
03892 inc = INTVAL (increment);
03893 if (inc > 0)
03894 {
03895 abs_diff = INTVAL (final_value) - INTVAL (initial_value);
03896 abs_inc = inc;
03897 }
03898 else if (inc < 0)
03899 {
03900 abs_diff = INTVAL (initial_value) - INTVAL (final_value);
03901 abs_inc = -inc;
03902 }
03903 else
03904 abort ();
03905
03906
03907
03908
03909
03910 abs_diff &= ((unsigned HOST_WIDE_INT) 1
03911 << (GET_MODE_BITSIZE (GET_MODE (iteration_var)) - 1)
03912 << 1) - 1;
03913
03914
03915
03916
03917
03918 if (compare_dir == 0 && (abs_diff % abs_inc) != 0)
03919 return 0;
03920
03921
03922
03923
03924 loop_info->n_iterations = abs_diff / abs_inc + ((abs_diff % abs_inc) != 0);
03925 return loop_info->n_iterations;
03926 }
03927
03928
03929
03930
03931
03932 static rtx
03933 remap_split_bivs (loop, x)
03934 struct loop *loop;
03935 rtx x;
03936 {
03937 struct loop_ivs *ivs = LOOP_IVS (loop);
03938 enum rtx_code code;
03939 int i;
03940 const char *fmt;
03941
03942 if (x == 0)
03943 return x;
03944
03945 code = GET_CODE (x);
03946 switch (code)
03947 {
03948 case SCRATCH:
03949 case PC:
03950 case CC0:
03951 case CONST_INT:
03952 case CONST_DOUBLE:
03953 case CONST:
03954 case SYMBOL_REF:
03955 case LABEL_REF:
03956 return x;
03957
03958 case REG:
03959 #if 0
03960
03961
03962 #endif
03963 if (REGNO (x) < ivs->n_regs
03964 && REG_IV_TYPE (ivs, REGNO (x)) == BASIC_INDUCT)
03965 return REG_IV_CLASS (ivs, REGNO (x))->biv->src_reg;
03966 break;
03967
03968 default:
03969 break;
03970 }
03971
03972 fmt = GET_RTX_FORMAT (code);
03973 for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
03974 {
03975 if (fmt[i] == 'e')
03976 XEXP (x, i) = remap_split_bivs (loop, XEXP (x, i));
03977 else if (fmt[i] == 'E')
03978 {
03979 int j;
03980 for (j = 0; j < XVECLEN (x, i); j++)
03981 XVECEXP (x, i, j) = remap_split_bivs (loop, XVECEXP (x, i, j));
03982 }
03983 }
03984 return x;
03985 }
03986
03987
03988
03989
03990
03991
03992
03993
03994
03995
03996
03997
03998
03999
04000
04001
04002 int
04003 set_dominates_use (regno, first_uid, last_uid, copy_start, copy_end)
04004 int regno;
04005 int first_uid;
04006 int last_uid;
04007 rtx copy_start;
04008 rtx copy_end;
04009 {
04010 int passed_jump = 0;
04011 rtx p = NEXT_INSN (copy_start);
04012
04013 while (INSN_UID (p) != first_uid)
04014 {
04015 if (GET_CODE (p) == JUMP_INSN)
04016 passed_jump = 1;
04017
04018 if (p == copy_end)
04019 return 0;
04020 p = NEXT_INSN (p);
04021 }
04022
04023
04024 if (! INSN_P (p) || ! dead_or_set_regno_p (p, regno))
04025 return 0;
04026
04027
04028 if (passed_jump == 0)
04029 return 1;
04030
04031 while (INSN_UID (p) != last_uid)
04032 {
04033
04034
04035 if (GET_CODE (p) == CODE_LABEL)
04036 return 0;
04037
04038
04039 else if (p == copy_end)
04040 return 1;
04041 p = NEXT_INSN (p);
04042 }
04043
04044
04045 return 1;
04046 }
04047
04048
04049
04050
04051
04052
04053
04054 static rtx
04055 ujump_to_loop_cont (loop_start, loop_cont)
04056 rtx loop_start;
04057 rtx loop_cont;
04058 {
04059 rtx x, label, label_ref;
04060
04061
04062 loop_start = next_nonnote_insn (loop_start);
04063
04064 x = pc_set (loop_start);
04065 if (!x)
04066 return NULL_RTX;
04067
04068 label_ref = SET_SRC (x);
04069 if (!label_ref)
04070 return NULL_RTX;
04071
04072
04073 label = next_nonnote_insn (loop_cont);
04074 if (label == 0 || GET_CODE (label) != CODE_LABEL)
04075 return NULL_RTX;
04076
04077
04078 if (CODE_LABEL_NUMBER (label) == CODE_LABEL_NUMBER (XEXP (label_ref, 0)))
04079 return loop_start;
04080 else
04081 return NULL_RTX;
04082 }