Rename reorder_node to reorder_node_after_edge_deletion.
[libfirm] / optimal.c
index 7969b37..c4ea1c1 100644 (file)
--- a/optimal.c
+++ b/optimal.c
@@ -50,7 +50,8 @@ pbqp_edge **edge_bucket;
 pbqp_edge **rm_bucket;
 pbqp_node **node_buckets[4];
 pbqp_node **reduced_bucket = NULL;
-static int         buckets_filled = 0;
+pbqp_node  *merged_node = NULL;
+static int  buckets_filled = 0;
 
 static void insert_into_edge_bucket(pbqp_edge *edge)
 {
@@ -109,8 +110,8 @@ void fill_node_buckets(pbqp *pbqp)
        node_len = pbqp->num_nodes;
 
        #if KAPS_TIMING
-               ir_timer_t *t_fill_buckets = ir_timer_register("be_pbqp_fill_buckets", "PBQP Fill Nodes into buckets");
-               ir_timer_reset_and_start(t_fill_buckets);
+               ir_timer_t *t_fill_buckets = ir_timer_new();
+               ir_timer_start(t_fill_buckets);
        #endif
 
        for (node_index = 0; node_index < node_len; ++node_index) {
@@ -133,7 +134,7 @@ void fill_node_buckets(pbqp *pbqp)
 
        #if KAPS_TIMING
                ir_timer_stop(t_fill_buckets);
-               printf("%-20s: %8.3lf msec\n", ir_timer_get_description(t_fill_buckets), (double)ir_timer_elapsed_usec(t_fill_buckets) / 1000.0);
+               printf("PBQP Fill Nodes into buckets: %10.3lf msec\n", (double)ir_timer_elapsed_usec(t_fill_buckets) / 1000.0);
        #endif
 }
 
@@ -144,9 +145,10 @@ static void normalize_towards_source(pbqp_edge *edge)
        pbqp_node      *tgt_node;
        vector         *src_vec;
        vector         *tgt_vec;
-       int             src_len;
-       int             tgt_len;
-       int             src_index;
+       unsigned        src_len;
+       unsigned        tgt_len;
+       unsigned        src_index;
+       unsigned        new_infinity = 0;
 
        assert(edge);
 
@@ -175,22 +177,28 @@ static void normalize_towards_source(pbqp_edge *edge)
                if (min != 0) {
                        if (src_vec->entries[src_index].data == INF_COSTS) {
                                pbqp_matrix_set_row_value(mat, src_index, 0);
-                       } else {
-                               pbqp_matrix_sub_row_value(mat, src_index, tgt_vec, min);
+                               continue;
                        }
+
+                       pbqp_matrix_sub_row_value(mat, src_index, tgt_vec, min);
                        src_vec->entries[src_index].data = pbqp_add(
                                        src_vec->entries[src_index].data, min);
 
                        if (min == INF_COSTS) {
-                               unsigned edge_index;
-                               unsigned edge_len = pbqp_node_get_degree(src_node);
-
-                               for (edge_index = 0; edge_index < edge_len; ++edge_index) {
-                                       pbqp_edge *edge_candidate = src_node->edges[edge_index];
-                                       if (edge_candidate != edge) {
-                                               insert_into_edge_bucket(edge_candidate);
-                                       }
-                               }
+                               new_infinity = 1;
+                       }
+               }
+       }
+
+       if (new_infinity) {
+               unsigned edge_index;
+               unsigned edge_len = pbqp_node_get_degree(src_node);
+
+               for (edge_index = 0; edge_index < edge_len; ++edge_index) {
+                       pbqp_edge *edge_candidate = src_node->edges[edge_index];
+
+                       if (edge_candidate != edge) {
+                               insert_into_edge_bucket(edge_candidate);
                        }
                }
        }
@@ -203,9 +211,10 @@ static void normalize_towards_target(pbqp_edge *edge)
        pbqp_node      *tgt_node;
        vector         *src_vec;
        vector         *tgt_vec;
-       int             src_len;
-       int             tgt_len;
-       int             tgt_index;
+       unsigned        src_len;
+       unsigned        tgt_len;
+       unsigned        tgt_index;
+       unsigned        new_infinity = 0;
 
        assert(edge);
 
@@ -227,28 +236,35 @@ static void normalize_towards_target(pbqp_edge *edge)
        mat = edge->costs;
        assert(mat);
 
