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 ref *rd)
00226 {
00227 int regno = DF_REF_REGNO (rd);
00228 struct bb_info *bb_info = DF_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->ru_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 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_reg_used (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 ref *use)
00282 {
00283 int i;
00284 int regno = DF_REF_REGNO (use);
00285 struct 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 bb_info *bb_info;
00289
00290 bb_info = DF_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->rd_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 bb_info *bb_info;
00317 bitmap_iterator bi;
00318
00319 bb_info = DF_BB_INFO (df, g->bb);
00320
00321
00322
00323 EXECUTE_IF_SET_IN_BITMAP (bb_info->rd_gen, 0, rd_num, bi)
00324 {
00325 struct ref *rd = df->defs[rd_num];
00326
00327 add_deps_for_def (g, df, rd);
00328 }
00329
00330
00331
00332 EXECUTE_IF_SET_IN_BITMAP (bb_info->ru_kill, 0, u_num, bi)
00333 {
00334 struct ref *use = df->uses[u_num];
00335
00336
00337 if (BLOCK_FOR_INSN (use->insn) == g->bb)
00338 add_deps_for_use (g, df,use);
00339 }
00340 }
00341
00342
00343
00344 static void
00345 add_inter_loop_mem_dep (ddg_ptr g, ddg_node_ptr from, ddg_node_ptr to)
00346 {
00347 if (mem_write_insn_p (from->insn))
00348 {
00349 if (mem_read_insn_p (to->insn))
00350 create_ddg_dep_no_link (g, from, to, TRUE_DEP, MEM_DEP, 1);
00351 else if (from->cuid != to->cuid)
00352 create_ddg_dep_no_link (g, from, to, OUTPUT_DEP, MEM_DEP, 1);
00353 }
00354 else
00355 {
00356 if (mem_read_insn_p (to->insn))
00357 return;
00358 else if (from->cuid != to->cuid)
00359 {
00360 create_ddg_dep_no_link (g, from, to, ANTI_DEP, MEM_DEP, 1);
00361 create_ddg_dep_no_link (g, to, from, TRUE_DEP, MEM_DEP, 1);
00362 }
00363 }
00364
00365 }
00366
00367
00368
00369 static void
00370 build_intra_loop_deps (ddg_ptr g)
00371 {
00372 int i;
00373
00374 struct deps tmp_deps;
00375 rtx head, tail, link;
00376
00377
00378 init_deps_global ();
00379 init_deps (&tmp_deps);
00380
00381
00382 get_block_head_tail (g->bb->index, &head, &tail);
00383 sched_analyze (&tmp_deps, head, tail);
00384
00385
00386
00387 for (i = 0; i < g->num_nodes; i++)
00388 {
00389 ddg_node_ptr dest_node = &g->nodes[i];
00390
00391 if (! INSN_P (dest_node->insn))
00392 continue;
00393
00394 for (link = LOG_LINKS (dest_node->insn); link; link = XEXP (link, 1))
00395 {
00396 ddg_node_ptr src_node = get_node_of_insn (g, XEXP (link, 0));
00397
00398 if (!src_node)
00399 continue;
00400
00401 add_forward_dependence (XEXP (link, 0), dest_node->insn,
00402 REG_NOTE_KIND (link));
00403 create_ddg_dependence (g, src_node, dest_node,
00404 INSN_DEPEND (src_node->insn));
00405 }
00406
00407
00408
00409 if (mem_access_insn_p (dest_node->insn))
00410 {
00411 int j;
00412
00413 for (j = 0; j <= i; j++)
00414 {
00415 ddg_node_ptr j_node = &g->nodes[j];
00416 if (mem_access_insn_p (j_node->insn))
00417
00418
00419 if (! TEST_BIT (dest_node->successors, j))
00420 add_inter_loop_mem_dep (g, dest_node, j_node);
00421 }
00422 }
00423 }
00424
00425
00426 finish_deps_global ();
00427 free_deps (&tmp_deps);
00428 }
00429
00430
00431
00432
00433
00434 ddg_ptr
00435 create_ddg (basic_block bb, struct df *df, int closing_branch_deps)
00436 {
00437 ddg_ptr g;
00438 rtx insn, first_note;
00439 int i;
00440 int num_nodes = 0;
00441
00442 g = (ddg_ptr) xcalloc (1, sizeof (struct ddg));
00443
00444 g->bb = bb;
00445 g->closing_branch_deps = closing_branch_deps;
00446
00447
00448 for (insn = BB_HEAD (bb); insn != NEXT_INSN (BB_END (bb));
00449 insn = NEXT_INSN (insn))
00450 {
00451 if (! INSN_P (insn) || GET_CODE (PATTERN (insn)) == USE)
00452 continue;
00453
00454 if (mem_read_insn_p (insn))
00455 g->num_loads++;
00456 if (mem_write_insn_p (insn))
00457 g->num_stores++;
00458 num_nodes++;
00459 }
00460
00461
00462 if (num_nodes <= 1)
00463 {
00464 free (g);
00465 return NULL;
00466 }
00467
00468
00469 g->num_nodes = num_nodes;
00470 g->nodes = (ddg_node_ptr) xcalloc (num_nodes, sizeof (struct ddg_node));
00471 g->closing_branch = NULL;
00472 i = 0;
00473 first_note = NULL_RTX;
00474 for (insn = BB_HEAD (bb); insn != NEXT_INSN (BB_END (bb));
00475 insn = NEXT_INSN (insn))
00476 {
00477 if (! INSN_P (insn))
00478 {
00479 if (! first_note && NOTE_P (insn)
00480 && NOTE_LINE_NUMBER (insn) != NOTE_INSN_BASIC_BLOCK)
00481 first_note = insn;
00482 continue;
00483 }
00484 if (JUMP_P (insn))
00485 {
00486 gcc_assert (!g->closing_branch);
00487 g->closing_branch = &g->nodes[i];
00488 }
00489 else if (GET_CODE (PATTERN (insn)) == USE)
00490 {
00491 if (! first_note)
00492 first_note = insn;
00493 continue;
00494 }
00495
00496 g->nodes[i].cuid = i;
00497 g->nodes[i].successors = sbitmap_alloc (num_nodes);
00498 sbitmap_zero (g->nodes[i].successors);
00499 g->nodes[i].predecessors = sbitmap_alloc (num_nodes);
00500 sbitmap_zero (g->nodes[i].predecessors);
00501 g->nodes[i].first_note = (first_note ? first_note : insn);
00502 g->nodes[i++].insn = insn;
00503 first_note = NULL_RTX;
00504 }
00505
00506
00507 gcc_assert (g->closing_branch);
00508
00509
00510
00511 build_intra_loop_deps (g);
00512 build_inter_loop_deps (g, df);
00513 return g;
00514 }
00515
00516
00517 void
00518 free_ddg (ddg_ptr g)
00519 {
00520 int i;
00521
00522 if (!g)
00523 return;
00524
00525 for (i = 0; i < g->num_nodes; i++)
00526 {
00527 ddg_edge_ptr e = g->nodes[i].out;
00528
00529 while (e)
00530 {
00531 ddg_edge_ptr next = e->next_out;
00532
00533 free (e);
00534 e = next;
00535 }
00536 sbitmap_free (g->nodes[i].successors);
00537 sbitmap_free (g->nodes[i].predecessors);
00538 }
00539 if (g->num_backarcs > 0)
00540 free (g->backarcs);
00541 free (g->nodes);
00542 free (g);
00543 }
00544
00545 void
00546 print_ddg_edge (FILE *dump_file, ddg_edge_ptr e)
00547 {
00548 char dep_c;
00549
00550 switch (e->type) {
00551 case OUTPUT_DEP :
00552 dep_c = 'O';
00553 break;
00554 case ANTI_DEP :
00555 dep_c = 'A';
00556 break;
00557 default:
00558 dep_c = 'T';
00559 }
00560
00561 fprintf (dump_file, " [%d -(%c,%d,%d)-> %d] ", INSN_UID (e->src->insn),
00562 dep_c, e->latency, e->distance, INSN_UID (e->dest->insn));
00563 }
00564
00565
00566 void
00567 print_ddg (FILE *dump_file, ddg_ptr g)
00568 {
00569 int i;
00570
00571 for (i = 0; i < g->num_nodes; i++)
00572 {
00573 ddg_edge_ptr e;
00574
00575 print_rtl_single (dump_file, g->nodes[i].insn);
00576 fprintf (dump_file, "OUT ARCS: ");
00577 for (e = g->nodes[i].out; e; e = e->next_out)
00578 print_ddg_edge (dump_file, e);
00579
00580 fprintf (dump_file, "\nIN ARCS: ");
00581 for (e = g->nodes[i].in; e; e = e->next_in)
00582 print_ddg_edge (dump_file, e);
00583
00584 fprintf (dump_file, "\n");
00585 }
00586 }
00587
00588
00589 void
00590 vcg_print_ddg (FILE *dump_file, ddg_ptr g)
00591 {
00592 int src_cuid;
00593
00594 fprintf (dump_file, "graph: {\n");
00595 for (src_cuid = 0; src_cuid < g->num_nodes; src_cuid++)
00596 {
00597 ddg_edge_ptr e;
00598 int src_uid = INSN_UID (g->nodes[src_cuid].insn);
00599
00600 fprintf (dump_file, "node: {title: \"%d_%d\" info1: \"", src_cuid, src_uid);
00601 print_rtl_single (dump_file, g->nodes[src_cuid].insn);
00602 fprintf (dump_file, "\"}\n");
00603 for (e = g->nodes[src_cuid].out; e; e = e->next_out)
00604 {
00605 int dst_uid = INSN_UID (e->dest->insn);
00606 int dst_cuid = e->dest->cuid;
00607
00608
00609 if (e->distance > 0)
00610 fprintf (dump_file, "backedge: {color: red ");
00611 else
00612 fprintf (dump_file, "edge: { ");
00613
00614 fprintf (dump_file, "sourcename: \"%d_%d\" ", src_cuid, src_uid);
00615 fprintf (dump_file, "targetname: \"%d_%d\" ", dst_cuid, dst_uid);
00616 fprintf (dump_file, "label: \"%d_%d\"}\n", e->latency, e->distance);
00617 }
00618 }
00619 fprintf (dump_file, "}\n");
00620 }
00621
00622
00623 static ddg_edge_ptr
00624 create_ddg_edge (ddg_node_ptr src, ddg_node_ptr dest,
00625 dep_type t, dep_data_type dt, int l, int d)
00626 {
00627 ddg_edge_ptr e = (ddg_edge_ptr) xmalloc (sizeof (struct ddg_edge));
00628
00629 e->src = src;
00630 e->dest = dest;
00631 e->type = t;
00632 e->data_type = dt;
00633 e->latency = l;
00634 e->distance = d;
00635 e->next_in = e->next_out = NULL;
00636 e->aux.info = 0;
00637 return e;
00638 }
00639
00640
00641 static void
00642 add_edge_to_ddg (ddg_ptr g ATTRIBUTE_UNUSED, ddg_edge_ptr e)
00643 {
00644 ddg_node_ptr src = e->src;
00645 ddg_node_ptr dest = e->dest;
00646
00647
00648 gcc_assert (src->successors && dest->predecessors);
00649
00650 SET_BIT (src->successors, dest->cuid);
00651 SET_BIT (dest->predecessors, src->cuid);
00652 e->next_in = dest->in;
00653 dest->in = e;
00654 e->next_out = src->out;
00655 src->out = e;
00656 }
00657
00658
00659
00660
00661
00662
00663 static void
00664 set_recurrence_length (ddg_scc_ptr scc, ddg_ptr g)
00665 {
00666 int j;
00667 int result = -1;
00668
00669 for (j = 0; j < scc->num_backarcs; j++)
00670 {
00671 ddg_edge_ptr backarc = scc->backarcs[j];
00672 int length;
00673 int distance = backarc->distance;
00674 ddg_node_ptr src = backarc->dest;
00675 ddg_node_ptr dest = backarc->src;
00676
00677 length = longest_simple_path (g, src->cuid, dest->cuid, scc->nodes);
00678 if (length < 0 )
00679 {
00680
00681 continue;
00682 }
00683 length += backarc->latency;
00684 result = MAX (result, (length / distance));
00685 }
00686 scc->recurrence_length = result;
00687 }
00688
00689
00690
00691 static ddg_scc_ptr
00692 create_scc (ddg_ptr g, sbitmap nodes)
00693 {
00694 ddg_scc_ptr scc;
00695 int u;
00696
00697 scc = (ddg_scc_ptr) xmalloc (sizeof (struct ddg_scc));
00698 scc->backarcs = NULL;
00699 scc->num_backarcs = 0;
00700 scc->nodes = sbitmap_alloc (g->num_nodes);
00701 sbitmap_copy (scc->nodes, nodes);
00702
00703
00704 EXECUTE_IF_SET_IN_SBITMAP (nodes, 0, u,
00705 {
00706 ddg_edge_ptr e;
00707 ddg_node_ptr n = &g->nodes[u];
00708
00709 for (e = n->out; e; e = e->next_out)
00710 if (TEST_BIT (nodes, e->dest->cuid))
00711 {
00712 e->aux.count = IN_SCC;
00713 if (e->distance > 0)
00714 add_backarc_to_scc (scc, e);
00715 }
00716 });
00717
00718 set_recurrence_length (scc, g);
00719 return scc;
00720 }
00721
00722
00723 static void
00724 free_scc (ddg_scc_ptr scc)
00725 {
00726 if (!scc)
00727 return;
00728
00729 sbitmap_free (scc->nodes);
00730 if (scc->num_backarcs > 0)
00731 free (scc->backarcs);
00732 free (scc);
00733 }
00734
00735
00736
00737 static void
00738 add_backarc_to_ddg (ddg_ptr g, ddg_edge_ptr e)
00739 {
00740 int size = (g->num_backarcs + 1) * sizeof (ddg_edge_ptr);
00741
00742 add_edge_to_ddg (g, e);
00743 g->backarcs = (ddg_edge_ptr *) xrealloc (g->backarcs, size);
00744 g->backarcs[g->num_backarcs++] = e;
00745 }
00746
00747
00748 static void
00749 add_backarc_to_scc (ddg_scc_ptr scc, ddg_edge_ptr e)
00750 {
00751 int size = (scc->num_backarcs + 1) * sizeof (ddg_edge_ptr);
00752
00753 scc->backarcs = (ddg_edge_ptr *) xrealloc (scc->backarcs, size);
00754 scc->backarcs[scc->num_backarcs++] = e;
00755 }
00756
00757
00758 static void
00759 add_scc_to_ddg (ddg_all_sccs_ptr g, ddg_scc_ptr scc)
00760 {
00761 int size = (g->num_sccs + 1) * sizeof (ddg_scc_ptr);
00762
00763 g->sccs = (ddg_scc_ptr *) xrealloc (g->sccs, size);
00764 g->sccs[g->num_sccs++] = scc;
00765 }
00766
00767
00768 ddg_node_ptr
00769 get_node_of_insn (ddg_ptr g, rtx insn)
00770 {
00771 int i;
00772
00773 for (i = 0; i < g->num_nodes; i++)
00774 if (insn == g->nodes[i].insn)
00775 return &g->nodes[i];
00776 return NULL;
00777 }
00778
00779
00780
00781
00782 void
00783 find_successors (sbitmap succ, ddg_ptr g, sbitmap ops)
00784 {
00785 int i;
00786
00787 EXECUTE_IF_SET_IN_SBITMAP (ops, 0, i,
00788 {
00789 const sbitmap node_succ = NODE_SUCCESSORS (&g->nodes[i]);
00790 sbitmap_a_or_b (succ, succ, node_succ);
00791 });
00792
00793
00794 sbitmap_difference (succ, succ, ops);
00795 }
00796
00797
00798
00799
00800 void
00801 find_predecessors (sbitmap preds, ddg_ptr g, sbitmap ops)
00802 {
00803 int i;
00804
00805 EXECUTE_IF_SET_IN_SBITMAP (ops, 0, i,
00806 {
00807 const sbitmap node_preds = NODE_PREDECESSORS (&g->nodes[i]);
00808 sbitmap_a_or_b (preds, preds, node_preds);
00809 });
00810
00811
00812 sbitmap_difference (preds, preds, ops);
00813 }
00814
00815
00816
00817
00818 static int
00819 compare_sccs (const void *s1, const void *s2)
00820 {
00821 int rec_l1 = (*(ddg_scc_ptr *)s1)->recurrence_length;
00822 int rec_l2 = (*(ddg_scc_ptr *)s2)->recurrence_length;
00823 return ((rec_l2 > rec_l1) - (rec_l2 < rec_l1));
00824
00825 }
00826
00827
00828 static void
00829 order_sccs (ddg_all_sccs_ptr g)
00830 {
00831 qsort (g->sccs, g->num_sccs, sizeof (ddg_scc_ptr),
00832 (int (*) (const void *, const void *)) compare_sccs);
00833 }
00834
00835
00836
00837 ddg_all_sccs_ptr
00838 create_ddg_all_sccs (ddg_ptr g)
00839 {
00840 int i;
00841 int num_nodes = g->num_nodes;
00842 sbitmap from = sbitmap_alloc (num_nodes);
00843 sbitmap to = sbitmap_alloc (num_nodes);
00844 sbitmap scc_nodes = sbitmap_alloc (num_nodes);
00845 ddg_all_sccs_ptr sccs = (ddg_all_sccs_ptr)
00846 xmalloc (sizeof (struct ddg_all_sccs));
00847
00848 sccs->ddg = g;
00849 sccs->sccs = NULL;
00850 sccs->num_sccs = 0;
00851
00852 for (i = 0; i < g->num_backarcs; i++)
00853 {
00854 ddg_scc_ptr scc;
00855 ddg_edge_ptr backarc = g->backarcs[i];
00856 ddg_node_ptr src = backarc->src;
00857 ddg_node_ptr dest = backarc->dest;
00858
00859
00860 if (backarc->aux.count == IN_SCC)
00861 continue;
00862
00863 sbitmap_zero (from);
00864 sbitmap_zero (to);
00865 SET_BIT (from, dest->cuid);
00866 SET_BIT (to, src->cuid);
00867
00868 if (find_nodes_on_paths (scc_nodes, g, from, to))
00869 {
00870 scc = create_scc (g, scc_nodes);
00871 add_scc_to_ddg (sccs, scc);
00872 }
00873 }
00874 order_sccs (sccs);
00875 sbitmap_free (from);
00876 sbitmap_free (to);
00877 sbitmap_free (scc_nodes);
00878 return sccs;
00879 }
00880
00881
00882 void
00883 free_ddg_all_sccs (ddg_all_sccs_ptr all_sccs)
00884 {
00885 int i;
00886
00887 if (!all_sccs)
00888 return;
00889
00890 for (i = 0; i < all_sccs->num_sccs; i++)
00891 free_scc (all_sccs->sccs[i]);
00892
00893 free (all_sccs);
00894 }
00895
00896
00897
00898
00899
00900 int
00901 find_nodes_on_paths (sbitmap result, ddg_ptr g, sbitmap from, sbitmap to)
00902 {
00903 int answer;
00904 int change, u;
00905 int num_nodes = g->num_nodes;
00906 sbitmap workset = sbitmap_alloc (num_nodes);
00907 sbitmap reachable_from = sbitmap_alloc (num_nodes);
00908 sbitmap reach_to = sbitmap_alloc (num_nodes);
00909 sbitmap tmp = sbitmap_alloc (num_nodes);
00910
00911 sbitmap_copy (reachable_from, from);
00912 sbitmap_copy (tmp, from);
00913
00914 change = 1;
00915 while (change)
00916 {
00917 change = 0;
00918 sbitmap_copy (workset, tmp);
00919 sbitmap_zero (tmp);
00920 EXECUTE_IF_SET_IN_SBITMAP (workset, 0, u,
00921 {
00922 ddg_edge_ptr e;
00923 ddg_node_ptr u_node = &g->nodes[u];
00924
00925 for (e = u_node->out; e != (ddg_edge_ptr) 0; e = e->next_out)
00926 {
00927 ddg_node_ptr v_node = e->dest;
00928 int v = v_node->cuid;
00929
00930 if (!TEST_BIT (reachable_from, v))
00931 {
00932 SET_BIT (reachable_from, v);
00933 SET_BIT (tmp, v);
00934 change = 1;
00935 }
00936 }
00937 });
00938 }
00939
00940 sbitmap_copy (reach_to, to);
00941 sbitmap_copy (tmp, to);
00942
00943 change = 1;
00944 while (change)
00945 {
00946 change = 0;
00947 sbitmap_copy (workset, tmp);
00948 sbitmap_zero (tmp);
00949 EXECUTE_IF_SET_IN_SBITMAP (workset, 0, u,
00950 {
00951 ddg_edge_ptr e;
00952 ddg_node_ptr u_node = &g->nodes[u];
00953
00954 for (e = u_node->in; e != (ddg_edge_ptr) 0; e = e->next_in)
00955 {
00956 ddg_node_ptr v_node = e->src;
00957 int v = v_node->cuid;
00958
00959 if (!TEST_BIT (reach_to, v))
00960 {
00961 SET_BIT (reach_to, v);
00962 SET_BIT (tmp, v);
00963 change = 1;
00964 }
00965 }
00966 });
00967 }
00968
00969 answer = sbitmap_a_and_b_cg (result, reachable_from, reach_to);
00970 sbitmap_free (workset);
00971 sbitmap_free (reachable_from);
00972 sbitmap_free (reach_to);
00973 sbitmap_free (tmp);
00974 return answer;
00975 }
00976
00977
00978
00979
00980
00981
00982 static int
00983 update_dist_to_successors (ddg_node_ptr u_node, sbitmap nodes, sbitmap tmp)
00984 {
00985 ddg_edge_ptr e;
00986 int result = 0;
00987
00988 for (e = u_node->out; e; e = e->next_out)
00989 {
00990 ddg_node_ptr v_node = e->dest;
00991 int v = v_node->cuid;
00992
00993 if (TEST_BIT (nodes, v)
00994 && (e->distance == 0)
00995 && (v_node->aux.count < u_node->aux.count + e->latency))
00996 {
00997 v_node->aux.count = u_node->aux.count + e->latency;
00998 SET_BIT (tmp, v);
00999 result = 1;
01000 }
01001 }
01002 return result;
01003 }
01004
01005
01006
01007
01008 int
01009 longest_simple_path (struct ddg * g, int src, int dest, sbitmap nodes)
01010 {
01011 int i, u;
01012 int change = 1;
01013 int result;
01014 int num_nodes = g->num_nodes;
01015 sbitmap workset = sbitmap_alloc (num_nodes);
01016 sbitmap tmp = sbitmap_alloc (num_nodes);
01017
01018
01019
01020
01021 for (i = 0; i < g->num_nodes; i++)
01022 g->nodes[i].aux.count = -1;
01023 g->nodes[src].aux.count = 0;
01024
01025 sbitmap_zero (tmp);
01026 SET_BIT (tmp, src);
01027
01028 while (change)
01029 {
01030 change = 0;
01031 sbitmap_copy (workset, tmp);
01032 sbitmap_zero (tmp);
01033 EXECUTE_IF_SET_IN_SBITMAP (workset, 0, u,
01034 {
01035 ddg_node_ptr u_node = &g->nodes[u];
01036
01037 change |= update_dist_to_successors (u_node, nodes, tmp);
01038 });
01039 }
01040 result = g->nodes[dest].aux.count;
01041 sbitmap_free (workset);
01042 sbitmap_free (tmp);
01043 return result;
01044 }