Try to fix a rare edges bug:
authorMichael Beck <beck@ipd.info.uni-karlsruhe.de>
Tue, 12 Jan 2010 22:27:48 +0000 (22:27 +0000)
committerMichael Beck <beck@ipd.info.uni-karlsruhe.de>
Tue, 12 Jan 2010 22:27:48 +0000 (22:27 +0000)
- if a node was built with edges disabled gets dead, but is revived by CSE when edges are enabled, it had NO edges
- tries to keep track of such dead nodes ...

[r26954]

ir/ir/iredges.c
ir/ir/iredges_t.h
ir/ir/irnode.c
ir/ir/iropt.c
ir/ir/irtypes.h

index b420089..8863bfe 100644 (file)
@@ -479,6 +479,34 @@ static void edges_node_deleted_kind(ir_node *old, ir_edge_kind_t kind, ir_graph
        }
 }
 
+/**
+ * A node might be revivaled by CSE. Assure its edges.
+ *
+ * @param irn   the node
+ * @param kind  the kind of edges to remove
+ * @param irg   the irg of the old node
+ */
+static void edges_node_revival_kind(ir_node *irn, ir_edge_kind_t kind, ir_graph *irg)
+{
+       irn_edge_info_t *info;
+       int             i, n;
+
+       if (!edges_activated_kind(irg, kind))
+               return;
+
+       info = _get_irn_edge_info(irn, kind);
+       if (info->edges_built)
+               return;
+
+       DBG((dbg, LEVEL_5, "node revivaled (kind: %s): %+F\n", get_kind_str(kind), irn));
+
+       foreach_tgt(irn, i, n, kind) {
+               ir_node *tgt = get_n(irn, i, kind);
+               edges_notify_edge_kind(irn, i, tgt, NULL, kind, irg);
+       }
+       info->edges_built = 1;
+}
+
 struct build_walker {
        ir_graph       *irg;
        ir_edge_kind_t kind;
@@ -501,6 +529,7 @@ static void build_edges_walker(ir_node *irn, void *data) {
                ir_node *pred = get_n(irn, i, kind);
                edges_notify_edge_kind(irn, i, pred, NULL, kind, irg);
        }
+       _get_irn_edge_info(irn, kind)->edges_built = 1;
 }
 
 /**
@@ -512,7 +541,8 @@ static void init_lh_walker(ir_node *irn, void *data) {
        ir_edge_kind_t      kind = w->kind;
        list_head           *head = _get_irn_outs_head(irn, kind);
        INIT_LIST_HEAD(head);
-       _get_irn_edge_info(irn, kind)->out_count = 0;
+       _get_irn_edge_info(irn, kind)->edges_built = 0;
+       _get_irn_edge_info(irn, kind)->out_count   = 0;
 }
 
 /**
@@ -533,7 +563,8 @@ static void init_lh_walker_dep(ir_node *irn, void *data) {
        int                 i;
 
        INIT_LIST_HEAD(head);
-       _get_irn_edge_info(irn, kind)->out_count = 0;
+       _get_irn_edge_info(irn, kind)->edges_built = 0;
+       _get_irn_edge_info(irn, kind)->out_count   = 0;
 
        for (i = get_irn_deps(irn) - 1; i >= 0; --i) {
                ir_node *dep = get_irn_dep(irn, i);
@@ -541,7 +572,8 @@ static void init_lh_walker_dep(ir_node *irn, void *data) {
                head = _get_irn_outs_head(dep, kind);
 
                INIT_LIST_HEAD(head);
-               _get_irn_edge_info(dep, kind)->out_count = 0;
+               _get_irn_edge_info(dep, kind)->edges_built = 0;
+               _get_irn_edge_info(dep, kind)->out_count   = 0;
        }
 }
 
@@ -557,8 +589,7 @@ typedef struct visitor_info_t {
 static void visitor(ir_node *irn, void *data) {
        visitor_info_t *info = data;
 
-       if (!irn_visited(irn)) {
-               mark_irn_visited(irn);
+       if (!irn_visited_else_mark(irn)) {
                info->visit(irn, info->data);
        }
 }
@@ -968,6 +999,10 @@ void edges_node_deleted(ir_node *irn, ir_graph *irg) {
        edges_node_deleted_kind(irn, EDGE_KIND_BLOCK, irg);
 }
 
+void edges_node_revival(ir_node *irn, ir_graph *irg) {
+       edges_node_revival_kind(irn, EDGE_KIND_NORMAL, irg);
+       edges_node_revival_kind(irn, EDGE_KIND_BLOCK, irg);
+}
 
 const ir_edge_t *(get_irn_out_edge_first_kind)(const ir_node *irn, ir_edge_kind_t kind) {
        return _get_irn_out_edge_first_kind(irn, kind);
index d82e8a6..c2b291b 100644 (file)
@@ -143,6 +143,11 @@ void edges_notify_edge_kind(ir_node *src, int pos, ir_node *tgt, ir_node *old_tg
 */
 void edges_node_deleted(ir_node *old, ir_graph *irg);
 
+/**
+ * A node might be revivaled by CSE.
+ */
+void edges_node_revival(ir_node *node, ir_graph *irg);
+
 void edges_invalidate_kind(ir_node *irn, ir_edge_kind_t kind, ir_graph *irg);
 
 /**
index 19a36e9..f61d90a 100644 (file)
@@ -168,8 +168,12 @@ new_ir_node(dbg_info *db, ir_graph *irg, ir_node *block, ir_op *op, ir_mode *mod
        res->out     = NULL;
        res->node_nr = get_irp_new_node_nr();
 
-       for (i = 0; i < EDGE_KIND_LAST; ++i)
+       for (i = 0; i < EDGE_KIND_LAST; ++i) {
                INIT_LIST_HEAD(&res->edge_info[i].outs_head);
+               /* edges will be build immediately */
+               res->edge_info[i].edges_built = 1;
+               res->edge_info[i].out_count = 0;
+       }
 
        /* don't put this into the for loop, arity is -1 for some nodes! */
        edges_notify_edge(res, -1, res->in[0], NULL, irg);
index 6542ecf..29d1990 100644 (file)
@@ -6368,6 +6368,9 @@ ir_node *identify_remember(pset *value_table, ir_node *n) {
 
        if (o != n) {
                update_known_irn(o, n);
+
+               /* n is reachable again */
+               edges_node_revival(n, get_irn_irg(n));
        }
 
        return o;
index c10b4e4..ae0b465 100644 (file)
@@ -340,7 +340,8 @@ typedef union {
  */
 typedef struct _irn_edge_kind_info_t {
        struct list_head outs_head;  /**< The list of all outs. */
-       int out_count;               /**< Number of outs in the list. */
+       unsigned edges_built : 1;    /**< Set edges where built for this node. */
+       unsigned out_count : 31;     /**< Number of outs in the list. */
 } irn_edge_info_t;
 
 typedef irn_edge_info_t irn_edges_info_t[EDGE_KIND_LAST];