+       /* Normalize towards target node. */
        for (tgt_index = 0; tgt_index < tgt_len; ++tgt_index) {
                num min = pbqp_matrix_get_col_min(mat, tgt_index, src_vec);
 
                if (min != 0) {
                        if (tgt_vec->entries[tgt_index].data == INF_COSTS) {
                                pbqp_matrix_set_col_value(mat, tgt_index, 0);
-                       } else {
-                               pbqp_matrix_sub_col_value(mat, tgt_index, src_vec, min);
+                               continue;
                        }
+
+                       pbqp_matrix_sub_col_value(mat, tgt_index, src_vec, min);
                        tgt_vec->entries[tgt_index].data = pbqp_add(
                                        tgt_vec->entries[tgt_index].data, min);
 
                        if (min == INF_COSTS) {
-                               unsigned edge_index;
-                               unsigned edge_len = pbqp_node_get_degree(tgt_node);
-
-                               for (edge_index = 0; edge_index < edge_len; ++edge_index) {
-                                       pbqp_edge *edge_candidate = tgt_node->edges[edge_index];
-                                       if (edge_candidate != edge) {
-                                               insert_into_edge_bucket(edge_candidate);
-                                       }
-                               }
+                               new_infinity = 1;
+                       }
+               }
+       }
+
+       if (new_infinity) {
+               unsigned edge_index;
+               unsigned edge_len = pbqp_node_get_degree(tgt_node);
+
+               for (edge_index = 0; edge_index < edge_len; ++edge_index) {
+                       pbqp_edge *edge_candidate = tgt_node->edges[edge_index];
+
+                       if (edge_candidate != edge) {
+                               insert_into_edge_bucket(edge_candidate);
                        }
                }
        }
@@ -353,11 +369,11 @@ static void merge_source_into_target(pbqp *pbqp, pbqp_edge *edge)
                assert(old_matrix);
 
                if (old_edge->tgt == src_node) {
-                       other_node = edge->src;
+                       other_node = old_edge->src;
                        other_len  = old_matrix->rows;
                }
                else {
-                       other_node = edge->tgt;
+                       other_node = old_edge->tgt;
                        other_len = old_matrix->cols;
                }
                assert(other_node);
@@ -400,15 +416,15 @@ static void merge_source_into_target(pbqp *pbqp, pbqp_edge *edge)
 
                add_edge_costs(pbqp, tgt_node->index, other_node->index, new_matrix);
 
-               disconnect_edge(src_node, old_edge);
-               disconnect_edge(other_node, old_edge);
+               delete_edge(old_edge);
 
                new_edge = get_edge(pbqp, tgt_node->index, other_node->index);
                insert_into_rm_bucket(new_edge);
        }
 
-       /* Reduce the remaining source node via RI. */
-       apply_RI(pbqp);
+#if KAPS_STATISTIC
+       pbqp->num_r1--;
+#endif
 }
 
 /**
@@ -510,11 +526,11 @@ static void merge_target_into_source(pbqp *pbqp, pbqp_edge *edge)
                assert(old_matrix);
 
                if (old_edge->tgt == tgt_node) {
-                       other_node = edge->src;
+                       other_node = old_edge->src;
                        other_len  = old_matrix->rows;
                }
                else {
-                       other_node = edge->tgt;
+                       other_node = old_edge->tgt;
                        other_len = old_matrix->cols;
                }
                assert(other_node);
@@ -557,15 +573,15 @@ static void merge_target_into_source(pbqp *pbqp, pbqp_edge *edge)
 
                add_edge_costs(pbqp, src_node->index, other_node->index, new_matrix);
 
-               disconnect_edge(tgt_node, old_edge);
-               disconnect_edge(other_node, old_edge);
+               delete_edge(old_edge);
 
                new_edge = get_edge(pbqp, src_node->index, other_node->index);
                insert_into_rm_bucket(new_edge);
        }
 
-       /* Reduce the remaining source node via RI. */
-       apply_RI(pbqp);
+#if KAPS_STATISTIC
+       pbqp->num_r1--;
+#endif
 }
 
 /**
@@ -600,9 +616,11 @@ void apply_RM(pbqp *pbqp, pbqp_node *node)
                else
                        merge_source_into_target(pbqp, edge);
        }
+
+       merged_node = node;
 }
 
-void reorder_node(pbqp_node *node)
+void reorder_node_after_edge_deletion(pbqp_node *node)
 {
        unsigned    degree     = pbqp_node_get_degree(node);
        /* Assume node lost one incident edge. */
