* @brief Always available outs.
* @author Sebastian Hack, Michael Beck, Andreas Schoesser
* @date 14.1.2005
- * @version $Id$
* @brief
* This are out-edges (also called def-use edges) that are dynamically
* updated as the graph changes.
return NULL;
}
+static ir_node *get_irn_safe_n(const ir_node *node, int n)
+{
+ if (n == -1 && is_Block(node))
+ return NULL;
+ return get_irn_n(node, n);
+}
+
static const ir_edge_kind_info_t edge_kind_info[EDGE_KIND_LAST] = {
- { "normal" , set_irn_n, -1, get_irn_arity, get_irn_n },
- { "block succs", NULL, 0, get_irn_arity, get_block_n },
- { "dependency", set_irn_dep, 0, get_irn_deps, get_irn_dep }
+ { "normal" , set_irn_n, -1, get_irn_arity, get_irn_safe_n },
+ { "block succs", NULL, 0, get_irn_arity, get_block_n },
+ { "dependency", set_irn_dep, 0, get_irn_deps, get_irn_dep }
};
#define foreach_tgt(irn, i, n, kind) for (i = edge_kind_info[kind].first_idx, n = edge_kind_info[kind].get_arity(irn); i < n; ++i)
*/
static int edges_dbg = 0;
-#ifdef DEBUG_libfirm
-/* a static variable holding the last number assigned to a new edge */
-static long last_edge_num = -1;
-#endif
-
/**
* Returns an ID for the given edge.
*/
static inline long edge_get_id(const ir_edge_t *e)
{
-#ifdef DEBUG_libfirm
- return e->edge_nr;
-#else /* DEBUG_libfirm */
return (long)e;
-#endif /* DEBUG_libfirm */
}
/**
*/
void edges_reset_private_data(ir_graph *irg, int offset, unsigned size)
{
- irg_edge_info_t *info = _get_irg_edge_info(irg, EDGE_KIND_NORMAL);
+ irg_edge_info_t *info = get_irg_edge_info(irg, EDGE_KIND_NORMAL);
ir_edge_t *edge;
ir_edgeset_iterator_t iter;
void edges_init_graph_kind(ir_graph *irg, ir_edge_kind_t kind)
{
if (edges_activated_kind(irg, kind)) {
- irg_edge_info_t *info = _get_irg_edge_info(irg, kind);
+ irg_edge_info_t *info = get_irg_edge_info(irg, kind);
size_t amount = irg->estimated_node_count * 2;
edges_used = 1;
* @return The corresponding edge object or NULL,
* if no such edge exists.
*/
-const ir_edge_t *get_irn_edge_kind(ir_graph *irg, const ir_node *src, int pos, ir_edge_kind_t kind)
+const ir_edge_t *get_irn_edge_kind(const ir_node *src, int pos, ir_edge_kind_t kind)
{
+ ir_graph *irg = get_irn_irg(src);
if (edges_activated_kind(irg, kind)) {
- irg_edge_info_t *info = _get_irg_edge_info(irg, kind);
+ irg_edge_info_t *info = get_irg_edge_info(irg, kind);
ir_edge_t key;
key.src = (ir_node *)src;
*/
static inline void edge_change_cnt(ir_node *tgt, ir_edge_kind_t kind, int ofs)
{
- irn_edge_info_t *info = _get_irn_edge_info(tgt, kind);
+ irn_edge_info_t *info = get_irn_edge_info(tgt, kind);
info->out_count += ofs;
-
-#if 0
- ir_graph *irg = get_irn_irg(tgt);
- assert(info->out_count >= 0);
- if (info->out_count == 0 && kind == EDGE_KIND_NORMAL) {
- /* tgt lost it's last user */
- int i;
-
- for (i = get_irn_arity(tgt) - 1; i >= -1; --i) {
- ir_node *prev = get_irn_n(tgt, i);
-
- edges_notify_edge(tgt, i, NULL, prev, irg);
- }
- for (i = get_irn_deps(tgt) - 1; i >= 0; --i) {
- ir_node *prev = get_irn_dep(tgt, i);
-
- edges_notify_edge_kind(tgt, i, NULL, prev, EDGE_KIND_DEP, irg);
-
- }
- }
-#endif
}
/**
*/
static inline void verify_list_head(ir_node *irn, ir_edge_kind_t kind)
{
- int err = 0;
- int num = 0;
- pset *lh_set = pset_new_ptr(16);
- const struct list_head *head = _get_irn_outs_head(irn, kind);
+ int err = 0;
+ int num = 0;
+ pset *lh_set = pset_new_ptr(16);
+ const struct list_head *head = &get_irn_edge_info(irn, kind)->outs_head;
const struct list_head *pos;
list_for_each(pos, head) {
if (!edges_activated_kind(irg, kind))
return;
- info = _get_irg_edge_info(irg, kind);
+ info = get_irg_edge_info(irg, kind);
edges = &info->edges;
foreach_ir_edgeset(edges, e, iter) {
ir_printf("%+F %d %d\n", e->src, e->pos, e->invalid);
irg_edge_info_t *info;
ir_edgeset_t *edges;
ir_edge_t templ;
- ir_edge_t *edge;
assert(edges_activated_kind(irg, kind));
if (tgt == old_tgt)
return;
- info = _get_irg_edge_info(irg, kind);
+ info = get_irg_edge_info(irg, kind);
edges = &info->edges;
/* Initialize the edge template to search in the set. */
*/
if (tgt == NULL) {
/* search the edge in the set. */
- edge = ir_edgeset_find(edges, &templ);
+ ir_edge_t *edge = ir_edgeset_find(edges, &templ);
/* mark the edge invalid if it was found */
if (edge) {
edge->invalid = 1;
edge->pos = -2;
edge->src = NULL;
-#ifdef DEBUG_libfirm
- edge->edge_nr = -1;
-#endif /* DEBUG_libfirm */
edge_change_cnt(old_tgt, kind, -1);
} else {
/* If the edge was not found issue a warning on the debug stream */
* old target was != NULL) or added (if the old target was
* NULL).
*/
- struct list_head *head = _get_irn_outs_head(tgt, kind);
+ struct list_head *head = &get_irn_edge_info(tgt, kind)->outs_head;
assert(head->next && head->prev &&
"target list head must have been initialized");
/* If the old target is not null, the edge is moved. */
if (old_tgt) {
- edge = ir_edgeset_find(edges, &templ);
+ ir_edge_t *edge = ir_edgeset_find(edges, &templ);
assert(edge && "edge to redirect not found!");
assert(! edge->invalid && "Invalid edge encountered");
edge->list.next = NULL;
edge->list.prev = NULL;
memset(edge + 1, 0, edges_private_size);
- DEBUG_ONLY(edge->src_nr = get_irn_node_nr(src));
new_edge = ir_edgeset_insert(edges, edge);
if (new_edge != edge) {
msg = "adding";
list_add(&edge->list, head);
- DEBUG_ONLY(edge->edge_nr = ++last_edge_num);
}
edge_change_cnt(tgt, kind, +1);
- } /* else */
+ }
#ifndef DEBUG_libfirm
/* verify list heads */
DBG((dbg, LEVEL_5, "announce out edge: %+F %d-> %+F(%+F): %s\n", src, pos, tgt, old_tgt, msg));
}
-void edges_notify_edge(ir_node *src, int pos, ir_node *tgt, ir_node *old_tgt, ir_graph *irg)
+void edges_notify_edge(ir_node *src, int pos, ir_node *tgt, ir_node *old_tgt,
+ ir_graph *irg)
{
if (edges_activated_kind(irg, EDGE_KIND_NORMAL)) {
edges_notify_edge_kind(src, pos, tgt, old_tgt, EDGE_KIND_NORMAL, irg);
}
- if (edges_activated_kind(irg, EDGE_KIND_BLOCK) && is_Block(src)) {
- ir_node *bl_old = old_tgt ? get_nodes_block(skip_Proj(old_tgt)) : NULL;
- ir_node *bl_tgt = NULL;
-
- if (tgt)
- bl_tgt = is_Bad(tgt) ? tgt : get_nodes_block(skip_Proj(tgt));
-
- edges_notify_edge_kind(src, pos, bl_tgt, bl_old, EDGE_KIND_BLOCK, irg);
+ if (edges_activated_kind(irg, EDGE_KIND_BLOCK)) {
+ if (is_Block(src)) {
+ ir_node *bl_old = old_tgt ? get_nodes_block(old_tgt) : NULL;
+ ir_node *bl_tgt = NULL;
+
+ if (tgt)
+ bl_tgt = is_Bad(tgt) ? tgt : get_nodes_block(tgt);
+
+ edges_notify_edge_kind(src, pos, bl_tgt, bl_old, EDGE_KIND_BLOCK, irg);
+ } else if (get_irn_mode(src) == mode_X && old_tgt != NULL && is_Block(old_tgt)) {
+ /* moving a jump node from one block to another */
+ const ir_edge_t *edge;
+ const ir_edge_t *next;
+ foreach_out_edge_kind_safe(old_tgt, edge, next, EDGE_KIND_BLOCK) {
+ ir_node *succ = get_edge_src_irn(edge);
+ int succ_pos = get_edge_src_pos(edge);
+ ir_node *block_pred = get_Block_cfgpred(succ, succ_pos);
+ if (block_pred != src)
+ continue;
+ edges_notify_edge_kind(succ, succ_pos, tgt, old_tgt,
+ EDGE_KIND_BLOCK, irg);
+ }
+ }
}
}
* @param kind the kind of edges to remove
* @param irg the irg of the old node
*/
-static void edges_node_deleted_kind(ir_node *old, ir_edge_kind_t kind, ir_graph *irg)
+static void edges_node_deleted_kind(ir_node *old, ir_edge_kind_t kind)
{
int i, n;
+ ir_graph *irg = get_irn_irg(old);
if (!edges_activated_kind(irg, kind))
return;
* @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)
+static void edges_node_revival_kind(ir_node *irn, ir_edge_kind_t kind)
{
irn_edge_info_t *info;
int i, n;
+ ir_graph *irg = get_irn_irg(irn);
if (!edges_activated_kind(irg, kind))
return;
- info = _get_irn_edge_info(irn, kind);
+ info = get_irn_edge_info(irn, kind);
if (info->edges_built)
return;
}
typedef struct build_walker {
- ir_graph *irg;
ir_edge_kind_t kind;
bitset_t *reachable;
unsigned problem_found;
build_walker *w = (build_walker*)data;
int i, n;
ir_edge_kind_t kind = w->kind;
- ir_graph *irg = w->irg;
- get_edge_src_n_func_t *get_n;
+ ir_graph *irg = get_irn_irg(irn);
- get_n = edge_kind_info[kind].get_n;
foreach_tgt(irn, i, n, kind) {
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;
+ get_irn_edge_info(irn, kind)->edges_built = 1;
}
/**
{
build_walker *w = (build_walker*)data;
ir_edge_kind_t kind = w->kind;
- list_head *head = _get_irn_outs_head(irn, kind);
+ list_head *head = &get_irn_edge_info(irn, kind)->outs_head;
INIT_LIST_HEAD(head);
- _get_irn_edge_info(irn, kind)->edges_built = 0;
- _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;
}
/**
{
build_walker *w = (build_walker*)data;
ir_edge_kind_t kind = w->kind;
- list_head *head = _get_irn_outs_head(irn, kind);
+ list_head *head = &get_irn_edge_info(irn, kind)->outs_head;
int i;
INIT_LIST_HEAD(head);
- _get_irn_edge_info(irn, kind)->edges_built = 0;
- _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);
- head = _get_irn_outs_head(dep, kind);
+ head = &get_irn_edge_info(dep, kind)->outs_head;
INIT_LIST_HEAD(head);
- _get_irn_edge_info(dep, kind)->edges_built = 0;
- _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;
}
}
if (is_Deleted(irn))
return;
+ if (!is_Block(irn) && is_Deleted(get_nodes_block(irn)))
+ return;
if (!irn_visited_else_mark(irn)) {
info->visit(irn, info->data);
void edges_activate_kind(ir_graph *irg, ir_edge_kind_t kind)
{
struct build_walker w;
- irg_edge_info_t *info = _get_irg_edge_info(irg, kind);
+ irg_edge_info_t *info = get_irg_edge_info(irg, kind);
visitor_info_t visit;
- w.irg = irg;
w.kind = kind;
visit.data = &w;
void edges_deactivate_kind(ir_graph *irg, ir_edge_kind_t kind)
{
- irg_edge_info_t *info = _get_irg_edge_info(irg, kind);
+ irg_edge_info_t *info = get_irg_edge_info(irg, kind);
info->activated = 0;
if (info->allocated) {
int (edges_activated_kind)(const ir_graph *irg, ir_edge_kind_t kind)
{
- return _edges_activated_kind(irg, kind);
+ return edges_activated_kind_(irg, kind);
}
* sent to.
* @param irg The graph.
*/
-void edges_reroute_kind(ir_node *from, ir_node *to, ir_edge_kind_t kind, ir_graph *irg)
+void edges_reroute_kind(ir_node *from, ir_node *to, ir_edge_kind_t kind)
{
+ ir_graph *irg = get_irn_irg(from);
set_edge_func_t *set_edge = edge_kind_info[kind].set_edge;
if (set_edge && edges_activated_kind(irg, kind)) {
- struct list_head *head = _get_irn_outs_head(from, kind);
+ struct list_head *head = &get_irn_edge_info(from, kind)->outs_head;
DBG((dbg, LEVEL_5, "reroute from %+F to %+F\n", from, to));
static void verify_set_presence(ir_node *irn, void *data)
{
build_walker *w = (build_walker*)data;
- ir_edgeset_t *edges = &_get_irg_edge_info(w->irg, w->kind)->edges;
+ ir_graph *irg = get_irn_irg(irn);
+ ir_edgeset_t *edges = &get_irg_edge_info(irg, w->kind)->edges;
int i, n;
foreach_tgt(irn, i, n, w->kind) {
e->present = 1;
} else {
w->problem_found = 1;
-#if 0
- ir_fprintf(stderr, "Edge Verifier: edge %+F,%d -> %+F (kind: \"%s\") is missing\n",
- irn, i, get_n(irn, i, w->kind), get_kind_str(w->kind));
-#endif
}
}
}
if (w->kind == EDGE_KIND_NORMAL && get_irn_arity(e->src) <= e->pos) {
w->problem_found = 1;
-#if 0
- ir_fprintf(stderr, "Edge Verifier: edge(%ld) %+F -> %+F recorded at src position %d, but src has arity %d\n",
- edge_get_id(e), e->src, irn, e->pos, get_irn_arity(e->src));
-#endif
continue;
}
if (irn != tgt) {
w->problem_found = 1;
-#if 0
- ir_fprintf(stderr, "Edge Verifier: edge(%ld) %+F,%d (kind \"%s\") is no out edge of %+F but of %+F\n",
- edge_get_id(e), e->src, e->pos, get_kind_str(w->kind), irn, tgt);
-#endif
}
}
}
int edges_verify_kind(ir_graph *irg, ir_edge_kind_t kind)
{
struct build_walker w;
- ir_edgeset_t *edges = &_get_irg_edge_info(irg, kind)->edges;
+ ir_edgeset_t *edges = &get_irg_edge_info(irg, kind)->edges;
ir_edge_t *e;
ir_edgeset_iterator_t iter;
- w.irg = irg;
w.kind = kind;
w.reachable = bitset_alloca(get_irg_last_idx(irg));
w.problem_found = 0;
*/
static void clear_links(ir_node *irn, void *env)
{
- build_walker *w = (build_walker*)env;
bitset_t *bs;
+ ir_graph *irg;
+ (void) env;
if (IGNORE_NODE(irn)) {
set_irn_link(irn, NULL);
return;
}
- bs = bitset_malloc(get_irg_last_idx(w->irg));
+ irg = get_irn_irg(irn);
+ bs = bitset_malloc(get_irg_last_idx(irg));
set_irn_link(irn, bs);
}
int first;
(void) env;
- first = -1;
+ first = is_Block(irn) ? 0 : -1;
for (i = get_irn_arity(irn) - 1; i >= first; --i) {
ir_node *op = get_irn_n(irn, i);
bitset_t *bs = (bitset_t*)get_irn_link(op);
size_t idx;
const struct list_head *head;
const struct list_head *pos;
+ ir_graph *irg;
if (IGNORE_NODE(irn))
return;
bs = (bitset_t*)get_irn_link(irn);
list_cnt = 0;
ref_cnt = 0;
- edge_cnt = _get_irn_edge_info(irn, EDGE_KIND_NORMAL)->out_count;
- head = _get_irn_outs_head(irn, EDGE_KIND_NORMAL);
+ edge_cnt = get_irn_edge_info(irn, EDGE_KIND_NORMAL)->out_count;
+ head = &get_irn_edge_info(irn, EDGE_KIND_NORMAL)->outs_head;
/* We can iterate safely here, list heads have already been verified. */
list_for_each(pos, head) {
/* check all nodes that reference us and count edges that point number
* of ins that actually point to us */
+ irg = get_irn_irg(irn);
ref_cnt = 0;
bitset_foreach(bs, idx) {
int i, arity;
- ir_node *src = get_idx_irn(w->irg, idx);
+ ir_node *src = get_idx_irn(irg, idx);
arity = get_irn_arity(src);
for (i = 0; i < arity; ++i) {
w->problem_found = 1;
ir_fprintf(stderr, "Edge Verifier: %+F reachable by %d node(s), but the list contains %d edge(s)\n",
irn, ref_cnt, list_cnt);
-
- /* Matze: buggy if a node has multiple ins pointing at irn */
-#if 0
- list_for_each(pos, head) {
- ir_edge_t *edge = list_entry(pos, ir_edge_t, list);
- bitset_flip(bs, get_irn_idx(edge->src));
- }
-
- if (ref_cnt < list_cnt)
- fprintf(stderr," following nodes are recorded in list, but not as user:\n");
- else
- fprintf(stderr," following nodes are user, but not recorded in list:\n");
-
- fprintf(stderr," ");
- bitset_foreach(bs, idx) {
- ir_node *src = get_idx_irn(w->irg, idx);
- ir_fprintf(stderr, " %+F", src);
- }
- fprintf(stderr, "\n");
-#endif
}
bitset_free(bs);
/* verify normal edges only */
problem_found = edges_verify_kind(irg, EDGE_KIND_NORMAL);
- w.irg = irg;
w.kind = EDGE_KIND_NORMAL;
w.problem_found = 0;
return activated;
}
-void edges_node_deleted(ir_node *irn, ir_graph *irg)
+void edges_node_deleted(ir_node *irn)
{
- edges_node_deleted_kind(irn, EDGE_KIND_NORMAL, irg);
- edges_node_deleted_kind(irn, EDGE_KIND_BLOCK, irg);
+ edges_node_deleted_kind(irn, EDGE_KIND_NORMAL);
+ edges_node_deleted_kind(irn, EDGE_KIND_BLOCK);
}
-void edges_node_revival(ir_node *irn, ir_graph *irg)
+void edges_node_revival(ir_node *irn)
{
- edges_node_revival_kind(irn, EDGE_KIND_NORMAL, irg);
- edges_node_revival_kind(irn, EDGE_KIND_BLOCK, irg);
+ edges_node_revival_kind(irn, EDGE_KIND_NORMAL);
+ edges_node_revival_kind(irn, EDGE_KIND_BLOCK);
}
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);
+ return get_irn_out_edge_first_kind_(irn, kind);
}
const ir_edge_t *(get_irn_out_edge_next)(const ir_node *irn, const ir_edge_t *last)
{
- return _get_irn_out_edge_next(irn, last);
+ return get_irn_out_edge_next_(irn, last);
}
ir_node *(get_edge_src_irn)(const ir_edge_t *edge)
{
- return _get_edge_src_irn(edge);
+ return get_edge_src_irn_(edge);
}
int (get_edge_src_pos)(const ir_edge_t *edge)
{
- return _get_edge_src_pos(edge);
+ return get_edge_src_pos_(edge);
}
int (get_irn_n_edges_kind)(const ir_node *irn, ir_edge_kind_t kind)
{
- return _get_irn_n_edges_kind(irn, kind);
+ return get_irn_n_edges_kind_(irn, kind);
}
static void irg_walk_edges2(ir_node *node, irg_walk_func *pre,
{
const ir_edge_t *edge, *next;
- if (irn_visited(node))
+ if (irn_visited_else_mark(node))
return;
- mark_irn_visited(node);
if (pre != NULL)
pre(node, env);