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 #include "config.h"
00037 #include "system.h"
00038 #include "coretypes.h"
00039 #include "tm.h"
00040 #include "tree.h"
00041 #include "rtl.h"
00042 #include "tm_p.h"
00043 #include "hard-reg-set.h"
00044 #include "basic-block.h"
00045 #include "output.h"
00046 #include "diagnostic.h"
00047 #include "tree-flow.h"
00048 #include "tree-dump.h"
00049 #include "cfgloop.h"
00050 #include "tree-pass.h"
00051 #include "ggc.h"
00052 #include "tree-chrec.h"
00053 #include "tree-scalar-evolution.h"
00054 #include "params.h"
00055 #include "flags.h"
00056 #include "tree-inline.h"
00057
00058
00059
00060 enum unroll_level
00061 {
00062 UL_SINGLE_ITER,
00063
00064 UL_NO_GROWTH,
00065
00066 UL_ALL
00067 };
00068
00069
00070
00071
00072 static void
00073 create_canonical_iv (struct loop *loop, edge exit, tree niter)
00074 {
00075 edge in;
00076 tree cond, type, var;
00077 block_stmt_iterator incr_at;
00078 enum tree_code cmp;
00079
00080 if (dump_file && (dump_flags & TDF_DETAILS))
00081 {
00082 fprintf (dump_file, "Added canonical iv to loop %d, ", loop->num);
00083 print_generic_expr (dump_file, niter, TDF_SLIM);
00084 fprintf (dump_file, " iterations.\n");
00085 }
00086
00087 cond = last_stmt (exit->src);
00088 in = EDGE_SUCC (exit->src, 0);
00089 if (in == exit)
00090 in = EDGE_SUCC (exit->src, 1);
00091
00092
00093
00094
00095
00096
00097 type = TREE_TYPE (niter);
00098 niter = fold_build2 (PLUS_EXPR, type,
00099 niter,
00100 build_int_cst (type, 1));
00101 incr_at = bsi_last (in->src);
00102 create_iv (niter,
00103 build_int_cst (type, -1),
00104 NULL_TREE, loop,
00105 &incr_at, false, NULL, &var);
00106
00107 cmp = (exit->flags & EDGE_TRUE_VALUE) ? EQ_EXPR : NE_EXPR;
00108 COND_EXPR_COND (cond) = build2 (cmp, boolean_type_node,
00109 var,
00110 build_int_cst (type, 0));
00111 update_stmt (cond);
00112 }
00113
00114
00115
00116 unsigned
00117 tree_num_loop_insns (struct loop *loop)
00118 {
00119 basic_block *body = get_loop_body (loop);
00120 block_stmt_iterator bsi;
00121 unsigned size = 1, i;
00122
00123 for (i = 0; i < loop->num_nodes; i++)
00124 for (bsi = bsi_start (body[i]); !bsi_end_p (bsi); bsi_next (&bsi))
00125 size += estimate_num_insns (bsi_stmt (bsi));
00126 free (body);
00127
00128 return size;
00129 }
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145 static unsigned HOST_WIDE_INT
00146 estimated_unrolled_size (unsigned HOST_WIDE_INT ninsns,
00147 unsigned HOST_WIDE_INT nunroll)
00148 {
00149 HOST_WIDE_INT unr_insns = 2 * ((HOST_WIDE_INT) ninsns - 4) / 3;
00150 if (unr_insns <= 0)
00151 unr_insns = 1;
00152 unr_insns *= (nunroll + 1);
00153
00154 return unr_insns;
00155 }
00156
00157
00158
00159
00160
00161 static bool
00162 try_unroll_loop_completely (struct loops *loops ATTRIBUTE_UNUSED,
00163 struct loop *loop,
00164 edge exit, tree niter,
00165 enum unroll_level ul)
00166 {
00167 unsigned HOST_WIDE_INT n_unroll, ninsns, max_unroll, unr_insns;
00168 tree old_cond, cond, dont_exit, do_exit;
00169
00170 if (loop->inner)
00171 return false;
00172
00173 if (!host_integerp (niter, 1))
00174 return false;
00175 n_unroll = tree_low_cst (niter, 1);
00176
00177 max_unroll = PARAM_VALUE (PARAM_MAX_COMPLETELY_PEEL_TIMES);
00178 if (n_unroll > max_unroll)
00179 return false;
00180
00181 if (n_unroll)
00182 {
00183 if (ul == UL_SINGLE_ITER)
00184 return false;
00185
00186 ninsns = tree_num_loop_insns (loop);
00187
00188 if (n_unroll * ninsns
00189 > (unsigned) PARAM_VALUE (PARAM_MAX_COMPLETELY_PEELED_INSNS))
00190 return false;
00191
00192 if (ul == UL_NO_GROWTH)
00193 {
00194 unr_insns = estimated_unrolled_size (ninsns, n_unroll);
00195
00196 if (dump_file && (dump_flags & TDF_DETAILS))
00197 {
00198 fprintf (dump_file, " Loop size: %d\n", (int) ninsns);
00199 fprintf (dump_file, " Estimated size after unrolling: %d\n",
00200 (int) unr_insns);
00201 }
00202
00203 if (unr_insns > ninsns)
00204 {
00205 if (dump_file && (dump_flags & TDF_DETAILS))
00206 fprintf (dump_file, "Not unrolling loop %d:\n", loop->num);
00207 return false;
00208 }
00209 }
00210 }
00211
00212 if (exit->flags & EDGE_TRUE_VALUE)
00213 {
00214 dont_exit = boolean_false_node;
00215 do_exit = boolean_true_node;
00216 }
00217 else
00218 {
00219 dont_exit = boolean_true_node;
00220 do_exit = boolean_false_node;
00221 }
00222 cond = last_stmt (exit->src);
00223
00224 if (n_unroll)
00225 {
00226 sbitmap wont_exit;
00227 edge *edges_to_remove = XNEWVEC (edge, n_unroll);
00228 unsigned int n_to_remove = 0;
00229
00230 old_cond = COND_EXPR_COND (cond);
00231 COND_EXPR_COND (cond) = dont_exit;
00232 update_stmt (cond);
00233 initialize_original_copy_tables ();
00234
00235 wont_exit = sbitmap_alloc (n_unroll + 1);
00236 sbitmap_ones (wont_exit);
00237 RESET_BIT (wont_exit, 0);
00238
00239 if (!tree_duplicate_loop_to_header_edge (loop, loop_preheader_edge (loop),
00240 loops, n_unroll, wont_exit,
00241 exit, edges_to_remove,
00242 &n_to_remove,
00243 DLTHE_FLAG_UPDATE_FREQ
00244 | DLTHE_FLAG_COMPLETTE_PEEL))
00245 {
00246 COND_EXPR_COND (cond) = old_cond;
00247 update_stmt (cond);
00248 free_original_copy_tables ();
00249 free (wont_exit);
00250 free (edges_to_remove);
00251 return false;
00252 }
00253 free (wont_exit);
00254 free (edges_to_remove);
00255 free_original_copy_tables ();
00256 }
00257
00258 COND_EXPR_COND (cond) = do_exit;
00259 update_stmt (cond);
00260
00261 update_ssa (TODO_update_ssa);
00262
00263 if (dump_file && (dump_flags & TDF_DETAILS))
00264 fprintf (dump_file, "Unrolled loop %d completely.\n", loop->num);
00265
00266 return true;
00267 }
00268
00269
00270
00271
00272
00273
00274
00275 static bool
00276 canonicalize_loop_induction_variables (struct loops *loops, struct loop *loop,
00277 bool create_iv, enum unroll_level ul,
00278 bool try_eval)
00279 {
00280 edge exit = NULL;
00281 tree niter;
00282
00283 niter = number_of_iterations_in_loop (loop);
00284 if (TREE_CODE (niter) == INTEGER_CST)
00285 {
00286 exit = loop->single_exit;
00287 if (!just_once_each_iteration_p (loop, exit->src))
00288 return false;
00289
00290
00291
00292
00293 niter = fold_build2 (MINUS_EXPR, TREE_TYPE (niter), niter,
00294 build_int_cst (TREE_TYPE (niter), 1));
00295 }
00296 else
00297 {
00298
00299
00300 if (!loop->single_exit)
00301 niter = find_loop_niter (loop, &exit);
00302
00303
00304 if (try_eval
00305 && (chrec_contains_undetermined (niter)
00306 || TREE_CODE (niter) != INTEGER_CST))
00307 niter = find_loop_niter_by_eval (loop, &exit);
00308
00309 if (chrec_contains_undetermined (niter)
00310 || TREE_CODE (niter) != INTEGER_CST)
00311 return false;
00312 }
00313
00314 if (dump_file && (dump_flags & TDF_DETAILS))
00315 {
00316 fprintf (dump_file, "Loop %d iterates ", loop->num);
00317 print_generic_expr (dump_file, niter, TDF_SLIM);
00318 fprintf (dump_file, " times.\n");
00319 }
00320
00321 if (try_unroll_loop_completely (loops, loop, exit, niter, ul))
00322 return true;
00323
00324 if (create_iv)
00325 create_canonical_iv (loop, exit, niter);
00326
00327 return false;
00328 }
00329
00330
00331
00332
00333 unsigned int
00334 canonicalize_induction_variables (struct loops *loops)
00335 {
00336 unsigned i;
00337 struct loop *loop;
00338 bool changed = false;
00339
00340 for (i = 1; i < loops->num; i++)
00341 {
00342 loop = loops->parray[i];
00343
00344 if (loop)
00345 changed |= canonicalize_loop_induction_variables (loops, loop,
00346 true, UL_SINGLE_ITER,
00347 true);
00348 }
00349
00350
00351
00352 scev_reset ();
00353
00354 if (changed)
00355 return TODO_cleanup_cfg;
00356 return 0;
00357 }
00358
00359
00360
00361
00362
00363 unsigned int
00364 tree_unroll_loops_completely (struct loops *loops, bool may_increase_size)
00365 {
00366 unsigned i;
00367 struct loop *loop;
00368 bool changed = false;
00369 enum unroll_level ul;
00370
00371 for (i = 1; i < loops->num; i++)
00372 {
00373 loop = loops->parray[i];
00374
00375 if (!loop)
00376 continue;
00377
00378 if (may_increase_size && maybe_hot_bb_p (loop->header))
00379 ul = UL_ALL;
00380 else
00381 ul = UL_NO_GROWTH;
00382 changed |= canonicalize_loop_induction_variables (loops, loop,
00383 false, ul,
00384 !flag_tree_loop_ivcanon);
00385 }
00386
00387
00388
00389 scev_reset ();
00390
00391 if (changed)
00392 return TODO_cleanup_cfg;
00393 return 0;
00394 }
00395
00396
00397
00398 static bool
00399 empty_loop_p (struct loop *loop)
00400 {
00401 edge exit;
00402 struct tree_niter_desc niter;
00403 tree phi, def;
00404 basic_block *body;
00405 block_stmt_iterator bsi;
00406 unsigned i;
00407 tree stmt;
00408
00409
00410
00411
00412 exit = single_dom_exit (loop);
00413 if (!exit)
00414 return false;
00415
00416
00417 if (!number_of_iterations_exit (loop, exit, &niter, false))
00418 return false;
00419
00420
00421 for (phi = phi_nodes (exit->dest); phi; phi = PHI_CHAIN (phi))
00422 {
00423 if (!is_gimple_reg (PHI_RESULT (phi)))
00424 continue;
00425
00426 def = PHI_ARG_DEF_FROM_EDGE (phi, exit);
00427
00428 if (!expr_invariant_in_loop_p (loop, def))
00429 return false;
00430 }
00431
00432
00433
00434 body = get_loop_body (loop);
00435 for (i = 0; i < loop->num_nodes; i++)
00436 {
00437
00438 if (body[i]->flags & BB_IRREDUCIBLE_LOOP)
00439 {
00440 free (body);
00441 return false;
00442 }
00443
00444 for (bsi = bsi_start (body[i]); !bsi_end_p (bsi); bsi_next (&bsi))
00445 {
00446 stmt = bsi_stmt (bsi);
00447 if (!ZERO_SSA_OPERANDS (stmt, SSA_OP_VIRTUAL_DEFS)
00448 || stmt_ann (stmt)->has_volatile_ops)
00449 {
00450 free (body);
00451 return false;
00452 }
00453
00454
00455
00456 switch (TREE_CODE (stmt))
00457 {
00458 case RETURN_EXPR:
00459 case MODIFY_EXPR:
00460 stmt = get_call_expr_in (stmt);
00461 if (!stmt)
00462 break;
00463
00464 case CALL_EXPR:
00465 if (TREE_SIDE_EFFECTS (stmt))
00466 {
00467 free (body);
00468 return false;
00469 }
00470 break;
00471
00472 case ASM_EXPR:
00473
00474 if (ASM_VOLATILE_P (stmt))
00475 {
00476 free (body);
00477 return false;
00478 }
00479 break;
00480
00481 default:
00482 break;
00483 }
00484 }
00485 }
00486 free (body);
00487
00488 return true;
00489 }
00490
00491
00492
00493 static void
00494 remove_empty_loop (struct loop *loop)
00495 {
00496 edge exit = single_dom_exit (loop), non_exit;
00497 tree cond_stmt = last_stmt (exit->src);
00498 tree do_exit;
00499 basic_block *body;
00500 unsigned n_before, freq_in, freq_h;
00501 gcov_type exit_count = exit->count;
00502
00503 non_exit = EDGE_SUCC (exit->src, 0);
00504 if (non_exit == exit)
00505 non_exit = EDGE_SUCC (exit->src, 1);
00506
00507 if (exit->flags & EDGE_TRUE_VALUE)
00508 do_exit = boolean_true_node;
00509 else
00510 do_exit = boolean_false_node;
00511
00512 COND_EXPR_COND (cond_stmt) = do_exit;
00513 update_stmt (cond_stmt);
00514
00515
00516 exit->probability = REG_BR_PROB_BASE;
00517 non_exit->probability = 0;
00518 non_exit->count = 0;
00519
00520
00521
00522
00523
00524
00525 freq_h = loop->header->frequency;
00526 freq_in = EDGE_FREQUENCY (loop_preheader_edge (loop));
00527 if (freq_h != 0)
00528 {
00529 body = get_loop_body_in_dom_order (loop);
00530 for (n_before = 1; n_before <= loop->num_nodes; n_before++)
00531 if (body[n_before - 1] == exit->src)
00532 break;
00533 scale_bbs_frequencies_int (body, n_before, freq_in, freq_h);
00534 scale_bbs_frequencies_int (body + n_before, loop->num_nodes - n_before,
00535 0, 1);
00536 free (body);
00537 }
00538
00539
00540
00541 exit->count = exit_count;
00542 }
00543
00544
00545
00546
00547 static bool
00548 try_remove_empty_loop (struct loop *loop, bool *changed)
00549 {
00550 bool nonempty_subloop = false;
00551 struct loop *sub;
00552
00553
00554 for (sub = loop->inner; sub; sub = sub->next)
00555 nonempty_subloop |= !try_remove_empty_loop (sub, changed);
00556
00557 if (nonempty_subloop || !empty_loop_p (loop))
00558 return false;
00559
00560 remove_empty_loop (loop);
00561 *changed = true;
00562 return true;
00563 }
00564
00565
00566
00567 unsigned int
00568 remove_empty_loops (struct loops *loops)
00569 {
00570 bool changed = false;
00571 struct loop *loop;
00572
00573 for (loop = loops->tree_root->inner; loop; loop = loop->next)
00574 try_remove_empty_loop (loop, &changed);
00575
00576 if (changed)
00577 {
00578 scev_reset ();
00579 return TODO_cleanup_cfg;
00580 }
00581 return 0;
00582 }