@@ -613,12 +631,6 @@ void reorder_node(pbqp_node *node)
        /* Same bucket as before */
        if (degree > 2) return;
 
-       if (!node_bucket_contains(node_buckets[old_degree], node)) {
-               /* Old arity is new arity, so we have nothing to do. */
-               assert(node_bucket_contains(node_buckets[degree], node));
-               return;
-       }
-
        /* Delete node from old bucket... */
        node_bucket_remove(&node_buckets[old_degree], node);
 
@@ -639,13 +651,15 @@ void simplify_edge(pbqp *pbqp, pbqp_edge *edge)
        assert(pbqp);
        assert(edge);
 
+       (void) pbqp;
+
        src_node = edge->src;
        tgt_node = edge->tgt;
        assert(src_node);
        assert(tgt_node);
 
        /* If edge are already deleted, we have nothing to do. */
-       if (!is_connected(src_node, edge) || !is_connected(tgt_node, edge))
+       if (is_deleted(edge))
                return;
 
 #if    KAPS_DUMP
@@ -698,8 +712,6 @@ void simplify_edge(pbqp *pbqp, pbqp_edge *edge)
 #endif
 
                delete_edge(edge);
-               reorder_node(src_node);
-               reorder_node(tgt_node);
        }
 }
 
@@ -711,8 +723,8 @@ void initial_simplify_edges(pbqp *pbqp)
        assert(pbqp);
 
        #if KAPS_TIMING
-               ir_timer_t *t_int_simpl = ir_timer_register("be_pbqp_init_simp", "PBQP Initial simplify edges");
-               ir_timer_reset_and_start(t_int_simpl);
+               ir_timer_t *t_int_simpl = ir_timer_new();
+               ir_timer_start(t_int_simpl);
        #endif
 
 #if    KAPS_DUMP
@@ -750,7 +762,7 @@ void initial_simplify_edges(pbqp *pbqp)
 
        #if KAPS_TIMING
                ir_timer_stop(t_int_simpl);
-               printf("%-20s: %8.3lf msec\n", ir_timer_get_description(t_int_simpl), (double)ir_timer_elapsed_usec(t_int_simpl) / 1000.0);
+               printf("PBQP Initial simplify edges:  %10.3lf msec\n", (double)ir_timer_elapsed_usec(t_int_simpl) / 1000.0);
        #endif
 }
 
@@ -761,7 +773,7 @@ num determine_solution(pbqp *pbqp)
        num      solution   = 0;
 
        #if KAPS_TIMING
-               ir_timer_t *t_det_solution = ir_timer_register("be_det_solution", "PBQP Determine Solution");
+               ir_timer_t *t_det_solution = ir_timer_new();
                ir_timer_reset_and_start(t_det_solution);
        #endif
 
@@ -771,6 +783,8 @@ num determine_solution(pbqp *pbqp)
 
        assert(pbqp);
 
+       (void) pbqp;
+
 #if    KAPS_DUMP
        file = pbqp->dump_file;
 
@@ -816,7 +830,7 @@ num determine_solution(pbqp *pbqp)
 
        #if KAPS_TIMING
                ir_timer_stop(t_det_solution);
-               printf("%-20s: %8.3lf msec\n", ir_timer_get_description(t_det_solution), (double)ir_timer_elapsed_usec(t_det_solution) / 1000.0);
+               printf("PBQP Determine Solution:      %10.3lf msec\n", (double)ir_timer_elapsed_usec(t_det_solution) / 1000.0);
        #endif
 
        return solution;
@@ -833,6 +847,8 @@ static void back_propagate_RI(pbqp *pbqp, pbqp_node *node)
        assert(pbqp);
        assert(node);
 
+       (void) pbqp;
+
        edge = node->edges[0];
        mat = edge->costs;
        is_src = edge->src == node;
@@ -1019,7 +1035,7 @@ void apply_RI(pbqp *pbqp)
        }
 #endif
 
-       reorder_node(other_node);
+       reorder_node_after_edge_deletion(other_node);
 
 #if KAPS_STATISTIC
        pbqp->num_r1++;
@@ -1155,8 +1171,8 @@ void apply_RII(pbqp *pbqp)
                /* Free local matrix. */
                obstack_free(&pbqp->obstack, mat);
 
-               reorder_node(src_node);
-               reorder_node(tgt_node);
+               reorder_node_after_edge_deletion(src_node);
+               reorder_node_after_edge_deletion(tgt_node);
        }
 
 #if    KAPS_DUMP
