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 "rtl.h"
00024 #include "hard-reg-set.h"
00025 #include "basic-block.h"
00026 #include "toplev.h"
00027
00028
00029
00030 #define HEAVY_EDGE_RATIO 8
00031
00032 static void flow_loops_cfg_dump PARAMS ((const struct loops *,
00033 FILE *));
00034 static void flow_loop_entry_edges_find PARAMS ((struct loop *));
00035 static void flow_loop_exit_edges_find PARAMS ((struct loop *));
00036 static int flow_loop_nodes_find PARAMS ((basic_block, struct loop *));
00037 static void flow_loop_pre_header_scan PARAMS ((struct loop *));
00038 static basic_block flow_loop_pre_header_find PARAMS ((basic_block,
00039 dominance_info));
00040 static int flow_loop_level_compute PARAMS ((struct loop *));
00041 static int flow_loops_level_compute PARAMS ((struct loops *));
00042 static basic_block make_forwarder_block PARAMS ((basic_block, int, int,
00043 edge, int));
00044 static void canonicalize_loop_headers PARAMS ((void));
00045 static bool glb_enum_p PARAMS ((basic_block, void *));
00046 static void redirect_edge_with_latch_update PARAMS ((edge, basic_block));
00047 static void flow_loop_free PARAMS ((struct loop *));
00048
00049
00050
00051 static void
00052 flow_loops_cfg_dump (loops, file)
00053 const struct loops *loops;
00054 FILE *file;
00055 {
00056 int i;
00057 basic_block bb;
00058
00059 if (! loops->num || ! file || ! loops->cfg.dom)
00060 return;
00061
00062 FOR_EACH_BB (bb)
00063 {
00064 edge succ;
00065
00066 fprintf (file, ";; %d succs { ", bb->index);
00067 for (succ = bb->succ; succ; succ = succ->succ_next)
00068 fprintf (file, "%d ", succ->dest->index);
00069 fprintf (file, "}\n");
00070 }
00071
00072
00073 if (loops->cfg.dfs_order)
00074 {
00075 fputs (";; DFS order: ", file);
00076 for (i = 0; i < n_basic_blocks; i++)
00077 fprintf (file, "%d ", loops->cfg.dfs_order[i]);
00078
00079 fputs ("\n", file);
00080 }
00081
00082
00083 if (loops->cfg.rc_order)
00084 {
00085 fputs (";; RC order: ", file);
00086 for (i = 0; i < n_basic_blocks; i++)
00087 fprintf (file, "%d ", loops->cfg.rc_order[i]);
00088
00089 fputs ("\n", file);
00090 }
00091 }
00092
00093
00094
00095 bool
00096 flow_loop_nested_p (outer, loop)
00097 const struct loop *outer;
00098 const struct loop *loop;
00099 {
00100 return loop->depth > outer->depth
00101 && loop->pred[outer->depth] == outer;
00102 }
00103
00104
00105
00106
00107 void
00108 flow_loop_dump (loop, file, loop_dump_aux, verbose)
00109 const struct loop *loop;
00110 FILE *file;
00111 void (*loop_dump_aux) PARAMS((const struct loop *, FILE *, int));
00112 int verbose;
00113 {
00114 basic_block *bbs;
00115 int i;
00116
00117 if (! loop || ! loop->header)
00118 return;
00119
00120 fprintf (file, ";;\n;; Loop %d:%s\n", loop->num,
00121 loop->invalid ? " invalid" : "");
00122
00123 fprintf (file, ";; header %d, latch %d, pre-header %d\n",
00124 loop->header->index, loop->latch->index,
00125 loop->pre_header ? loop->pre_header->index : -1);
00126 fprintf (file, ";; depth %d, level %d, outer %ld\n",
00127 loop->depth, loop->level,
00128 (long) (loop->outer ? loop->outer->num : -1));
00129
00130 if (loop->pre_header_edges)
00131 flow_edge_list_print (";; pre-header edges", loop->pre_header_edges,
00132 loop->num_pre_header_edges, file);
00133
00134 flow_edge_list_print (";; entry edges", loop->entry_edges,
00135 loop->num_entries, file);
00136 fprintf (file, ";; nodes:");
00137 bbs = get_loop_body (loop);
00138 for (i = 0; i < loop->num_nodes; i++)
00139 fprintf (file, " %d", bbs[i]->index);
00140 free (bbs);
00141 fprintf (file, "\n");
00142 flow_edge_list_print (";; exit edges", loop->exit_edges,
00143 loop->num_exits, file);
00144
00145 if (loop_dump_aux)
00146 loop_dump_aux (loop, file, verbose);
00147 }
00148
00149
00150
00151
00152 void
00153 flow_loops_dump (loops, file, loop_dump_aux, verbose)
00154 const struct loops *loops;
00155 FILE *file;
00156 void (*loop_dump_aux) PARAMS((const struct loop *, FILE *, int));
00157 int verbose;
00158 {
00159 int i;
00160 int num_loops;
00161
00162 num_loops = loops->num;
00163 if (! num_loops || ! file)
00164 return;
00165
00166 fprintf (file, ";; %d loops found, %d levels\n",
00167 num_loops, loops->levels);
00168
00169 for (i = 0; i < num_loops; i++)
00170 {
00171 struct loop *loop = loops->parray[i];
00172
00173 if (!loop)
00174 continue;
00175
00176 flow_loop_dump (loop, file, loop_dump_aux, verbose);
00177 }
00178
00179 if (verbose)
00180 flow_loops_cfg_dump (loops, file);
00181 }
00182
00183
00184 static void
00185 flow_loop_free (loop)
00186 struct loop *loop;
00187 {
00188 if (loop->pre_header_edges)
00189 free (loop->pre_header_edges);
00190 if (loop->entry_edges)
00191 free (loop->entry_edges);
00192 if (loop->exit_edges)
00193 free (loop->exit_edges);
00194 if (loop->pred)
00195 free (loop->pred);
00196 free (loop);
00197 }
00198
00199
00200
00201 void
00202 flow_loops_free (loops)
00203 struct loops *loops;
00204 {
00205 if (loops->parray)
00206 {
00207 int i;
00208
00209 if (! loops->num)
00210 abort ();
00211
00212
00213 for (i = 0; i < loops->num; i++)
00214 {
00215 struct loop *loop = loops->parray[i];
00216
00217 if (!loop)
00218 continue;
00219
00220 flow_loop_free (loop);
00221 }
00222
00223 free (loops->parray);
00224 loops->parray = NULL;
00225
00226 if (loops->cfg.dom)
00227 free_dominance_info (loops->cfg.dom);
00228
00229 if (loops->cfg.dfs_order)
00230 free (loops->cfg.dfs_order);
00231 if (loops->cfg.rc_order)
00232 free (loops->cfg.rc_order);
00233
00234 }
00235 }
00236
00237
00238
00239 static void
00240 flow_loop_entry_edges_find (loop)
00241 struct loop *loop;
00242 {
00243 edge e;
00244 int num_entries;
00245
00246 num_entries = 0;
00247 for (e = loop->header->pred; e; e = e->pred_next)
00248 {
00249 if (flow_loop_outside_edge_p (loop, e))
00250 num_entries++;
00251 }
00252
00253 if (! num_entries)
00254 abort ();
00255
00256 loop->entry_edges = (edge *) xmalloc (num_entries * sizeof (edge *));
00257
00258 num_entries = 0;
00259 for (e = loop->header->pred; e; e = e->pred_next)
00260 {
00261 if (flow_loop_outside_edge_p (loop, e))
00262 loop->entry_edges[num_entries++] = e;
00263 }
00264
00265 loop->num_entries = num_entries;
00266 }
00267
00268
00269
00270 static void
00271 flow_loop_exit_edges_find (loop)
00272 struct loop *loop;
00273 {
00274 edge e;
00275 basic_block node, *bbs;
00276 int num_exits, i;
00277
00278 loop->exit_edges = NULL;
00279 loop->num_exits = 0;
00280
00281
00282
00283
00284 num_exits = 0;
00285 bbs = get_loop_body (loop);
00286 for (i = 0; i < loop->num_nodes; i++)
00287 {
00288 node = bbs[i];
00289 for (e = node->succ; e; e = e->succ_next)
00290 {
00291 basic_block dest = e->dest;
00292
00293 if (!flow_bb_inside_loop_p (loop, dest))
00294 num_exits++;
00295 }
00296 }
00297
00298 if (! num_exits)
00299 {
00300 free (bbs);
00301 return;
00302 }
00303
00304 loop->exit_edges = (edge *) xmalloc (num_exits * sizeof (edge *));
00305
00306
00307 num_exits = 0;
00308 for (i = 0; i < loop->num_nodes; i++)
00309 {
00310 node = bbs[i];
00311 for (e = node->succ; e; e = e->succ_next)
00312 {
00313 basic_block dest = e->dest;
00314
00315 if (!flow_bb_inside_loop_p (loop, dest))
00316 loop->exit_edges[num_exits++] = e;
00317 }
00318 }
00319 free (bbs);
00320 loop->num_exits = num_exits;
00321 }
00322
00323
00324
00325
00326 static int
00327 flow_loop_nodes_find (header, loop)
00328 basic_block header;
00329 struct loop *loop;
00330 {
00331 basic_block *stack;
00332 int sp;
00333 int num_nodes = 1;
00334 int findex, lindex;
00335
00336 header->loop_father = loop;
00337 header->loop_depth = loop->depth;
00338 findex = lindex = header->index;
00339
00340 if (loop->latch->loop_father != loop)
00341 {
00342 stack = (basic_block *) xmalloc (n_basic_blocks * sizeof (basic_block));
00343 sp = 0;
00344 num_nodes++;
00345 stack[sp++] = loop->latch;
00346 loop->latch->loop_father = loop;
00347 loop->latch->loop_depth = loop->depth;
00348
00349 while (sp)
00350 {
00351 basic_block node;
00352 edge e;
00353
00354 node = stack[--sp];
00355
00356 for (e = node->pred; e; e = e->pred_next)
00357 {
00358 basic_block ancestor = e->src;
00359
00360 if (ancestor != ENTRY_BLOCK_PTR
00361 && ancestor->loop_father != loop)
00362 {
00363 ancestor->loop_father = loop;
00364 ancestor->loop_depth = loop->depth;
00365 num_nodes++;
00366 stack[sp++] = ancestor;
00367 }
00368 }
00369 }
00370 free (stack);
00371 }
00372 return num_nodes;
00373 }
00374
00375
00376
00377
00378 static void
00379 flow_loop_pre_header_scan (loop)
00380 struct loop *loop;
00381 {
00382 int num;
00383 basic_block ebb;
00384 edge e;
00385
00386 loop->num_pre_header_edges = 0;
00387 if (loop->num_entries != 1)
00388 return;
00389
00390 ebb = loop->entry_edges[0]->src;
00391 if (ebb == ENTRY_BLOCK_PTR)
00392 return;
00393
00394
00395
00396
00397 for (num = 1; ebb->pred->src != ENTRY_BLOCK_PTR && ! ebb->pred->pred_next;
00398 num++)
00399 ebb = ebb->pred->src;
00400
00401 loop->pre_header_edges = (edge *) xmalloc (num * sizeof (edge));
00402 loop->num_pre_header_edges = num;
00403
00404
00405
00406
00407 for (e = loop->entry_edges[0]; num; e = e->src->pred)
00408 loop->pre_header_edges[--num] = e;
00409 }
00410
00411
00412
00413
00414
00415 static basic_block
00416 flow_loop_pre_header_find (header, dom)
00417 basic_block header;
00418 dominance_info dom;
00419 {
00420 basic_block pre_header;
00421 edge e;
00422
00423
00424
00425 pre_header = NULL;
00426 for (e = header->pred; e; e = e->pred_next)
00427 {
00428 basic_block node = e->src;
00429
00430 if (node != ENTRY_BLOCK_PTR
00431 && ! dominated_by_p (dom, node, header))
00432 {
00433 if (pre_header == NULL)
00434 pre_header = node;
00435 else
00436 {
00437
00438
00439 pre_header = NULL;
00440 break;
00441 }
00442 }
00443 }
00444
00445 return pre_header;
00446 }
00447
00448
00449
00450
00451 void
00452 flow_loop_tree_node_add (father, loop)
00453 struct loop *father;
00454 struct loop *loop;
00455 {
00456 loop->next = father->inner;
00457 father->inner = loop;
00458 loop->outer = father;
00459
00460 loop->depth = father->depth + 1;
00461 loop->pred = xmalloc (sizeof (struct loop *) * loop->depth);
00462 memcpy (loop->pred, father->pred, sizeof (struct loop *) * father->depth);
00463 loop->pred[father->depth] = father;
00464 }
00465
00466
00467
00468 void
00469 flow_loop_tree_node_remove (loop)
00470 struct loop *loop;
00471 {
00472 struct loop *prev, *father;
00473
00474 father = loop->outer;
00475 loop->outer = NULL;
00476
00477
00478 if (father->inner == loop)
00479 father->inner = loop->next;
00480 else
00481 {
00482 for (prev = father->inner; prev->next != loop; prev = prev->next);
00483 prev->next = loop->next;
00484 }
00485
00486 loop->depth = -1;
00487 free (loop->pred);
00488 loop->pred = NULL;
00489 }
00490
00491
00492
00493
00494 static int
00495 flow_loop_level_compute (loop)
00496 struct loop *loop;
00497 {
00498 struct loop *inner;
00499 int level = 1;
00500
00501 if (! loop)
00502 return 0;
00503
00504
00505
00506
00507
00508
00509 for (inner = loop->inner; inner; inner = inner->next)
00510 {
00511 int ilevel = flow_loop_level_compute (inner) + 1;
00512
00513 if (ilevel > level)
00514 level = ilevel;
00515 }
00516
00517 loop->level = level;
00518 return level;
00519 }
00520
00521
00522
00523
00524
00525 static int
00526 flow_loops_level_compute (loops)
00527 struct loops *loops;
00528 {
00529 return flow_loop_level_compute (loops->tree_root);
00530 }
00531
00532
00533
00534
00535 int
00536 flow_loop_scan (loops, loop, flags)
00537 struct loops *loops;
00538 struct loop *loop;
00539 int flags;
00540 {
00541 if (flags & LOOP_ENTRY_EDGES)
00542 {
00543
00544
00545
00546 flow_loop_entry_edges_find (loop);
00547 }
00548
00549 if (flags & LOOP_EXIT_EDGES)
00550 {
00551
00552 flow_loop_exit_edges_find (loop);
00553 }
00554
00555 if (flags & LOOP_PRE_HEADER)
00556 {
00557
00558 loop->pre_header
00559 = flow_loop_pre_header_find (loop->header, loops->cfg.dom);
00560
00561
00562
00563 flow_loop_pre_header_scan (loop);
00564 }
00565
00566 return 1;
00567 }
00568
00569 #define HEADER_BLOCK(B) (* (int *) (B)->aux)
00570 #define LATCH_EDGE(E) (*(int *) (E)->aux)
00571
00572
00573 static void
00574 redirect_edge_with_latch_update (e, to)
00575 edge e;
00576 basic_block to;
00577 {
00578 basic_block jump;
00579
00580 jump = redirect_edge_and_branch_force (e, to);
00581 if (jump)
00582 {
00583 alloc_aux_for_block (jump, sizeof (int));
00584 HEADER_BLOCK (jump) = 0;
00585 alloc_aux_for_edge (jump->pred, sizeof (int));
00586 LATCH_EDGE (jump->succ) = LATCH_EDGE (e);
00587 LATCH_EDGE (jump->pred) = 0;
00588 }
00589 }
00590
00591
00592
00593
00594
00595
00596
00597 static basic_block
00598 make_forwarder_block (bb, redirect_latch, redirect_nonlatch, except,
00599 conn_latch)
00600 basic_block bb;
00601 int redirect_latch;
00602 int redirect_nonlatch;
00603 edge except;
00604 int conn_latch;
00605 {
00606 edge e, next_e, fallthru;
00607 basic_block dummy;
00608 rtx insn;
00609
00610 insn = PREV_INSN (first_insn_after_basic_block_note (bb));
00611
00612 fallthru = split_block (bb, insn);
00613 dummy = fallthru->src;
00614 bb = fallthru->dest;
00615
00616 bb->aux = xmalloc (sizeof (int));
00617 HEADER_BLOCK (dummy) = 0;
00618 HEADER_BLOCK (bb) = 1;
00619
00620
00621 for (e = dummy->pred; e; e = next_e)
00622 {
00623 next_e = e->pred_next;
00624 if (e == except
00625 || !((redirect_latch && LATCH_EDGE (e))
00626 || (redirect_nonlatch && !LATCH_EDGE (e))))
00627 {
00628 dummy->frequency -= EDGE_FREQUENCY (e);
00629 dummy->count -= e->count;
00630 if (dummy->frequency < 0)
00631 dummy->frequency = 0;
00632 if (dummy->count < 0)
00633 dummy->count = 0;
00634 redirect_edge_with_latch_update (e, bb);
00635 }
00636 }
00637
00638 alloc_aux_for_edge (fallthru, sizeof (int));
00639 LATCH_EDGE (fallthru) = conn_latch;
00640
00641 return dummy;
00642 }
00643
00644
00645 static void
00646 canonicalize_loop_headers ()
00647 {
00648 dominance_info dom;
00649 basic_block header;
00650 edge e;
00651
00652
00653 dom = calculate_dominance_info (CDI_DOMINATORS);
00654
00655 alloc_aux_for_blocks (sizeof (int));
00656 alloc_aux_for_edges (sizeof (int));
00657
00658
00659 FOR_EACH_BB (header)
00660 {
00661 int num_latches = 0;
00662 int have_abnormal_edge = 0;
00663
00664 for (e = header->pred; e; e = e->pred_next)
00665 {
00666 basic_block latch = e->src;
00667
00668 if (e->flags & EDGE_ABNORMAL)
00669 have_abnormal_edge = 1;
00670
00671 if (latch != ENTRY_BLOCK_PTR
00672 && dominated_by_p (dom, latch, header))
00673 {
00674 num_latches++;
00675 LATCH_EDGE (e) = 1;
00676 }
00677 }
00678 if (have_abnormal_edge)
00679 HEADER_BLOCK (header) = 0;
00680 else
00681 HEADER_BLOCK (header) = num_latches;
00682 }
00683
00684 if (HEADER_BLOCK (ENTRY_BLOCK_PTR->succ->dest))
00685 {
00686 basic_block bb;
00687
00688
00689
00690 bb = split_edge (ENTRY_BLOCK_PTR->succ);
00691
00692 alloc_aux_for_edge (bb->succ, sizeof (int));
00693 LATCH_EDGE (bb->succ) = 0;
00694 alloc_aux_for_block (bb, sizeof (int));
00695 HEADER_BLOCK (bb) = 0;
00696 }
00697
00698 FOR_EACH_BB (header)
00699 {
00700 int num_latch;
00701 int want_join_latch;
00702 int max_freq, is_heavy;
00703 edge heavy;
00704
00705 if (!HEADER_BLOCK (header))
00706 continue;
00707
00708 num_latch = HEADER_BLOCK (header);
00709
00710 want_join_latch = (num_latch > 1);
00711
00712 if (!want_join_latch)
00713 continue;
00714
00715
00716 is_heavy = 1;
00717 heavy = NULL;
00718 max_freq = 0;
00719 for (e = header->pred; e; e = e->pred_next)
00720 if (LATCH_EDGE (e) &&
00721 EDGE_FREQUENCY (e) > max_freq)
00722 max_freq = EDGE_FREQUENCY (e);
00723 for (e = header->pred; e; e = e->pred_next)
00724 if (LATCH_EDGE (e) &&
00725 EDGE_FREQUENCY (e) >= max_freq / HEAVY_EDGE_RATIO)
00726 {
00727 if (heavy)
00728 {
00729 is_heavy = 0;
00730 break;
00731 }
00732 else
00733 heavy = e;
00734 }
00735
00736 if (is_heavy)
00737 {
00738 basic_block new_header =
00739 make_forwarder_block (header, true, true, heavy, 0);
00740 if (num_latch > 2)
00741 make_forwarder_block (new_header, true, false, NULL, 1);
00742 }
00743 else
00744 make_forwarder_block (header, true, false, NULL, 1);
00745 }
00746
00747 free_aux_for_blocks ();
00748 free_aux_for_edges ();
00749 free_dominance_info (dom);
00750 }
00751
00752
00753
00754
00755
00756
00757 int
00758 flow_loops_find (loops, flags)
00759 struct loops *loops;
00760 int flags;
00761 {
00762 int i;
00763 int b;
00764 int num_loops;
00765 edge e;
00766 sbitmap headers;
00767 dominance_info dom;
00768 int *dfs_order;
00769 int *rc_order;
00770 basic_block header;
00771 basic_block bb;
00772
00773
00774
00775
00776 if (! (flags & LOOP_TREE))
00777 abort ();
00778
00779 memset (loops, 0, sizeof *loops);
00780
00781
00782
00783 if (n_basic_blocks == 0)
00784 return 0;
00785
00786 dfs_order = NULL;
00787 rc_order = NULL;
00788
00789
00790 canonicalize_loop_headers ();
00791
00792
00793 dom = loops->cfg.dom = calculate_dominance_info (CDI_DOMINATORS);
00794
00795
00796
00797 headers = sbitmap_alloc (last_basic_block);
00798 sbitmap_zero (headers);
00799
00800 num_loops = 0;
00801 FOR_EACH_BB (header)
00802 {
00803 int more_latches = 0;
00804
00805 header->loop_depth = 0;
00806
00807 for (e = header->pred; e; e = e->pred_next)
00808 {
00809 basic_block latch = e->src;
00810
00811 if (e->flags & EDGE_ABNORMAL)
00812 {
00813 if (more_latches)
00814 {
00815 RESET_BIT (headers, header->index);
00816 num_loops--;
00817 }
00818 break;
00819 }
00820
00821
00822
00823
00824
00825
00826 if (latch != ENTRY_BLOCK_PTR && dominated_by_p (dom, latch, header))
00827 {
00828
00829 if (more_latches)
00830 abort ();
00831 more_latches = 1;
00832 SET_BIT (headers, header->index);
00833 num_loops++;
00834 }
00835 }
00836 }
00837
00838
00839 loops->parray = (struct loop **) xcalloc (num_loops + 1, sizeof (struct loop *));
00840
00841
00842 loops->parray[0] = xcalloc (1, sizeof (struct loop));
00843 loops->parray[0]->next = NULL;
00844 loops->parray[0]->inner = NULL;
00845 loops->parray[0]->outer = NULL;
00846 loops->parray[0]->depth = 0;
00847 loops->parray[0]->pred = NULL;
00848 loops->parray[0]->num_nodes = n_basic_blocks + 2;
00849 loops->parray[0]->latch = EXIT_BLOCK_PTR;
00850 loops->parray[0]->header = ENTRY_BLOCK_PTR;
00851 ENTRY_BLOCK_PTR->loop_father = loops->parray[0];
00852 EXIT_BLOCK_PTR->loop_father = loops->parray[0];
00853
00854 loops->tree_root = loops->parray[0];
00855
00856
00857
00858 loops->num = 1;
00859 FOR_EACH_BB (bb)
00860 bb->loop_father = loops->tree_root;
00861
00862 if (num_loops)
00863 {
00864
00865
00866 dfs_order = (int *) xmalloc (n_basic_blocks * sizeof (int));
00867 rc_order = (int *) xmalloc (n_basic_blocks * sizeof (int));
00868 flow_depth_first_order_compute (dfs_order, rc_order);
00869
00870
00871 loops->cfg.dom = dom;
00872 loops->cfg.dfs_order = dfs_order;
00873 loops->cfg.rc_order = rc_order;
00874
00875 num_loops = 1;
00876
00877 for (b = 0; b < n_basic_blocks; b++)
00878 {
00879 struct loop *loop;
00880
00881
00882
00883 if (!TEST_BIT (headers, rc_order[b]))
00884 continue;
00885
00886 header = BASIC_BLOCK (rc_order[b]);
00887
00888 loop = loops->parray[num_loops] = xcalloc (1, sizeof (struct loop));
00889
00890 loop->header = header;
00891 loop->num = num_loops;
00892 num_loops++;
00893
00894
00895 for (e = header->pred; e; e = e->pred_next)
00896 {
00897 basic_block latch = e->src;
00898
00899 if (latch != ENTRY_BLOCK_PTR
00900 && dominated_by_p (dom, latch, header))
00901 {
00902 loop->latch = latch;
00903 break;
00904 }
00905 }
00906
00907 flow_loop_tree_node_add (header->loop_father, loop);
00908 loop->num_nodes = flow_loop_nodes_find (loop->header, loop);
00909 }
00910
00911 sbitmap_free (headers);
00912
00913
00914
00915 loops->levels = flow_loops_level_compute (loops);
00916
00917
00918 for (i = 1; i < num_loops; i++)
00919 flow_loop_scan (loops, loops->parray[i], flags);
00920
00921 loops->num = num_loops;
00922 }
00923 else
00924 {
00925 loops->cfg.dom = NULL;
00926 free_dominance_info (dom);
00927 }
00928 #ifdef ENABLE_CHECKING
00929 verify_flow_info ();
00930 verify_loop_structure (loops, 0);
00931 #endif
00932
00933 return loops->num;
00934 }
00935
00936
00937
00938
00939 int
00940 flow_loops_update (loops, flags)
00941 struct loops *loops;
00942 int flags;
00943 {
00944
00945
00946 if (loops->parray)
00947 flow_loops_free (loops);
00948
00949 return flow_loops_find (loops, flags);
00950 }
00951
00952
00953 bool
00954 flow_bb_inside_loop_p (loop, bb)
00955 const struct loop *loop;
00956 const basic_block bb;
00957 {
00958 struct loop *source_loop;
00959
00960 if (bb == ENTRY_BLOCK_PTR || bb == EXIT_BLOCK_PTR)
00961 return 0;
00962
00963 source_loop = bb->loop_father;
00964 return loop == source_loop || flow_loop_nested_p (loop, source_loop);
00965 }
00966
00967
00968
00969 bool
00970 flow_loop_outside_edge_p (loop, e)
00971 const struct loop *loop;
00972 edge e;
00973 {
00974 if (e->dest != loop->header)
00975 abort ();
00976 return !flow_bb_inside_loop_p (loop, e->src);
00977 }
00978
00979
00980 static bool
00981 glb_enum_p (bb, glb_header)
00982 basic_block bb;
00983 void *glb_header;
00984 {
00985 return bb != (basic_block) glb_header;
00986 }
00987
00988
00989 basic_block *
00990 get_loop_body (loop)
00991 const struct loop *loop;
00992 {
00993 basic_block *tovisit, bb;
00994 int tv = 0;
00995
00996 if (!loop->num_nodes)
00997 abort ();
00998
00999 tovisit = xcalloc (loop->num_nodes, sizeof (basic_block));
01000 tovisit[tv++] = loop->header;
01001
01002 if (loop->latch == EXIT_BLOCK_PTR)
01003 {
01004
01005 if (loop->num_nodes != n_basic_blocks + 2)
01006 abort ();
01007 FOR_EACH_BB (bb)
01008 tovisit[tv++] = bb;
01009 tovisit[tv++] = EXIT_BLOCK_PTR;
01010 }
01011 else if (loop->latch != loop->header)
01012 {
01013 tv = dfs_enumerate_from (loop->latch, 1, glb_enum_p,
01014 tovisit + 1, loop->num_nodes - 1,
01015 loop->header) + 1;
01016 }
01017
01018 if (tv != loop->num_nodes)
01019 abort ();
01020 return tovisit;
01021 }
01022
01023
01024 void
01025 add_bb_to_loop (bb, loop)
01026 basic_block bb;
01027 struct loop *loop;
01028 {
01029 int i;
01030
01031 bb->loop_father = loop;
01032 bb->loop_depth = loop->depth;
01033 loop->num_nodes++;
01034 for (i = 0; i < loop->depth; i++)
01035 loop->pred[i]->num_nodes++;
01036 }
01037
01038
01039 void
01040 remove_bb_from_loops (bb)
01041 basic_block bb;
01042 {
01043 int i;
01044 struct loop *loop = bb->loop_father;
01045
01046 loop->num_nodes--;
01047 for (i = 0; i < loop->depth; i++)
01048 loop->pred[i]->num_nodes--;
01049 bb->loop_father = NULL;
01050 bb->loop_depth = 0;
01051 }
01052
01053
01054 struct loop *
01055 find_common_loop (loop_s, loop_d)
01056 struct loop *loop_s;
01057 struct loop *loop_d;
01058 {
01059 if (!loop_s) return loop_d;
01060 if (!loop_d) return loop_s;
01061
01062 if (loop_s->depth < loop_d->depth)
01063 loop_d = loop_d->pred[loop_s->depth];
01064 else if (loop_s->depth > loop_d->depth)
01065 loop_s = loop_s->pred[loop_d->depth];
01066
01067 while (loop_s != loop_d)
01068 {
01069 loop_s = loop_s->outer;
01070 loop_d = loop_d->outer;
01071 }
01072 return loop_s;
01073 }
01074
01075
01076
01077
01078
01079
01080
01081 void
01082 verify_loop_structure (loops, flags)
01083 struct loops *loops;
01084 int flags;
01085 {
01086 int *sizes, i, j;
01087 basic_block *bbs, bb;
01088 struct loop *loop;
01089 int err = 0;
01090
01091
01092 sizes = xcalloc (loops->num, sizeof (int));
01093 sizes[0] = 2;
01094
01095 FOR_EACH_BB (bb)
01096 for (loop = bb->loop_father; loop; loop = loop->outer)
01097 sizes[loop->num]++;
01098
01099 for (i = 0; i < loops->num; i++)
01100 {
01101 if (!loops->parray[i])
01102 continue;
01103
01104 if (loops->parray[i]->num_nodes != sizes[i])
01105 {
01106 error ("Size of loop %d should be %d, not %d.",
01107 i, sizes[i], loops->parray[i]->num_nodes);
01108 err = 1;
01109 }
01110 }
01111
01112 free (sizes);
01113
01114
01115 for (i = 1; i < loops->num; i++)
01116 {
01117 loop = loops->parray[i];
01118 if (!loop)
01119 continue;
01120 bbs = get_loop_body (loop);
01121
01122 for (j = 0; j < loop->num_nodes; j++)
01123 if (!flow_bb_inside_loop_p (loop, bbs[j]))
01124 {
01125 error ("Bb %d do not belong to loop %d.",
01126 bbs[j]->index, i);
01127 err = 1;
01128 }
01129 free (bbs);
01130 }
01131
01132
01133 for (i = 1; i < loops->num; i++)
01134 {
01135 loop = loops->parray[i];
01136 if (!loop)
01137 continue;
01138
01139 if ((flags & VLS_EXPECT_PREHEADERS)
01140 && (!loop->header->pred->pred_next
01141 || loop->header->pred->pred_next->pred_next))
01142 {
01143 error ("Loop %d's header does not have exactly 2 entries.", i);
01144 err = 1;
01145 }
01146 if (flags & VLS_EXPECT_SIMPLE_LATCHES)
01147 {
01148 if (!loop->latch->succ
01149 || loop->latch->succ->succ_next)
01150 {
01151 error ("Loop %d's latch does not have exactly 1 successor.", i);
01152 err = 1;
01153 }
01154 if (loop->latch->succ->dest != loop->header)
01155 {
01156 error ("Loop %d's latch does not have header as successor.", i);
01157 err = 1;
01158 }
01159 if (loop->latch->loop_father != loop)
01160 {
01161 error ("Loop %d's latch does not belong directly to it.", i);
01162 err = 1;
01163 }
01164 }
01165 if (loop->header->loop_father != loop)
01166 {
01167 error ("Loop %d's header does not belong directly to it.", i);
01168 err = 1;
01169 }
01170 }
01171
01172 if (err)
01173 abort ();
01174 }
01175
01176
01177 edge
01178 loop_latch_edge (loop)
01179 struct loop *loop;
01180 {
01181 edge e;
01182
01183 for (e = loop->header->pred; e->src != loop->latch; e = e->pred_next)
01184 continue;
01185
01186 return e;
01187 }
01188
01189
01190 edge
01191 loop_preheader_edge (loop)
01192 struct loop *loop;
01193 {
01194 edge e;
01195
01196 for (e = loop->header->pred; e->src == loop->latch; e = e->pred_next)
01197 continue;
01198
01199 return e;
01200 }
01201