From 896321f0a34f3aed88c02b159d056ef7afc2ce41 Mon Sep 17 00:00:00 2001 From: Michael Beck Date: Tue, 12 Jan 2010 22:27:48 +0000 Subject: [PATCH] Try to fix a rare edges bug: - 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 | 45 ++++++++++++++++++++++++++++++++++++++++----- ir/ir/iredges_t.h | 5 +++++ ir/ir/irnode.c | 6 +++++- ir/ir/iropt.c | 3 +++ ir/ir/irtypes.h | 3 ++- 5 files changed, 55 insertions(+), 7 deletions(-) diff --git a/ir/ir/iredges.c b/ir/ir/iredges.c index b4200890e..8863bfe71 100644 --- a/ir/ir/iredges.c +++ b/ir/ir/iredges.c @@ -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); diff --git a/ir/ir/iredges_t.h b/ir/ir/iredges_t.h index d82e8a6c6..c2b291b5e 100644 --- a/ir/ir/iredges_t.h +++ b/ir/ir/iredges_t.h @@ -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); /** diff --git a/ir/ir/irnode.c b/ir/ir/irnode.c index 19a36e91d..f61d90af6 100644 --- a/ir/ir/irnode.c +++ b/ir/ir/irnode.c @@ -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); diff --git a/ir/ir/iropt.c b/ir/ir/iropt.c index 6542ecfc9..29d19901a 100644 --- a/ir/ir/iropt.c +++ b/ir/ir/iropt.c @@ -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; diff --git a/ir/ir/irtypes.h b/ir/ir/irtypes.h index c10b4e41a..ae0b465d4 100644 --- a/ir/ir/irtypes.h +++ b/ir/ir/irtypes.h @@ -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]; -- 2.20.1