00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include "config.h"
00024 #include "system.h"
00025 #include "rtl.h"
00026 #include "hard-reg-set.h"
00027 #include "basic-block.h"
00028 #include "insn-config.h"
00029 #include "recog.h"
00030 #include "toplev.h"
00031 #include "tm_p.h"
00032
00033
00034 struct depth_first_search_dsS {
00035
00036 basic_block *stack;
00037
00038
00039
00040 unsigned int sp;
00041
00042
00043 sbitmap visited_blocks;
00044 };
00045 typedef struct depth_first_search_dsS *depth_first_search_ds;
00046
00047 static void flow_dfs_compute_reverse_init
00048 PARAMS ((depth_first_search_ds));
00049 static void flow_dfs_compute_reverse_add_bb
00050 PARAMS ((depth_first_search_ds, basic_block));
00051 static basic_block flow_dfs_compute_reverse_execute
00052 PARAMS ((depth_first_search_ds));
00053 static void flow_dfs_compute_reverse_finish
00054 PARAMS ((depth_first_search_ds));
00055 static void remove_fake_successors PARAMS ((basic_block));
00056 static bool need_fake_edge_p PARAMS ((rtx));
00057 static bool flow_active_insn_p PARAMS ((rtx));
00058
00059
00060
00061
00062 static bool
00063 flow_active_insn_p (insn)
00064 rtx insn;
00065 {
00066 if (active_insn_p (insn))
00067 return true;
00068
00069
00070
00071
00072
00073
00074 if (GET_CODE (PATTERN (insn)) == CLOBBER
00075 && GET_CODE (XEXP (PATTERN (insn), 0)) == REG
00076 && REG_FUNCTION_VALUE_P (XEXP (PATTERN (insn), 0)))
00077 return true;
00078
00079 return false;
00080 }
00081
00082
00083
00084
00085 bool
00086 forwarder_block_p (bb)
00087 basic_block bb;
00088 {
00089 rtx insn;
00090
00091 if (bb == EXIT_BLOCK_PTR || bb == ENTRY_BLOCK_PTR
00092 || !bb->succ || bb->succ->succ_next)
00093 return false;
00094
00095 for (insn = bb->head; insn != bb->end; insn = NEXT_INSN (insn))
00096 if (INSN_P (insn) && flow_active_insn_p (insn))
00097 return false;
00098
00099 return (!INSN_P (insn)
00100 || (GET_CODE (insn) == JUMP_INSN && simplejump_p (insn))
00101 || !flow_active_insn_p (insn));
00102 }
00103
00104
00105
00106 bool
00107 can_fallthru (src, target)
00108 basic_block src, target;
00109 {
00110 rtx insn = src->end;
00111 rtx insn2 = target->head;
00112
00113 if (src->next_bb != target)
00114 return 0;
00115
00116 if (!active_insn_p (insn2))
00117 insn2 = next_active_insn (insn2);
00118
00119
00120 return next_active_insn (insn) == insn2;
00121 }
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133 bool
00134 mark_dfs_back_edges ()
00135 {
00136 edge *stack;
00137 int *pre;
00138 int *post;
00139 int sp;
00140 int prenum = 1;
00141 int postnum = 1;
00142 sbitmap visited;
00143 bool found = false;
00144
00145
00146 pre = (int *) xcalloc (last_basic_block, sizeof (int));
00147 post = (int *) xcalloc (last_basic_block, sizeof (int));
00148
00149
00150 stack = (edge *) xmalloc ((n_basic_blocks + 1) * sizeof (edge));
00151 sp = 0;
00152
00153
00154 visited = sbitmap_alloc (last_basic_block);
00155
00156
00157 sbitmap_zero (visited);
00158
00159
00160 stack[sp++] = ENTRY_BLOCK_PTR->succ;
00161
00162 while (sp)
00163 {
00164 edge e;
00165 basic_block src;
00166 basic_block dest;
00167
00168
00169 e = stack[sp - 1];
00170 src = e->src;
00171 dest = e->dest;
00172 e->flags &= ~EDGE_DFS_BACK;
00173
00174
00175 if (dest != EXIT_BLOCK_PTR && ! TEST_BIT (visited, dest->index))
00176 {
00177
00178 SET_BIT (visited, dest->index);
00179
00180 pre[dest->index] = prenum++;
00181 if (dest->succ)
00182 {
00183
00184
00185 stack[sp++] = dest->succ;
00186 }
00187 else
00188 post[dest->index] = postnum++;
00189 }
00190 else
00191 {
00192 if (dest != EXIT_BLOCK_PTR && src != ENTRY_BLOCK_PTR
00193 && pre[src->index] >= pre[dest->index]
00194 && post[dest->index] == 0)
00195 e->flags |= EDGE_DFS_BACK, found = true;
00196
00197 if (! e->succ_next && src != ENTRY_BLOCK_PTR)
00198 post[src->index] = postnum++;
00199
00200 if (e->succ_next)
00201 stack[sp - 1] = e->succ_next;
00202 else
00203 sp--;
00204 }
00205 }
00206
00207 free (pre);
00208 free (post);
00209 free (stack);
00210 sbitmap_free (visited);
00211
00212 return found;
00213 }
00214
00215
00216
00217 void
00218 set_edge_can_fallthru_flag ()
00219 {
00220 basic_block bb;
00221
00222 FOR_EACH_BB (bb)
00223 {
00224 edge e;
00225
00226 for (e = bb->succ; e; e = e->succ_next)
00227 {
00228 e->flags &= ~EDGE_CAN_FALLTHRU;
00229
00230
00231 if (e->flags & EDGE_FALLTHRU)
00232 e->flags |= EDGE_CAN_FALLTHRU;
00233 }
00234
00235
00236
00237 if (!bb->succ || !bb->succ->succ_next || bb->succ->succ_next->succ_next)
00238 continue;
00239 if (!any_condjump_p (bb->end))
00240 continue;
00241 if (!invert_jump (bb->end, JUMP_LABEL (bb->end), 0))
00242 continue;
00243 invert_jump (bb->end, JUMP_LABEL (bb->end), 0);
00244 bb->succ->flags |= EDGE_CAN_FALLTHRU;
00245 bb->succ->succ_next->flags |= EDGE_CAN_FALLTHRU;
00246 }
00247 }
00248
00249
00250
00251
00252 static bool
00253 need_fake_edge_p (insn)
00254 rtx insn;
00255 {
00256 if (!INSN_P (insn))
00257 return false;
00258
00259 if ((GET_CODE (insn) == CALL_INSN
00260 && !SIBLING_CALL_P (insn)
00261 && !find_reg_note (insn, REG_NORETURN, NULL)
00262 && !find_reg_note (insn, REG_ALWAYS_RETURN, NULL)
00263 && !CONST_OR_PURE_CALL_P (insn)))
00264 return true;
00265
00266 return ((GET_CODE (PATTERN (insn)) == ASM_OPERANDS
00267 && MEM_VOLATILE_P (PATTERN (insn)))
00268 || (GET_CODE (PATTERN (insn)) == PARALLEL
00269 && asm_noperands (insn) != -1
00270 && MEM_VOLATILE_P (XVECEXP (PATTERN (insn), 0, 0)))
00271 || GET_CODE (PATTERN (insn)) == ASM_INPUT);
00272 }
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282 int
00283 flow_call_edges_add (blocks)
00284 sbitmap blocks;
00285 {
00286 int i;
00287 int blocks_split = 0;
00288 int last_bb = last_basic_block;
00289 bool check_last_block = false;
00290
00291 if (n_basic_blocks == 0)
00292 return 0;
00293
00294 if (! blocks)
00295 check_last_block = true;
00296 else
00297 check_last_block = TEST_BIT (blocks, EXIT_BLOCK_PTR->prev_bb->index);
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311 if (check_last_block)
00312 {
00313 basic_block bb = EXIT_BLOCK_PTR->prev_bb;
00314 rtx insn = bb->end;
00315
00316
00317 while (insn != bb->head
00318 && keep_with_call_p (insn))
00319 insn = PREV_INSN (insn);
00320
00321 if (need_fake_edge_p (insn))
00322 {
00323 edge e;
00324
00325 for (e = bb->succ; e; e = e->succ_next)
00326 if (e->dest == EXIT_BLOCK_PTR)
00327 {
00328 insert_insn_on_edge (gen_rtx_USE (VOIDmode, const0_rtx), e);
00329 commit_edge_insertions ();
00330 break;
00331 }
00332 }
00333 }
00334
00335
00336
00337
00338
00339 for (i = 0; i < last_bb; i++)
00340 {
00341 basic_block bb = BASIC_BLOCK (i);
00342 rtx insn;
00343 rtx prev_insn;
00344
00345 if (!bb)
00346 continue;
00347
00348 if (blocks && !TEST_BIT (blocks, i))
00349 continue;
00350
00351 for (insn = bb->end; ; insn = prev_insn)
00352 {
00353 prev_insn = PREV_INSN (insn);
00354 if (need_fake_edge_p (insn))
00355 {
00356 edge e;
00357 rtx split_at_insn = insn;
00358
00359
00360
00361 if (GET_CODE (insn) == CALL_INSN)
00362 while (split_at_insn != bb->end
00363 && keep_with_call_p (NEXT_INSN (split_at_insn)))
00364 split_at_insn = NEXT_INSN (split_at_insn);
00365
00366
00367
00368
00369
00370
00371 #ifdef ENABLE_CHECKING
00372 if (split_at_insn == bb->end)
00373 for (e = bb->succ; e; e = e->succ_next)
00374 if (e->dest == EXIT_BLOCK_PTR)
00375 abort ();
00376 #endif
00377
00378
00379
00380 if (split_at_insn != bb->end)
00381 {
00382 e = split_block (bb, split_at_insn);
00383 if (e)
00384 blocks_split++;
00385 }
00386
00387 make_edge (bb, EXIT_BLOCK_PTR, EDGE_FAKE);
00388 }
00389
00390 if (insn == bb->head)
00391 break;
00392 }
00393 }
00394
00395 if (blocks_split)
00396 verify_flow_info ();
00397
00398 return blocks_split;
00399 }
00400
00401
00402
00403
00404
00405 void
00406 find_unreachable_blocks ()
00407 {
00408 edge e;
00409 basic_block *tos, *worklist, bb;
00410
00411 tos = worklist =
00412 (basic_block *) xmalloc (sizeof (basic_block) * n_basic_blocks);
00413
00414
00415
00416 FOR_EACH_BB (bb)
00417 bb->flags &= ~BB_REACHABLE;
00418
00419
00420
00421
00422
00423 for (e = ENTRY_BLOCK_PTR->succ; e; e = e->succ_next)
00424 {
00425 *tos++ = e->dest;
00426
00427
00428 e->dest->flags |= BB_REACHABLE;
00429 }
00430
00431
00432
00433 while (tos != worklist)
00434 {
00435 basic_block b = *--tos;
00436
00437 for (e = b->succ; e; e = e->succ_next)
00438 if (!(e->dest->flags & BB_REACHABLE))
00439 {
00440 *tos++ = e->dest;
00441 e->dest->flags |= BB_REACHABLE;
00442 }
00443 }
00444
00445 free (worklist);
00446 }
00447
00448
00449
00450
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461 struct edge_list *
00462 create_edge_list ()
00463 {
00464 struct edge_list *elist;
00465 edge e;
00466 int num_edges;
00467 int block_count;
00468 basic_block bb;
00469
00470 block_count = n_basic_blocks + 2;
00471
00472 num_edges = 0;
00473
00474
00475
00476 FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR, EXIT_BLOCK_PTR, next_bb)
00477 {
00478 for (e = bb->succ; e; e = e->succ_next)
00479 num_edges++;
00480 }
00481
00482 elist = (struct edge_list *) xmalloc (sizeof (struct edge_list));
00483 elist->num_blocks = block_count;
00484 elist->num_edges = num_edges;
00485 elist->index_to_edge = (edge *) xmalloc (sizeof (edge) * num_edges);
00486
00487 num_edges = 0;
00488
00489
00490 FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR, EXIT_BLOCK_PTR, next_bb)
00491 for (e = bb->succ; e; e = e->succ_next)
00492 elist->index_to_edge[num_edges++] = e;
00493
00494 return elist;
00495 }
00496
00497
00498
00499 void
00500 free_edge_list (elist)
00501 struct edge_list *elist;
00502 {
00503 if (elist)
00504 {
00505 free (elist->index_to_edge);
00506 free (elist);
00507 }
00508 }
00509
00510
00511
00512 void
00513 print_edge_list (f, elist)
00514 FILE *f;
00515 struct edge_list *elist;
00516 {
00517 int x;
00518
00519 fprintf (f, "Compressed edge list, %d BBs + entry & exit, and %d edges\n",
00520 elist->num_blocks - 2, elist->num_edges);
00521
00522 for (x = 0; x < elist->num_edges; x++)
00523 {
00524 fprintf (f, " %-4d - edge(", x);
00525 if (INDEX_EDGE_PRED_BB (elist, x) == ENTRY_BLOCK_PTR)
00526 fprintf (f, "entry,");
00527 else
00528 fprintf (f, "%d,", INDEX_EDGE_PRED_BB (elist, x)->index);
00529
00530 if (INDEX_EDGE_SUCC_BB (elist, x) == EXIT_BLOCK_PTR)
00531 fprintf (f, "exit)\n");
00532 else
00533 fprintf (f, "%d)\n", INDEX_EDGE_SUCC_BB (elist, x)->index);
00534 }
00535 }
00536
00537
00538
00539
00540
00541 void
00542 verify_edge_list (f, elist)
00543 FILE *f;
00544 struct edge_list *elist;
00545 {
00546 int pred, succ, index;
00547 edge e;
00548 basic_block bb, p, s;
00549
00550 FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR, EXIT_BLOCK_PTR, next_bb)
00551 {
00552 for (e = bb->succ; e; e = e->succ_next)
00553 {
00554 pred = e->src->index;
00555 succ = e->dest->index;
00556 index = EDGE_INDEX (elist, e->src, e->dest);
00557 if (index == EDGE_INDEX_NO_EDGE)
00558 {
00559 fprintf (f, "*p* No index for edge from %d to %d\n", pred, succ);
00560 continue;
00561 }
00562
00563 if (INDEX_EDGE_PRED_BB (elist, index)->index != pred)
00564 fprintf (f, "*p* Pred for index %d should be %d not %d\n",
00565 index, pred, INDEX_EDGE_PRED_BB (elist, index)->index);
00566 if (INDEX_EDGE_SUCC_BB (elist, index)->index != succ)
00567 fprintf (f, "*p* Succ for index %d should be %d not %d\n",
00568 index, succ, INDEX_EDGE_SUCC_BB (elist, index)->index);
00569 }
00570 }
00571
00572
00573
00574
00575 FOR_BB_BETWEEN (p, ENTRY_BLOCK_PTR, EXIT_BLOCK_PTR, next_bb)
00576 FOR_BB_BETWEEN (s, ENTRY_BLOCK_PTR->next_bb, NULL, next_bb)
00577 {
00578 int found_edge = 0;
00579
00580 for (e = p->succ; e; e = e->succ_next)
00581 if (e->dest == s)
00582 {
00583 found_edge = 1;
00584 break;
00585 }
00586
00587 for (e = s->pred; e; e = e->pred_next)
00588 if (e->src == p)
00589 {
00590 found_edge = 1;
00591 break;
00592 }
00593
00594 if (EDGE_INDEX (elist, p, s)
00595 == EDGE_INDEX_NO_EDGE && found_edge != 0)
00596 fprintf (f, "*** Edge (%d, %d) appears to not have an index\n",
00597 p->index, s->index);
00598 if (EDGE_INDEX (elist, p, s)
00599 != EDGE_INDEX_NO_EDGE && found_edge == 0)
00600 fprintf (f, "*** Edge (%d, %d) has index %d, but there is no edge\n",
00601 p->index, s->index, EDGE_INDEX (elist, p, s));
00602 }
00603 }
00604
00605
00606
00607
00608 int
00609 find_edge_index (edge_list, pred, succ)
00610 struct edge_list *edge_list;
00611 basic_block pred, succ;
00612 {
00613 int x;
00614
00615 for (x = 0; x < NUM_EDGES (edge_list); x++)
00616 if (INDEX_EDGE_PRED_BB (edge_list, x) == pred
00617 && INDEX_EDGE_SUCC_BB (edge_list, x) == succ)
00618 return x;
00619
00620 return (EDGE_INDEX_NO_EDGE);
00621 }
00622
00623
00624
00625 void
00626 flow_nodes_print (str, nodes, file)
00627 const char *str;
00628 const sbitmap nodes;
00629 FILE *file;
00630 {
00631 int node;
00632
00633 if (! nodes)
00634 return;
00635
00636 fprintf (file, "%s { ", str);
00637 EXECUTE_IF_SET_IN_SBITMAP (nodes, 0, node, {fprintf (file, "%d ", node);});
00638 fputs ("}\n", file);
00639 }
00640
00641
00642
00643 void
00644 flow_edge_list_print (str, edge_list, num_edges, file)
00645 const char *str;
00646 const edge *edge_list;
00647 int num_edges;
00648 FILE *file;
00649 {
00650 int i;
00651
00652 if (! edge_list)
00653 return;
00654
00655 fprintf (file, "%s { ", str);
00656 for (i = 0; i < num_edges; i++)
00657 fprintf (file, "%d->%d ", edge_list[i]->src->index,
00658 edge_list[i]->dest->index);
00659
00660 fputs ("}\n", file);
00661 }
00662
00663
00664
00665
00666
00667
00668 static void
00669 remove_fake_successors (bb)
00670 basic_block bb;
00671 {
00672 edge e;
00673
00674 for (e = bb->succ; e;)
00675 {
00676 edge tmp = e;
00677
00678 e = e->succ_next;
00679 if ((tmp->flags & EDGE_FAKE) == EDGE_FAKE)
00680 remove_edge (tmp);
00681 }
00682 }
00683
00684
00685
00686
00687
00688 void
00689 remove_fake_edges ()
00690 {
00691 basic_block bb;
00692
00693 FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR, EXIT_BLOCK_PTR, next_bb)
00694 remove_fake_successors (bb);
00695 }
00696
00697
00698
00699
00700
00701 void
00702 add_noreturn_fake_exit_edges ()
00703 {
00704 basic_block bb;
00705
00706 FOR_EACH_BB (bb)
00707 if (bb->succ == NULL)
00708 make_single_succ_edge (bb, EXIT_BLOCK_PTR, EDGE_FAKE);
00709 }
00710
00711
00712
00713
00714
00715
00716
00717
00718
00719
00720
00721
00722 void
00723 connect_infinite_loops_to_exit ()
00724 {
00725 basic_block unvisited_block;
00726 struct depth_first_search_dsS dfs_ds;
00727
00728
00729
00730 flow_dfs_compute_reverse_init (&dfs_ds);
00731 flow_dfs_compute_reverse_add_bb (&dfs_ds, EXIT_BLOCK_PTR);
00732
00733
00734 while (1)
00735 {
00736 unvisited_block = flow_dfs_compute_reverse_execute (&dfs_ds);
00737 if (!unvisited_block)
00738 break;
00739
00740 make_edge (unvisited_block, EXIT_BLOCK_PTR, EDGE_FAKE);
00741 flow_dfs_compute_reverse_add_bb (&dfs_ds, unvisited_block);
00742 }
00743
00744 flow_dfs_compute_reverse_finish (&dfs_ds);
00745 return;
00746 }
00747
00748
00749
00750 void
00751 flow_reverse_top_sort_order_compute (rts_order)
00752 int *rts_order;
00753 {
00754 edge *stack;
00755 int sp;
00756 int postnum = 0;
00757 sbitmap visited;
00758
00759
00760 stack = (edge *) xmalloc ((n_basic_blocks + 1) * sizeof (edge));
00761 sp = 0;
00762
00763
00764 visited = sbitmap_alloc (last_basic_block);
00765
00766
00767 sbitmap_zero (visited);
00768
00769
00770 stack[sp++] = ENTRY_BLOCK_PTR->succ;
00771
00772 while (sp)
00773 {
00774 edge e;
00775 basic_block src;
00776 basic_block dest;
00777
00778
00779 e = stack[sp - 1];
00780 src = e->src;
00781 dest = e->dest;
00782
00783
00784 if (dest != EXIT_BLOCK_PTR && ! TEST_BIT (visited, dest->index))
00785 {
00786
00787 SET_BIT (visited, dest->index);
00788
00789 if (dest->succ)
00790
00791
00792 stack[sp++] = dest->succ;
00793 else
00794 rts_order[postnum++] = dest->index;
00795 }
00796 else
00797 {
00798 if (! e->succ_next && src != ENTRY_BLOCK_PTR)
00799 rts_order[postnum++] = src->index;
00800
00801 if (e->succ_next)
00802 stack[sp - 1] = e->succ_next;
00803 else
00804 sp--;
00805 }
00806 }
00807
00808 free (stack);
00809 sbitmap_free (visited);
00810 }
00811
00812
00813
00814
00815
00816
00817
00818
00819 int
00820 flow_depth_first_order_compute (dfs_order, rc_order)
00821 int *dfs_order;
00822 int *rc_order;
00823 {
00824 edge *stack;
00825 int sp;
00826 int dfsnum = 0;
00827 int rcnum = n_basic_blocks - 1;
00828 sbitmap visited;
00829
00830
00831 stack = (edge *) xmalloc ((n_basic_blocks + 1) * sizeof (edge));
00832 sp = 0;
00833
00834
00835 visited = sbitmap_alloc (last_basic_block);
00836
00837
00838 sbitmap_zero (visited);
00839
00840
00841 stack[sp++] = ENTRY_BLOCK_PTR->succ;
00842
00843 while (sp)
00844 {
00845 edge e;
00846 basic_block src;
00847 basic_block dest;
00848
00849
00850 e = stack[sp - 1];
00851 src = e->src;
00852 dest = e->dest;
00853
00854
00855 if (dest != EXIT_BLOCK_PTR && ! TEST_BIT (visited, dest->index))
00856 {
00857
00858 SET_BIT (visited, dest->index);
00859
00860 if (dfs_order)
00861 dfs_order[dfsnum] = dest->index;
00862
00863 dfsnum++;
00864
00865 if (dest->succ)
00866
00867
00868 stack[sp++] = dest->succ;
00869 else if (rc_order)
00870
00871
00872 rc_order[rcnum--] = dest->index;
00873 }
00874 else
00875 {
00876 if (! e->succ_next && src != ENTRY_BLOCK_PTR
00877 && rc_order)
00878
00879
00880 rc_order[rcnum--] = src->index;
00881
00882 if (e->succ_next)
00883 stack[sp - 1] = e->succ_next;
00884 else
00885 sp--;
00886 }
00887 }
00888
00889 free (stack);
00890 sbitmap_free (visited);
00891
00892
00893
00894 if (dfsnum > n_basic_blocks)
00895 abort ();
00896
00897
00898 if (dfsnum < n_basic_blocks)
00899 abort ();
00900
00901 return dfsnum;
00902 }
00903
00904 struct dfst_node
00905 {
00906 unsigned nnodes;
00907 struct dfst_node **node;
00908 struct dfst_node *up;
00909 };
00910
00911
00912
00913
00914
00915
00916
00917
00918
00919
00920
00921
00922 void
00923 flow_preorder_transversal_compute (pot_order)
00924 int *pot_order;
00925 {
00926 edge e;
00927 edge *stack;
00928 int i;
00929 int max_successors;
00930 int sp;
00931 sbitmap visited;
00932 struct dfst_node *node;
00933 struct dfst_node *dfst;
00934 basic_block bb;
00935
00936
00937 stack = (edge *) xmalloc ((n_basic_blocks + 1) * sizeof (edge));
00938 sp = 0;
00939
00940
00941 dfst = (struct dfst_node *) xcalloc (last_basic_block,
00942 sizeof (struct dfst_node));
00943
00944 FOR_EACH_BB (bb)
00945 {
00946 max_successors = 0;
00947 for (e = bb->succ; e; e = e->succ_next)
00948 max_successors++;
00949
00950 dfst[bb->index].node
00951 = (max_successors
00952 ? (struct dfst_node **) xcalloc (max_successors,
00953 sizeof (struct dfst_node *))
00954 : NULL);
00955 }
00956
00957
00958 visited = sbitmap_alloc (last_basic_block);
00959
00960
00961 sbitmap_zero (visited);
00962
00963
00964 stack[sp++] = ENTRY_BLOCK_PTR->succ;
00965
00966 while (sp)
00967 {
00968 basic_block src;
00969 basic_block dest;
00970
00971
00972 e = stack[sp - 1];
00973 src = e->src;
00974 dest = e->dest;
00975
00976
00977 if (dest != EXIT_BLOCK_PTR && ! TEST_BIT (visited, dest->index))
00978 {
00979
00980 SET_BIT (visited, dest->index);
00981
00982
00983 if (src != ENTRY_BLOCK_PTR)
00984 {
00985 dfst[src->index].node[dfst[src->index].nnodes++]
00986 = &dfst[dest->index];
00987 dfst[dest->index].up = &dfst[src->index];
00988 }
00989
00990 if (dest->succ)
00991
00992
00993 stack[sp++] = dest->succ;
00994 }
00995
00996 else if (e->succ_next)
00997 stack[sp - 1] = e->succ_next;
00998 else
00999 sp--;
01000 }
01001
01002 free (stack);
01003 sbitmap_free (visited);
01004
01005
01006
01007
01008 i = 0;
01009 node = &dfst[ENTRY_BLOCK_PTR->next_bb->index];
01010 pot_order[i++] = 0;
01011
01012 while (node)
01013 {
01014 if (node->nnodes)
01015 {
01016 node = node->node[--node->nnodes];
01017 pot_order[i++] = node - dfst;
01018 }
01019 else
01020 node = node->up;
01021 }
01022
01023
01024
01025 for (i = 0; i < last_basic_block; i++)
01026 if (dfst[i].node)
01027 free (dfst[i].node);
01028
01029 free (dfst);
01030 }
01031
01032
01033
01034
01035
01036
01037
01038
01039
01040
01041
01042
01043
01044
01045
01046
01047
01048
01049
01050
01051
01052
01053
01054
01055
01056
01057
01058
01059
01060
01061
01062 static void
01063 flow_dfs_compute_reverse_init (data)
01064 depth_first_search_ds data;
01065 {
01066
01067 data->stack = (basic_block *) xmalloc ((n_basic_blocks - (INVALID_BLOCK + 1))
01068 * sizeof (basic_block));
01069 data->sp = 0;
01070
01071
01072 data->visited_blocks = sbitmap_alloc (last_basic_block - (INVALID_BLOCK + 1));
01073
01074
01075 sbitmap_zero (data->visited_blocks);
01076
01077 return;
01078 }
01079
01080
01081
01082
01083
01084 static void
01085 flow_dfs_compute_reverse_add_bb (data, bb)
01086 depth_first_search_ds data;
01087 basic_block bb;
01088 {
01089 data->stack[data->sp++] = bb;
01090 SET_BIT (data->visited_blocks, bb->index - (INVALID_BLOCK + 1));
01091 }
01092
01093
01094
01095
01096
01097
01098 static basic_block
01099 flow_dfs_compute_reverse_execute (data)
01100 depth_first_search_ds data;
01101 {
01102 basic_block bb;
01103 edge e;
01104
01105 while (data->sp > 0)
01106 {
01107 bb = data->stack[--data->sp];
01108
01109
01110 for (e = bb->pred; e; e = e->pred_next)
01111 if (!TEST_BIT (data->visited_blocks,
01112 e->src->index - (INVALID_BLOCK + 1)))
01113 flow_dfs_compute_reverse_add_bb (data, e->src);
01114 }
01115
01116
01117 FOR_BB_BETWEEN (bb, EXIT_BLOCK_PTR, NULL, prev_bb)
01118 if (!TEST_BIT (data->visited_blocks, bb->index - (INVALID_BLOCK + 1)))
01119 return bb;
01120
01121 return NULL;
01122 }
01123
01124
01125
01126
01127 static void
01128 flow_dfs_compute_reverse_finish (data)
01129 depth_first_search_ds data;
01130 {
01131 free (data->stack);
01132 sbitmap_free (data->visited_blocks);
01133 }
01134
01135
01136
01137
01138 int
01139 dfs_enumerate_from (bb, reverse, predicate, rslt, rslt_max, data)
01140 basic_block bb;
01141 int reverse;
01142 bool (*predicate) PARAMS ((basic_block, void *));
01143 basic_block *rslt;
01144 int rslt_max;
01145 void *data;
01146 {
01147 basic_block *st, lbb;
01148 int sp = 0, tv = 0;
01149
01150 st = xcalloc (rslt_max, sizeof (basic_block));
01151 rslt[tv++] = st[sp++] = bb;
01152 bb->flags |= BB_VISITED;
01153 while (sp)
01154 {
01155 edge e;
01156 lbb = st[--sp];
01157 if (reverse)
01158 {
01159 for (e = lbb->pred; e; e = e->pred_next)
01160 if (!(e->src->flags & BB_VISITED) && predicate (e->src, data))
01161 {
01162 if (tv == rslt_max)
01163 abort ();
01164 rslt[tv++] = st[sp++] = e->src;
01165 e->src->flags |= BB_VISITED;
01166 }
01167 }
01168 else
01169 {
01170 for (e = lbb->succ; e; e = e->succ_next)
01171 if (!(e->dest->flags & BB_VISITED) && predicate (e->dest, data))
01172 {
01173 if (tv == rslt_max)
01174 abort ();
01175 rslt[tv++] = st[sp++] = e->dest;
01176 e->dest->flags |= BB_VISITED;
01177 }
01178 }
01179 }
01180 free (st);
01181 for (sp = 0; sp < tv; sp++)
01182 rslt[sp]->flags &= ~BB_VISITED;
01183 return tv;
01184 }