00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "config.h"
00025 #include "system.h"
00026 #include "coretypes.h"
00027 #include "tm.h"
00028 #include "toplev.h"
00029 #include "rtl.h"
00030 #include "tm_p.h"
00031 #include "hard-reg-set.h"
00032 #include "regs.h"
00033 #include "function.h"
00034 #include "flags.h"
00035 #include "insn-config.h"
00036 #include "insn-attr.h"
00037 #include "except.h"
00038 #include "recog.h"
00039 #include "sched-int.h"
00040 #include "target.h"
00041 #include "cfglayout.h"
00042 #include "cfgloop.h"
00043 #include "sbitmap.h"
00044 #include "expr.h"
00045 #include "bitmap.h"
00046 #include "df.h"
00047 #include "ddg.h"
00048
00049
00050 enum edge_flag {NOT_IN_SCC = 0, IN_SCC};
00051
00052
00053 static void add_backarc_to_ddg (ddg_ptr, ddg_edge_ptr);
00054 static void add_backarc_to_scc (ddg_scc_ptr, ddg_edge_ptr);
00055 static void add_scc_to_ddg (ddg_all_sccs_ptr, ddg_scc_ptr);
00056 static void create_ddg_dependence (ddg_ptr, ddg_node_ptr, ddg_node_ptr, rtx);
00057 static void create_ddg_dep_no_link (ddg_ptr, ddg_node_ptr, ddg_node_ptr,
00058 dep_type, dep_data_type, int);
00059 static ddg_edge_ptr create_ddg_edge (ddg_node_ptr, ddg_node_ptr, dep_type,
00060 dep_data_type, int, int);
00061 static void add_edge_to_ddg (ddg_ptr g, ddg_edge_ptr);
00062
00063
00064 static bool mem_ref_p;
00065
00066
00067 static int
00068 mark_mem_use (rtx *x, void *data ATTRIBUTE_UNUSED)
00069 {
00070 if (MEM_P (*x))
00071 mem_ref_p = true;
00072 return 0;
00073 }
00074
00075
00076 static void
00077 mark_mem_use_1 (rtx *x, void *data)
00078 {
00079 for_each_rtx (x, mark_mem_use, data);
00080 }
00081
00082
00083 static bool
00084 mem_read_insn_p (rtx insn)
00085 {
00086 mem_ref_p = false;
00087 note_uses (&PATTERN (insn), mark_mem_use_1, NULL);
00088 return mem_ref_p;
00089 }
00090
00091 static void
00092 mark_mem_store (rtx loc, rtx setter ATTRIBUTE_UNUSED, void *data ATTRIBUTE_UNUSED)
00093 {
00094 if (MEM_P (loc))
00095 mem_ref_p = true;
00096 }
00097
00098
00099 static bool
00100 mem_write_insn_p (rtx insn)
00101 {
00102 mem_ref_p = false;
00103 note_stores (PATTERN (insn), mark_mem_store, NULL);
00104 return mem_ref_p;
00105 }
00106
00107
00108 static bool
00109 rtx_mem_access_p (rtx x)
00110 {
00111 int i, j;
00112 const char *fmt;
00113 enum rtx_code code;
00114
00115 if (x == 0)
00116 return false;
00117
00118 if (MEM_P (x))
00119 return true;
00120
00121 code = GET_CODE (x);
00122 fmt = GET_RTX_FORMAT (code);
00123 for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
00124 {
00125 if (fmt[i] == 'e')
00126 {
00127 if (rtx_mem_access_p (XEXP (x, i)))
00128 return true;
00129 }
00130 else if (fmt[i] == 'E')
00131 for (j = 0; j < XVECLEN (x, i); j++)
00132 {
00133 if (rtx_mem_access_p (XVECEXP (x, i, j)))
00134 return true;
00135 }
00136 }
00137 return false;
00138 }
00139
00140
00141 static bool
00142 mem_access_insn_p (rtx insn)
00143 {
00144 return rtx_mem_access_p (PATTERN (insn));
00145 }
00146
00147
00148
00149 static void
00150 create_ddg_dependence (ddg_ptr g, ddg_node_ptr src_node,
00151 ddg_node_ptr dest_node, rtx link)
00152 {
00153 ddg_edge_ptr e;
00154 int latency, distance = 0;
00155 int interloop = (src_node->cuid >= dest_node->cuid);
00156 dep_type t = TRUE_DEP;
00157 dep_data_type dt = (mem_access_insn_p (src_node->insn)
00158 && mem_access_insn_p (dest_node->insn) ? MEM_DEP
00159 : REG_DEP);
00160
00161
00162
00163 if (interloop)
00164 distance = 1;
00165
00166 gcc_assert (link);
00167
00168
00169 if (REG_NOTE_KIND (link) == REG_DEP_ANTI)
00170 t = ANTI_DEP;
00171 else if (REG_NOTE_KIND (link) == REG_DEP_OUTPUT)
00172 t = OUTPUT_DEP;
00173 latency = insn_cost (src_node->insn, link, dest_node->insn);
00174
00175 e = create_ddg_edge (src_node, dest_node, t, dt, latency, distance);
00176
00177 if (interloop)
00178 {
00179
00180
00181
00182
00183
00184 if (!(t == OUTPUT_DEP && src_node == dest_node)
00185 && !(t == ANTI_DEP && dt == REG_DEP))
00186 add_backarc_to_ddg (g, e);
00187 else
00188 free (e);
00189 }
00190 else if (t == ANTI_DEP && dt == REG_DEP)
00191 free (e);
00192 else
00193 add_edge_to_ddg (g, e);
00194 }
00195
00196
00197 static void
00198 create_ddg_dep_no_link (ddg_ptr g, ddg_node_ptr from, ddg_node_ptr to,
00199 dep_type d_t, dep_data_type d_dt, int distance)
00200 {
00201 ddg_edge_ptr e;
00202 int l;
00203 rtx link = alloc_INSN_LIST (to->insn, NULL_RTX);
00204
00205 if (d_t == ANTI_DEP)
00206 PUT_REG_NOTE_KIND (link, REG_DEP_ANTI);
00207 else if (d_t == OUTPUT_DEP)
00208 PUT_REG_NOTE_KIND (link, REG_DEP_OUTPUT);
00209
00210 l = insn_cost (from->insn, link, to->insn);
00211 free_INSN_LIST_node (link);
00212
00213 e = create_ddg_edge (from, to, d_t, d_dt, l, distance);
00214 if (distance > 0)
00215 add_backarc_to_ddg (g, e);
00216 else
00217 add_edge_to_ddg (g, e);
00218 }
00219
00220
00221
00222
00223
00224 static void
00225 add_deps_for_def (ddg_ptr g, struct df *df, struct df_ref *rd)
00226 {
00227 int regno = DF_REF_REGNO (rd);
00228 struct df_ru_bb_info *bb_info = DF_RU_BB_INFO (df, g->bb);
00229 struct df_link *r_use;
00230 int use_before_def = false;
00231 rtx def_insn = DF_REF_INSN (rd);
00232 ddg_node_ptr src_node = get_node_of_insn (g, def_insn);
00233
00234
00235
00236 for (r_use = DF_REF_CHAIN (rd); r_use != NULL; r_use = r_use->next)
00237 {
00238 if (bitmap_bit_p (bb_info->gen, r_use->ref->id))
00239 {
00240 rtx use_insn = DF_REF_INSN (r_use->ref);
00241 ddg_node_ptr dest_node = get_node_of_insn (g, use_insn);
00242
00243 gcc_assert (src_node && dest_node);
00244
00245
00246 use_before_def = true;
00247 create_ddg_dep_no_link (g, src_node, dest_node, TRUE_DEP,
00248 REG_DEP, 1);
00249 }
00250 }
00251
00252
00253
00254
00255
00256
00257
00258 if (! use_before_def)
00259 {
00260 struct df_ref *def = df_bb_regno_first_def_find (df, g->bb, regno);
00261 int i;
00262 ddg_node_ptr dest_node;
00263
00264 if (!def || rd->id == def->id)
00265 return;
00266
00267
00268 for (i = src_node->cuid + 1; i < g->num_nodes; i++)
00269 if (df_find_use (df, g->nodes[i].insn, rd->reg))
00270 return;
00271
00272 dest_node = get_node_of_insn (g, def->insn);
00273 create_ddg_dep_no_link (g, src_node, dest_node, OUTPUT_DEP, REG_DEP, 1);
00274 }
00275 }
00276
00277
00278
00279
00280 static void
00281 add_deps_for_use (ddg_ptr g, struct df *df, struct df_ref *use)
00282 {
00283 int i;
00284 int regno = DF_REF_REGNO (use);
00285 struct df_ref *first_def = df_bb_regno_first_def_find (df, g->bb, regno);
00286 ddg_node_ptr use_node;
00287 ddg_node_ptr def_node;
00288 struct df_rd_bb_info *bb_info;
00289
00290 bb_info = DF_RD_BB_INFO (df, g->bb);
00291
00292 if (!first_def)
00293 return;
00294
00295 use_node = get_node_of_insn (g, use->insn);
00296 def_node = get_node_of_insn (g, first_def->insn);
00297
00298 gcc_assert (use_node && def_node);
00299
00300
00301 for (i = use_node->cuid + 1; i < g->num_nodes; i++)
00302 if (df_find_def (df, g->nodes[i].insn, use->reg))
00303 return;
00304
00305
00306
00307 if (! bitmap_bit_p (bb_info->gen, first_def->id))
00308 create_ddg_dep_no_link (g, use_node, def_node, ANTI_DEP, REG_DEP, 1);
00309 }
00310
00311
00312 static void
00313 build_inter_loop_deps (ddg_ptr g, struct df *df)
00314 {
00315 unsigned rd_num, u_num;
00316 struct df_rd_bb_info *rd_bb_info;
00317 struct df_ru_bb_info *ru_bb_info;
00318 bitmap_iterator bi;
00319
00320 rd_bb_info = DF_RD_BB_INFO (df, g->bb);
00321
00322
00323
00324 EXECUTE_IF_SET_IN_BITMAP (rd_bb_info->gen, 0, rd_num, bi)
00325 {
00326 struct df_ref *rd = DF_DEFS_GET (df, rd_num);
00327
00328 add_deps_for_def (g, df, rd);
00329 }
00330
00331 ru_bb_info = DF_RU_BB_INFO (df, g->bb);
00332
00333
00334
00335 EXECUTE_IF_SET_IN_BITMAP (ru_bb_info->kill, 0, u_num, bi)
00336 {
00337 struct df_ref *use = DF_USES_GET (df, u_num);
00338
00339
00340 if (BLOCK_FOR_INSN (use->insn) == g->bb)
00341 add_deps_for_use (g, df, use);
00342 }
00343 }
00344
00345
00346
00347 static void
00348 add_inter_loop_mem_dep (ddg_ptr g, ddg_node_ptr from, ddg_node_ptr to)
00349 {
00350 if (mem_write_insn_p (from->insn))
00351 {
00352 if (mem_read_insn_p (to->insn))
00353 create_ddg_dep_no_link (g, from, to, TRUE_DEP, MEM_DEP, 1);
00354 else if (from->cuid != to->cuid)
00355 create_ddg_dep_no_link (g, from, to, OUTPUT_DEP, MEM_DEP, 1);
00356 }
00357 else
00358 {
00359 if (mem_read_insn_p (to->insn))
00360 return;
00361 else if (from->cuid != to->cuid)
00362 {
00363 create_ddg_dep_no_link (g, from, to, ANTI_DEP, MEM_DEP, 1);
00364 create_ddg_dep_no_link (g, to, from, TRUE_DEP, MEM_DEP, 1);
00365 }
00366 }
00367
00368 }
00369
00370
00371
00372 static void
00373 build_intra_loop_deps (ddg_ptr g)
00374 {
00375 int i;
00376
00377 struct deps tmp_deps;
00378 rtx head, tail, link;
00379
00380
00381 init_deps_global ();
00382 init_deps (&tmp_deps);
00383
00384
00385 get_ebb_head_tail (g->bb, g->bb, &head, &tail);
00386 sched_analyze (&tmp_deps, head, tail);
00387
00388
00389
00390 for (i = 0; i < g->num_nodes; i++)
00391 {
00392 ddg_node_ptr dest_node = &g->nodes[i];
00393
00394 if (! INSN_P (dest_node->insn))
00395 continue;
00396
00397 for (link = LOG_LINKS (dest_node->insn); link; link = XEXP (link, 1))
00398 {
00399 ddg_node_ptr src_node = get_node_of_insn (g, XEXP (link, 0));
00400
00401 if (!src_node)
00402 continue;
00403
00404 add_forw_dep (dest_node->insn, link);
00405 create_ddg_dependence (g, src_node, dest_node,
00406 INSN_DEPEND (src_node->insn));
00407 }
00408
00409
00410
00411 if (mem_access_insn_p (dest_node->insn))
00412 {
00413 int j;
00414
00415 for (j = 0; j <= i; j++)
00416 {
00417 ddg_node_ptr j_node = &g->nodes[j];
00418 if (mem_access_insn_p (j_node->insn))
00419
00420
00421 if (! TEST_BIT (dest_node->successors, j))
00422 add_inter_loop_mem_dep (g, dest_node, j_node);
00423 }
00424 }
00425 }
00426
00427
00428 finish_deps_global ();
00429 free_deps (&tmp_deps);
00430 }
00431
00432
00433
00434
00435
00436 ddg_ptr
00437 create_ddg (basic_block bb, struct df *df, int closing_branch_deps)
00438 {
00439 ddg_ptr g;
00440 rtx insn, first_note;
00441 int i;
00442 int num_nodes = 0;
00443
00444 g = (ddg_ptr) xcalloc (1, sizeof (struct ddg));
00445
00446 g->bb = bb;
00447 g->closing_branch_deps = closing_branch_deps;
00448
00449
00450 for (insn = BB_HEAD (bb); insn != NEXT_INSN (BB_END (bb));
00451 insn = NEXT_INSN (insn))
00452 {
00453 if (! INSN_P (insn) || GET_CODE (PATTERN (insn)) == USE)
00454 continue;
00455
00456 if (mem_read_insn_p (insn))
00457 g->num_loads++;
00458 if (mem_write_insn_p (insn))
00459 g->num_stores++;
00460 num_nodes++;
00461 }
00462
00463
00464 if (num_nodes <= 1)
00465 {
00466 free (g);
00467 return NULL;
00468 }
00469
00470
00471 g->num_nodes = num_nodes;
00472 g->nodes = (ddg_node_ptr) xcalloc (num_nodes, sizeof (struct ddg_node));
00473 g->closing_branch = NULL;
00474 i = 0;
00475 first_note = NULL_RTX;
00476 for (insn = BB_HEAD (bb); insn != NEXT_INSN (BB_END (bb));
00477 insn = NEXT_INSN (insn))
00478 {
00479 if (! INSN_P (insn))
00480 {
00481 if (! first_note && NOTE_P (insn)
00482 && NOTE_LINE_NUMBER (insn) != NOTE_INSN_BASIC_BLOCK)
00483 first_note = insn;
00484 continue;
00485 }
00486 if (JUMP_P (insn))
00487 {
00488 gcc_assert (!g->closing_branch);
00489 g->closing_branch = &g->nodes[i];
00490 }
00491 else if (GET_CODE (PATTERN (insn)) == USE)
00492 {
00493 if (! first_note)
00494 first_note = insn;
00495 continue;
00496 }
00497
00498 g->nodes[i].cuid = i;
00499 g->nodes[i].successors = sbitmap_alloc (num_nodes);
00500 sbitmap_zero (g->nodes[i].successors);
00501 g->nodes[i].predecessors = sbitmap_alloc (num_nodes);
00502 sbitmap_zero (g->nodes[i].predecessors);
00503 g->nodes[i].first_note = (first_note ? first_note : insn);
00504 g->nodes[i++].insn = insn;
00505 first_note = NULL_RTX;
00506 }
00507
00508
00509 gcc_assert (g->closing_branch);
00510
00511
00512
00513 build_intra_loop_deps (g);
00514 build_inter_loop_deps (g, df);
00515 return g;
00516 }
00517
00518
00519 void
00520 free_ddg (ddg_ptr g)
00521 {
00522 int i;
00523
00524 if (!g)
00525 return;
00526
00527 for (i = 0; i < g->num_nodes; i++)
00528 {
00529 ddg_edge_ptr e = g->nodes[i].out;
00530
00531 while (e)
00532 {
00533 ddg_edge_ptr next = e->next_out;
00534
00535 free (e);
00536 e = next;
00537 }
00538 sbitmap_free (g->nodes[i].successors);
00539 sbitmap_free (g->nodes[i].predecessors);
00540 }
00541 if (g->num_backarcs > 0)
00542 free (g->backarcs);
00543 free (g->nodes);
00544 free (g);
00545 }
00546
00547 void
00548 print_ddg_edge (FILE *file, ddg_edge_ptr e)
00549 {
00550 char dep_c;
00551
00552 switch (e->type) {
00553 case OUTPUT_DEP :
00554 dep_c = 'O';
00555 break;
00556 case ANTI_DEP :
00557 dep_c = 'A';
00558 break;
00559 default:
00560 dep_c = 'T';
00561 }
00562
00563 fprintf (file, " [%d -(%c,%d,%d)-> %d] ", INSN_UID (e->src->insn),
00564 dep_c, e->latency, e->distance, INSN_UID (e->dest->insn));
00565 }
00566
00567
00568 void
00569 print_ddg (FILE *file, ddg_ptr g)
00570 {
00571 int i;
00572
00573 for (i = 0; i < g->num_nodes; i++)
00574 {
00575 ddg_edge_ptr e;
00576
00577 print_rtl_single (file, g->nodes[i].insn);
00578 fprintf (file, "OUT ARCS: ");
00579 for (e = g->nodes[i].out; e; e = e->next_out)
00580 print_ddg_edge (file, e);
00581
00582 fprintf (file, "\nIN ARCS: ");
00583 for (e = g->nodes[i].in; e; e = e->next_in)
00584 print_ddg_edge (file, e);
00585
00586 fprintf (file, "\n");
00587 }
00588 }
00589
00590
00591 void
00592 vcg_print_ddg (FILE *file, ddg_ptr g)
00593 {
00594 int src_cuid;
00595
00596 fprintf (file, "graph: {\n");
00597 for (src_cuid = 0; src_cuid < g->num_nodes; src_cuid++)
00598 {
00599 ddg_edge_ptr e;
00600 int src_uid = INSN_UID (g->nodes[src_cuid].insn);
00601
00602 fprintf (file, "node: {title: \"%d_%d\" info1: \"", src_cuid, src_uid);
00603 print_rtl_single (file, g->nodes[src_cuid].insn);
00604 fprintf (file, "\"}\n");
00605 for (e = g->nodes[src_cuid].out; e; e = e->next_out)
00606 {
00607 int dst_uid = INSN_UID (e->dest->insn);
00608 int dst_cuid = e->dest->cuid;
00609
00610
00611 if (e->distance > 0)
00612 fprintf (file, "backedge: {color: red ");
00613 else
00614 fprintf (file, "edge: { ");
00615
00616 fprintf (file, "sourcename: \"%d_%d\" ", src_cuid, src_uid);
00617 fprintf (file, "targetname: \"%d_%d\" ", dst_cuid, dst_uid);
00618 fprintf (file, "label: \"%d_%d\"}\n", e->latency, e->distance);
00619 }
00620 }
00621 fprintf (file, "}\n");
00622 }
00623
00624
00625 static ddg_edge_ptr
00626 create_ddg_edge (ddg_node_ptr src, ddg_node_ptr dest,
00627 dep_type t, dep_data_type dt, int l, int d)
00628 {
00629 ddg_edge_ptr e = (ddg_edge_ptr) xmalloc (sizeof (struct ddg_edge));
00630
00631 e->src = src;
00632 e->dest = dest;
00633 e->type = t;
00634 e->data_type = dt;
00635 e->latency = l;
00636 e->distance = d;
00637 e->next_in = e->next_out = NULL;
00638 e->aux.info = 0;
00639 return e;
00640 }
00641
00642
00643 static void
00644 add_edge_to_ddg (ddg_ptr g ATTRIBUTE_UNUSED, ddg_edge_ptr e)
00645 {
00646 ddg_node_ptr src = e->src;
00647 ddg_node_ptr dest = e->dest;
00648
00649
00650 gcc_assert (src->successors && dest->predecessors);
00651
00652 SET_BIT (src->successors, dest->cuid);
00653 SET_BIT (dest->predecessors, src->cuid);
00654 e->next_in = dest->in;
00655 dest->in = e;
00656 e->next_out = src->out;
00657 src->out = e;
00658 }
00659
00660
00661
00662
00663
00664
00665 static void
00666 set_recurrence_length (ddg_scc_ptr scc, ddg_ptr g)
00667 {
00668 int j;
00669 int result = -1;
00670
00671 for (j = 0; j < scc->num_backarcs; j++)
00672 {
00673 ddg_edge_ptr backarc = scc->backarcs[j];
00674 int length;
00675 int distance = backarc->distance;
00676 ddg_node_ptr src = backarc->dest;
00677 ddg_node_ptr dest = backarc->src;
00678
00679 length = longest_simple_path (g, src->cuid, dest->cuid, scc->nodes);
00680 if (length < 0 )
00681 {
00682
00683 continue;
00684 }
00685 length += backarc->latency;
00686 result = MAX (result, (length / distance));
00687 }
00688 scc->recurrence_length = result;
00689 }
00690
00691
00692
00693 static ddg_scc_ptr
00694 create_scc (ddg_ptr g, sbitmap nodes)
00695 {
00696 ddg_scc_ptr scc;
00697 unsigned int u = 0;
00698 sbitmap_iterator sbi;
00699
00700 scc = (ddg_scc_ptr) xmalloc (sizeof (struct ddg_scc));
00701 scc->backarcs = NULL;
00702 scc->num_backarcs = 0;
00703 scc->nodes = sbitmap_alloc (g->num_nodes);
00704 sbitmap_copy (scc->nodes, nodes);
00705
00706
00707 EXECUTE_IF_SET_IN_SBITMAP (nodes, 0, u, sbi)
00708 {
00709 ddg_edge_ptr e;
00710 ddg_node_ptr n = &g->nodes[u];
00711
00712 for (e = n->out; e; e = e->next_out)
00713 if (TEST_BIT (nodes, e->dest->cuid))
00714 {
00715 e->aux.count = IN_SCC;
00716 if (e->distance > 0)
00717 add_backarc_to_scc (scc, e);
00718 }
00719 }
00720
00721 set_recurrence_length (scc, g);
00722 return scc;
00723 }
00724
00725
00726 static void
00727 free_scc (ddg_scc_ptr scc)
00728 {
00729 if (!scc)
00730 return;
00731
00732 sbitmap_free (scc->nodes);
00733 if (scc->num_backarcs > 0)
00734 free (scc->backarcs);
00735 free (scc);
00736 }
00737
00738
00739
00740 static void
00741 add_backarc_to_ddg (ddg_ptr g, ddg_edge_ptr e)
00742 {
00743 int size = (g->num_backarcs + 1) * sizeof (ddg_edge_ptr);
00744
00745 add_edge_to_ddg (g, e);
00746 g->backarcs = (ddg_edge_ptr *) xrealloc (g->backarcs, size);
00747 g->backarcs[g->num_backarcs++] = e;
00748 }
00749
00750
00751 static void
00752 add_backarc_to_scc (ddg_scc_ptr scc, ddg_edge_ptr e)
00753 {
00754 int size = (scc->num_backarcs + 1) * sizeof (ddg_edge_ptr);
00755
00756 scc->backarcs = (ddg_edge_ptr *) xrealloc (scc->backarcs, size);
00757 scc->backarcs[scc->num_backarcs++] = e;
00758 }
00759
00760
00761 static void
00762 add_scc_to_ddg (ddg_all_sccs_ptr g, ddg_scc_ptr scc)
00763 {
00764 int size = (g->num_sccs + 1) * sizeof (ddg_scc_ptr);
00765
00766 g->sccs = (ddg_scc_ptr *) xrealloc (g->sccs, size);
00767 g->sccs[g->num_sccs++] = scc;
00768 }
00769
00770
00771 ddg_node_ptr
00772 get_node_of_insn (ddg_ptr g, rtx insn)
00773 {
00774 int i;
00775
00776 for (i = 0; i < g->num_nodes; i++)
00777 if (insn == g->nodes[i].insn)
00778 return &g->nodes[i];
00779 return NULL;
00780 }
00781
00782
00783
00784
00785 void
00786 find_successors (sbitmap succ, ddg_ptr g, sbitmap ops)
00787 {
00788 unsigned int i = 0;
00789 sbitmap_iterator sbi;
00790
00791 EXECUTE_IF_SET_IN_SBITMAP (ops, 0, i, sbi)
00792 {
00793 const sbitmap node_succ = NODE_SUCCESSORS (&g->nodes[i]);
00794 sbitmap_a_or_b (succ, succ, node_succ);
00795 };
00796
00797
00798 sbitmap_difference (succ, succ, ops);
00799 }
00800
00801
00802
00803
00804 void
00805 find_predecessors (sbitmap preds, ddg_ptr g, sbitmap ops)
00806 {
00807 unsigned int i = 0;
00808 sbitmap_iterator sbi;
00809
00810 EXECUTE_IF_SET_IN_SBITMAP (ops, 0, i, sbi)
00811 {
00812 const sbitmap node_preds = NODE_PREDECESSORS (&g->nodes[i]);
00813 sbitmap_a_or_b (preds, preds, node_preds);
00814 };
00815
00816
00817 sbitmap_difference (preds, preds, ops);
00818 }
00819
00820
00821
00822
00823 static int
00824 compare_sccs (const void *s1, const void *s2)
00825 {
00826 int rec_l1 = (*(ddg_scc_ptr *)s1)->recurrence_length;
00827 int rec_l2 = (*(ddg_scc_ptr *)s2)->recurrence_length;
00828 return ((rec_l2 > rec_l1) - (rec_l2 < rec_l1));
00829
00830 }
00831
00832
00833 static void
00834 order_sccs (ddg_all_sccs_ptr g)
00835 {
00836 qsort (g->sccs, g->num_sccs, sizeof (ddg_scc_ptr),
00837 (int (*) (const void *, const void *)) compare_sccs);
00838 }
00839
00840
00841
00842 ddg_all_sccs_ptr
00843 create_ddg_all_sccs (ddg_ptr g)
00844 {
00845 int i;
00846 int num_nodes = g->num_nodes;
00847 sbitmap from = sbitmap_alloc (num_nodes);
00848 sbitmap to = sbitmap_alloc (num_nodes);
00849 sbitmap scc_nodes = sbitmap_alloc (num_nodes);
00850 ddg_all_sccs_ptr sccs = (ddg_all_sccs_ptr)
00851 xmalloc (sizeof (struct ddg_all_sccs));
00852
00853 sccs->ddg = g;
00854 sccs->sccs = NULL;
00855 sccs->num_sccs = 0;
00856
00857 for (i = 0; i < g->num_backarcs; i++)
00858 {
00859 ddg_scc_ptr scc;
00860 ddg_edge_ptr backarc = g->backarcs[i];
00861 ddg_node_ptr src = backarc->src;
00862 ddg_node_ptr dest = backarc->dest;
00863
00864
00865 if (backarc->aux.count == IN_SCC)
00866 continue;
00867
00868 sbitmap_zero (from);
00869 sbitmap_zero (to);
00870 SET_BIT (from, dest->cuid);
00871 SET_BIT (to, src->cuid);
00872
00873 if (find_nodes_on_paths (scc_nodes, g, from, to))
00874 {
00875 scc = create_scc (g, scc_nodes);
00876 add_scc_to_ddg (sccs, scc);
00877 }
00878 }
00879 order_sccs (sccs);
00880 sbitmap_free (from);
00881 sbitmap_free (to);
00882 sbitmap_free (scc_nodes);
00883 return sccs;
00884 }
00885
00886
00887 void
00888 free_ddg_all_sccs (ddg_all_sccs_ptr all_sccs)
00889 {
00890 int i;
00891
00892 if (!all_sccs)
00893 return;
00894
00895 for (i = 0; i < all_sccs->num_sccs; i++)
00896 free_scc (all_sccs->sccs[i]);
00897
00898 free (all_sccs);
00899 }
00900
00901
00902
00903
00904
00905 int
00906 find_nodes_on_paths (sbitmap result, ddg_ptr g, sbitmap from, sbitmap to)
00907 {
00908 int answer;
00909 int change;
00910 unsigned int u = 0;
00911 int num_nodes = g->num_nodes;
00912 sbitmap_iterator sbi;
00913
00914 sbitmap workset = sbitmap_alloc (num_nodes);
00915 sbitmap reachable_from = sbitmap_alloc (num_nodes);
00916 sbitmap reach_to = sbitmap_alloc (num_nodes);
00917 sbitmap tmp = sbitmap_alloc (num_nodes);
00918
00919 sbitmap_copy (reachable_from, from);
00920 sbitmap_copy (tmp, from);
00921
00922 change = 1;
00923 while (change)
00924 {
00925 change = 0;
00926 sbitmap_copy (workset, tmp);
00927 sbitmap_zero (tmp);
00928 EXECUTE_IF_SET_IN_SBITMAP (workset, 0, u, sbi)
00929 {
00930 ddg_edge_ptr e;
00931 ddg_node_ptr u_node = &g->nodes[u];
00932
00933 for (e = u_node->out; e != (ddg_edge_ptr) 0; e = e->next_out)
00934 {
00935 ddg_node_ptr v_node = e->dest;
00936 int v = v_node->cuid;
00937
00938 if (!TEST_BIT (reachable_from, v))
00939 {
00940 SET_BIT (reachable_from, v);
00941 SET_BIT (tmp, v);
00942 change = 1;
00943 }
00944 }
00945 }
00946 }
00947
00948 sbitmap_copy (reach_to, to);
00949 sbitmap_copy (tmp, to);
00950
00951 change = 1;
00952 while (change)
00953 {
00954 change = 0;
00955 sbitmap_copy (workset, tmp);
00956 sbitmap_zero (tmp);
00957 EXECUTE_IF_SET_IN_SBITMAP (workset, 0, u, sbi)
00958 {
00959 ddg_edge_ptr e;
00960 ddg_node_ptr u_node = &g->nodes[u];
00961
00962 for (e = u_node->in; e != (ddg_edge_ptr) 0; e = e->next_in)
00963 {
00964 ddg_node_ptr v_node = e->src;
00965 int v = v_node->cuid;
00966
00967 if (!TEST_BIT (reach_to, v))
00968 {
00969 SET_BIT (reach_to, v);
00970 SET_BIT (tmp, v);
00971 change = 1;
00972 }
00973 }
00974 }
00975 }
00976
00977 answer = sbitmap_a_and_b_cg (result, reachable_from, reach_to);
00978 sbitmap_free (workset);
00979 sbitmap_free (reachable_from);
00980 sbitmap_free (reach_to);
00981 sbitmap_free (tmp);
00982 return answer;
00983 }
00984
00985
00986
00987
00988
00989
00990 static int
00991 update_dist_to_successors (ddg_node_ptr u_node, sbitmap nodes, sbitmap tmp)
00992 {
00993 ddg_edge_ptr e;
00994 int result = 0;
00995
00996 for (e = u_node->out; e; e = e->next_out)
00997 {
00998 ddg_node_ptr v_node = e->dest;
00999 int v = v_node->cuid;
01000
01001 if (TEST_BIT (nodes, v)
01002 && (e->distance == 0)
01003 && (v_node->aux.count < u_node->aux.count + e->latency))
01004 {
01005 v_node->aux.count = u_node->aux.count + e->latency;
01006 SET_BIT (tmp, v);
01007 result = 1;
01008 }
01009 }
01010 return result;
01011 }
01012
01013
01014
01015
01016 int
01017 longest_simple_path (struct ddg * g, int src, int dest, sbitmap nodes)
01018 {
01019 int i;
01020 unsigned int u = 0;
01021 int change = 1;
01022 int result;
01023 int num_nodes = g->num_nodes;
01024 sbitmap workset = sbitmap_alloc (num_nodes);
01025 sbitmap tmp = sbitmap_alloc (num_nodes);
01026
01027
01028
01029
01030 for (i = 0; i < g->num_nodes; i++)
01031 g->nodes[i].aux.count = -1;
01032 g->nodes[src].aux.count = 0;
01033
01034 sbitmap_zero (tmp);
01035 SET_BIT (tmp, src);
01036
01037 while (change)
01038 {
01039 sbitmap_iterator sbi;
01040
01041 change = 0;
01042 sbitmap_copy (workset, tmp);
01043 sbitmap_zero (tmp);
01044 EXECUTE_IF_SET_IN_SBITMAP (workset, 0, u, sbi)
01045 {
01046 ddg_node_ptr u_node = &g->nodes[u];
01047
01048 change |= update_dist_to_successors (u_node, nodes, tmp);
01049 }
01050 }
01051 result = g->nodes[dest].aux.count;
01052 sbitmap_free (workset);
01053 sbitmap_free (tmp);
01054 return result;
01055 }