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 #include "config.h"
00051 #include "system.h"
00052 #include "coretypes.h"
00053 #include "tm.h"
00054 #include "rtl.h"
00055 #include "hard-reg-set.h"
00056 #include "obstack.h"
00057 #include "basic-block.h"
00058 #include "cfgloop.h"
00059 #include "expr.h"
00060 #include "output.h"
00061
00062
00063
00064 struct insn_info
00065 {
00066
00067 unsigned luid;
00068
00069
00070
00071 rtx prev_def;
00072
00073
00074 struct rtx_iv iv;
00075 };
00076
00077 static struct insn_info *insn_info;
00078
00079
00080
00081 static rtx *last_def;
00082
00083
00084
00085 static struct rtx_iv *bivs;
00086
00087
00088
00089 static unsigned max_insn_no;
00090
00091
00092
00093
00094 static unsigned max_reg_no;
00095
00096
00097
00098 extern void dump_iv_info (FILE *, struct rtx_iv *);
00099 void
00100 dump_iv_info (FILE *file, struct rtx_iv *iv)
00101 {
00102 if (!iv->base)
00103 {
00104 fprintf (file, "not simple");
00105 return;
00106 }
00107
00108 if (iv->step == const0_rtx
00109 && !iv->first_special)
00110 fprintf (file, "invariant ");
00111
00112 print_rtl (file, iv->base);
00113 if (iv->step != const0_rtx)
00114 {
00115 fprintf (file, " + ");
00116 print_rtl (file, iv->step);
00117 fprintf (file, " * iteration");
00118 }
00119 fprintf (file, " (in %s)", GET_MODE_NAME (iv->mode));
00120
00121 if (iv->mode != iv->extend_mode)
00122 fprintf (file, " %s to %s",
00123 rtx_name[iv->extend],
00124 GET_MODE_NAME (iv->extend_mode));
00125
00126 if (iv->mult != const1_rtx)
00127 {
00128 fprintf (file, " * ");
00129 print_rtl (file, iv->mult);
00130 }
00131 if (iv->delta != const0_rtx)
00132 {
00133 fprintf (file, " + ");
00134 print_rtl (file, iv->delta);
00135 }
00136 if (iv->first_special)
00137 fprintf (file, " (first special)");
00138 }
00139
00140
00141
00142 static void
00143 assign_luids (basic_block bb)
00144 {
00145 unsigned i = 0, uid;
00146 rtx insn;
00147
00148 FOR_BB_INSNS (bb, insn)
00149 {
00150 uid = INSN_UID (insn);
00151 insn_info[uid].luid = i++;
00152 insn_info[uid].prev_def = NULL_RTX;
00153 insn_info[uid].iv.analysed = false;
00154 }
00155 }
00156
00157
00158
00159
00160 rtx
00161 lowpart_subreg (enum machine_mode outer_mode, rtx expr,
00162 enum machine_mode inner_mode)
00163 {
00164 return simplify_gen_subreg (outer_mode, expr, inner_mode,
00165 subreg_lowpart_offset (outer_mode, inner_mode));
00166 }
00167
00168
00169
00170 static bool
00171 simple_reg_p (rtx reg)
00172 {
00173 unsigned r;
00174
00175 if (GET_CODE (reg) == SUBREG)
00176 {
00177 if (!subreg_lowpart_p (reg))
00178 return false;
00179 reg = SUBREG_REG (reg);
00180 }
00181
00182 if (!REG_P (reg))
00183 return false;
00184
00185 r = REGNO (reg);
00186 if (HARD_REGISTER_NUM_P (r))
00187 return false;
00188
00189 if (GET_MODE_CLASS (GET_MODE (reg)) != MODE_INT)
00190 return false;
00191
00192 if (last_def[r] == const0_rtx)
00193 return false;
00194
00195 return true;
00196 }
00197
00198
00199
00200 static bool
00201 simple_set_p (rtx lhs, rtx rhs)
00202 {
00203 rtx op0, op1;
00204
00205 if (!REG_P (lhs)
00206 || !simple_reg_p (lhs))
00207 return false;
00208
00209 if (CONSTANT_P (rhs))
00210 return true;
00211
00212 switch (GET_CODE (rhs))
00213 {
00214 case SUBREG:
00215 case REG:
00216 return simple_reg_p (rhs);
00217
00218 case SIGN_EXTEND:
00219 case ZERO_EXTEND:
00220 case NEG:
00221 return simple_reg_p (XEXP (rhs, 0));
00222
00223 case PLUS:
00224 case MINUS:
00225 case MULT:
00226 case ASHIFT:
00227 op0 = XEXP (rhs, 0);
00228 op1 = XEXP (rhs, 1);
00229
00230 if (!simple_reg_p (op0)
00231 && !CONSTANT_P (op0))
00232 return false;
00233
00234 if (!simple_reg_p (op1)
00235 && !CONSTANT_P (op1))
00236 return false;
00237
00238 if (GET_CODE (rhs) == MULT
00239 && !CONSTANT_P (op0)
00240 && !CONSTANT_P (op1))
00241 return false;
00242
00243 if (GET_CODE (rhs) == ASHIFT
00244 && CONSTANT_P (op0))
00245 return false;
00246
00247 return true;
00248
00249 default:
00250 return false;
00251 }
00252 }
00253
00254
00255
00256 static rtx
00257 mark_single_set (rtx insn, rtx set)
00258 {
00259 rtx def = SET_DEST (set), src;
00260 unsigned regno, uid;
00261
00262 src = find_reg_equal_equiv_note (insn);
00263 if (src)
00264 src = XEXP (src, 0);
00265 else
00266 src = SET_SRC (set);
00267
00268 if (!simple_set_p (SET_DEST (set), src))
00269 return NULL_RTX;
00270
00271 regno = REGNO (def);
00272 uid = INSN_UID (insn);
00273
00274 bivs[regno].analysed = false;
00275 insn_info[uid].prev_def = last_def[regno];
00276 last_def[regno] = insn;
00277
00278 return def;
00279 }
00280
00281
00282
00283 static void
00284 kill_sets (rtx reg, rtx by ATTRIBUTE_UNUSED, void *except)
00285 {
00286 if (GET_CODE (reg) == SUBREG)
00287 reg = SUBREG_REG (reg);
00288 if (!REG_P (reg))
00289 return;
00290 if (reg == except)
00291 return;
00292
00293 last_def[REGNO (reg)] = const0_rtx;
00294 }
00295
00296
00297
00298
00299 static void
00300 mark_sets (basic_block bb, bool dom)
00301 {
00302 rtx insn, set, def;
00303
00304 FOR_BB_INSNS (bb, insn)
00305 {
00306 if (!INSN_P (insn))
00307 continue;
00308
00309 if (dom
00310 && (set = single_set (insn)))
00311 def = mark_single_set (insn, set);
00312 else
00313 def = NULL_RTX;
00314
00315 note_stores (PATTERN (insn), kill_sets, def);
00316 }
00317 }
00318
00319
00320
00321 void
00322 iv_analysis_loop_init (struct loop *loop)
00323 {
00324 basic_block *body = get_loop_body_in_dom_order (loop);
00325 unsigned b;
00326
00327 if ((unsigned) get_max_uid () >= max_insn_no)
00328 {
00329
00330 max_insn_no = get_max_uid () + 100;
00331 if (insn_info)
00332 free (insn_info);
00333 insn_info = xmalloc (max_insn_no * sizeof (struct insn_info));
00334 }
00335
00336 if ((unsigned) max_reg_num () >= max_reg_no)
00337 {
00338 max_reg_no = max_reg_num () + 100;
00339 if (last_def)
00340 free (last_def);
00341 last_def = xmalloc (max_reg_no * sizeof (rtx));
00342 if (bivs)
00343 free (bivs);
00344 bivs = xmalloc (max_reg_no * sizeof (struct rtx_iv));
00345 }
00346
00347 memset (last_def, 0, max_reg_num () * sizeof (rtx));
00348
00349 for (b = 0; b < loop->num_nodes; b++)
00350 {
00351 assign_luids (body[b]);
00352 mark_sets (body[b], just_once_each_iteration_p (loop, body[b]));
00353 }
00354
00355 free (body);
00356 }
00357
00358
00359
00360
00361
00362 rtx
00363 iv_get_reaching_def (rtx insn, rtx reg)
00364 {
00365 unsigned regno, luid, auid;
00366 rtx ainsn;
00367 basic_block bb, abb;
00368
00369 if (GET_CODE (reg) == SUBREG)
00370 {
00371 if (!subreg_lowpart_p (reg))
00372 return const0_rtx;
00373 reg = SUBREG_REG (reg);
00374 }
00375 if (!REG_P (reg))
00376 return NULL_RTX;
00377
00378 regno = REGNO (reg);
00379 if (!last_def[regno]
00380 || last_def[regno] == const0_rtx)
00381 return last_def[regno];
00382
00383 bb = BLOCK_FOR_INSN (insn);
00384 luid = insn_info[INSN_UID (insn)].luid;
00385
00386 ainsn = last_def[regno];
00387 while (1)
00388 {
00389 abb = BLOCK_FOR_INSN (ainsn);
00390
00391 if (dominated_by_p (CDI_DOMINATORS, bb, abb))
00392 break;
00393
00394 auid = INSN_UID (ainsn);
00395 ainsn = insn_info[auid].prev_def;
00396
00397 if (!ainsn)
00398 return NULL_RTX;
00399 }
00400
00401 while (1)
00402 {
00403 abb = BLOCK_FOR_INSN (ainsn);
00404 if (abb != bb)
00405 return ainsn;
00406
00407 auid = INSN_UID (ainsn);
00408 if (luid > insn_info[auid].luid)
00409 return ainsn;
00410
00411 ainsn = insn_info[auid].prev_def;
00412 if (!ainsn)
00413 return NULL_RTX;
00414 }
00415 }
00416
00417
00418
00419
00420 static bool
00421 iv_constant (struct rtx_iv *iv, rtx cst, enum machine_mode mode)
00422 {
00423 if (mode == VOIDmode)
00424 mode = GET_MODE (cst);
00425
00426 iv->analysed = true;
00427 iv->mode = mode;
00428 iv->base = cst;
00429 iv->step = const0_rtx;
00430 iv->first_special = false;
00431 iv->extend = UNKNOWN;
00432 iv->extend_mode = iv->mode;
00433 iv->delta = const0_rtx;
00434 iv->mult = const1_rtx;
00435
00436 return true;
00437 }
00438
00439
00440
00441 static bool
00442 iv_subreg (struct rtx_iv *iv, enum machine_mode mode)
00443 {
00444
00445 if (iv->step == const0_rtx
00446 && !iv->first_special)
00447 {
00448 rtx val = get_iv_value (iv, const0_rtx);
00449 val = lowpart_subreg (mode, val, iv->extend_mode);
00450
00451 iv->base = val;
00452 iv->extend = UNKNOWN;
00453 iv->mode = iv->extend_mode = mode;
00454 iv->delta = const0_rtx;
00455 iv->mult = const1_rtx;
00456 return true;
00457 }
00458
00459 if (iv->extend_mode == mode)
00460 return true;
00461
00462 if (GET_MODE_BITSIZE (mode) > GET_MODE_BITSIZE (iv->mode))
00463 return false;
00464
00465 iv->extend = UNKNOWN;
00466 iv->mode = mode;
00467
00468 iv->base = simplify_gen_binary (PLUS, iv->extend_mode, iv->delta,
00469 simplify_gen_binary (MULT, iv->extend_mode,
00470 iv->base, iv->mult));
00471 iv->step = simplify_gen_binary (MULT, iv->extend_mode, iv->step, iv->mult);
00472 iv->mult = const1_rtx;
00473 iv->delta = const0_rtx;
00474 iv->first_special = false;
00475
00476 return true;
00477 }
00478
00479
00480
00481 static bool
00482 iv_extend (struct rtx_iv *iv, enum rtx_code extend, enum machine_mode mode)
00483 {
00484
00485 if (iv->step == const0_rtx
00486 && !iv->first_special)
00487 {
00488 rtx val = get_iv_value (iv, const0_rtx);
00489 val = simplify_gen_unary (extend, mode, val, iv->extend_mode);
00490
00491 iv->base = val;
00492 iv->extend = UNKNOWN;
00493 iv->mode = iv->extend_mode = mode;
00494 iv->delta = const0_rtx;
00495 iv->mult = const1_rtx;
00496 return true;
00497 }
00498
00499 if (mode != iv->extend_mode)
00500 return false;
00501
00502 if (iv->extend != UNKNOWN
00503 && iv->extend != extend)
00504 return false;
00505
00506 iv->extend = extend;
00507
00508 return true;
00509 }
00510
00511
00512
00513 static bool
00514 iv_neg (struct rtx_iv *iv)
00515 {
00516 if (iv->extend == UNKNOWN)
00517 {
00518 iv->base = simplify_gen_unary (NEG, iv->extend_mode,
00519 iv->base, iv->extend_mode);
00520 iv->step = simplify_gen_unary (NEG, iv->extend_mode,
00521 iv->step, iv->extend_mode);
00522 }
00523 else
00524 {
00525 iv->delta = simplify_gen_unary (NEG, iv->extend_mode,
00526 iv->delta, iv->extend_mode);
00527 iv->mult = simplify_gen_unary (NEG, iv->extend_mode,
00528 iv->mult, iv->extend_mode);
00529 }
00530
00531 return true;
00532 }
00533
00534
00535
00536 static bool
00537 iv_add (struct rtx_iv *iv0, struct rtx_iv *iv1, enum rtx_code op)
00538 {
00539 enum machine_mode mode;
00540 rtx arg;
00541
00542
00543 if (iv0->extend == UNKNOWN
00544 && iv0->mode == iv0->extend_mode
00545 && iv0->step == const0_rtx
00546 && GET_MODE_SIZE (iv0->extend_mode) < GET_MODE_SIZE (iv1->extend_mode))
00547 {
00548 iv0->extend_mode = iv1->extend_mode;
00549 iv0->base = simplify_gen_unary (ZERO_EXTEND, iv0->extend_mode,
00550 iv0->base, iv0->mode);
00551 }
00552 if (iv1->extend == UNKNOWN
00553 && iv1->mode == iv1->extend_mode
00554 && iv1->step == const0_rtx
00555 && GET_MODE_SIZE (iv1->extend_mode) < GET_MODE_SIZE (iv0->extend_mode))
00556 {
00557 iv1->extend_mode = iv0->extend_mode;
00558 iv1->base = simplify_gen_unary (ZERO_EXTEND, iv1->extend_mode,
00559 iv1->base, iv1->mode);
00560 }
00561
00562 mode = iv0->extend_mode;
00563 if (mode != iv1->extend_mode)
00564 return false;
00565
00566 if (iv0->extend == UNKNOWN && iv1->extend == UNKNOWN)
00567 {
00568 if (iv0->mode != iv1->mode)
00569 return false;
00570
00571 iv0->base = simplify_gen_binary (op, mode, iv0->base, iv1->base);
00572 iv0->step = simplify_gen_binary (op, mode, iv0->step, iv1->step);
00573
00574 return true;
00575 }
00576
00577
00578 if (iv1->extend == UNKNOWN
00579 && iv1->mode == mode
00580 && iv1->step == const0_rtx)
00581 {
00582 iv0->delta = simplify_gen_binary (op, mode, iv0->delta, iv1->base);
00583 return true;
00584 }
00585
00586 if (iv0->extend == UNKNOWN
00587 && iv0->mode == mode
00588 && iv0->step == const0_rtx)
00589 {
00590 arg = iv0->base;
00591 *iv0 = *iv1;
00592 if (op == MINUS
00593 && !iv_neg (iv0))
00594 return false;
00595
00596 iv0->delta = simplify_gen_binary (PLUS, mode, iv0->delta, arg);
00597 return true;
00598 }
00599
00600 return false;
00601 }
00602
00603
00604
00605 static bool
00606 iv_mult (struct rtx_iv *iv, rtx mby)
00607 {
00608 enum machine_mode mode = iv->extend_mode;
00609
00610 if (GET_MODE (mby) != VOIDmode
00611 && GET_MODE (mby) != mode)
00612 return false;
00613
00614 if (iv->extend == UNKNOWN)
00615 {
00616 iv->base = simplify_gen_binary (MULT, mode, iv->base, mby);
00617 iv->step = simplify_gen_binary (MULT, mode, iv->step, mby);
00618 }
00619 else
00620 {
00621 iv->delta = simplify_gen_binary (MULT, mode, iv->delta, mby);
00622 iv->mult = simplify_gen_binary (MULT, mode, iv->mult, mby);
00623 }
00624
00625 return true;
00626 }
00627
00628
00629
00630 static bool
00631 iv_shift (struct rtx_iv *iv, rtx mby)
00632 {
00633 enum machine_mode mode = iv->extend_mode;
00634
00635 if (GET_MODE (mby) != VOIDmode
00636 && GET_MODE (mby) != mode)
00637 return false;
00638
00639 if (iv->extend == UNKNOWN)
00640 {
00641 iv->base = simplify_gen_binary (ASHIFT, mode, iv->base, mby);
00642 iv->step = simplify_gen_binary (ASHIFT, mode, iv->step, mby);
00643 }
00644 else
00645 {
00646 iv->delta = simplify_gen_binary (ASHIFT, mode, iv->delta, mby);
00647 iv->mult = simplify_gen_binary (ASHIFT, mode, iv->mult, mby);
00648 }
00649
00650 return true;
00651 }
00652
00653
00654
00655
00656
00657 static bool
00658 get_biv_step_1 (rtx insn, rtx reg,
00659 rtx *inner_step, enum machine_mode *inner_mode,
00660 enum rtx_code *extend, enum machine_mode outer_mode,
00661 rtx *outer_step)
00662 {
00663 rtx set, lhs, rhs, op0 = NULL_RTX, op1 = NULL_RTX;
00664 rtx next, nextr, def_insn, tmp;
00665 enum rtx_code code;
00666
00667 set = single_set (insn);
00668 rhs = find_reg_equal_equiv_note (insn);
00669 if (rhs)
00670 rhs = XEXP (rhs, 0);
00671 else
00672 rhs = SET_SRC (set);
00673 lhs = SET_DEST (set);
00674
00675 code = GET_CODE (rhs);
00676 switch (code)
00677 {
00678 case SUBREG:
00679 case REG:
00680 next = rhs;
00681 break;
00682
00683 case PLUS:
00684 case MINUS:
00685 op0 = XEXP (rhs, 0);
00686 op1 = XEXP (rhs, 1);
00687
00688 if (code == PLUS && CONSTANT_P (op0))
00689 {
00690 tmp = op0; op0 = op1; op1 = tmp;
00691 }
00692
00693 if (!simple_reg_p (op0)
00694 || !CONSTANT_P (op1))
00695 return false;
00696
00697 if (GET_MODE (rhs) != outer_mode)
00698 {
00699
00700
00701
00702
00703
00704
00705
00706
00707 if (GET_CODE (op0) != SUBREG)
00708 return false;
00709 if (GET_MODE (SUBREG_REG (op0)) != outer_mode)
00710 return false;
00711 }
00712
00713 next = op0;
00714 break;
00715
00716 case SIGN_EXTEND:
00717 case ZERO_EXTEND:
00718 if (GET_MODE (rhs) != outer_mode)
00719 return false;
00720
00721 op0 = XEXP (rhs, 0);
00722 if (!simple_reg_p (op0))
00723 return false;
00724
00725 next = op0;
00726 break;
00727
00728 default:
00729 return false;
00730 }
00731
00732 if (GET_CODE (next) == SUBREG)
00733 {
00734 if (!subreg_lowpart_p (next))
00735 return false;
00736
00737 nextr = SUBREG_REG (next);
00738 if (GET_MODE (nextr) != outer_mode)
00739 return false;
00740 }
00741 else
00742 nextr = next;
00743
00744 def_insn = iv_get_reaching_def (insn, nextr);
00745 if (def_insn == const0_rtx)
00746 return false;
00747
00748 if (!def_insn)
00749 {
00750 if (!rtx_equal_p (nextr, reg))
00751 return false;
00752
00753 *inner_step = const0_rtx;
00754 *extend = UNKNOWN;
00755 *inner_mode = outer_mode;
00756 *outer_step = const0_rtx;
00757 }
00758 else if (!get_biv_step_1 (def_insn, reg,
00759 inner_step, inner_mode, extend, outer_mode,
00760 outer_step))
00761 return false;
00762
00763 if (GET_CODE (next) == SUBREG)
00764 {
00765 enum machine_mode amode = GET_MODE (next);
00766
00767 if (GET_MODE_SIZE (amode) > GET_MODE_SIZE (*inner_mode))
00768 return false;
00769
00770 *inner_mode = amode;
00771 *inner_step = simplify_gen_binary (PLUS, outer_mode,
00772 *inner_step, *outer_step);
00773 *outer_step = const0_rtx;
00774 *extend = UNKNOWN;
00775 }
00776
00777 switch (code)
00778 {
00779 case REG:
00780 case SUBREG:
00781 break;
00782
00783 case PLUS:
00784 case MINUS:
00785 if (*inner_mode == outer_mode
00786
00787 || GET_MODE (rhs) != outer_mode)
00788 *inner_step = simplify_gen_binary (code, outer_mode,
00789 *inner_step, op1);
00790 else
00791 *outer_step = simplify_gen_binary (code, outer_mode,
00792 *outer_step, op1);
00793 break;
00794
00795 case SIGN_EXTEND:
00796 case ZERO_EXTEND:
00797 if (GET_MODE (op0) != *inner_mode
00798 || *extend != UNKNOWN
00799 || *outer_step != const0_rtx)
00800 abort ();
00801
00802 *extend = code;
00803 break;
00804
00805 default:
00806 abort ();
00807 }
00808
00809 return true;
00810 }
00811
00812
00813
00814
00815
00816
00817
00818 static bool
00819 get_biv_step (rtx reg, rtx *inner_step, enum machine_mode *inner_mode,
00820 enum rtx_code *extend, enum machine_mode *outer_mode,
00821 rtx *outer_step)
00822 {
00823 *outer_mode = GET_MODE (reg);
00824
00825 if (!get_biv_step_1 (last_def[REGNO (reg)], reg,
00826 inner_step, inner_mode, extend, *outer_mode,
00827 outer_step))
00828 return false;
00829
00830 if (*inner_mode != *outer_mode
00831 && *extend == UNKNOWN)
00832 abort ();
00833
00834 if (*inner_mode == *outer_mode
00835 && *extend != UNKNOWN)
00836 abort ();
00837
00838 if (*inner_mode == *outer_mode
00839 && *outer_step != const0_rtx)
00840 abort ();
00841
00842 return true;
00843 }
00844
00845
00846
00847
00848 static bool
00849 iv_analyze_biv (rtx def, struct rtx_iv *iv)
00850 {
00851 unsigned regno;
00852 rtx inner_step, outer_step;
00853 enum machine_mode inner_mode, outer_mode;
00854 enum rtx_code extend;
00855
00856 if (dump_file)
00857 {
00858 fprintf (dump_file, "Analysing ");
00859 print_rtl (dump_file, def);
00860 fprintf (dump_file, " for bivness.\n");
00861 }
00862
00863 if (!REG_P (def))
00864 {
00865 if (!CONSTANT_P (def))
00866 return false;
00867
00868 return iv_constant (iv, def, VOIDmode);
00869 }
00870
00871 regno = REGNO (def);
00872 if (last_def[regno] == const0_rtx)
00873 {
00874 if (dump_file)
00875 fprintf (dump_file, " not simple.\n");
00876 return false;
00877 }
00878
00879 if (last_def[regno] && bivs[regno].analysed)
00880 {
00881 if (dump_file)
00882 fprintf (dump_file, " already analysed.\n");
00883
00884 *iv = bivs[regno];
00885 return iv->base != NULL_RTX;
00886 }
00887
00888 if (!last_def[regno])
00889 {
00890 iv_constant (iv, def, VOIDmode);
00891 goto end;
00892 }
00893
00894 iv->analysed = true;
00895 if (!get_biv_step (def, &inner_step, &inner_mode, &extend,
00896 &outer_mode, &outer_step))
00897 {
00898 iv->base = NULL_RTX;
00899 goto end;
00900 }
00901
00902
00903
00904
00905
00906
00907
00908 iv->base = simplify_gen_binary (MINUS, outer_mode, def, outer_step);
00909 iv->step = simplify_gen_binary (PLUS, outer_mode, inner_step, outer_step);
00910 iv->mode = inner_mode;
00911 iv->extend_mode = outer_mode;
00912 iv->extend = extend;
00913 iv->mult = const1_rtx;
00914 iv->delta = outer_step;
00915 iv->first_special = inner_mode != outer_mode;
00916
00917 end:
00918 if (dump_file)
00919 {
00920 fprintf (dump_file, " ");
00921 dump_iv_info (dump_file, iv);
00922 fprintf (dump_file, "\n");
00923 }
00924
00925 bivs[regno] = *iv;
00926
00927 return iv->base != NULL_RTX;
00928 }
00929
00930
00931
00932 static bool
00933 iv_analyze_op (rtx insn, rtx op, struct rtx_iv *iv)
00934 {
00935 rtx def_insn;
00936 unsigned regno;
00937 bool inv = CONSTANT_P (op);
00938
00939 if (dump_file)
00940 {
00941 fprintf (dump_file, "Analysing operand ");
00942 print_rtl (dump_file, op);
00943 fprintf (dump_file, " of insn ");
00944 print_rtl_single (dump_file, insn);
00945 }
00946
00947 if (GET_CODE (op) == SUBREG)
00948 {
00949 if (!subreg_lowpart_p (op))
00950 return false;
00951
00952 if (!iv_analyze_op (insn, SUBREG_REG (op), iv))
00953 return false;
00954
00955 return iv_subreg (iv, GET_MODE (op));
00956 }
00957
00958 if (!inv)
00959 {
00960 regno = REGNO (op);
00961 if (!last_def[regno])
00962 inv = true;
00963 else if (last_def[regno] == const0_rtx)
00964 {
00965 if (dump_file)
00966 fprintf (dump_file, " not simple.\n");
00967 return false;
00968 }
00969 }
00970
00971 if (inv)
00972 {
00973 iv_constant (iv, op, VOIDmode);
00974
00975 if (dump_file)
00976 {
00977 fprintf (dump_file, " ");
00978 dump_iv_info (dump_file, iv);
00979 fprintf (dump_file, "\n");
00980 }
00981 return true;
00982 }
00983
00984 def_insn = iv_get_reaching_def (insn, op);
00985 if (def_insn == const0_rtx)
00986 {
00987 if (dump_file)
00988 fprintf (dump_file, " not simple.\n");
00989 return false;
00990 }
00991
00992 return iv_analyze (def_insn, op, iv);
00993 }
00994
00995
00996
00997 bool
00998 iv_analyze (rtx insn, rtx def, struct rtx_iv *iv)
00999 {
01000 unsigned uid;
01001 rtx set, rhs, mby = NULL_RTX, tmp;
01002 rtx op0 = NULL_RTX, op1 = NULL_RTX;
01003 struct rtx_iv iv0, iv1;
01004 enum machine_mode amode;
01005 enum rtx_code code;
01006
01007 if (insn == const0_rtx)
01008 return false;
01009
01010 if (GET_CODE (def) == SUBREG)
01011 {
01012 if (!subreg_lowpart_p (def))
01013 return false;
01014
01015 if (!iv_analyze (insn, SUBREG_REG (def), iv))
01016 return false;
01017
01018 return iv_subreg (iv, GET_MODE (def));
01019 }
01020
01021 if (!insn)
01022 return iv_analyze_biv (def, iv);
01023
01024 if (dump_file)
01025 {
01026 fprintf (dump_file, "Analysing def of ");
01027 print_rtl (dump_file, def);
01028 fprintf (dump_file, " in insn ");
01029 print_rtl_single (dump_file, insn);
01030 }
01031
01032 uid = INSN_UID (insn);
01033 if (insn_info[uid].iv.analysed)
01034 {
01035 if (dump_file)
01036 fprintf (dump_file, " already analysed.\n");
01037 *iv = insn_info[uid].iv;
01038 return iv->base != NULL_RTX;
01039 }
01040
01041 iv->mode = VOIDmode;
01042 iv->base = NULL_RTX;
01043 iv->step = NULL_RTX;
01044
01045 set = single_set (insn);
01046 rhs = find_reg_equal_equiv_note (insn);
01047 if (rhs)
01048 rhs = XEXP (rhs, 0);
01049 else
01050 rhs = SET_SRC (set);
01051 code = GET_CODE (rhs);
01052
01053 if (CONSTANT_P (rhs))
01054 {
01055 op0 = rhs;
01056 amode = GET_MODE (def);
01057 }
01058 else
01059 {
01060 switch (code)
01061 {
01062 case SUBREG:
01063 if (!subreg_lowpart_p (rhs))
01064 goto end;
01065 op0 = rhs;
01066 break;
01067
01068 case REG:
01069 op0 = rhs;
01070 break;
01071
01072 case SIGN_EXTEND:
01073 case ZERO_EXTEND:
01074 case NEG:
01075 op0 = XEXP (rhs, 0);
01076 break;
01077
01078 case PLUS:
01079 case MINUS:
01080 op0 = XEXP (rhs, 0);
01081 op1 = XEXP (rhs, 1);
01082 break;
01083
01084 case MULT:
01085 op0 = XEXP (rhs, 0);
01086 mby = XEXP (rhs, 1);
01087 if (!CONSTANT_P (mby))
01088 {
01089 if (!CONSTANT_P (op0))
01090 abort ();
01091 tmp = op0;
01092 op0 = mby;
01093 mby = tmp;
01094 }
01095 break;
01096
01097 case ASHIFT:
01098 if (CONSTANT_P (XEXP (rhs, 0)))
01099 abort ();
01100 op0 = XEXP (rhs, 0);
01101 mby = XEXP (rhs, 1);
01102 break;
01103
01104 default:
01105 abort ();
01106 }
01107
01108 amode = GET_MODE (rhs);
01109 }
01110
01111 if (op0)
01112 {
01113 if (!iv_analyze_op (insn, op0, &iv0))
01114 goto end;
01115
01116 if (iv0.mode == VOIDmode)
01117 {
01118 iv0.mode = amode;
01119 iv0.extend_mode = amode;
01120 }
01121 }
01122
01123 if (op1)
01124 {
01125 if (!iv_analyze_op (insn, op1, &iv1))
01126 goto end;
01127
01128 if (iv1.mode == VOIDmode)
01129 {
01130 iv1.mode = amode;
01131 iv1.extend_mode = amode;
01132 }
01133 }
01134
01135 switch (code)
01136 {
01137 case SIGN_EXTEND:
01138 case ZERO_EXTEND:
01139 if (!iv_extend (&iv0, code, amode))
01140 goto end;
01141 break;
01142
01143 case NEG:
01144 if (!iv_neg (&iv0))
01145 goto end;
01146 break;
01147
01148 case PLUS:
01149 case MINUS:
01150 if (!iv_add (&iv0, &iv1, code))
01151 goto end;
01152 break;
01153
01154 case MULT:
01155 if (!iv_mult (&iv0, mby))
01156 goto end;
01157 break;
01158
01159 case ASHIFT:
01160 if (!iv_shift (&iv0, mby))
01161 goto end;
01162 break;
01163
01164 default:
01165 break;
01166 }
01167
01168 *iv = iv0;
01169
01170 end:
01171 iv->analysed = true;
01172 insn_info[uid].iv = *iv;
01173
01174 if (dump_file)
01175 {
01176 print_rtl (dump_file, def);
01177 fprintf (dump_file, " in insn ");
01178 print_rtl_single (dump_file, insn);
01179 fprintf (dump_file, " is ");
01180 dump_iv_info (dump_file, iv);
01181 fprintf (dump_file, "\n");
01182 }
01183
01184 return iv->base != NULL_RTX;
01185 }
01186
01187
01188
01189
01190
01191 bool
01192 biv_p (rtx insn, rtx reg)
01193 {
01194 struct rtx_iv iv;
01195
01196 if (!REG_P (reg))
01197 return false;
01198
01199 if (last_def[REGNO (reg)] != insn)
01200 return false;
01201
01202 return iv_analyze_biv (reg, &iv);
01203 }
01204
01205
01206
01207 rtx
01208 get_iv_value (struct rtx_iv *iv, rtx iteration)
01209 {
01210 rtx val;
01211
01212
01213
01214 if (iv->first_special)
01215 abort ();
01216
01217 if (iv->step != const0_rtx && iteration != const0_rtx)
01218 val = simplify_gen_binary (PLUS, iv->extend_mode, iv->base,
01219 simplify_gen_binary (MULT, iv->extend_mode,
01220 iv->step, iteration));
01221 else
01222 val = iv->base;
01223
01224 if (iv->extend_mode == iv->mode)
01225 return val;
01226
01227 val = lowpart_subreg (iv->mode, val, iv->extend_mode);
01228
01229 if (iv->extend == UNKNOWN)
01230 return val;
01231
01232 val = simplify_gen_unary (iv->extend, iv->extend_mode, val, iv->mode);
01233 val = simplify_gen_binary (PLUS, iv->extend_mode, iv->delta,
01234 simplify_gen_binary (MULT, iv->extend_mode,
01235 iv->mult, val));
01236
01237 return val;
01238 }
01239
01240
01241
01242 void
01243 iv_analysis_done (void)
01244 {
01245 max_insn_no = 0;
01246 max_reg_no = 0;
01247 if (insn_info)
01248 {
01249 free (insn_info);
01250 insn_info = NULL;
01251 }
01252 if (last_def)
01253 {
01254 free (last_def);
01255 last_def = NULL;
01256 }
01257 if (bivs)
01258 {
01259 free (bivs);
01260 bivs = NULL;
01261 }
01262 }
01263
01264
01265
01266 static unsigned HOST_WIDEST_INT
01267 inverse (unsigned HOST_WIDEST_INT x, int mod)
01268 {
01269 unsigned HOST_WIDEST_INT mask =
01270 ((unsigned HOST_WIDEST_INT) 1 << (mod - 1) << 1) - 1;
01271 unsigned HOST_WIDEST_INT rslt = 1;
01272 int i;
01273
01274 for (i = 0; i < mod - 1; i++)
01275 {
01276 rslt = (rslt * x) & mask;
01277 x = (x * x) & mask;
01278 }
01279
01280 return rslt;
01281 }
01282
01283
01284
01285 static unsigned HOST_WIDEST_INT
01286 determine_max_iter (struct niter_desc *desc)
01287 {
01288 rtx niter = desc->niter_expr;
01289 rtx mmin, mmax, left, right;
01290 unsigned HOST_WIDEST_INT nmax, inc;
01291
01292 if (GET_CODE (niter) == AND
01293 && GET_CODE (XEXP (niter, 0)) == CONST_INT)
01294 {
01295 nmax = INTVAL (XEXP (niter, 0));
01296 if (!(nmax & (nmax + 1)))
01297 {
01298 desc->niter_max = nmax;
01299 return nmax;
01300 }
01301 }
01302
01303 get_mode_bounds (desc->mode, desc->signed_p, desc->mode, &mmin, &mmax);
01304 nmax = INTVAL (mmax) - INTVAL (mmin);
01305
01306 if (GET_CODE (niter) == UDIV)
01307 {
01308 if (GET_CODE (XEXP (niter, 1)) != CONST_INT)
01309 {
01310 desc->niter_max = nmax;
01311 return nmax;
01312 }
01313 inc = INTVAL (XEXP (niter, 1));
01314 niter = XEXP (niter, 0);
01315 }
01316 else
01317 inc = 1;
01318
01319 if (GET_CODE (niter) == PLUS)
01320 {
01321 left = XEXP (niter, 0);
01322 right = XEXP (niter, 0);
01323
01324 if (GET_CODE (right) == CONST_INT)
01325 right = GEN_INT (-INTVAL (right));
01326 }
01327 else if (GET_CODE (niter) == MINUS)
01328 {
01329 left = XEXP (niter, 0);
01330 right = XEXP (niter, 0);
01331 }
01332 else
01333 {
01334 left = niter;
01335 right = mmin;
01336 }
01337
01338 if (GET_CODE (left) == CONST_INT)
01339 mmax = left;
01340 if (GET_CODE (right) == CONST_INT)
01341 mmin = right;
01342 nmax = INTVAL (mmax) - INTVAL (mmin);
01343
01344 desc->niter_max = nmax / inc;
01345 return nmax / inc;
01346 }
01347
01348
01349
01350 static int
01351 altered_reg_used (rtx *reg, void *alt)
01352 {
01353 if (!REG_P (*reg))
01354 return 0;
01355
01356 return REGNO_REG_SET_P (alt, REGNO (*reg));
01357 }
01358
01359
01360
01361 static void
01362 mark_altered (rtx expr, rtx by ATTRIBUTE_UNUSED, void *alt)
01363 {
01364 if (GET_CODE (expr) == SUBREG)
01365 expr = SUBREG_REG (expr);
01366 if (!REG_P (expr))
01367 return;
01368
01369 SET_REGNO_REG_SET (alt, REGNO (expr));
01370 }
01371
01372
01373
01374 static bool
01375 simple_rhs_p (rtx rhs)
01376 {
01377 rtx op0, op1;
01378
01379 if (CONSTANT_P (rhs)
01380 || REG_P (rhs))
01381 return true;
01382
01383 switch (GET_CODE (rhs))
01384 {
01385 case PLUS:
01386 case MINUS:
01387 op0 = XEXP (rhs, 0);
01388 op1 = XEXP (rhs, 1);
01389
01390 if (REG_P (op0) && CONSTANT_P (op1))
01391 return true;
01392 if (REG_P (op1) && CONSTANT_P (op0))
01393 return true;
01394
01395 return false;
01396
01397 default:
01398 return false;
01399 }
01400 }
01401
01402
01403
01404
01405 static void
01406 simplify_using_assignment (rtx insn, rtx *expr, regset altered)
01407 {
01408 rtx set = single_set (insn);
01409 rtx lhs = NULL_RTX, rhs;
01410 bool ret = false;
01411
01412 if (set)
01413 {
01414 lhs = SET_DEST (set);
01415 if (!REG_P (lhs)
01416 || altered_reg_used (&lhs, altered))
01417 ret = true;
01418 }
01419 else
01420 ret = true;
01421
01422 note_stores (PATTERN (insn), mark_altered, altered);
01423 if (CALL_P (insn))
01424 {
01425 int i;
01426
01427
01428 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
01429 if (TEST_HARD_REG_BIT (regs_invalidated_by_call, i))
01430 SET_REGNO_REG_SET (altered, i);
01431 }
01432
01433 if (ret)
01434 return;
01435
01436 rhs = find_reg_equal_equiv_note (insn);
01437 if (rhs)
01438 rhs = XEXP (rhs, 0);
01439 else
01440 rhs = SET_SRC (set);
01441
01442 if (!simple_rhs_p (rhs))
01443 return;
01444
01445 if (for_each_rtx (&rhs, altered_reg_used, altered))
01446 return;
01447
01448 *expr = simplify_replace_rtx (*expr, lhs, rhs);
01449 }
01450
01451
01452
01453 static bool
01454 implies_p (rtx a, rtx b)
01455 {
01456 rtx op0, op1, opb0, opb1, r;
01457 enum machine_mode mode;
01458
01459 if (GET_CODE (a) == EQ)
01460 {
01461 op0 = XEXP (a, 0);
01462 op1 = XEXP (a, 1);
01463
01464 if (REG_P (op0))
01465 {
01466 r = simplify_replace_rtx (b, op0, op1);
01467 if (r == const_true_rtx)
01468 return true;
01469 }
01470
01471 if (REG_P (op1))
01472 {
01473 r = simplify_replace_rtx (b, op1, op0);
01474 if (r == const_true_rtx)
01475 return true;
01476 }
01477 }
01478
01479
01480 if ((GET_CODE (a) == GT || GET_CODE (a) == LT)
01481 && (GET_CODE (b) == GE || GET_CODE (b) == LE))
01482 {
01483 op0 = XEXP (a, 0);
01484 op1 = XEXP (a, 1);
01485 opb0 = XEXP (b, 0);
01486 opb1 = XEXP (b, 1);
01487
01488 if (GET_CODE (a) == GT)
01489 {
01490 r = op0;
01491 op0 = op1;
01492 op1 = r;
01493 }
01494
01495 if (GET_CODE (b) == GE)
01496 {
01497 r = opb0;
01498 opb0 = opb1;
01499 opb1 = r;
01500 }
01501
01502 mode = GET_MODE (op0);
01503 if (mode != GET_MODE (opb0))
01504 mode = VOIDmode;
01505 else if (mode == VOIDmode)
01506 {
01507 mode = GET_MODE (op1);
01508 if (mode != GET_MODE (opb1))
01509 mode = VOIDmode;
01510 }
01511
01512 if (mode != VOIDmode
01513 && rtx_equal_p (op1, opb1)
01514 && simplify_gen_binary (MINUS, mode, opb0, op0) == const1_rtx)
01515 return true;
01516 }
01517
01518 return false;
01519 }
01520
01521
01522
01523
01524
01525
01526
01527
01528 rtx
01529 canon_condition (rtx cond)
01530 {
01531 rtx tem;
01532 rtx op0, op1;
01533 enum rtx_code code;
01534 enum machine_mode mode;
01535
01536 code = GET_CODE (cond);
01537 op0 = XEXP (cond, 0);
01538 op1 = XEXP (cond, 1);
01539
01540 if (swap_commutative_operands_p (op0, op1))
01541 {
01542 code = swap_condition (code);
01543 tem = op0;
01544 op0 = op1;
01545 op1 = tem;
01546 }
01547
01548 mode = GET_MODE (op0);
01549 if (mode == VOIDmode)
01550 mode = GET_MODE (op1);
01551 if (mode == VOIDmode)
01552 abort ();
01553
01554 if (GET_CODE (op1) == CONST_INT
01555 && GET_MODE_CLASS (mode) != MODE_CC
01556 && GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT)
01557 {
01558 HOST_WIDE_INT const_val = INTVAL (op1);
01559 unsigned HOST_WIDE_INT uconst_val = const_val;
01560 unsigned HOST_WIDE_INT max_val
01561 = (unsigned HOST_WIDE_INT) GET_MODE_MASK (mode);
01562
01563 switch (code)
01564 {
01565 case LE:
01566 if ((unsigned HOST_WIDE_INT) const_val != max_val >> 1)
01567 code = LT, op1 = gen_int_mode (const_val + 1, GET_MODE (op0));
01568 break;
01569
01570
01571
01572 case GE:
01573 if ((HOST_WIDE_INT) (const_val & max_val)
01574 != (((HOST_WIDE_INT) 1
01575 << (GET_MODE_BITSIZE (GET_MODE (op0)) - 1))))
01576 code = GT, op1 = gen_int_mode (const_val - 1, mode);
01577 break;
01578
01579 case LEU:
01580 if (uconst_val < max_val)
01581 code = LTU, op1 = gen_int_mode (uconst_val + 1, mode);
01582 break;
01583
01584 case GEU:
01585 if (uconst_val != 0)
01586 code = GTU, op1 = gen_int_mode (uconst_val - 1, mode);
01587 break;
01588
01589 default:
01590 break;
01591 }
01592 }
01593
01594 if (op0 != XEXP (cond, 0)
01595 || op1 != XEXP (cond, 1)
01596 || code != GET_CODE (cond)
01597 || GET_MODE (cond) != SImode)
01598 cond = gen_rtx_fmt_ee (code, SImode, op0, op1);
01599
01600 return cond;
01601 }
01602
01603
01604
01605
01606 void
01607 simplify_using_condition (rtx cond, rtx *expr, regset altered)
01608 {
01609 rtx rev, reve, exp = *expr;
01610
01611 if (!COMPARISON_P (exp))
01612 return;
01613
01614
01615
01616 if (altered
01617 && for_each_rtx (&cond, altered_reg_used, altered))
01618 return;
01619
01620 rev = reversed_condition (cond);
01621 reve = reversed_condition (exp);
01622
01623 cond = canon_condition (cond);
01624 exp = canon_condition (exp);
01625 if (rev)
01626 rev = canon_condition (rev);
01627 if (reve)
01628 reve = canon_condition (reve);
01629
01630 if (rtx_equal_p (exp, cond))
01631 {
01632 *expr = const_true_rtx;
01633 return;
01634 }
01635
01636
01637 if (rev && rtx_equal_p (exp, rev))
01638 {
01639 *expr = const0_rtx;
01640 return;
01641 }
01642
01643 if (implies_p (cond, exp))
01644 {
01645 *expr = const_true_rtx;
01646 return;
01647 }
01648
01649 if (reve && implies_p (cond, reve))
01650 {
01651 *expr = const0_rtx;
01652 return;
01653 }
01654
01655
01656
01657 if (rev && implies_p (exp, rev))
01658 {
01659 *expr = const0_rtx;
01660 return;
01661 }
01662
01663
01664 if (rev && reve && implies_p (reve, rev))
01665 {
01666 *expr = const_true_rtx;
01667 return;
01668 }
01669
01670
01671
01672 return;
01673 }
01674
01675
01676
01677
01678 static void
01679 eliminate_implied_condition (enum rtx_code op, rtx a, rtx *b)
01680 {
01681 if (op == AND)
01682 {
01683
01684 if (implies_p (a, *b))
01685 *b = const_true_rtx;
01686 }
01687 else if (op == IOR)
01688 {
01689
01690 if (implies_p (*b, a))
01691 *b = const0_rtx;
01692 }
01693 else
01694 abort ();
01695 }
01696
01697
01698
01699
01700 static void
01701 eliminate_implied_conditions (enum rtx_code op, rtx *head, rtx tail)
01702 {
01703 rtx elt;
01704
01705 for (elt = tail; elt; elt = XEXP (elt, 1))
01706 eliminate_implied_condition (op, *head, &XEXP (elt, 0));
01707 for (elt = tail; elt; elt = XEXP (elt, 1))
01708 eliminate_implied_condition (op, XEXP (elt, 0), head);
01709 }
01710
01711
01712
01713
01714 static void
01715 simplify_using_initial_values (struct loop *loop, enum rtx_code op, rtx *expr)
01716 {
01717 rtx head, tail, insn;
01718 rtx neutral, aggr;
01719 regset altered;
01720 edge e;
01721
01722 if (!*expr)
01723 return;
01724
01725 if (CONSTANT_P (*expr))
01726 return;
01727
01728 if (GET_CODE (*expr) == EXPR_LIST)
01729 {
01730 head = XEXP (*expr, 0);
01731 tail = XEXP (*expr, 1);
01732
01733 eliminate_implied_conditions (op, &head, tail);
01734
01735 if (op == AND)
01736 {
01737 neutral = const_true_rtx;
01738 aggr = const0_rtx;
01739 }
01740 else if (op == IOR)
01741 {
01742 neutral = const0_rtx;
01743 aggr = const_true_rtx;
01744 }
01745 else
01746 abort ();
01747
01748 simplify_using_initial_values (loop, UNKNOWN, &head);
01749 if (head == aggr)
01750 {
01751 XEXP (*expr, 0) = aggr;
01752 XEXP (*expr, 1) = NULL_RTX;
01753 return;
01754 }
01755 else if (head == neutral)
01756 {
01757 *expr = tail;
01758 simplify_using_initial_values (loop, op, expr);
01759 return;
01760 }
01761 simplify_using_initial_values (loop, op, &tail);
01762
01763 if (tail && XEXP (tail, 0) == aggr)
01764 {
01765 *expr = tail;
01766 return;
01767 }
01768
01769 XEXP (*expr, 0) = head;
01770 XEXP (*expr, 1) = tail;
01771 return;
01772 }
01773
01774 if (op != UNKNOWN)
01775 abort ();
01776
01777 e = loop_preheader_edge (loop);
01778 if (e->src == ENTRY_BLOCK_PTR)
01779 return;
01780
01781 altered = ALLOC_REG_SET (®_obstack);
01782
01783 while (1)
01784 {
01785 basic_block tmp_bb;
01786
01787 insn = BB_END (e->src);
01788 if (any_condjump_p (insn))
01789 {
01790 rtx cond = get_condition (BB_END (e->src), NULL, false, true);
01791
01792 if (cond && (e->flags & EDGE_FALLTHRU))
01793 cond = reversed_condition (cond);
01794 if (cond)
01795 {
01796 simplify_using_condition (cond, expr, altered);
01797 if (CONSTANT_P (*expr))
01798 {
01799 FREE_REG_SET (altered);
01800 return;
01801 }
01802 }
01803 }
01804
01805 FOR_BB_INSNS_REVERSE (e->src, insn)
01806 {
01807 if (!INSN_P (insn))
01808 continue;
01809
01810 simplify_using_assignment (insn, expr, altered);
01811 if (CONSTANT_P (*expr))
01812 {
01813 FREE_REG_SET (altered);
01814 return;
01815 }
01816 }
01817
01818
01819
01820
01821 tmp_bb = e->src;
01822 e = EDGE_PRED (tmp_bb, 0);
01823 if (EDGE_COUNT (tmp_bb->preds) > 1
01824 || e->src == ENTRY_BLOCK_PTR)
01825 break;
01826 }
01827
01828 FREE_REG_SET (altered);
01829 }
01830
01831
01832
01833
01834
01835 static void
01836 shorten_into_mode (struct rtx_iv *iv, enum machine_mode mode,
01837 enum rtx_code cond, bool signed_p, struct niter_desc *desc)
01838 {
01839 rtx mmin, mmax, cond_over, cond_under;
01840
01841 get_mode_bounds (mode, signed_p, iv->extend_mode, &mmin, &mmax);
01842 cond_under = simplify_gen_relational (LT, SImode, iv->extend_mode,
01843 iv->base, mmin);
01844 cond_over = simplify_gen_relational (GT, SImode, iv->extend_mode,
01845 iv->base, mmax);
01846
01847 switch (cond)
01848 {
01849 case LE:
01850 case LT:
01851 case LEU:
01852 case LTU:
01853 if (cond_under != const0_rtx)
01854 desc->infinite =
01855 alloc_EXPR_LIST (0, cond_under, desc->infinite);
01856 if (cond_over != const0_rtx)
01857 desc->noloop_assumptions =
01858 alloc_EXPR_LIST (0, cond_over, desc->noloop_assumptions);
01859 break;
01860
01861 case GE:
01862 case GT:
01863 case GEU:
01864 case GTU:
01865 if (cond_over != const0_rtx)
01866 desc->infinite =
01867 alloc_EXPR_LIST (0, cond_over, desc->infinite);
01868 if (cond_under != const0_rtx)
01869 desc->noloop_assumptions =
01870 alloc_EXPR_LIST (0, cond_under, desc->noloop_assumptions);
01871 break;
01872
01873 case NE:
01874 if (cond_over != const0_rtx)
01875 desc->infinite =
01876 alloc_EXPR_LIST (0, cond_over, desc->infinite);
01877 if (cond_under != const0_rtx)
01878 desc->infinite =
01879 alloc_EXPR_LIST (0, cond_under, desc->infinite);
01880 break;
01881
01882 default:
01883 abort ();
01884 }
01885
01886 iv->mode = mode;
01887 iv->extend = signed_p ? SIGN_EXTEND : ZERO_EXTEND;
01888 }
01889
01890
01891
01892
01893
01894 static bool
01895 canonicalize_iv_subregs (struct rtx_iv *iv0, struct rtx_iv *iv1,
01896 enum rtx_code cond, struct niter_desc *desc)
01897 {
01898 enum machine_mode comp_mode;
01899 bool signed_p;
01900
01901
01902
01903 if (iv0->first_special || iv0->mult != const1_rtx || iv0->delta != const0_rtx)
01904 return false;
01905 if (iv1->first_special || iv1->mult != const1_rtx || iv1->delta != const0_rtx)
01906 return false;
01907
01908
01909 switch (cond)
01910 {
01911 case LE:
01912 case LT:
01913 if (iv0->extend == ZERO_EXTEND
01914 || iv1->extend == ZERO_EXTEND)
01915 return false;
01916 signed_p = true;
01917 break;
01918
01919 case LEU:
01920 case LTU:
01921 if (iv0->extend == SIGN_EXTEND
01922 || iv1->extend == SIGN_EXTEND)
01923 return false;
01924 signed_p = false;
01925 break;
01926
01927 case NE:
01928 if (iv0->extend != UNKNOWN
01929 && iv1->extend != UNKNOWN
01930 && iv0->extend != iv1->extend)
01931 return false;
01932
01933 signed_p = false;
01934 if (iv0->extend != UNKNOWN)
01935 signed_p = iv0->extend == SIGN_EXTEND;
01936 if (iv1->extend != UNKNOWN)
01937 signed_p = iv1->extend == SIGN_EXTEND;
01938 break;
01939
01940 default:
01941 abort ();
01942 }
01943
01944
01945
01946
01947
01948
01949
01950
01951
01952
01953
01954
01955
01956
01957 comp_mode = iv0->extend_mode;
01958 if (GET_MODE_BITSIZE (comp_mode) < GET_MODE_BITSIZE (iv1->extend_mode))
01959 comp_mode = iv1->extend_mode;
01960
01961 if (iv0->extend_mode != comp_mode)
01962 {
01963 if (iv0->mode != iv0->extend_mode
01964 || iv0->step != const0_rtx)
01965 return false;
01966
01967 iv0->base = simplify_gen_unary (signed_p ? SIGN_EXTEND : ZERO_EXTEND,
01968 comp_mode, iv0->base, iv0->mode);
01969 iv0->extend_mode = comp_mode;
01970 }
01971
01972 if (iv1->extend_mode != comp_mode)
01973 {
01974 if (iv1->mode != iv1->extend_mode
01975 || iv1->step != const0_rtx)
01976 return false;
01977
01978 iv1->base = simplify_gen_unary (signed_p ? SIGN_EXTEND : ZERO_EXTEND,
01979 comp_mode, iv1->base, iv1->mode);
01980 iv1->extend_mode = comp_mode;
01981 }
01982
01983
01984
01985
01986 if (iv0->mode == iv0->extend_mode
01987 && iv0->step == const0_rtx
01988 && iv0->mode != iv1->mode)
01989 shorten_into_mode (iv0, iv1->mode, cond, signed_p, desc);
01990
01991 if (iv1->mode == iv1->extend_mode
01992 && iv1->step == const0_rtx
01993 && iv0->mode != iv1->mode)
01994 shorten_into_mode (iv1, iv0->mode, swap_condition (cond), signed_p, desc);
01995
01996 if (iv0->mode != iv1->mode)
01997 return false;
01998
01999 desc->mode = iv0->mode;
02000 desc->signed_p = signed_p;
02001
02002 return true;
02003 }
02004
02005
02006
02007
02008
02009 static void
02010 iv_number_of_iterations (struct loop *loop, rtx insn, rtx condition,
02011 struct niter_desc *desc)
02012 {
02013 rtx op0, op1, delta, step, bound, may_xform, def_insn, tmp, tmp0, tmp1;
02014 struct rtx_iv iv0, iv1, tmp_iv;
02015 rtx assumption, may_not_xform;
02016 enum rtx_code cond;
02017 enum machine_mode mode, comp_mode;
02018 rtx mmin, mmax, mode_mmin, mode_mmax;
02019 unsigned HOST_WIDEST_INT s, size, d, inv;
02020 HOST_WIDEST_INT up, down, inc, step_val;
02021 int was_sharp = false;
02022 rtx old_niter;
02023 bool step_is_pow2;
02024
02025
02026
02027
02028
02029
02030
02031 desc->assumptions = NULL_RTX;
02032 desc->noloop_assumptions = NULL_RTX;
02033 desc->infinite = NULL_RTX;
02034 desc->simple_p = true;
02035
02036 desc->const_iter = false;
02037 desc->niter_expr = NULL_RTX;
02038 desc->niter_max = 0;
02039
02040 cond = GET_CODE (condition);
02041 if (!COMPARISON_P (condition))
02042 abort ();
02043
02044 mode = GET_MODE (XEXP (condition, 0));
02045 if (mode == VOIDmode)
02046 mode = GET_MODE (XEXP (condition, 1));
02047
02048 if (mode == VOIDmode)
02049 abort ();
02050
02051
02052 if (GET_MODE_CLASS (mode) != MODE_INT
02053 && GET_MODE_CLASS (mode) != MODE_PARTIAL_INT)
02054 goto fail;
02055
02056 op0 = XEXP (condition, 0);
02057 def_insn = iv_get_reaching_def (insn, op0);
02058 if (!iv_analyze (def_insn, op0, &iv0))
02059 goto fail;
02060 if (iv0.extend_mode == VOIDmode)
02061 iv0.mode = iv0.extend_mode = mode;
02062
02063 op1 = XEXP (condition, 1);
02064 def_insn = iv_get_reaching_def (insn, op1);
02065 if (!iv_analyze (def_insn, op1, &iv1))
02066 goto fail;
02067 if (iv1.extend_mode == VOIDmode)
02068 iv1.mode = iv1.extend_mode = mode;
02069
02070 if (GET_MODE_BITSIZE (iv0.extend_mode) > HOST_BITS_PER_WIDE_INT
02071 || GET_MODE_BITSIZE (iv1.extend_mode) > HOST_BITS_PER_WIDE_INT)
02072 goto fail;
02073
02074
02075
02076 switch (cond)
02077 {
02078 case GE:
02079 case GT:
02080 case GEU:
02081 case GTU:
02082 tmp_iv = iv0; iv0 = iv1; iv1 = tmp_iv;
02083 cond = swap_condition (cond);
02084 break;
02085 case NE:
02086 case LE:
02087 case LEU:
02088 case LT:
02089 case LTU:
02090 break;
02091 default:
02092 goto fail;
02093 }
02094
02095
02096
02097
02098
02099
02100 if (!canonicalize_iv_subregs (&iv0, &iv1, cond, desc))
02101 goto fail;
02102
02103 comp_mode = iv0.extend_mode;
02104 mode = iv0.mode;
02105 size = GET_MODE_BITSIZE (mode);
02106 get_mode_bounds (mode, (cond == LE || cond == LT), comp_mode, &mmin, &mmax);
02107 mode_mmin = lowpart_subreg (mode, mmin, comp_mode);
02108 mode_mmax = lowpart_subreg (mode, mmax, comp_mode);
02109
02110 if (GET_CODE (iv0.step) != CONST_INT || GET_CODE (iv1.step) != CONST_INT)
02111 goto fail;
02112
02113
02114
02115
02116 if (iv0.step != const0_rtx && iv1.step != const0_rtx)
02117 {
02118 if (cond != NE)
02119 goto fail;
02120
02121 iv0.step = simplify_gen_binary (MINUS, comp_mode, iv0.step, iv1.step);
02122 iv1.step = const0_rtx;
02123 }
02124
02125
02126
02127 if (iv0.step == const0_rtx && iv1.step == const0_rtx)
02128 goto fail;
02129
02130 if (cond != NE)
02131 {
02132 if (iv0.step == const0_rtx)
02133 step_val = -INTVAL (iv1.step);
02134 else
02135 step_val = INTVAL (iv0.step);
02136
02137
02138 if (step_val < 0)
02139 goto fail;
02140
02141 step_is_pow2 = !(step_val & (step_val - 1));
02142 }
02143 else
02144 {
02145
02146
02147 step_is_pow2 = false;
02148 step_val = 0;
02149 }
02150
02151
02152
02153 switch (cond)
02154 {
02155 case LT:
02156 case LTU:
02157
02158
02159
02160
02161
02162
02163 if (iv0.step == const0_rtx)
02164 {
02165 tmp = lowpart_subreg (mode, iv0.base, comp_mode);
02166 assumption = simplify_gen_relational (EQ, SImode, mode, tmp,
02167 mode_mmax);
02168 if (assumption == const_true_rtx)
02169 goto zero_iter_simplify;
02170 iv0.base = simplify_gen_binary (PLUS, comp_mode,
02171 iv0.base, const1_rtx);
02172 }
02173 else
02174 {
02175 tmp = lowpart_subreg (mode, iv1.base, comp_mode);
02176 assumption = simplify_gen_relational (EQ, SImode, mode, tmp,
02177 mode_mmin);
02178 if (assumption == const_true_rtx)
02179 goto zero_iter_simplify;
02180 iv1.base = simplify_gen_binary (PLUS, comp_mode,
02181 iv1.base, constm1_rtx);
02182 }
02183
02184 if (assumption != const0_rtx)
02185 desc->noloop_assumptions =
02186 alloc_EXPR_LIST (0, assumption, desc->noloop_assumptions);
02187 cond = (cond == LT) ? LE : LEU;
02188
02189
02190
02191 was_sharp = true;
02192 break;
02193 default: ;
02194 }
02195
02196
02197 if (cond != NE)
02198 {
02199 if (iv0.step == const0_rtx)
02200 {
02201 tmp = lowpart_subreg (mode, iv0.base, comp_mode);
02202 if (rtx_equal_p (tmp, mode_mmin))
02203 {
02204 desc->infinite =
02205 alloc_EXPR_LIST (0, const_true_rtx, NULL_RTX);
02206
02207 goto zero_iter_simplify;
02208 }
02209 }
02210 else
02211 {
02212 tmp = lowpart_subreg (mode, iv1.base, comp_mode);
02213 if (rtx_equal_p (tmp, mode_mmax))
02214 {
02215 desc->infinite =
02216 alloc_EXPR_LIST (0, const_true_rtx, NULL_RTX);
02217
02218 goto zero_iter_simplify;
02219 }
02220 }
02221 }
02222
02223
02224
02225
02226
02227
02228
02229 if (cond != NE)
02230 {
02231 if (iv0.step == const0_rtx)
02232 step = simplify_gen_unary (NEG, comp_mode, iv1.step, comp_mode);
02233 else
02234 step = iv0.step;
02235 delta = simplify_gen_binary (MINUS, comp_mode, iv1.base, iv0.base);
02236 delta = lowpart_subreg (mode, delta, comp_mode);
02237 delta = simplify_gen_binary (UMOD, mode, delta, step);
02238 may_xform = const0_rtx;
02239 may_not_xform = const_true_rtx;
02240
02241 if (GET_CODE (delta) == CONST_INT)
02242 {
02243 if (was_sharp && INTVAL (delta) == INTVAL (step) - 1)
02244 {
02245
02246
02247
02248
02249
02250
02251
02252
02253
02254 may_xform = const_true_rtx;
02255 }
02256 else if (iv0.step == const0_rtx)
02257 {
02258 bound = simplify_gen_binary (PLUS, comp_mode, mmin, step);
02259 bound = simplify_gen_binary (MINUS, comp_mode, bound, delta);
02260 bound = lowpart_subreg (mode, bound, comp_mode);
02261 tmp = lowpart_subreg (mode, iv0.base, comp_mode);
02262 may_xform = simplify_gen_relational (cond, SImode, mode,
02263 bound, tmp);
02264 may_not_xform = simplify_gen_relational (reverse_condition (cond),
02265 SImode, mode,
02266 bound, tmp);
02267 }
02268 else
02269 {
02270 bound = simplify_gen_binary (MINUS, comp_mode, mmax, step);
02271 bound = simplify_gen_binary (PLUS, comp_mode, bound, delta);
02272 bound = lowpart_subreg (mode, bound, comp_mode);
02273 tmp = lowpart_subreg (mode, iv1.base, comp_mode);
02274 may_xform = simplify_gen_relational (cond, SImode, mode,
02275 tmp, bound);
02276 may_not_xform = simplify_gen_relational (reverse_condition (cond),
02277 SImode, mode,
02278 tmp, bound);
02279 }
02280 }
02281
02282 if (may_xform != const0_rtx)
02283 {
02284
02285
02286
02287 if (may_xform != const_true_rtx)
02288 {
02289
02290
02291
02292 if (step_is_pow2)
02293 desc->infinite = alloc_EXPR_LIST (0, may_not_xform,
02294 desc->infinite);
02295 else
02296 desc->assumptions = alloc_EXPR_LIST (0, may_xform,
02297 desc->assumptions);
02298 }
02299
02300
02301
02302
02303 inc = INTVAL (iv0.step) - INTVAL (iv1.step);
02304 if (GET_CODE (iv1.base) == CONST_INT)
02305 up = INTVAL (iv1.base);
02306 else
02307 up = INTVAL (mode_mmax) - inc;
02308 down = INTVAL (GET_CODE (iv0.base) == CONST_INT
02309 ? iv0.base
02310 : mode_mmin);
02311 desc->niter_max = (up - down) / inc + 1;
02312
02313 if (iv0.step == const0_rtx)
02314 {
02315 iv0.base = simplify_gen_binary (PLUS, comp_mode, iv0.base, delta);
02316 iv0.base = simplify_gen_binary (MINUS, comp_mode, iv0.base, step);
02317 }
02318 else
02319 {
02320 iv1.base = simplify_gen_binary (MINUS, comp_mode, iv1.base, delta);
02321 iv1.base = simplify_gen_binary (PLUS, comp_mode, iv1.base, step);
02322 }
02323
02324 tmp0 = lowpart_subreg (mode, iv0.base, comp_mode);
02325 tmp1 = lowpart_subreg (mode, iv1.base, comp_mode);
02326 assumption = simplify_gen_relational (reverse_condition (cond),
02327 SImode, mode, tmp0, tmp1);
02328 if (assumption == const_true_rtx)
02329 goto zero_iter_simplify;
02330 else if (assumption != const0_rtx)
02331 desc->noloop_assumptions =
02332 alloc_EXPR_LIST (0, assumption, desc->noloop_assumptions);
02333 cond = NE;
02334 }
02335 }
02336
02337
02338 if (cond == NE)
02339 {
02340
02341
02342
02343
02344 iv1.base = simplify_gen_binary (MINUS, comp_mode, iv1.base, iv0.base);
02345 iv0.base = const0_rtx;
02346 iv0.step = simplify_gen_binary (MINUS, comp_mode, iv0.step, iv1.step);
02347 iv1.step = const0_rtx;
02348 if (INTVAL (iv0.step) < 0)
02349 {
02350 iv0.step = simplify_gen_unary (NEG, comp_mode, iv0.step, mode);
02351 iv1.base = simplify_gen_unary (NEG, comp_mode, iv1.base, mode);
02352 }
02353 iv0.step = lowpart_subreg (mode, iv0.step, comp_mode);
02354
02355
02356
02357
02358 s = INTVAL (iv0.step); d = 1;
02359 while (s % 2 != 1)
02360 {
02361 s /= 2;
02362 d *= 2;
02363 size--;
02364 }
02365 bound = GEN_INT (((unsigned HOST_WIDEST_INT) 1 << (size - 1 ) << 1) - 1);
02366
02367 tmp1 = lowpart_subreg (mode, iv1.base, comp_mode);
02368 tmp = simplify_gen_binary (UMOD, mode, tmp1, GEN_INT (d));
02369 assumption = simplify_gen_relational (NE, SImode, mode, tmp, const0_rtx);
02370 desc->infinite = alloc_EXPR_LIST (0, assumption, desc->infinite);
02371
02372 tmp = simplify_gen_binary (UDIV, mode, tmp1, GEN_INT (d));
02373 inv = inverse (s, size);
02374 inv = trunc_int_for_mode (inv, mode);
02375 tmp = simplify_gen_binary (MULT, mode, tmp, GEN_INT (inv));
02376 desc->niter_expr = simplify_gen_binary (AND, mode, tmp, bound);
02377 }
02378 else
02379 {
02380 if (iv1.step == const0_rtx)
02381
02382
02383
02384
02385
02386
02387 {
02388 step = iv0.step;
02389 tmp0 = lowpart_subreg (mode, iv0.base, comp_mode);
02390 tmp1 = lowpart_subreg (mode, iv1.base, comp_mode);
02391
02392 bound = simplify_gen_binary (MINUS, mode, mode_mmax,
02393 lowpart_subreg (mode, step,
02394 comp_mode));
02395 if (step_is_pow2)
02396 {
02397 rtx t0, t1;
02398
02399
02400
02401 assumption = simplify_gen_relational (reverse_condition (cond),
02402 SImode, mode,
02403 tmp1, bound);
02404
02405 t0 = simplify_gen_binary (UMOD, mode, copy_rtx (tmp0), step);
02406 t1 = simplify_gen_binary (UMOD, mode, copy_rtx (tmp1), step);
02407 tmp = simplify_gen_relational (cond, SImode, mode, t0, t1);
02408 assumption = simplify_gen_binary (AND, SImode, assumption, tmp);
02409 desc->infinite =
02410 alloc_EXPR_LIST (0, assumption, desc->infinite);
02411 }
02412 else
02413 {
02414 assumption = simplify_gen_relational (cond, SImode, mode,
02415 tmp1, bound);
02416 desc->assumptions =
02417 alloc_EXPR_LIST (0, assumption, desc->assumptions);
02418 }
02419
02420 tmp = simplify_gen_binary (PLUS, comp_mode, iv1.base, iv0.step);
02421 tmp = lowpart_subreg (mode, tmp, comp_mode);
02422 assumption = simplify_gen_relational (reverse_condition (cond),
02423 SImode, mode, tmp0, tmp);
02424
02425 delta = simplify_gen_binary (PLUS, mode, tmp1, step);
02426 delta = simplify_gen_binary (MINUS, mode, delta, tmp0);
02427 }
02428 else
02429 {
02430
02431
02432
02433 step = simplify_gen_unary (NEG, mode, iv1.step, mode);
02434 tmp0 = lowpart_subreg (mode, iv0.base, comp_mode);
02435 tmp1 = lowpart_subreg (mode, iv1.base, comp_mode);
02436
02437 bound = simplify_gen_binary (MINUS, mode, mode_mmin,
02438 lowpart_subreg (mode, step, comp_mode));
02439 if (step_is_pow2)
02440 {
02441 rtx t0, t1;
02442
02443
02444
02445 assumption = simplify_gen_relational (reverse_condition (cond),
02446 SImode, mode,
02447 bound, tmp0);
02448
02449 t0 = simplify_gen_binary (UMOD, mode, copy_rtx (tmp0), step);
02450 t1 = simplify_gen_binary (UMOD, mode, copy_rtx (tmp1), step);
02451 tmp = simplify_gen_relational (cond, SImode, mode, t0, t1);
02452 assumption = simplify_gen_binary (AND, SImode, assumption, tmp);
02453 desc->infinite =
02454 alloc_EXPR_LIST (0, assumption, desc->infinite);
02455 }
02456 else
02457 {
02458 assumption = simplify_gen_relational (cond, SImode, mode,
02459 bound, tmp0);
02460 desc->assumptions =
02461 alloc_EXPR_LIST (0, assumption, desc->assumptions);
02462 }
02463
02464 tmp = simplify_gen_binary (PLUS, comp_mode, iv0.base, iv1.step);
02465 tmp = lowpart_subreg (mode, tmp, comp_mode);
02466 assumption = simplify_gen_relational (reverse_condition (cond),
02467 SImode, mode,
02468 tmp, tmp1);
02469 delta = simplify_gen_binary (MINUS, mode, tmp0, step);
02470 delta = simplify_gen_binary (MINUS, mode, tmp1, delta);
02471 }
02472 if (assumption == const_true_rtx)
02473 goto zero_iter_simplify;
02474 else if (assumption != const0_rtx)
02475 desc->noloop_assumptions =
02476 alloc_EXPR_LIST (0, assumption, desc->noloop_assumptions);
02477 delta = simplify_gen_binary (UDIV, mode, delta, step);
02478 desc->niter_expr = delta;
02479 }
02480
02481 old_niter = desc->niter_expr;
02482
02483 simplify_using_initial_values (loop, AND, &desc->assumptions);
02484 if (desc->assumptions
02485 && XEXP (desc->assumptions, 0) == const0_rtx)
02486 goto fail;
02487 simplify_using_initial_values (loop, IOR, &desc->noloop_assumptions);
02488 simplify_using_initial_values (loop, IOR, &desc->infinite);
02489 simplify_using_initial_values (loop, UNKNOWN, &desc->niter_expr);
02490
02491
02492
02493
02494
02495
02496
02497
02498
02499
02500
02501
02502
02503
02504
02505
02506 simplify_using_initial_values (loop, AND, &desc->assumptions);
02507 if (desc->assumptions
02508 && XEXP (desc->assumptions, 0) == const0_rtx)
02509 goto fail;
02510 simplify_using_initial_values (loop, IOR, &desc->noloop_assumptions);
02511 simplify_using_initial_values (loop, IOR, &desc->infinite);
02512 simplify_using_initial_values (loop, UNKNOWN, &desc->niter_expr);
02513
02514 if (desc->noloop_assumptions
02515 && XEXP (desc->noloop_assumptions, 0) == const_true_rtx)
02516 goto zero_iter;
02517
02518 if (GET_CODE (desc->niter_expr) == CONST_INT)
02519 {
02520 unsigned HOST_WIDEST_INT val = INTVAL (desc->niter_expr);
02521
02522 desc->const_iter = true;
02523 desc->niter_max = desc->niter = val & GET_MODE_MASK (desc->mode);
02524 }
02525 else
02526 {
02527 if (!desc->niter_max)
02528 desc->niter_max = determine_max_iter (desc);
02529
02530
02531
02532
02533
02534
02535
02536 desc->niter_expr = old_niter;
02537 }
02538
02539 return;
02540
02541 zero_iter_simplify:
02542
02543 simplify_using_initial_values (loop, AND, &desc->assumptions);
02544 if (desc->assumptions
02545 && XEXP (desc->assumptions, 0) == const0_rtx)
02546 goto fail;
02547 simplify_using_initial_values (loop, IOR, &desc->infinite);
02548
02549
02550 zero_iter:
02551 desc->const_iter = true;
02552 desc->niter = 0;
02553 desc->niter_max = 0;
02554 desc->noloop_assumptions = NULL_RTX;
02555 desc->niter_expr = const0_rtx;
02556 return;
02557
02558 fail:
02559 desc->simple_p = false;
02560 return;
02561 }
02562
02563
02564
02565
02566 static void
02567 check_simple_exit (struct loop *loop, edge e, struct niter_desc *desc)
02568 {
02569 basic_block exit_bb;
02570 rtx condition, at;
02571 edge ein;
02572
02573 exit_bb = e->src;
02574 desc->simple_p = false;
02575
02576
02577 if (exit_bb->loop_father != loop)
02578 return;
02579
02580
02581 if (!dominated_by_p (CDI_DOMINATORS, loop->latch, exit_bb))
02582 return;
02583
02584
02585 if (!any_condjump_p (BB_END (exit_bb)))
02586 return;
02587
02588 ein = EDGE_SUCC (exit_bb, 0);
02589 if (ein == e)
02590 ein = EDGE_SUCC (exit_bb, 1);
02591
02592 desc->out_edge = e;
02593 desc->in_edge = ein;
02594
02595
02596 if (!(condition = get_condition (BB_END (ein->src), &at, false, false)))
02597 return;
02598
02599 if (ein->flags & EDGE_FALLTHRU)
02600 {
02601 condition = reversed_condition (condition);
02602 if (!condition)
02603 return;
02604 }
02605
02606
02607
02608 iv_number_of_iterations (loop, at, condition, desc);
02609 }
02610
02611
02612
02613 void
02614 find_simple_exit (struct loop *loop, struct niter_desc *desc)
02615 {
02616 unsigned i;
02617 basic_block *body;
02618 edge e;
02619 struct niter_desc act;
02620 bool any = false;
02621 edge_iterator ei;
02622
02623 desc->simple_p = false;
02624 body = get_loop_body (loop);
02625
02626 for (i = 0; i < loop->num_nodes; i++)
02627 {
02628 FOR_EACH_EDGE (e, ei, body[i]->succs)
02629 {
02630 if (flow_bb_inside_loop_p (loop, e->dest))
02631 continue;
02632
02633 check_simple_exit (loop, e, &act);
02634 if (!act.simple_p)
02635 continue;
02636
02637 if (!any)
02638 any = true;
02639 else
02640 {
02641
02642 if (!act.const_iter
02643 || (desc->const_iter && act.niter >= desc->niter))
02644 continue;
02645
02646
02647
02648 if (act.infinite && !desc->infinite)
02649 continue;
02650 }
02651
02652 *desc = act;
02653 }
02654 }
02655
02656 if (dump_file)
02657 {
02658 if (desc->simple_p)
02659 {
02660 fprintf (dump_file, "Loop %d is simple:\n", loop->num);
02661 fprintf (dump_file, " simple exit %d -> %d\n",
02662 desc->out_edge->src->index,
02663 desc->out_edge->dest->index);
02664 if (desc->assumptions)
02665 {
02666 fprintf (dump_file, " assumptions: ");
02667 print_rtl (dump_file, desc->assumptions);
02668 fprintf (dump_file, "\n");
02669 }
02670 if (desc->noloop_assumptions)
02671 {
02672 fprintf (dump_file, " does not roll if: ");
02673 print_rtl (dump_file, desc->noloop_assumptions);
02674 fprintf (dump_file, "\n");
02675 }
02676 if (desc->infinite)
02677 {
02678 fprintf (dump_file, " infinite if: ");
02679 print_rtl (dump_file, desc->infinite);
02680 fprintf (dump_file, "\n");
02681 }
02682
02683 fprintf (dump_file, " number of iterations: ");
02684 print_rtl (dump_file, desc->niter_expr);
02685 fprintf (dump_file, "\n");
02686
02687 fprintf (dump_file, " upper bound: ");
02688 fprintf (dump_file, HOST_WIDEST_INT_PRINT_DEC, desc->niter_max);
02689 fprintf (dump_file, "\n");
02690 }
02691 else
02692 fprintf (dump_file, "Loop %d is not simple.\n", loop->num);
02693 }
02694
02695 free (body);
02696 }
02697
02698
02699
02700
02701 struct niter_desc *
02702 get_simple_loop_desc (struct loop *loop)
02703 {
02704 struct niter_desc *desc = simple_loop_desc (loop);
02705
02706 if (desc)
02707 return desc;
02708
02709 desc = xmalloc (sizeof (struct niter_desc));
02710 iv_analysis_loop_init (loop);
02711 find_simple_exit (loop, desc);
02712 loop->aux = desc;
02713
02714 return desc;
02715 }
02716
02717
02718
02719 void
02720 free_simple_loop_desc (struct loop *loop)
02721 {
02722 struct niter_desc *desc = simple_loop_desc (loop);
02723
02724 if (!desc)
02725 return;
02726
02727 free (desc);
02728 loop->aux = NULL;
02729 }