00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "config.h"
00022 #include "system.h"
00023 #include "coretypes.h"
00024 #include "tm.h"
00025 #include "rtl.h"
00026 #include "hard-reg-set.h"
00027 #include "obstack.h"
00028 #include "basic-block.h"
00029 #include "cfgloop.h"
00030 #include "cfglayout.h"
00031 #include "params.h"
00032 #include "output.h"
00033 #include "expr.h"
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 static struct loop *unswitch_loop (struct loops *, struct loop *,
00083 basic_block, rtx, rtx);
00084 static void unswitch_single_loop (struct loops *, struct loop *, rtx, int);
00085 static rtx may_unswitch_on (basic_block, struct loop *, rtx *);
00086
00087
00088
00089
00090
00091 rtx
00092 compare_and_jump_seq (rtx op0, rtx op1, enum rtx_code comp, rtx label, int prob,
00093 rtx cinsn)
00094 {
00095 rtx seq, jump, cond;
00096 enum machine_mode mode;
00097
00098 mode = GET_MODE (op0);
00099 if (mode == VOIDmode)
00100 mode = GET_MODE (op1);
00101
00102 start_sequence ();
00103 if (GET_MODE_CLASS (mode) == MODE_CC)
00104 {
00105
00106
00107 gcc_assert (cinsn);
00108 cond = XEXP (SET_SRC (pc_set (cinsn)), 0);
00109 gcc_assert (GET_CODE (cond) == comp);
00110 gcc_assert (rtx_equal_p (op0, XEXP (cond, 0)));
00111 gcc_assert (rtx_equal_p (op1, XEXP (cond, 1)));
00112 emit_jump_insn (copy_insn (PATTERN (cinsn)));
00113 jump = get_last_insn ();
00114 JUMP_LABEL (jump) = JUMP_LABEL (cinsn);
00115 LABEL_NUSES (JUMP_LABEL (jump))++;
00116 redirect_jump (jump, label, 0);
00117 }
00118 else
00119 {
00120 gcc_assert (!cinsn);
00121
00122 op0 = force_operand (op0, NULL_RTX);
00123 op1 = force_operand (op1, NULL_RTX);
00124 do_compare_rtx_and_jump (op0, op1, comp, 0,
00125 mode, NULL_RTX, NULL_RTX, label);
00126 jump = get_last_insn ();
00127 JUMP_LABEL (jump) = label;
00128 LABEL_NUSES (label)++;
00129 }
00130 REG_NOTES (jump) = gen_rtx_EXPR_LIST (REG_BR_PROB, GEN_INT (prob),
00131 REG_NOTES (jump));
00132 seq = get_insns ();
00133 end_sequence ();
00134
00135 return seq;
00136 }
00137
00138
00139 void
00140 unswitch_loops (struct loops *loops)
00141 {
00142 int i, num;
00143 struct loop *loop;
00144
00145
00146 num = loops->num;
00147
00148 for (i = 1; i < num; i++)
00149 {
00150
00151 loop = loops->parray[i];
00152 if (!loop)
00153 continue;
00154
00155 if (loop->inner)
00156 continue;
00157
00158 unswitch_single_loop (loops, loop, NULL_RTX, 0);
00159 #ifdef ENABLE_CHECKING
00160 verify_dominators (CDI_DOMINATORS);
00161 verify_loop_structure (loops);
00162 #endif
00163 }
00164
00165 iv_analysis_done ();
00166 }
00167
00168
00169
00170
00171
00172 static rtx
00173 may_unswitch_on (basic_block bb, struct loop *loop, rtx *cinsn)
00174 {
00175 rtx test, at, op[2], stest;
00176 struct rtx_iv iv;
00177 unsigned i;
00178 enum machine_mode mode;
00179
00180
00181 if (EDGE_COUNT (bb->succs) != 2)
00182 return NULL_RTX;
00183 if (!any_condjump_p (BB_END (bb)))
00184 return NULL_RTX;
00185
00186
00187 if (!flow_bb_inside_loop_p (loop, EDGE_SUCC (bb, 0)->dest)
00188 || !flow_bb_inside_loop_p (loop, EDGE_SUCC (bb, 1)->dest))
00189 return NULL_RTX;
00190
00191
00192
00193 if (!just_once_each_iteration_p (loop, bb))
00194 return NULL_RTX;
00195
00196
00197 test = get_condition (BB_END (bb), &at, true, false);
00198 if (!test)
00199 return NULL_RTX;
00200
00201 for (i = 0; i < 2; i++)
00202 {
00203 op[i] = XEXP (test, i);
00204
00205 if (CONSTANT_P (op[i]))
00206 continue;
00207
00208 if (!iv_analyze (at, op[i], &iv))
00209 return NULL_RTX;
00210 if (iv.step != const0_rtx
00211 || iv.first_special)
00212 return NULL_RTX;
00213
00214 op[i] = get_iv_value (&iv, const0_rtx);
00215 }
00216
00217 mode = GET_MODE (op[0]);
00218 if (mode == VOIDmode)
00219 mode = GET_MODE (op[1]);
00220 if (GET_MODE_CLASS (mode) == MODE_CC)
00221 {
00222 if (at != BB_END (bb))
00223 return NULL_RTX;
00224
00225 if (!rtx_equal_p (op[0], XEXP (test, 0))
00226 || !rtx_equal_p (op[1], XEXP (test, 1)))
00227 return NULL_RTX;
00228
00229 *cinsn = BB_END (bb);
00230 return test;
00231 }
00232
00233 stest = simplify_gen_relational (GET_CODE (test), SImode,
00234 mode, op[0], op[1]);
00235 if (stest == const0_rtx
00236 || stest == const_true_rtx)
00237 return stest;
00238
00239 return canon_condition (gen_rtx_fmt_ee (GET_CODE (test), SImode,
00240 op[0], op[1]));
00241 }
00242
00243
00244 rtx
00245 reversed_condition (rtx cond)
00246 {
00247 enum rtx_code reversed;
00248 reversed = reversed_comparison_code (cond, NULL);
00249 if (reversed == UNKNOWN)
00250 return NULL_RTX;
00251 else
00252 return gen_rtx_fmt_ee (reversed,
00253 GET_MODE (cond), XEXP (cond, 0),
00254 XEXP (cond, 1));
00255 }
00256
00257
00258
00259
00260
00261 static void
00262 unswitch_single_loop (struct loops *loops, struct loop *loop,
00263 rtx cond_checked, int num)
00264 {
00265 basic_block *bbs;
00266 struct loop *nloop;
00267 unsigned i;
00268 rtx cond, rcond = NULL_RTX, conds, rconds, acond, cinsn;
00269 int repeat;
00270 edge e;
00271
00272
00273 if (num > PARAM_VALUE (PARAM_MAX_UNSWITCH_LEVEL))
00274 {
00275 if (dump_file)
00276 fprintf (dump_file, ";; Not unswitching anymore, hit max level\n");
00277 return;
00278 }
00279
00280
00281 if (loop->inner)
00282 {
00283 if (dump_file)
00284 fprintf (dump_file, ";; Not unswitching, not innermost loop\n");
00285 return;
00286 }
00287
00288
00289 if (!can_duplicate_loop_p (loop))
00290 {
00291 if (dump_file)
00292 fprintf (dump_file, ";; Not unswitching, can't duplicate loop\n");
00293 return;
00294 }
00295
00296
00297 if (num_loop_insns (loop) > PARAM_VALUE (PARAM_MAX_UNSWITCH_INSNS))
00298 {
00299 if (dump_file)
00300 fprintf (dump_file, ";; Not unswitching, loop too big\n");
00301 return;
00302 }
00303
00304
00305 if (!maybe_hot_bb_p (loop->header))
00306 {
00307 if (dump_file)
00308 fprintf (dump_file, ";; Not unswitching, not hot area\n");
00309 return;
00310 }
00311
00312
00313 if (expected_loop_iterations (loop) < 1)
00314 {
00315 if (dump_file)
00316 fprintf (dump_file, ";; Not unswitching, loop iterations < 1\n");
00317 return;
00318 }
00319
00320 do
00321 {
00322 repeat = 0;
00323 cinsn = NULL_RTX;
00324
00325
00326 bbs = get_loop_body (loop);
00327 iv_analysis_loop_init (loop);
00328 for (i = 0; i < loop->num_nodes; i++)
00329 if ((cond = may_unswitch_on (bbs[i], loop, &cinsn)))
00330 break;
00331
00332 if (i == loop->num_nodes)
00333 {
00334 free (bbs);
00335 return;
00336 }
00337
00338 if (cond != const0_rtx
00339 && cond != const_true_rtx)
00340 {
00341 rcond = reversed_condition (cond);
00342 if (rcond)
00343 rcond = canon_condition (rcond);
00344
00345
00346 for (acond = cond_checked; acond; acond = XEXP (acond, 1))
00347 simplify_using_condition (XEXP (acond, 0), &cond, NULL);
00348 }
00349
00350 if (cond == const_true_rtx)
00351 {
00352
00353 e = FALLTHRU_EDGE (bbs[i]);
00354 remove_path (loops, e);
00355 free (bbs);
00356 repeat = 1;
00357 }
00358 else if (cond == const0_rtx)
00359 {
00360
00361 e = BRANCH_EDGE (bbs[i]);
00362 remove_path (loops, e);
00363 free (bbs);
00364 repeat = 1;
00365 }
00366 } while (repeat);
00367
00368
00369 conds = alloc_EXPR_LIST (0, cond, cond_checked);
00370 if (rcond)
00371 rconds = alloc_EXPR_LIST (0, rcond, cond_checked);
00372 else
00373 rconds = cond_checked;
00374
00375 if (dump_file)
00376 fprintf (dump_file, ";; Unswitching loop\n");
00377
00378
00379 nloop = unswitch_loop (loops, loop, bbs[i], cond, cinsn);
00380 gcc_assert (nloop);
00381
00382
00383 unswitch_single_loop (loops, nloop, rconds, num + 1);
00384 unswitch_single_loop (loops, loop, conds, num + 1);
00385
00386 free_EXPR_LIST_node (conds);
00387 if (rcond)
00388 free_EXPR_LIST_node (rconds);
00389
00390 free (bbs);
00391 }
00392
00393
00394
00395
00396
00397
00398
00399
00400 static struct loop *
00401 unswitch_loop (struct loops *loops, struct loop *loop, basic_block unswitch_on,
00402 rtx cond, rtx cinsn)
00403 {
00404 edge entry, latch_edge, true_edge, false_edge, e;
00405 basic_block switch_bb, unswitch_on_alt;
00406 struct loop *nloop;
00407 sbitmap zero_bitmap;
00408 int irred_flag, prob;
00409 rtx seq;
00410
00411
00412 gcc_assert (flow_bb_inside_loop_p (loop, unswitch_on));
00413 gcc_assert (EDGE_COUNT (unswitch_on->succs) == 2);
00414 gcc_assert (just_once_each_iteration_p (loop, unswitch_on));
00415 gcc_assert (!loop->inner);
00416 gcc_assert (flow_bb_inside_loop_p (loop, EDGE_SUCC (unswitch_on, 0)->dest));
00417 gcc_assert (flow_bb_inside_loop_p (loop, EDGE_SUCC (unswitch_on, 1)->dest));
00418
00419 entry = loop_preheader_edge (loop);
00420
00421
00422 irred_flag = entry->flags & EDGE_IRREDUCIBLE_LOOP;
00423 entry->flags &= ~EDGE_IRREDUCIBLE_LOOP;
00424 zero_bitmap = sbitmap_alloc (2);
00425 sbitmap_zero (zero_bitmap);
00426 if (!duplicate_loop_to_header_edge (loop, entry, loops, 1,
00427 zero_bitmap, NULL, NULL, NULL, 0))
00428 {
00429 sbitmap_free (zero_bitmap);
00430 return NULL;
00431 }
00432 sbitmap_free (zero_bitmap);
00433 entry->flags |= irred_flag;
00434
00435
00436 unswitch_on_alt = get_bb_copy (unswitch_on);
00437 true_edge = BRANCH_EDGE (unswitch_on_alt);
00438 false_edge = FALLTHRU_EDGE (unswitch_on);
00439 latch_edge = single_succ_edge (get_bb_copy (loop->latch));
00440
00441
00442 prob = true_edge->probability;
00443 switch_bb = create_empty_bb (EXIT_BLOCK_PTR->prev_bb);
00444 seq = compare_and_jump_seq (XEXP (cond, 0), XEXP (cond, 1), GET_CODE (cond),
00445 block_label (true_edge->dest),
00446 prob, cinsn);
00447 emit_insn_after (seq, BB_END (switch_bb));
00448 e = make_edge (switch_bb, true_edge->dest, 0);
00449 e->probability = prob;
00450 e->count = latch_edge->count * prob / REG_BR_PROB_BASE;
00451 e = make_edge (switch_bb, FALLTHRU_EDGE (unswitch_on)->dest, EDGE_FALLTHRU);
00452 e->probability = false_edge->probability;
00453 e->count = latch_edge->count * (false_edge->probability) / REG_BR_PROB_BASE;
00454
00455 if (irred_flag)
00456 {
00457 switch_bb->flags |= BB_IRREDUCIBLE_LOOP;
00458 EDGE_SUCC (switch_bb, 0)->flags |= EDGE_IRREDUCIBLE_LOOP;
00459 EDGE_SUCC (switch_bb, 1)->flags |= EDGE_IRREDUCIBLE_LOOP;
00460 }
00461 else
00462 {
00463 switch_bb->flags &= ~BB_IRREDUCIBLE_LOOP;
00464 EDGE_SUCC (switch_bb, 0)->flags &= ~EDGE_IRREDUCIBLE_LOOP;
00465 EDGE_SUCC (switch_bb, 1)->flags &= ~EDGE_IRREDUCIBLE_LOOP;
00466 }
00467
00468
00469 nloop = loopify (loops, latch_edge,
00470 single_pred_edge (get_bb_copy (loop->header)), switch_bb,
00471 BRANCH_EDGE (switch_bb), FALLTHRU_EDGE (switch_bb), true);
00472
00473
00474 remove_path (loops, true_edge);
00475 remove_path (loops, false_edge);
00476
00477
00478
00479 fix_loop_placement (loop);
00480 fix_loop_placement (nloop);
00481
00482
00483 loop_split_edge_with (loop_preheader_edge (loop), NULL_RTX);
00484 loop_split_edge_with (loop_preheader_edge (nloop), NULL_RTX);
00485
00486 return nloop;
00487 }