@@ -1170,6 +1186,119 @@ void apply_RII(pbqp *pbqp)
        simplify_edge(pbqp, edge);
 }
 
+static void select_column(pbqp_edge *edge, unsigned col_index)
+{
+       pbqp_matrix    *mat;
+       pbqp_node      *src_node;
+       pbqp_node      *tgt_node;
+       vector         *src_vec;
+       vector         *tgt_vec;
+       unsigned        src_len;
+       unsigned        tgt_len;
+       unsigned        src_index;
+       unsigned        new_infinity = 0;
+
+       assert(edge);
+
+       src_node = edge->src;
+       tgt_node = edge->tgt;
+       assert(src_node);
+       assert(tgt_node);
+
+       src_vec = src_node->costs;
+       tgt_vec = tgt_node->costs;
+       assert(src_vec);
+       assert(tgt_vec);
+
+       src_len = src_vec->len;
+       tgt_len = tgt_vec->len;
+       assert(src_len > 0);
+       assert(tgt_len > 0);
+
+       mat = edge->costs;
+       assert(mat);
+
+       for (src_index = 0; src_index < src_len; ++src_index) {
+               num elem = mat->entries[src_index * tgt_len + col_index];
+
+               if (elem != 0) {
+                       if (elem == INF_COSTS && src_vec->entries[src_index].data != INF_COSTS)
+                               new_infinity = 1;
+
+                       src_vec->entries[src_index].data = pbqp_add(
+                                       src_vec->entries[src_index].data, elem);
+               }
+       }
+
+       if (new_infinity) {
+               unsigned edge_index;
+               unsigned edge_len = pbqp_node_get_degree(src_node);
+
+               for (edge_index = 0; edge_index < edge_len; ++edge_index) {
+                       pbqp_edge *edge_candidate = src_node->edges[edge_index];
+
+                       if (edge_candidate != edge) {
+                               insert_into_edge_bucket(edge_candidate);
+                       }
+               }
+       }
+
+       delete_edge(edge);
+}
+
+static void select_row(pbqp_edge *edge, unsigned row_index)
+{
+       pbqp_matrix    *mat;
+       pbqp_node      *src_node;
+       pbqp_node      *tgt_node;
+       vector         *tgt_vec;
+       unsigned        tgt_len;
+       unsigned        tgt_index;
+       unsigned        new_infinity = 0;
+
+       assert(edge);
+
+       src_node = edge->src;
+       tgt_node = edge->tgt;
+       assert(tgt_node);
+
+       tgt_vec = tgt_node->costs;
+       assert(tgt_vec);
+
+       tgt_len = tgt_vec->len;
+       assert(tgt_len > 0);
+
+       mat = edge->costs;
+       assert(mat);
+
+       for (tgt_index = 0; tgt_index < tgt_len; ++tgt_index) {
+               num elem = mat->entries[row_index * tgt_len + tgt_index];
+
+               if (elem != 0) {
+                       if (elem == INF_COSTS && tgt_vec->entries[tgt_index].data != INF_COSTS)
+                               new_infinity = 1;
+
+                       tgt_vec->entries[tgt_index].data = pbqp_add(
+                                       tgt_vec->entries[tgt_index].data, elem);
+               }
+       }
+
+       if (new_infinity) {
+               unsigned edge_index;
+               unsigned edge_len = pbqp_node_get_degree(tgt_node);
+
+               for (edge_index = 0; edge_index < edge_len; ++edge_index) {
+                       pbqp_edge *edge_candidate = tgt_node->edges[edge_index];
+
+                       if (edge_candidate != edge) {
+                               insert_into_edge_bucket(edge_candidate);
+                       }
+               }
+       }
+
+       delete_edge(edge);
+}
+
 void select_alternative(pbqp_node *node, unsigned selected_index)
 {
        unsigned  edge_index;
@@ -1191,9 +1320,14 @@ void select_alternative(pbqp_node *node, unsigned selected_index)
                }
        }
 
-       /* Add all incident edges to edge bucket, since they are now independent. */
+       /* Select corresponding row/column for incident edges. */
        for (edge_index = 0; edge_index < max_degree; ++edge_index) {
-               insert_into_edge_bucket(node->edges[edge_index]);
+               pbqp_edge *edge = node->edges[edge_index];
+
+               if (edge->src == node)
+                       select_row(edge, selected_index);
+               else
+                       select_column(edge, selected_index);
        }
 }