moved firmext code into the backend dir
[libfirm] / ir / be / grgen / plan_vs_dmst.c
1 /*
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
6  * Author:      Veit Batz
7  * Created:             11. Junly 2005
8  * CVS-ID:      $Id$
9  * Copyright:   (c) 2005 Universität Karlsruhe
10  * Licence:     This file protected by GPL -  GNU GENERAL PUBLIC LICENSE.
11  */
12
13 #ifdef _WIN32
14 #include <malloc.h>
15 #else
16 #include <alloca.h>
17 #endif
18
19 #include "common_t.h"
20
21 #include "auxilary_t.h"
22 #include "base_t.h"
23 #include "action_t.h"
24 #include "analyze_t.h"
25 #include "ana_vs_t.h"
26 #include "matchplan_t.h"
27
28 #include "uf_mpq.h"
29
30 #include "plan_vs_dmst.h"
31 #include "action_t.h"
32
33
34
35
36 typedef struct _ext_grs_vs_dmst_planer_private_t {
37         /* tells wether an edge has been chosen */
38         int *chosen;
39         /* tells wether a node has been already reached by the MDST */
40         int *mdst_reached;
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
67          * number of the  */
68         int *visited;
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;
74
75 } ext_grs_vs_dmst_planer_private_t;
76
77
78
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)))
83
84
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) {
87
88         ext_grs_edge_t *current_edge = edge;
89         assert(edge);
90
91         printf("An edge path:\n");
92         do
93         {
94                 printf("  edge %s\n", current_edge->name);
95                 current_edge = p->edge_path_succ[current_edge->aiid];
96         }
97         while (current_edge != NULL && current_edge != edge);
98         printf("\n\n");
99 }
100
101
102
103
104
105
106
107
108
109
110
111
112
113
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)
119 {
120         ext_grs_edge_t *current_edge = NULL;
121         int already_reached_node_found = 0;
122
123         /* walk the circle forming the current super node */
124         assert(start_edge && "NULL edge given");
125         current_edge = start_edge;
126         do {
127
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;
131
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,
137                                         p->edge_path_succ[
138                                                 p->super_node_last_edge[current_edge->aiid]->aiid
139                                         ]
140                                 );
141                 }
142                 if (already_reached_node_found) return 1;
143
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");
147         }
148         while (current_edge != start_edge);
149
150         /* report that no reached node has been found in the current super node */
151         return 0;
152 }
153
154
155
156
157
158
159
160
161
162
163
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)
169 {
170         ext_grs_edge_t *current_edge;
171
172         assert(start_edge);
173
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;
179         do {
180
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;
188
189
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 ];
193
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);
199                 }
200
201                 /* mark the current edge as chosen and its real target node as reached, except... (see above) */
202                 if (
203                         ! p->mdst_reached[current_edge->arg->aiid] &&
204                         ! super_node_contains_reached_node
205                 )
206                 {
207                         p->chosen[current_edge->aiid] = 1;
208                         p->mdst_reached[current_edge->arg->aiid] = 1;
209                 }
210
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);
214                 }
215
216                 /* process the next edge of the super node circle */
217                 current_edge = p->edge_path_succ[current_edge->aiid];
218                 assert(current_edge);
219         }
220         while (current_edge != start_edge);
221 }
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237 #if 0
238
239
240
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)
246 {
247
248         ext_grs_edge_t *current_edge = NULL;
249         int edge_killed = 0;
250
251         #ifdef EXT_GRS_DEBUG
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: ");
254         #endif
255
256
257         /* walk the circle forming the current super node */
258         assert(start_edge && "NULL edge given");
259         edge_killed = 0;
260
261         current_edge = start_edge;
262         #ifdef EXT_GRS_DEBUG
263                 printf("%s ", current_edge->name);
264         #endif
265         do {
266
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) {
269
270                         #ifdef EXT_GRS_DEBUG
271                                 printf(" Recursively stepping into super node:\n{\n");
272                         #endif
273
274                         expand_super_node_examine(p,
275                                 p->edge_path_succ[
276                                         p->super_node_last_edge[current_edge->aiid]->aiid
277                                 ]
278                         );
279
280                         #ifdef EXT_GRS_DEBUG
281                                 printf("}\n");
282                         #endif
283                 }
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 */
291                         edge_killed = 1;
292                 }
293                 else {
294                         /* otherwise the current edge is chosen, except
295                          * ... OR
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 )
298                         {
299                                 p->chosen[current_edge->aiid] = 1;
300                                 p->mdst_reached[current_edge->arg->aiid] = 1;
301                         }
302
303                 }
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");
307                 #ifdef EXT_GRS_DEBUG
308                         printf("%s ", current_edge->name);
309                 #endif
310         }
311         while (current_edge != start_edge);
312
313         #ifdef EXT_GRS_DEBUG
314                 printf("\n");
315         #endif
316 }
317
318
319
320
321
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)
328 {
329         ext_grs_edge_t *current_edge;
330
331         #ifdef EXT_GRS_DEBUG
332                 printf("\nExpanding a super node (kill). ");
333         #endif
334
335         assert(kill_edge);
336
337         #ifdef EXT_GRS_DEBUG
338                 printf("Kill-edge is %s\n", kill_edge->name);
339                 printf("The circle of edges forming the super node: ");
340         #endif
341
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);
347         #ifdef EXT_GRS_DEBUG
348                 printf("%s ", current_edge->name);
349         #endif
350         assert(current_edge != kill_edge); /* no loops allowed! */
351
352         do {
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);
357                 #ifdef EXT_GRS_DEBUG
358                         printf("%s ", current_edge->name);
359                 #endif
360         }
361         while (current_edge != kill_edge);
362
363         #ifdef EXT_GRS_DEBUG
364                 printf("\n");
365         #endif
366
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! */
374
375         do {
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];
379         }
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,
385                         p->edge_path_succ[
386                                 p->super_node_last_edge[kill_edge->aiid]->aiid
387                         ]
388                 );
389 }
390
391 #endif
392
393
394
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)
401 {
402         /* flag, tells whether there has already been placed a condition
403         * in the current edges mop (so additional condition mops have
404         * to be created) */
405         int already_placed = 0;
406
407         /* a condition index from a set of involved conditions */
408         lc_bitset_pos_t cond = (act->nodes_refering_conds[node->aiid])->size;
409
410         /* a matcher op */
411         ext_grs_match_op_t *mop;
412
413         if (act->n_conditions > 0) {
414                 lc_bitset_foreach(act->nodes_refering_conds[node->aiid], cond) {
415
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;
419
420                         /* otherwise check, whether all involved nodes
421                         * and edges have already been matched  */
422                         if (
423                                 ! lc_bitset_contains(
424                                 act->conds_involved_nodes[(int)cond],
425                                 p->already_matched_nodes)
426                                 ) continue;
427
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;
432                                 mop = & prog[j];
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
436                         }
437                         else {
438                                 mop = &prog[*prog_pos]; // AS
439                                 mop->condition = act->conditions[(int)cond];
440                                 already_placed = 1;
441                                 lc_bitset_set(p->already_placed_conditions, cond);  // AS
442                         }
443                 }
444         }
445 }
446
447
448
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)
455 {
456         /* flag, tells whether there has already been placed a condition
457          * in the current edges mop (so additional condition mops have
458          * to be created) */
459         int already_placed = 0;
460
461         /* a condition index from a set of involved conditions */
462         lc_bitset_pos_t cond;
463
464         /* a matcher op */
465         ext_grs_match_op_t *mop;
466
467         if (act->n_conditions > 0) {
468
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
475
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  */
482                         if (
483                                 ! lc_bitset_contains(
484                                         act->conds_involved_nodes[(int)cond],
485                                         p->already_matched_nodes)
486                         ) continue;
487                         /* otherwise check, whether all involved edges
488                          * and edges have already been matched  */
489                         if (
490                                 ! lc_bitset_contains(
491                                         act->conds_involved_edges[(int)cond],
492                                         p->already_matched_edges)
493                         ) continue;
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);
498                                 mop = & prog[j];
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
502                         }
503                         else {
504                                 mop = &prog[*prog_pos];  // AS
505                                 mop->condition = act->conditions[(int)cond];
506                                 already_placed = 1;
507                                 lc_bitset_set(p->already_placed_conditions, cond); // AS
508                         }
509                 }
510         }
511 }
512
513
514
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)
519 {
520
521         /* a matcher op */
522         ext_grs_match_op_t *mop;
523         int j = *prog_pos;
524
525         mop = &prog[j];
526
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;
530
531                 mop->kind = ext_grs_k_mop_edge;
532                 mop->edge = edge;
533                 mop->node = edge->func;
534
535                 mop->edge->first_mop_index = j;
536
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);
545                 }
546                 else {
547                         p->chosen[edge->backward_edge->aiid] = 2;
548                 }
549
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);
554
555                 emit_edges_conditions(act, edge, p, prog, prog_pos);
556         }
557         else {
558                 ext_grs_elem_t *genuine_elem;
559
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;
566
567                         if(genuine_edge->related_edge != NULL)
568                                 mop->kind = ext_grs_k_mop_preset_edge;
569                         else
570                                 mop->kind = ext_grs_k_mop_edge;
571                         mop->edge = genuine_edge;
572                         mop->node = genuine_edge->arg;
573
574                         mop->edge->first_mop_index = j;
575
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);
584                         }
585                         else {
586                                 p->chosen[genuine_edge->aiid] = 2;
587                         }
588
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);
593
594                         emit_edges_conditions(act, genuine_edge, p, prog, prog_pos);
595
596                 }
597                 else {
598                         /* pseudo edge represents a node matching */
599                         ext_grs_node_t *genuine_node = genuine_elem->val.n;
600
601                         assert(genuine_elem->kind == ext_grs_k_node && "invalid kind");
602                         assert(genuine_node == edge->arg);
603
604                         if(genuine_node->related_node != NULL)
605                                 mop->kind = ext_grs_k_mop_preset;
606                         else
607                                 mop->kind = ext_grs_k_mop_node;
608                         mop->edge = NULL;
609                         mop->node = genuine_node;
610
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;
615
616                         /* mark the genuine node as already been matched */
617                         lc_bitset_set(p->already_matched_nodes, genuine_node->aiid);
618
619                         emit_nodes_conditions(act, genuine_node, p, prog, prog_pos);
620                 }
621         }
622 }
623
624 #if 0
625 static ext_grs_match_op_t **emit_negative_plans(ext_grs_action_t *act)
626 {
627         lc_list_t *pos;
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;
632
633
634
635         lc_list_for_each(pos, (&act->negatives))
636                 num_negatives++;
637
638         result = (ext_grs_match_op_t **) malloc(num_negatives * sizeof(ext_grs_match_op_t *));
639
640         i = 0;
641         /* Handle all negative patterns, there can be several */
642         lc_list_for_each(pos, (&act->negatives))
643         {
644                 struct ext_grs_graph_t *neg_pattern;
645
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);
648
649                 /* TODO: Now walk through that graph and create search plan */
650
651
652                 i++;
653         }
654         return(result);
655 }
656 #endif
657
658
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)
664 {
665         ext_grs_match_plan_t *plan;
666         lc_list_t *neg_patterns;
667         lc_list_t *list_pos;
668         int num_negatives = 0, num_all_plans;
669         int i;
670
671         plan = malloc(sizeof(*plan));
672         memset(plan, 0, sizeof(*plan));
673         plan->action = act;
674
675
676         /* Compute a search plan for all negative patterns */
677
678         /* Count number of negative patterns */
679         lc_list_for_each(list_pos, (&act->negatives))
680                 num_negatives++;
681         num_all_plans = num_negatives + 1;
682
683         plan->progs = (ext_grs_match_op_t **) malloc(num_all_plans * sizeof(ext_grs_match_op_t *));
684
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));
688
689
690         neg_patterns = &act->negatives;
691         neg_patterns = neg_patterns->next;
692         for(i = 1; i < num_all_plans; i++)
693         {
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;
698         }
699
700
701         plan -> prog = plan -> progs[0];
702
703         plan -> length = (int *) malloc(num_all_plans * sizeof(int));
704         memset(plan -> length, 0, num_all_plans * sizeof(int));
705
706         plan->num_progs = num_all_plans;
707
708         return(plan);
709 }
710
711
712
713 /*
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 */
725 static int
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)
727 {
728         ext_grs_action_t *act = pattern->action;
729         ext_grs_node_t *current_node;
730         int j = 0;
731
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);
743
744
745         /* the current pos in the generated match program */
746
747
748         /* START from the patterns root */
749         current_node = &pattern->root_node;
750         while (1) {
751                 lc_list_t *pos;
752                 ext_grs_edge_t *cheapest_edge;
753                 ext_grs_match_op_t *mop;
754
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]) {
758
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]);
763
764                         if (
765                                 /* some edge belongs to the MDST, but no match opereation
766                                  * has been generated yet */
767                                 p->chosen[some_edge->aiid] == 1
768                         )
769                         {
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;
774                         }
775                 }
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]) {
783
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]);
788
789                         if (
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)
794                         )
795                         {
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;
800
801
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;
807                                 }
808                                 /* ...otherwise its the genuine edge */
809                                 else {
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;
815                                         }
816                                         else {
817                                                 /* just check for wrong kind and do nothing */
818                                                 assert (some_edge->genuine_elem.kind == ext_grs_k_node && "invalid kind");
819                                         }
820                                 }
821                         }
822                 }
823
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... */
827
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");
829
830                 /* add new match op to the plan */
831                 mop = & prog[j];
832
833                 if (p->visited[cheapest_edge->arg->aiid] <= phase)
834                         cheapest_edge->arg->first_mop_index = j;
835
836                 /* mark the target node of the edge as visited */
837                 p->visited[cheapest_edge->arg->aiid] = phase + 1;
838
839
840                 emit_mop(p, act, prog, cheapest_edge, &j);
841
842                 /* increment the pos in the match program */
843                 j++;
844                 /* increment the length of the search plan */
845                 /*plan->length++; */
846                 /* the next node to insert allowed incident out edges in the queue */
847                 current_node = cheapest_edge->arg;
848         }
849         return (j);
850 }
851
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)
856 {
857
858         /*int i; */
859
860         /* annotate all real, negative and pseudo edges with edge costs
861          * additionally do some init stuff with each edge */
862         lc_list_t *pos;
863
864         /* Go through all edges of this pattern */
865         lc_list_for_each(pos, &pattern->edges)
866         {
867         /*for (i = 0; i <= act->max_edge_aiid; i++) { */
868
869                 ext_grs_edge_t *edge = lc_list_entry(pos, ext_grs_edge_t, edge_list); /*act->edges[i]; */
870
871                 ir_opcode opc_arg;
872                 modecode mc_arg;
873                 ir_opcode opc_func;
874                 modecode mc_func;
875                 ir_opcode opc;
876                 modecode mc;
877
878                 int l;
879
880                 /* there might be gaps in the array of edges */
881                 /*if (!edge) continue; */
882                 assert(edge != NULL && "Edge was NULL!");
883
884                 /* for regular and pseudo edges annotate the v-structure costs */
885                 if (edge->kind == ext_grs_k_edge) {
886                         double n_vs;
887                         int n_inst = 0;
888
889
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);
894
895
896
897                         /* get v-structures of the function node */
898
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);
904                         }
905
906                         edge->cost = 0.0;
907                         if (edge->pos == ext_grs_NO_EDGE_POS)
908                                 if (n_inst != 0) {
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;
912                                 }
913                 }
914
915                 /* for pseudo edges... */
916                 else {
917                         ext_grs_elem_t *elem;
918                         assert(edge->kind == ext_grs_k_pseudo_edge && "invalid kind found");
919
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;
926                                 int n_inst = 0;
927
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 */
932
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);
938                                 }
939
940                                 if (n_inst > 0)
941                                         log_n_instances = _log2(n_inst);
942                                 else log_n_instances = 0.0;
943                                 edge->cost = log_n_instances + (double)is_negative;
944
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. */
947                                 if (is_negative)
948                                         if (edge->arg->related_node)
949                                                 edge->cost = 0.0;
950                         }
951                         else {
952                                 double n_vs;
953                                 int n_inst = 0;
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);
958
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");
961
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);
965
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!!! */ );
971                                 }
972
973                                 if (n_inst != 0)
974                                         edge->cost = n_vs / (double)n_inst;
975                                 else
976                                         edge->cost = 0.0;
977
978                                 edge->cost += (double)is_negative;
979                         }
980                 }
981         }
982 }
983
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)
986 {
987         lc_list_t *pattern_pos;
988         int i;
989
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);
994
995         lc_list_for_each(pattern_pos, &pattern->nodes)
996         {
997         /*for (i = 0; i <= act->max_node_aiid; i++) {*/
998
999                 lc_list_t *pos;
1000
1001
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;
1004
1005                 /* there might be gaps in the array of nodes */
1006                 /*if (!current_node)
1007                         continue;*/
1008
1009                 assert(current_node != 0 && "NULL Node in node List!!");
1010
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);
1020                 }
1021
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);
1025         }
1026 }
1027
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)
1032 {
1033         ext_grs_action_t *act = pattern->action;
1034         ext_grs_node_t *current_node = start_node;
1035
1036         /* the current circle node */
1037         ext_grs_node_t *circle_node;
1038
1039         ext_grs_edge_t *cheapest_edge;
1040         ext_grs_edge_t *current_edge;
1041         int node_id;
1042
1043
1044         /* an auxilary pq item */
1045         ext_grs_mpq_t *meld_pq;
1046
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
1049          * the last edge */
1050         ext_grs_edge_t *first_circle_edge, *last_circle_edge, *from_edge;
1051
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;
1057
1058         /* check for a consistent uf state */
1059         assert(p->visited[current_node->aiid] == phase && "visited by a future phase?!");
1060
1061
1062
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. */
1067 /*
1068 #ifdef EXT_GRS_DEBUG
1069         printf("Walk circle the 1st time. The processed edges are:\n");
1070 #endif
1071  */
1072         cheapest_edge = ext_grs_mpq_delete_min(pq[current_node->aiid]);
1073         assert(cheapest_edge && "there should have been a circle edge");
1074
1075 /*
1076         #ifdef EXT_GRS_DEBUG
1077                 printf("  %s\n", cheapest_edge->name);
1078         #endif
1079  */
1080
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
1086          * the first time */
1087         from_edge = p->edge_path_succ[last_circle_edge->aiid];
1088
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];
1092
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];
1097
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");
1101
1102         /* store modification of incoming edge costs in node */
1103         UF_CHANGE_VALUE(
1104                 current_node->aiid,
1105                 cheapest_edge->cost - UF_FIND_VALUE(cheapest_edge->arg->aiid)
1106         );
1107
1108         while (circle_node != current_node) { /* walk the hole circle */
1109
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]);
1114 /*
1115                 #ifdef EXT_GRS_DEBUG
1116                         printf("  %s\n", cheapest_edge->name);
1117                 #endif
1118  */
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");
1122
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];
1126
1127                 /* store the change of the costs of the incoming edges of
1128                  * the current circle node as value in the nodes uf structure */
1129                 UF_CHANGE_VALUE(
1130                         circle_node->aiid,
1131                         cheapest_edge->cost - UF_FIND_VALUE(cheapest_edge->arg->aiid)
1132                 );
1133
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];
1138
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];
1144
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");
1148
1149         }
1150
1151
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;
1156
1157         p->edge_path_succ[last_circle_edge->aiid] = first_circle_edge;
1158
1159
1160
1161
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 */
1166 /*
1167         #ifdef EXT_GRS_DEBUG
1168                 printf("Walk circle the 2nd time. The processed edges are:\n");
1169         #endif
1170  */
1171
1172         meld_pq = pq[last_circle_edge->arg->aiid];
1173         current_edge = first_circle_edge;
1174
1175         continue_edge = ext_grs_mpq_find_min( meld_pq );
1176         assert (continue_edge && "there's always an edge from the root node");
1177         while (
1178                 UF_FIND(continue_edge->func->aiid) == current_node->aiid  &&
1179                 continue_edge->func != &pattern->root_node
1180         )
1181         {
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");
1187         }
1188         current_end_edge = last_circle_edge;
1189
1190
1191         while (current_edge != last_circle_edge) {
1192
1193                 ext_grs_edge_t *some_edge = continue_edge;
1194
1195                 meld_pq =  ext_grs_mpq_meld(pq[current_edge->arg->aiid], meld_pq);
1196
1197                 continue_edge = ext_grs_mpq_find_min( meld_pq );
1198                 assert (continue_edge && "there's always an edge from the root node");
1199                 while (
1200                         UF_FIND(continue_edge->func->aiid) == current_node->aiid  &&
1201                         continue_edge->func != &pattern->root_node
1202                 )
1203                 {
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");
1209                 }
1210                 /* if continue_edge has changed... */
1211                 if (some_edge != continue_edge) {
1212                         some_edge = continue_edge;
1213                         current_end_edge = current_edge;
1214                 }
1215
1216                 current_edge = p->edge_path_succ[current_edge->aiid];
1217 /*
1218                 #ifdef EXT_GRS_DEBUG
1219                         printf("  %s\n", current_edge->name);
1220                 #endif
1221  */
1222
1223         }
1224
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;
1228
1229
1230
1231
1232
1233         p->edge_path_succ[continue_edge->aiid] = from_edge;
1234         p->super_node_last_edge[continue_edge->aiid] = current_end_edge;
1235
1236
1237         /* continue with cheapest edge leaving the circle */
1238         return continue_edge;
1239 }
1240
1241
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)
1245 {
1246
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 */
1251         lc_list_t *pos;
1252
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 */
1260         int phase = 1;
1261
1262
1263         memset(pq, 0, (act->max_node_aiid + 1) * sizeof(*pq));
1264
1265
1266         prepare_mdst_contraction_phase(pattern, & not_visited_nodes, pq);
1267
1268
1269         #ifdef EXT_GRS_DEBUG
1270                 printf(">>>> The MDST contraction phase: <<<<\n");
1271         #endif
1272
1273
1274
1275         while (! lc_list_empty(& not_visited_nodes))
1276         {
1277
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;
1282
1283                 pos = not_visited_nodes.next;
1284
1285
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);
1289                 #endif
1290
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);
1296
1297                 cheapest_edge = ext_grs_mpq_find_min(pq[current_node->aiid]);
1298                 p->edge_path_succ[cheapest_edge->aiid] = NULL;
1299
1300                 #ifdef EXT_GRS_DEBUG
1301                         printf("\n%s ", cheapest_edge->name);
1302                 #endif
1303
1304
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) */
1310                 while (1) {
1311
1312                         /* an auxilary id */
1313                         int node_id;
1314
1315                         assert (cheapest_edge != NULL && "every node except the root has an incomming edge");
1316
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;
1321                                 break;
1322                         }
1323
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];
1328
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
1331                          * visit phase */
1332                         if (p->visited[current_node->aiid] == 0) {/* not visited yet... */
1333
1334                                 previous_edge = cheapest_edge;
1335
1336                                 cheapest_edge = /* ...so get the next cheapest edge... */
1337                                         ext_grs_mpq_find_min(pq[current_node->aiid]);
1338
1339                                 #ifdef EXT_GRS_DEBUG
1340                                         printf("%s ", cheapest_edge->name);
1341                                 #endif
1342
1343                                 p->edge_path_succ[cheapest_edge->aiid] = previous_edge;
1344
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 */
1350                         }
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]);
1354
1355                                 #ifdef EXT_GRS_DEBUG
1356                                         printf("Loop!");
1357                                 #endif
1358
1359                                 cheapest_edge = ext_grs_mpq_find_min(pq[current_node->aiid]);
1360
1361                                 #ifdef EXT_GRS_DEBUG
1362                                         printf("%s ", cheapest_edge->name);
1363                                 #endif
1364
1365                                 p->edge_path_succ[cheapest_edge->aiid] = previous_edge;
1366                                 continue;
1367                         }
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 */
1371                         }
1372                         else {
1373
1374                                 #ifdef EXT_GRS_DEBUG
1375                                         printf("Circle! ");
1376                                 #endif
1377
1378                                 /* a circle has been formed */
1379                                 cheapest_edge = process_found_circle(pattern, p, pq, current_node, phase);
1380
1381                                 #ifdef EXT_GRS_DEBUG
1382                                         printf("Cheapest outgoing edge: %s\n", cheapest_edge->name);
1383                                 #endif
1384
1385                                 previous_edge = p->edge_path_succ[cheapest_edge->aiid];
1386
1387                         }
1388                 }
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 */
1392                 phase++;
1393         }
1394
1395         return phase;
1396 }
1397
1398
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) {
1402
1403         int i;
1404         ext_grs_edge_t *current_edge;
1405
1406         #ifdef EXT_GRS_DEBUG
1407                 printf("\n>>>> The MDST expansion phase: <<<<\n");
1408                 printf("Top level: ");
1409         #endif
1410
1411
1412         /* for all edge paths found, do... */
1413         for (i = 0; i < p->n_edge_path_roots; i++) {
1414
1415                 ext_grs_edge_t *end_edge;
1416                 ext_grs_edge_t *start_edge;
1417
1418                 /* walk the hole edge path till it ends */
1419                 current_edge = p->edge_path_roots[i];
1420                 while (current_edge != NULL) {
1421
1422                         assert(p->mdst_reached[current_edge->arg->aiid] == 0 &&
1423                                 "there should be no circles on top level");
1424
1425                         #ifdef EXT_GRS_DEBUG
1426                                 printf("%s ", current_edge->name);
1427                         #endif
1428
1429
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;
1438
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];
1441                         if (end_edge) {
1442                                 start_edge = p->edge_path_succ[end_edge->aiid];
1443                                 expand_super_node(p, start_edge);
1444                         }
1445
1446                         /* process the next edge on the current edge path */
1447                         current_edge = p->edge_path_succ[current_edge->aiid];
1448                 }
1449
1450         }
1451 }
1452
1453
1454
1455
1456 static void init(ext_grs_planer_t *planer, ext_grs_analyzer_t *alz) {
1457         planer->analyzer = alz;
1458 }
1459
1460
1461
1462
1463 static ext_grs_match_plan_t *compute_plan(
1464         ext_grs_planer_t *planer, ir_graph *irg, ext_grs_action_t *act)
1465 {
1466
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;
1472         int i;
1473
1474         /* keeps the number of the visit phase of the Edmonds MDST impl */
1475         int phase;
1476
1477
1478         /* Alloc memory for plan object and positive and negative search plan progs */
1479         plan = alloc_plan(act);
1480
1481
1482
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);
1487
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));
1490
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));
1496
1497         p->edge_path_roots = alloca((act->max_edge_aiid + 1) * sizeof(*p->edge_path_roots));
1498
1499
1500
1501
1502         if (act->mature == 0) {
1503                 printf("ERROR in module ext/grs: invoked planing for a nonmature action\n");
1504                 return NULL;
1505         }
1506
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));
1511                 plan->action = act;
1512                 plan->length[0] = 0;
1513                 plan->prog = NULL;
1514                 plan->progs = 0;
1515                 plan->num_progs = 0;
1516                 return plan;
1517         }
1518
1519
1520         /* Compute Progs for all patterns (positive and negative) */
1521
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++)
1526         {
1527                 /* the current positive or negayive pattern graph */
1528                 ext_grs_graph_t *pat;
1529
1530                 /* do some init */
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;
1538
1539                 /* init the mpq structure */
1540                 ext_grs_mpq_init();
1541
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);
1547
1548                 /* annotate the plan graph with edge costs due to the analysis
1549                 * results stored by the analyzer registered with the given
1550                 * planer */
1551
1552
1553                 /* first phase of the MDST computation: contract the all circles in the
1554                 * plan graph to super nodes */
1555
1556                 if(i == 0)
1557                 {
1558                         pat = act->pattern;
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);
1561                 }
1562                 else
1563                 {
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;
1568                 }
1569
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);
1573
1574         #ifdef EXT_GRS_DEBUG
1575                 {
1576                         /* dump the MDST */
1577                         double c = 0;
1578                         int i;
1579                         printf("dump the MDST: name, aiid, acc_cost\n");
1580                         for (i = 0; i <= act->max_edge_aiid; i++)
1581                                 if (act->edges[i])
1582                                         if (
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)
1585                                                 )
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);
1589                                                 }
1590                         printf("\n");
1591                 }
1592         #endif
1593
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 */
1596
1597                 /* Compute search plans for positive and negative pattern */
1598                 plan->length[i] = emit_plan(plan->progs[i], pat, p, phase);
1599         }
1600         return(plan);
1601 }
1602
1603
1604
1605
1606
1607
1608
1609
1610 /** yields an analyzer performing a v-structure statisitc */
1611 ext_grs_planer_t *ext_grs_get_vs_dmst_planer(void)
1612 {
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;
1618
1619         return planer;
1620 }