2 * Project: libFIRM/extension module/graph rewriting system
3 * File name: ext/grs/plan_vs.c
4 * Purpose: provides a planar wich performs a bypassing of
5 * v-structures by real valued costs
7 * Created: 11. Junly 2005
9 * Copyright: (c) 2005 Universität Karlsruhe
10 * Licence: This file protected by GPL - GNU GENERAL PUBLIC LICENSE.
21 #include "auxilary_t.h"
24 #include "analyze_t.h"
26 #include "matchplan_t.h"
30 #include "plan_vs_dmst.h"
36 typedef struct _ext_grs_vs_dmst_planer_private_t {
37 /* tells wether an edge has been chosen */
39 /* tells wether a node has been already reached by the MDST */
41 /* An array of edge ptrs. Each ptr
42 * denotes the edge visited during the MDST computation before the edge,
43 * with a given aiid, i.e. the path successor of this edge in forward direction.
44 * If the edge belongs to a circle found during the MDST computation, this ptr
45 * points to the next circle edge. If the edges tgt node is a super node,
46 * the ptr points to the next edge on the same level, i.e. if the edge belongs
47 * not to a super node itself, the ptr points to the path successor in
48 * forward direction, if the edge belongs to a super node itself, the
49 * ptr points to the next circle edge. */
50 ext_grs_edge_t **edge_path_succ;
51 /* An array of edge ptrs.
52 * If an edge with a given aiid is an outgoing edge of a super node build
53 * during the MDST computation the respective ptr points to the last edge
54 * of the circle on forward direction */
55 ext_grs_edge_t **super_node_last_edge;
56 /* needed in the actual plan generation, to remember which condition
57 * functions have already been placed in a matching op */
58 lc_bitset_t *already_placed_conditions;
59 /* needed in the actual plan generation, to remember which nodes have
60 * alredy been matvhed by a generated mop */
61 lc_bitset_t *already_matched_nodes;
62 /* needed in the actual plan generation, to remember which edges have
63 * alredy been matvhed by a generated mop */
64 lc_bitset_t *already_matched_edges;
65 /* tells wether a node with a given node id has been visited yet,
66 * if not the value in the array is '0', if yes the value is the
69 /* an array of edge ptr, each pointing to a root of an edge path builded
70 * during the MDST computation */
71 ext_grs_edge_t **edge_path_roots;
72 /* number of edge path roots stored in that array */
73 int n_edge_path_roots;
75 } ext_grs_vs_dmst_planer_private_t;
79 #define UF_FIND(e) (ext_grs_uf_find((e)+1) - 1)
80 #define UF_FIND_VALUE(e) (ext_grs_uf_find_value((e)+1))
81 #define UF_UNITE(r1,r2) (ext_grs_uf_unite((r1)+1,(r2)+1) - 1)
82 #define UF_CHANGE_VALUE(r,a) (ext_grs_uf_change_value((r)+1,(a)))
85 /* auxilary function for debugging purposes */
86 static void dump_edge_path(ext_grs_vs_dmst_planer_private_t *p, ext_grs_edge_t *edge) {
88 ext_grs_edge_t *current_edge = edge;
91 printf("An edge path:\n");
94 printf(" edge %s\n", current_edge->name);
95 current_edge = p->edge_path_succ[current_edge->aiid];
97 while (current_edge != NULL && current_edge != edge);
114 /* auxiliary function needed in the expansion step of the MDST algorithm,
115 * checks whether there is a reached node in a super node */
116 static int examine_super_node(
117 ext_grs_vs_dmst_planer_private_t *p,
118 ext_grs_edge_t *start_edge)
120 ext_grs_edge_t *current_edge = NULL;
121 int already_reached_node_found = 0;
123 /* walk the circle forming the current super node */
124 assert(start_edge && "NULL edge given");
125 current_edge = start_edge;
128 /* if the current edges real target node is already reached by an MDST edge,
129 * report, that a reached node is found in the current super node */
130 if ( p->mdst_reached[current_edge->arg->aiid] ) return 1;
132 /* if the current edges target node is a super node,
133 * recursively examine that super node too */
134 if (p->super_node_last_edge[current_edge->aiid]) {
135 already_reached_node_found =
136 examine_super_node(p,
138 p->super_node_last_edge[current_edge->aiid]->aiid
142 if (already_reached_node_found) return 1;
144 /* process the next edge of the circle */
145 current_edge = p->edge_path_succ[current_edge->aiid];
146 assert(current_edge && "in a circle the edge path should form a circle too");
148 while (current_edge != start_edge);
150 /* report that no reached node has been found in the current super node */
164 /* auxiliary function needed in the expansion step of the MDST algorithm,
165 * walks a super node and kills one specific edge */
166 static void expand_super_node(
167 ext_grs_vs_dmst_planer_private_t *p,
168 ext_grs_edge_t *start_edge)
170 ext_grs_edge_t *current_edge;
174 /* Walk the circle and choose every edge marking its target node as reached, except...
175 * ...the edge already has an already reached real target node OR
176 * ...the edges target node is a super node containing an already reached real node.
177 * If an edge has a super node as target node recursively expand that super node too. */
178 current_edge = start_edge;
181 /* tells whether the current edges target node is a super node
182 * containing an already reached real node */
183 int super_node_contains_reached_node = 0;
184 /* represents the start edge of a super node circle */
185 ext_grs_edge_t *super_node_start_edge = NULL;
186 /* represents the last edge of a super node circle */
187 ext_grs_edge_t *super_node_end_edge = NULL;
190 super_node_end_edge = p->super_node_last_edge[current_edge->aiid];
191 if (super_node_end_edge)
192 super_node_start_edge = p->edge_path_succ[ super_node_end_edge->aiid ];
194 /* if the current edges target is a super node, check whether
195 * this super node contains an already reached real node */
196 super_node_contains_reached_node = 0;
197 if (super_node_start_edge) {
198 super_node_contains_reached_node = examine_super_node(p, super_node_start_edge);
201 /* mark the current edge as chosen and its real target node as reached, except... (see above) */
203 ! p->mdst_reached[current_edge->arg->aiid] &&
204 ! super_node_contains_reached_node
207 p->chosen[current_edge->aiid] = 1;
208 p->mdst_reached[current_edge->arg->aiid] = 1;
211 /* if the current edges target node is a super node, then recursively expand it */
212 if (super_node_start_edge) {
213 expand_super_node(p, super_node_start_edge);
216 /* process the next edge of the super node circle */
217 current_edge = p->edge_path_succ[current_edge->aiid];
218 assert(current_edge);
220 while (current_edge != start_edge);
241 /* auxiliary function needed in the expansion step of the MDST algorithm,
242 * walks a super node where the edge to be killed is initially not known */
243 static void expand_super_node_examine(
244 ext_grs_vs_dmst_planer_private_t *p,
245 ext_grs_edge_t *start_edge)
248 ext_grs_edge_t *current_edge = NULL;
252 printf("Expanding a super node (examine). Start edge is %s\n", start_edge->name);
253 printf("The circle of edges forming the super node: ");
257 /* walk the circle forming the current super node */
258 assert(start_edge && "NULL edge given");
261 current_edge = start_edge;
263 printf("%s ", current_edge->name);
267 /* if the current edges target node is a super node, expand that super node */
268 if (p->super_node_last_edge[current_edge->aiid] != NULL) {
271 printf(" Recursively stepping into super node:\n{\n");
274 expand_super_node_examine(p,
276 p->super_node_last_edge[current_edge->aiid]->aiid
284 /* if the current edges real target node is already reached by an MDST edge,
285 * do NOT choose the current edge for the MDST but remember that there's already
286 * an edge in the current circle, which has not been chosen for the MDST */
287 if ( p->mdst_reached[current_edge->arg->aiid] ) {
288 /* all but exactly one edge of a circle have to be chosen for the MDST */
289 assert( !edge_killed && "more than one circle edge not chosen for the MDST");
290 /* remember that theres already is an edge not chosen */
294 /* otherwise the current edge is chosen, except
296 * ...it is the last edge of the current circle and no edge edge has been not killed yet */
297 if ( p->edge_path_succ[current_edge->aiid] != start_edge || edge_killed )
299 p->chosen[current_edge->aiid] = 1;
300 p->mdst_reached[current_edge->arg->aiid] = 1;
304 /* process the next edge of the circle */
305 current_edge = p->edge_path_succ[current_edge->aiid];
306 assert(current_edge && "in a circle the edge path should form a circle too");
308 printf("%s ", current_edge->name);
311 while (current_edge != start_edge);
322 /* auxilary function needed in the expansion step of the MDST algorithm,
323 * walks a super node where the given edge is the edge to be killed from
324 * the MDST and the other edges are to be chosen for the MDST */
325 static void expand_super_node_killing(
326 ext_grs_vs_dmst_planer_private_t *p,
327 ext_grs_edge_t *kill_edge)
329 ext_grs_edge_t *current_edge;
332 printf("\nExpanding a super node (kill). ");
338 printf("Kill-edge is %s\n", kill_edge->name);
339 printf("The circle of edges forming the super node: ");
342 /* walk the circle for the first time:
343 * every edge except the edge to be killed is marked as chosen, the real
344 * target node of such an edge is to be marked es reached by the MDST */
345 current_edge = p->edge_path_succ[kill_edge->aiid];
346 assert(current_edge);
348 printf("%s ", current_edge->name);
350 assert(current_edge != kill_edge); /* no loops allowed! */
353 p->mdst_reached[current_edge->arg->aiid] = 1;
354 p->chosen[current_edge->aiid] = 1;
355 current_edge = p->edge_path_succ[current_edge->aiid];
356 assert(current_edge);
358 printf("%s ", current_edge->name);
361 while (current_edge != kill_edge);
367 /* walk the circle for the second time...
368 * while every super node is expanded. Note that there is a different
369 * treatment of supernodes pointed to by the edge to be killed and by
370 * the other edges: two different functions are called */
371 current_edge = p->edge_path_succ[kill_edge->aiid];
372 assert(current_edge);
373 assert(current_edge != kill_edge); /* no loops allowed! */
376 if (p->super_node_last_edge[current_edge->aiid])
377 expand_super_node_killing(p, p->super_node_last_edge[current_edge->aiid]);
378 current_edge = p->edge_path_succ[current_edge->aiid];
380 while (current_edge != kill_edge);
381 /* now the super node pointed to by the edge to be killed is expanded
382 * (if there is one) */
383 if (p->super_node_last_edge[kill_edge->aiid])
384 expand_super_node_examine(p,
386 p->super_node_last_edge[kill_edge->aiid]->aiid
395 /* Place all conditions in the mop, which can now be computed
396 * and have not been computed yet. If there are more than one
397 * such conditions generate additional condition mops. */
398 static INLINE void emit_nodes_conditions(
399 ext_grs_action_t *act, ext_grs_node_t *node,
400 ext_grs_vs_dmst_planer_private_t *p, ext_grs_match_op_t *prog, int *prog_pos)
402 /* flag, tells whether there has already been placed a condition
403 * in the current edges mop (so additional condition mops have
405 int already_placed = 0;
407 /* a condition index from a set of involved conditions */
408 lc_bitset_pos_t cond = (act->nodes_refering_conds[node->aiid])->size;
411 ext_grs_match_op_t *mop;
413 if (act->n_conditions > 0) {
414 lc_bitset_foreach(act->nodes_refering_conds[node->aiid], cond) {
416 /* if current condition has already been placed in the plan
417 * currently generated, then skip */
418 if (lc_bitset_is_set(p->already_placed_conditions, cond)) continue;
420 /* otherwise check, whether all involved nodes
421 * and edges have already been matched */
423 ! lc_bitset_contains(
424 act->conds_involved_nodes[(int)cond],
425 p->already_matched_nodes)
428 /* otherwise place the condition in the mop or (if there has already
429 * been placed one) create a condition mop. */
430 if (already_placed) {
431 int j = ++(*prog_pos); // Create a condition mop;
433 mop->kind = ext_grs_k_mop_condition;
434 mop->condition = act->conditions[(int)cond];
435 lc_bitset_set(p->already_placed_conditions, cond); // AS
438 mop = &prog[*prog_pos]; // AS
439 mop->condition = act->conditions[(int)cond];
441 lc_bitset_set(p->already_placed_conditions, cond); // AS
449 /* Place all conditions in the mop, which can now be computed
450 * and have not been computed yet. If there are more than one
451 * such conditions generate additional condition mops. */
452 static INLINE void emit_edges_conditions(
453 ext_grs_action_t *act, ext_grs_edge_t *edge,
454 ext_grs_vs_dmst_planer_private_t *p, ext_grs_match_op_t *prog, int *prog_pos)
456 /* flag, tells whether there has already been placed a condition
457 * in the current edges mop (so additional condition mops have
459 int already_placed = 0;
461 /* a condition index from a set of involved conditions */
462 lc_bitset_pos_t cond;
465 ext_grs_match_op_t *mop;
467 if (act->n_conditions > 0) {
469 // Place conditions for source and target of the edge, if they have not been
470 // placed yet while emitting the "node operation".
471 if(edge->func != NULL) // AS
472 emit_nodes_conditions(act, edge->func, p, prog, prog_pos); // AS
473 if(edge->arg != NULL) // AS
474 emit_nodes_conditions(act, edge->arg, p, prog, prog_pos); // AS
476 lc_bitset_foreach(act->edges_refering_conds[edge->aiid], cond) {
477 /* if current condition has already been placed in the plan
478 * currently generated, then skip */
479 if (lc_bitset_is_set(p->already_placed_conditions, cond)) continue;
480 /* otherwise check, whether all involved nodes
481 * and edges have already been matched */
483 ! lc_bitset_contains(
484 act->conds_involved_nodes[(int)cond],
485 p->already_matched_nodes)
487 /* otherwise check, whether all involved edges
488 * and edges have already been matched */
490 ! lc_bitset_contains(
491 act->conds_involved_edges[(int)cond],
492 p->already_matched_edges)
494 /* otherwise place the condition in the mop or (if there has already
495 * been placed one) create a condition mop. */
496 if (already_placed) {
497 int j = ++(*prog_pos);
499 mop->kind = ext_grs_k_mop_condition;
500 mop->condition = act->conditions[(int)cond];
501 lc_bitset_set(p->already_placed_conditions, cond); // AS
504 mop = &prog[*prog_pos]; // AS
505 mop->condition = act->conditions[(int)cond];
507 lc_bitset_set(p->already_placed_conditions, cond); // AS
515 static void emit_mop(
516 ext_grs_vs_dmst_planer_private_t *p,
517 ext_grs_action_t *act, ext_grs_match_op_t *prog,
518 ext_grs_edge_t *edge, int *prog_pos)
522 ext_grs_match_op_t *mop;
527 /* write the respective node or edge into the mop */
528 if (edge->kind == ext_grs_k_edge) {
529 ext_grs_edge_t *back_edge;
531 mop->kind = ext_grs_k_mop_edge;
533 mop->node = edge->func;
535 mop->edge->first_mop_index = j;
537 /* mark the pseudo edge representing the backward
538 * traversal of the edge also as chosen such that
539 * it can not be used for the generation of matcher
540 * ops anymore, or if already chosen, remove it
541 * from the priority queue of allowed edges */
542 back_edge = edge->backward_edge;
543 if (p->chosen[back_edge->aiid] == 2) {
544 ext_grs_mpq_delete(back_edge);
547 p->chosen[edge->backward_edge->aiid] = 2;
550 /* mark the genuine node as already been matched */
551 lc_bitset_set(p->already_matched_edges, edge->aiid);
552 /* mark the genuine node as already been matched */
553 lc_bitset_set(p->already_matched_nodes, edge->arg->aiid);
555 emit_edges_conditions(act, edge, p, prog, prog_pos);
558 ext_grs_elem_t *genuine_elem;
560 assert(edge->kind == ext_grs_k_pseudo_edge && "invalid kind");
561 /* get the genuine elem */
562 genuine_elem = & edge->genuine_elem;
563 if (genuine_elem->kind == ext_grs_k_edge) {
564 /* pseudo edge represents a reverse edge matching */
565 ext_grs_edge_t *genuine_edge = genuine_elem->val.e;
567 if(genuine_edge->related_edge != NULL)
568 mop->kind = ext_grs_k_mop_preset_edge;
570 mop->kind = ext_grs_k_mop_edge;
571 mop->edge = genuine_edge;
572 mop->node = genuine_edge->arg;
574 mop->edge->first_mop_index = j;
576 /* mark the actual edge belonging to the
577 * pseudo edge representing the backward
578 * traversal of the that actual edge also as chosen
579 * such that it can not be used for the generation
580 * of matcher ops anymore, or if already chosen,
581 * remove it from the priority queue of allowed edges */
582 if (p->chosen[genuine_edge->aiid] == 2) {
583 ext_grs_mpq_delete(genuine_edge);
586 p->chosen[genuine_edge->aiid] = 2;
589 /* mark the genuine node as already been matched */
590 lc_bitset_set(p->already_matched_edges, genuine_edge->aiid);
591 /* mark the genuine node as already been matched */
592 lc_bitset_set(p->already_matched_nodes, genuine_edge->func->aiid);
594 emit_edges_conditions(act, genuine_edge, p, prog, prog_pos);
598 /* pseudo edge represents a node matching */
599 ext_grs_node_t *genuine_node = genuine_elem->val.n;
601 assert(genuine_elem->kind == ext_grs_k_node && "invalid kind");
602 assert(genuine_node == edge->arg);
604 if(genuine_node->related_node != NULL)
605 mop->kind = ext_grs_k_mop_preset;
607 mop->kind = ext_grs_k_mop_node;
609 mop->node = genuine_node;
611 if (genuine_node->op_condition)
612 mop->op_condition = genuine_node->op_condition;
613 if (genuine_node->mode_condition)
614 mop->mode_condition = genuine_node->mode_condition;
616 /* mark the genuine node as already been matched */
617 lc_bitset_set(p->already_matched_nodes, genuine_node->aiid);
619 emit_nodes_conditions(act, genuine_node, p, prog, prog_pos);
625 static ext_grs_match_op_t **emit_negative_plans(ext_grs_action_t *act)
628 /* Compute a search plan for all negative patterns */
629 /* Count number of negative patterns */
630 int num_negatives = 0, i;
631 ext_grs_match_op_t **result;
635 lc_list_for_each(pos, (&act->negatives))
638 result = (ext_grs_match_op_t **) malloc(num_negatives * sizeof(ext_grs_match_op_t *));
641 /* Handle all negative patterns, there can be several */
642 lc_list_for_each(pos, (&act->negatives))
644 struct ext_grs_graph_t *neg_pattern;
646 result[i] = (ext_grs_match_op_t *) malloc((act->n_nodes + act->n_edges + act->n_conditions) * sizeof(ext_grs_match_op_t));
647 neg_pattern = lc_list_entry(pos, ext_grs_graph_t, negative_list);
649 /* TODO: Now walk through that graph and create search plan */
659 /* ---------------------------------------------------------
660 Allocate the memory for the plan object and for the array
661 representing the match program all at once
662 --------------------------------------------------------- */
663 static ext_grs_match_plan_t *alloc_plan(ext_grs_action_t *act)
665 ext_grs_match_plan_t *plan;
666 lc_list_t *neg_patterns;
668 int num_negatives = 0, num_all_plans;
671 plan = malloc(sizeof(*plan));
672 memset(plan, 0, sizeof(*plan));
676 /* Compute a search plan for all negative patterns */
678 /* Count number of negative patterns */
679 lc_list_for_each(list_pos, (&act->negatives))
681 num_all_plans = num_negatives + 1;
683 plan->progs = (ext_grs_match_op_t **) malloc(num_all_plans * sizeof(ext_grs_match_op_t *));
685 /* Alloc mem for all search plans, 1 positive and n negative */
686 plan->progs[0] = (ext_grs_match_op_t *) malloc((act->n_nodes + act->n_edges + act->n_neg_nodes + act->n_neg_edges + act->n_conditions) * sizeof(ext_grs_match_op_t));
687 memset(plan->progs[0], 0, (act->n_nodes + act->n_edges + act->n_neg_nodes + act->n_neg_edges + act->n_conditions) * sizeof(ext_grs_match_op_t));
690 neg_patterns = &act->negatives;
691 neg_patterns = neg_patterns->next;
692 for(i = 1; i < num_all_plans; i++)
694 ext_grs_graph_t *pat = (ext_grs_graph_t *) lc_list_entry(neg_patterns, ext_grs_graph_t, negative_list);
695 plan->progs[i] = (ext_grs_match_op_t *) malloc((act->n_nodes + act->n_edges + act->n_neg_nodes + act->n_neg_edges + act->n_conditions) * sizeof(ext_grs_match_op_t));
696 memset(plan->progs[i], 0, (act->n_nodes + act->n_edges + act->n_neg_nodes + act->n_neg_edges + act->n_conditions) * sizeof(ext_grs_match_op_t));
697 neg_patterns = neg_patterns->next;
701 plan -> prog = plan -> progs[0];
703 plan -> length = (int *) malloc(num_all_plans * sizeof(int));
704 memset(plan -> length, 0, num_all_plans * sizeof(int));
706 plan->num_progs = num_all_plans;
714 * Generation of the matching plan usind the precoomputed MDST.
715 * HERE WE GO: comming from the root chose one edge after another as the
716 * next search plan edge by a modified Best-First manner:
717 * An edge can only be chosen iff
718 * - if it is an pseudo or benuine OUT edge AND
719 * - at least one of its incident nodes has already
720 * been visited by the final plan generation AND
721 * - it is part of the computed MDSR or BOTH of
722 * its incident nodes have already been chosen
723 * This is done by one big Priority queue were all edges
724 * are put in the moment they become allowed to be chosen */
726 emit_plan( ext_grs_match_op_t *prog /*ext_grs_match_plan_t *plan*/, ext_grs_graph_t *pattern /*ext_grs_action_t *act*/, ext_grs_vs_dmst_planer_private_t *p, int phase)
728 ext_grs_action_t *act = pattern->action;
729 ext_grs_node_t *current_node;
732 /* create the pq containing the allowed edges */
733 /* a priority queue for edges used after MDST computation in
734 * the final plan generation step */
735 ext_grs_mpq_t *edge_queue = ext_grs_mpq_create();
736 /* initialize the uf structure. This is because after the init
737 * a zero cost modification of incoming edges is associated to
738 * every pattern node. This MUST be done, because the cost
739 * modification stored on the if structure are used by the priority
740 * queue by to compute the actual cost of an edge. So if these
741 * modifications are NOT zero the order in the queue will be WRONG!!! */
742 ext_grs_uf_init(act->max_node_aiid + 1);
745 /* the current pos in the generated match program */
748 /* START from the patterns root */
749 current_node = &pattern->root_node;
752 ext_grs_edge_t *cheapest_edge;
753 ext_grs_match_op_t *mop;
755 /* put all out (that is in-flowing) edges in pq that are allowed
756 * to be matched by the fact, that they belong to the MDST */
757 lc_list_for_each(pos, & current_node->edges[ext_grs_in]) {
759 /* ATTENTION: if ported to GrGen these 'in' indeces have
760 * to be changed to 'out' !!!! */
761 ext_grs_edge_t *some_edge =
762 lc_list_entry(pos, ext_grs_edge_t, list[ext_grs_in]);
765 /* some edge belongs to the MDST, but no match opereation
766 * has been generated yet */
767 p->chosen[some_edge->aiid] == 1
770 ext_grs_mpq_insert(edge_queue, some_edge);
771 /* mark edge as processed
772 * (so it will not be inserted in the queue again) */
773 p->chosen[some_edge->aiid] = 2;
776 /* put all out (that is in-flowing) AND in (that is out-flowing)
777 * edges in pq that are allowed to be matched by the fact,
778 * that both of their incident nodes have already been matched.
779 * The in edges are added too, because the matching of the REAL
780 * edge coming from the (already matched) node at the other end
781 * of the plan graph edge may be cheaper */
782 lc_list_for_each(pos, & current_node->edges[ext_grs_in]) {
784 /* ATTENTION: if ported to GrGen these 'in' indeces have
785 * to be changed to 'out' !!!! */
786 ext_grs_edge_t *some_edge =
787 lc_list_entry(pos, ext_grs_edge_t, list[ext_grs_in]);
790 /* both incident nodes of some edge have arealready been
791 * processed by the final plan genration phase, but no match
792 * operation has been generated yet */
793 (p->chosen[some_edge->aiid] == 0 && p->visited[some_edge->arg->aiid] > phase)
796 ext_grs_mpq_insert(edge_queue, some_edge);
797 /* mark edge as processed
798 * (so it will not be inserted in the queue again) */
799 p->chosen[some_edge->aiid] = 2;
802 /* also insert the backward edge */
803 /* ...in case of a real edge its in fact the backward edge */
804 if (some_edge->kind == ext_grs_k_edge) {
805 ext_grs_mpq_insert(edge_queue, some_edge->backward_edge);
806 p->chosen[some_edge->backward_edge->aiid] = 2;
808 /* ...otherwise its the genuine edge */
810 assert (some_edge->kind == ext_grs_k_pseudo_edge && "invalid kind");
811 if (some_edge->genuine_elem.kind == ext_grs_k_edge) {
812 ext_grs_edge_t *genuine_edge = some_edge->genuine_elem.val.e;
813 ext_grs_mpq_insert(edge_queue, genuine_edge);
814 p->chosen[genuine_edge->aiid] = 2;
817 /* just check for wrong kind and do nothing */
818 assert (some_edge->genuine_elem.kind == ext_grs_k_node && "invalid kind");
824 /* get the cheapest edge */
825 cheapest_edge = ext_grs_mpq_delete_min(edge_queue);
826 if (cheapest_edge == NULL) break;/* if all edges processed... */
828 assert(j < (act->n_nodes + act->n_edges + act->n_neg_edges + act->n_neg_nodes + act->n_conditions) && "prog position out of bounds");
830 /* add new match op to the plan */
833 if (p->visited[cheapest_edge->arg->aiid] <= phase)
834 cheapest_edge->arg->first_mop_index = j;
836 /* mark the target node of the edge as visited */
837 p->visited[cheapest_edge->arg->aiid] = phase + 1;
840 emit_mop(p, act, prog, cheapest_edge, &j);
842 /* increment the pos in the match program */
844 /* increment the length of the search plan */
846 /* the next node to insert allowed incident out edges in the queue */
847 current_node = cheapest_edge->arg;
852 /* annotate the edges of the plan graph with edge costs due to the
853 * result of a previous v-structure analysis */
854 static void annotate_edge_costs(
855 ext_grs_graph_t *pattern /*ext_grs_action_t *act*/, ext_grs_irg_private_t *pr_g, ext_grs_vs_stat_t *vs_stat, int is_negative)
860 /* annotate all real, negative and pseudo edges with edge costs
861 * additionally do some init stuff with each edge */
864 /* Go through all edges of this pattern */
865 lc_list_for_each(pos, &pattern->edges)
867 /*for (i = 0; i <= act->max_edge_aiid; i++) { */
869 ext_grs_edge_t *edge = lc_list_entry(pos, ext_grs_edge_t, edge_list); /*act->edges[i]; */
880 /* there might be gaps in the array of edges */
881 /*if (!edge) continue; */
882 assert(edge != NULL && "Edge was NULL!");
884 /* for regular and pseudo edges annotate the v-structure costs */
885 if (edge->kind == ext_grs_k_edge) {
890 opc_arg = get_op_code(edge->arg->op);
891 mc_arg = get_mode_modecode(edge->arg->mode);
892 opc_func = get_op_code(edge->func->op);
893 mc_func = get_mode_modecode(edge->func->mode);
897 /* get v-structures of the function node */
899 /* compute the number of instnaces present for the
900 * func node (including all sub ops) */
901 for (l = 0; l < ARR_LEN(_ext_grs_all_sub_ops_of_op[opc_func]); l++) {
902 ir_opcode super_opc_func = get_op_code(_ext_grs_all_sub_ops_of_op[opc_func][l]);
903 n_inst += _ext_grs_N_INSTANCES(pr_g, super_opc_func, mc_func);
907 if (edge->pos == ext_grs_NO_EDGE_POS)
909 n_vs = _get_n_v_structures(
910 vs_stat, opc_func, mc_func, opc_arg, mc_arg, ext_grs_in);
911 edge->cost = (n_vs / (double)n_inst) + (double)is_negative;
915 /* for pseudo edges... */
917 ext_grs_elem_t *elem;
918 assert(edge->kind == ext_grs_k_pseudo_edge && "invalid kind found");
920 /* ...find out, whether they represent a node matching or the
921 * following of an edge in reverse direction */
922 elem = & edge->genuine_elem;
923 /* to do that, check the kind tag, which is stored first */
924 if ( elem->kind == ext_grs_k_node) {
925 double log_n_instances;
928 opc = get_op_code(edge->arg->op);
929 mc = get_mode_modecode(edge->arg->mode);
930 /* the genuine elem the pseudo edge belongs to is a node... */
931 /* thus the the costs are the log2 of the number of instances */
933 /* compute the number of instances present for the
934 * node (including all sub ops) */
935 for (l = 0; l < ARR_LEN(_ext_grs_all_sub_ops_of_op[opc]); l++) {
936 ir_opcode super_opc = get_op_code(_ext_grs_all_sub_ops_of_op[opc][l]);
937 n_inst += _ext_grs_N_INSTANCES(pr_g, super_opc, mc);
941 log_n_instances = _log2(n_inst);
942 else log_n_instances = 0.0;
943 edge->cost = log_n_instances + (double)is_negative;
945 /* check (for negative graphs) whether the node is related to
946 a positive node; if so, set the costs of the pseudo edge to zero. */
948 if (edge->arg->related_node)
954 opc_arg = get_op_code(edge->arg->op);
955 mc_arg = get_mode_modecode(edge->arg->mode);
956 opc_func = get_op_code(edge->func->op);
957 mc_func = get_mode_modecode(edge->func->mode);
959 /* the genuine elem the pseudo edge belongs to is an edge... */
960 assert(elem->kind == ext_grs_k_edge && "pattern elem of a wrong kind");
962 /* get v-structures of the argument node */
963 n_vs = _get_n_v_structures(
964 vs_stat, opc_func, mc_func, opc_arg, mc_arg, ext_grs_out);
966 /* compute the number of instances present for the
967 * func node (including all sub ops) */
968 for (l = 0; l < ARR_LEN(_ext_grs_all_sub_ops_of_op[opc_func]); l++) {
969 ir_opcode super_opc_func = get_op_code(_ext_grs_all_sub_ops_of_op[opc_func][l]);
970 n_inst += _ext_grs_N_INSTANCES(pr_g, super_opc_func, mc_func/* MAYBE WRONG!!! */ );
974 edge->cost = n_vs / (double)n_inst;
978 edge->cost += (double)is_negative;
984 static void prepare_mdst_contraction_phase(
985 /*ext_grs_action_t *act*/ext_grs_graph_t *pattern, lc_list_t *not_visited_nodes, ext_grs_mpq_t **pq)
987 lc_list_t *pattern_pos;
990 /* for all pattern nodes v do:
991 * - create a pq(v), put all the nodes edges in pq(v)
992 * - add v to the list of not yet processed nodes */
993 LC_INIT_LIST_HEAD(not_visited_nodes);
995 lc_list_for_each(pattern_pos, &pattern->nodes)
997 /*for (i = 0; i <= act->max_node_aiid; i++) {*/
1002 ext_grs_node_t *current_node = lc_list_entry(pattern_pos, ext_grs_node_t, node_list); /*act->nodes[i];*/
1003 i = current_node->aiid;
1005 /* there might be gaps in the array of nodes */
1006 /*if (!current_node)
1009 assert(current_node != 0 && "NULL Node in node List!!");
1011 /*assert(current_node->aiid == i && "found node with an inconsistent action internal id"); */
1012 /* create a new pq for each pattern node */
1013 pq[i] = ext_grs_mpq_create();
1014 /* fill the new pq with all graph theoretical incoming
1015 * edges of the node, i.e. with all out-flowing edges */
1016 lc_list_for_each(pos, & current_node->edges[ext_grs_out]) {
1017 ext_grs_edge_t *current_edge =
1018 lc_list_entry(pos, ext_grs_edge_t, list[ext_grs_out]);
1019 ext_grs_mpq_insert(pq[i], current_edge);
1022 /* add the current node to a list of nodes not yet
1023 * processed by Edmonds Algor. */
1024 lc_list_add(& current_node->not_visited_list, not_visited_nodes);
1028 static ext_grs_edge_t *
1029 process_found_circle(
1030 ext_grs_graph_t *pattern, ext_grs_vs_dmst_planer_private_t *p, ext_grs_mpq_t **pq,
1031 ext_grs_node_t *start_node, int phase)
1033 ext_grs_action_t *act = pattern->action;
1034 ext_grs_node_t *current_node = start_node;
1036 /* the current circle node */
1037 ext_grs_node_t *circle_node;
1039 ext_grs_edge_t *cheapest_edge;
1040 ext_grs_edge_t *current_edge;
1044 /* an auxilary pq item */
1045 ext_grs_mpq_t *meld_pq;
1047 /* the first edge of the edges forming the circle, the last edge forming the
1048 * circle (both seen in edge direction) and the edge processed before processing
1050 ext_grs_edge_t *first_circle_edge, *last_circle_edge, *from_edge;
1052 /* cheapest edge of the new made super node, it is incident
1053 * to the same node as kill edge */
1054 ext_grs_edge_t *continue_edge;
1055 /* the repsective incident incomming circle edge */
1056 ext_grs_edge_t *current_end_edge;
1058 /* check for a consistent uf state */
1059 assert(p->visited[current_node->aiid] == phase && "visited by a future phase?!");
1063 /* walk the circle and unite all (super)nodes uf sets. By uniting
1064 * the uf structure a second walk through the circle can find out
1065 * the cheapest edge entering the super node formed by the
1066 * current circle, such that this cheapest edge is not a loop edge. */
1068 #ifdef EXT_GRS_DEBUG
1069 printf("Walk circle the 1st time. The processed edges are:\n");
1072 cheapest_edge = ext_grs_mpq_delete_min(pq[current_node->aiid]);
1073 assert(cheapest_edge && "there should have been a circle edge");
1076 #ifdef EXT_GRS_DEBUG
1077 printf(" %s\n", cheapest_edge->name);
1081 /* the first of the processed cheapest edges is the last circle edge
1082 * followinf the edge direction (as the last of these edge is the
1083 * first circle edge in edge direction) */
1084 last_circle_edge = cheapest_edge;
1085 /* the edge processed before processing the last circle edge for
1087 from_edge = p->edge_path_succ[last_circle_edge->aiid];
1089 /* store the pq of the cheapest edges target (super)node temporarily
1090 * in the real target node of the cheapest edge */
1091 pq[cheapest_edge->arg->aiid] = pq[current_node->aiid];
1093 /* get the minimal cost edges source (super) node */
1094 node_id = UF_FIND(cheapest_edge->func->aiid);
1095 assert(node_id <= act->max_node_aiid && "node id found in uf structure to large");
1096 circle_node = act->nodes[node_id];
1098 /* check wether all circle nodes have been visited in the current phase */
1099 assert(p->visited[circle_node->aiid] == phase &&
1100 "all nodes of a circle should have been visited in the same phase");
1102 /* store modification of incoming edge costs in node */
1105 cheapest_edge->cost - UF_FIND_VALUE(cheapest_edge->arg->aiid)
1108 while (circle_node != current_node) { /* walk the hole circle */
1110 /* get a minimum cost edge of some_node, this edge must be the
1111 * first edge of the circle because the priviously chosen one
1112 * remains to be the first elem of the double linked lists */
1113 cheapest_edge = ext_grs_mpq_delete_min(pq[circle_node->aiid]);
1115 #ifdef EXT_GRS_DEBUG
1116 printf(" %s\n", cheapest_edge->name);
1119 /* check: there is a cheapest edge and as a circle edge it
1120 * has to be a chosen one */
1121 assert(cheapest_edge && "there should have been a circle edge");
1123 /* store the pq of the cheapest edges target (super)node temporarily
1124 * in the real target node of the cheapest edge */
1125 pq[cheapest_edge->arg->aiid] = pq[circle_node->aiid];
1127 /* store the change of the costs of the incoming edges of
1128 * the current circle node as value in the nodes uf structure */
1131 cheapest_edge->cost - UF_FIND_VALUE(cheapest_edge->arg->aiid)
1134 /* unite circle nodes to a super node */
1135 node_id = UF_UNITE(circle_node->aiid, current_node->aiid);
1136 /* ensure that the next node is united super node */
1137 current_node = act->nodes[node_id];
1139 /* get ready for the next iteration step... */
1140 /* ...and the current one to the tgt node of the cheapest edge */
1141 node_id = UF_FIND(cheapest_edge->func->aiid);
1142 assert(node_id < act->n_nodes + act->n_neg_nodes + act->n_pseudo_nodes && "node id found in uf structure to large");
1143 circle_node = act->nodes[node_id];
1145 /* check wether all circle nodes have been visited in the current phase */
1146 assert(p->visited[circle_node->aiid] == phase &&
1147 "all nodes of a circle should have been visited in the same phase");
1152 /* the last of the processed cheapest edges is the first circle edge
1153 * following the edge direction (as the first of these edge is the
1154 * last circle edge in edge direction) */
1155 first_circle_edge = cheapest_edge;
1157 p->edge_path_succ[last_circle_edge->aiid] = first_circle_edge;
1162 /* walk the circle again, this time using the stored edge path.
1163 * while walking the circle look for the cheapest incomming edge
1164 * which is not a loop. The loop property can be checked using
1165 * the already united uf sets representing the (super)nodes */
1167 #ifdef EXT_GRS_DEBUG
1168 printf("Walk circle the 2nd time. The processed edges are:\n");
1172 meld_pq = pq[last_circle_edge->arg->aiid];
1173 current_edge = first_circle_edge;
1175 continue_edge = ext_grs_mpq_find_min( meld_pq );
1176 assert (continue_edge && "there's always an edge from the root node");
1178 UF_FIND(continue_edge->func->aiid) == current_node->aiid &&
1179 continue_edge->func != &pattern->root_node
1182 /* a loop edge has to be deleted... */
1183 ext_grs_mpq_delete_min( meld_pq );
1184 /* ...and a new minimal one has to be chosen */
1185 continue_edge = ext_grs_mpq_find_min( meld_pq );
1186 assert (continue_edge != NULL && "there's always an edge from the root node");
1188 current_end_edge = last_circle_edge;
1191 while (current_edge != last_circle_edge) {
1193 ext_grs_edge_t *some_edge = continue_edge;
1195 meld_pq = ext_grs_mpq_meld(pq[current_edge->arg->aiid], meld_pq);
1197 continue_edge = ext_grs_mpq_find_min( meld_pq );
1198 assert (continue_edge && "there's always an edge from the root node");
1200 UF_FIND(continue_edge->func->aiid) == current_node->aiid &&
1201 continue_edge->func != &pattern->root_node
1204 /* a loop edge has to be deleted... */
1205 ext_grs_mpq_delete_min( meld_pq );
1206 /* ...and a new minimal one has to be chosen */
1207 continue_edge = ext_grs_mpq_find_min( meld_pq );
1208 assert (continue_edge != NULL && "there's always an edge from the root node");
1210 /* if continue_edge has changed... */
1211 if (some_edge != continue_edge) {
1212 some_edge = continue_edge;
1213 current_end_edge = current_edge;
1216 current_edge = p->edge_path_succ[current_edge->aiid];
1218 #ifdef EXT_GRS_DEBUG
1219 printf(" %s\n", current_edge->name);
1225 /* store the melded pq as new pq of the super node in the representative
1226 * node of the super node. */
1227 pq[current_node->aiid] = meld_pq;
1233 p->edge_path_succ[continue_edge->aiid] = from_edge;
1234 p->super_node_last_edge[continue_edge->aiid] = current_end_edge;
1237 /* continue with cheapest edge leaving the circle */
1238 return continue_edge;
1242 /* First phase of the MDST computation: contract all circles in
1243 * the plangraph to super nodes */
1244 static int mdst_contraction_phase(ext_grs_graph_t *pattern, ext_grs_vs_dmst_planer_private_t *p)
1247 ext_grs_action_t *act = pattern->action;
1248 /* a list of nodes not yet processed by Edmonds Algo */
1249 lc_list_t not_visited_nodes;
1250 /* needed for walking the list of unprocessed nodes */
1253 /* an array of meldable priority queues. Each mpq
1254 * will contain the edges of the node the id of which equals the
1255 * index in the mpq array. The edge costs will serve as key. */
1256 ext_grs_mpq_t **pq = alloca((act->max_node_aiid + 1) * sizeof(*pq));
1257 /* the current pattern node */
1258 ext_grs_node_t *current_node;
1259 /* visit phases of the contraction phase */
1263 memset(pq, 0, (act->max_node_aiid + 1) * sizeof(*pq));
1266 prepare_mdst_contraction_phase(pattern, & not_visited_nodes, pq);
1269 #ifdef EXT_GRS_DEBUG
1270 printf(">>>> The MDST contraction phase: <<<<\n");
1275 while (! lc_list_empty(& not_visited_nodes))
1278 /* a minimum cost edge */
1279 ext_grs_edge_t *cheapest_edge;
1280 /* be minimum cost edge processed in the last step */
1281 ext_grs_edge_t *previous_edge = NULL;
1283 pos = not_visited_nodes.next;
1286 current_node = lc_list_entry(pos, ext_grs_node_t, not_visited_list);
1287 #ifdef EXT_GRS_DEBUG
1288 printf("\nTaking a not yet visited node: %s\nChoosing edges: ", current_node->name);
1291 /* mark the current node as visited (with the number of the
1292 * corresponding visit phase)... */
1293 p->visited[current_node->aiid] = phase;
1294 /* del the current node from the list of unvisited nodes */
1295 lc_list_del( & current_node->not_visited_list);
1297 cheapest_edge = ext_grs_mpq_find_min(pq[current_node->aiid]);
1298 p->edge_path_succ[cheapest_edge->aiid] = NULL;
1300 #ifdef EXT_GRS_DEBUG
1301 printf("\n%s ", cheapest_edge->name);
1305 /* Edmonds Algo unites nodes to super nodes, thus the number
1306 * of nodes decreases, further more the root node has no incomming
1307 * (that is out-flow) edges, thus in that case one has to start with
1308 * another not yet visited node */
1309 /* note that root node has no in-edges (that is out-flow edges) */
1312 /* an auxilary id */
1315 assert (cheapest_edge != NULL && "every node except the root has an incomming edge");
1317 /* if tgt node of the cheapest edge is the root,
1318 * try another not yet visited node */
1319 if (cheapest_edge->func == & pattern->root_node) {
1320 p->edge_path_roots[p->n_edge_path_roots++] = cheapest_edge;
1324 /* find the next current node to choose a cheapest incoming edge from */
1325 node_id = UF_FIND(cheapest_edge->func->aiid);
1326 assert (node_id < act->n_nodes + act->n_neg_nodes + act->n_pseudo_nodes && "node id found in uf structure to large");
1327 current_node = act->nodes[node_id];
1329 /* check wether the src node of the minimal cost edge has already been
1330 * visited, and if so wether this has happend in a previous or in current
1332 if (p->visited[current_node->aiid] == 0) {/* not visited yet... */
1334 previous_edge = cheapest_edge;
1336 cheapest_edge = /* ...so get the next cheapest edge... */
1337 ext_grs_mpq_find_min(pq[current_node->aiid]);
1339 #ifdef EXT_GRS_DEBUG
1340 printf("%s ", cheapest_edge->name);
1343 p->edge_path_succ[cheapest_edge->aiid] = previous_edge;
1345 /* mark current node as visited by the current visit phase */
1346 p->visited[current_node->aiid] = phase;
1347 /* remove the node from the list of unvisited nodes */
1348 lc_list_del( & current_node->not_visited_list);
1349 continue; /* ...and go on further */
1351 else if (current_node->aiid == UF_FIND(cheapest_edge->arg->aiid)) { /* a loop edge found */
1352 /* remove every found loop from the (super)nodes pq */
1353 ext_grs_mpq_delete_min(pq[current_node->aiid]);
1355 #ifdef EXT_GRS_DEBUG
1359 cheapest_edge = ext_grs_mpq_find_min(pq[current_node->aiid]);
1361 #ifdef EXT_GRS_DEBUG
1362 printf("%s ", cheapest_edge->name);
1365 p->edge_path_succ[cheapest_edge->aiid] = previous_edge;
1368 else if (p->visited[current_node->aiid] < phase) { /* visited in a previous phase... */
1369 p->edge_path_roots[p->n_edge_path_roots++] = cheapest_edge;
1370 break; /* ...so start from a nother not yet visited node */
1374 #ifdef EXT_GRS_DEBUG
1378 /* a circle has been formed */
1379 cheapest_edge = process_found_circle(pattern, p, pq, current_node, phase);
1381 #ifdef EXT_GRS_DEBUG
1382 printf("Cheapest outgoing edge: %s\n", cheapest_edge->name);
1385 previous_edge = p->edge_path_succ[cheapest_edge->aiid];
1389 /* next visit phase has a greater marking number, that means that
1390 * we can decide in O(1) wether this node belongs to a circle
1391 * or has reverse a path to the root node of the current action */
1399 /* Second phase of the MDST computation: expand the condensed super nodes
1400 * and choose an appropriate entering edge of each super node expanded */
1401 static void mdst_expansion_phase(ext_grs_vs_dmst_planer_private_t *p) {
1404 ext_grs_edge_t *current_edge;
1406 #ifdef EXT_GRS_DEBUG
1407 printf("\n>>>> The MDST expansion phase: <<<<\n");
1408 printf("Top level: ");
1412 /* for all edge paths found, do... */
1413 for (i = 0; i < p->n_edge_path_roots; i++) {
1415 ext_grs_edge_t *end_edge;
1416 ext_grs_edge_t *start_edge;
1418 /* walk the hole edge path till it ends */
1419 current_edge = p->edge_path_roots[i];
1420 while (current_edge != NULL) {
1422 assert(p->mdst_reached[current_edge->arg->aiid] == 0 &&
1423 "there should be no circles on top level");
1425 #ifdef EXT_GRS_DEBUG
1426 printf("%s ", current_edge->name);
1430 /* follow the edge path until the target node of the current
1431 * edge is a super node and mark the real target nodes of the
1432 * edge path as already reached by an MDST edge (this is because
1433 * on the top level the edge do NOT belong to a super node, thus
1434 * all super nodes on the current edge path have exactly ONE ocomming
1435 * edge, and this edge must be chosen for the MDST!) */
1436 p->chosen[current_edge->aiid] = 1;
1437 p->mdst_reached[current_edge->arg->aiid] = 1;
1439 /* if the current edges target node is a super node, expand this super node! */
1440 end_edge = p->super_node_last_edge[current_edge->aiid];
1442 start_edge = p->edge_path_succ[end_edge->aiid];
1443 expand_super_node(p, start_edge);
1446 /* process the next edge on the current edge path */
1447 current_edge = p->edge_path_succ[current_edge->aiid];
1456 static void init(ext_grs_planer_t *planer, ext_grs_analyzer_t *alz) {
1457 planer->analyzer = alz;
1463 static ext_grs_match_plan_t *compute_plan(
1464 ext_grs_planer_t *planer, ir_graph *irg, ext_grs_action_t *act)
1467 lc_list_t *neg_pattern;
1468 /* the private data area of the planer */
1469 ext_grs_vs_dmst_planer_private_t *p = (ext_grs_vs_dmst_planer_private_t *) planer->data;
1470 /* the plan to be returned */
1471 ext_grs_match_plan_t *plan;
1474 /* keeps the number of the visit phase of the Edmonds MDST impl */
1478 /* Alloc memory for plan object and positive and negative search plan progs */
1479 plan = alloc_plan(act);
1483 /* init bitsets needed to store information needed in emitting condition */
1484 p->already_placed_conditions = lc_bitset_alloca(act->n_conditions);
1485 p->already_matched_nodes = lc_bitset_alloca(act->max_node_aiid+1);
1486 p->already_matched_edges = lc_bitset_alloca(act->max_edge_aiid+1);
1488 p->edge_path_succ = alloca((act->max_edge_aiid + 1) * sizeof(* p->edge_path_succ));
1489 p->super_node_last_edge = alloca((act->max_edge_aiid + 1) * sizeof(* p->super_node_last_edge));
1491 p->visited = alloca((act->max_node_aiid + 1) * sizeof(*p->visited));
1492 /* tells wether an edge has been chosen */
1493 p->chosen = alloca((act->max_edge_aiid + 1) * sizeof(* p->chosen));
1494 /* tells wether a node has been already reached by the MDST */
1495 p->mdst_reached = alloca((act->max_node_aiid + 1) * sizeof(* p->mdst_reached));
1497 p->edge_path_roots = alloca((act->max_edge_aiid + 1) * sizeof(*p->edge_path_roots));
1502 if (act->mature == 0) {
1503 printf("ERROR in module ext/grs: invoked planing for a nonmature action\n");
1507 /* for an empty pattern return an empty plan */
1508 if (act->n_nodes + act->n_neg_nodes <= 0) {
1509 plan = (ext_grs_match_plan_t *) malloc(sizeof(*plan));
1510 memset(plan, 0, sizeof(*plan));
1512 plan->length[0] = 0;
1515 plan->num_progs = 0;
1520 /* Compute Progs for all patterns (positive and negative) */
1522 /* act->negatives is the list head, call next node to find the first object in list */
1523 neg_pattern = &act->negatives;
1524 neg_pattern = neg_pattern->next;
1525 for(i = 0; i < plan->num_progs; i++)
1527 /* the current positive or negayive pattern graph */
1528 ext_grs_graph_t *pat;
1531 memset(p->visited, 0, (act->max_node_aiid + 1) * sizeof(* p->visited));
1532 memset(p->chosen, 0, (act->max_edge_aiid + 1) * sizeof(* p->chosen));
1533 memset(p->mdst_reached, 0, (act->max_node_aiid + 1) * sizeof(* p->mdst_reached));
1534 memset(p->edge_path_succ, 0, (act->max_edge_aiid + 1) * sizeof(* p->edge_path_succ));
1535 memset(p->super_node_last_edge, 0, (act->max_edge_aiid + 1) * sizeof(* p->super_node_last_edge));
1536 memset(p->edge_path_roots, 0, (act->max_edge_aiid + 1) * sizeof(*p->edge_path_roots));
1537 p->n_edge_path_roots = 0;
1539 /* init the mpq structure */
1542 /* Init the union find structure used to represent the united nodes
1543 * used by an implementation of Edmond's MDST-Algorithm used in this
1544 * planning procedure. Nodes and united nodes are represented by
1545 * node ids which are the elements of the union find structure */
1546 ext_grs_uf_init(act->max_node_aiid + 1);
1548 /* annotate the plan graph with edge costs due to the analysis
1549 * results stored by the analyzer registered with the given
1553 /* first phase of the MDST computation: contract the all circles in the
1554 * plan graph to super nodes */
1559 annotate_edge_costs(pat, _ext_grs_get_irg_private(irg), _get_irg_vs_stat(planer->analyzer, irg), 0);
1560 phase = mdst_contraction_phase(pat, p);
1564 pat = (ext_grs_graph_t *) lc_list_entry(neg_pattern, ext_grs_graph_t, negative_list);
1565 annotate_edge_costs(pat, _ext_grs_get_irg_private(irg), _get_irg_vs_stat(planer->analyzer, irg), 1);
1566 phase = mdst_contraction_phase(pat, p);
1567 neg_pattern = neg_pattern->next;
1570 /* second phase of the MDST computation: expand the condensed super nodes
1571 * and choose an appropriate entering edge of each super node expanded */
1572 mdst_expansion_phase(p);
1574 #ifdef EXT_GRS_DEBUG
1579 printf("dump the MDST: name, aiid, acc_cost\n");
1580 for (i = 0; i <= act->max_edge_aiid; i++)
1583 (act->edges[i]->kind == ext_grs_k_edge && act->edges[i]->graph == pat) ||
1584 (act->edges[i]->kind == ext_grs_k_pseudo_edge && act->edges[i]->genuine_elem.val.e->graph == pat)
1586 if (p->chosen[ act->edges[i]->aiid ]) {
1587 c += act->edges[i]->cost;
1588 printf("edge %s, %d, %lf\n", act->edges[i]->name, act->edges[i]->aiid, c);
1594 /* The MDST is now computed (all edges with chosen[edge->id] != 0 belong
1595 * to the MDST). Now the final plan generation can be done */
1597 /* Compute search plans for positive and negative pattern */
1598 plan->length[i] = emit_plan(plan->progs[i], pat, p, phase);
1610 /** yields an analyzer performing a v-structure statisitc */
1611 ext_grs_planer_t *ext_grs_get_vs_dmst_planer(void)
1613 ext_grs_planer_t *planer = malloc(sizeof(*planer));
1614 planer->data = malloc( sizeof(ext_grs_vs_dmst_planer_private_t) );
1615 planer->tag = "vs_dmst_planer";
1616 planer->init = init;
1617 planer->compute_plan = compute_plan;