X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=ir%2Fir%2Firedges.c;h=583169bdf80d372842970ed209105825f5226a46;hb=b4647d67ab7885d5da32c2a30242fbc4ed93d81b;hp=b593ed143842c9909400ef42c9ee6808a28bbccb;hpb=cb4ccdf2eae3bec5f1886f6ff44ebb395d0ba5af;p=libfirm diff --git a/ir/ir/iredges.c b/ir/ir/iredges.c index b593ed143..583169bdf 100644 --- a/ir/ir/iredges.c +++ b/ir/ir/iredges.c @@ -23,7 +23,7 @@ * @author Sebastian Hack, Michael Beck, Andreas Schoesser * @date 14.1.2005 * @version $Id$ - * @summary + * @brief * This are out-edges (also called def-use edges) that are dynamically * updated as the graph changes. */ @@ -39,6 +39,8 @@ #include "debug.h" #include "set.h" #include "bitset.h" +#include "error.h" +#include "irpass_t.h" #include "iredgeset.h" #include "hashptr.h" @@ -55,11 +57,14 @@ #define SetRangeEmpty(ptr,size) memset(ptr, 0, (size) * sizeof((ptr)[0])) #define hashset_init ir_edgeset_init +void ir_edgeset_init_size(ir_edgeset_t *self, size_t size); #define hashset_init_size ir_edgeset_init_size #define hashset_destroy ir_edgeset_destroy #define hashset_insert ir_edgeset_insert #define hashset_remove ir_edgeset_remove +ir_edge_t *ir_edgeset_find(const ir_edgeset_t *self, const ir_edge_t*); #define hashset_find ir_edgeset_find +size_t ir_edgeset_size(const ir_edgeset_t *self); #define hashset_size ir_edgeset_size #define hashset_iterator_init ir_edgeset_iterator_init #define hashset_iterator_next ir_edgeset_iterator_next @@ -74,8 +79,15 @@ */ typedef void (set_edge_func_t)(ir_node *src, int pos, ir_node *tgt); +/** + * A function that returns the "arity" of a given edge kind + * for a node. + */ typedef int (get_edge_src_arity_func_t)(const ir_node *src); +/** + * A function that returns the pos'th edge of a given edge kind for a node. + */ typedef ir_node *(get_edge_src_n_func_t)(const ir_node *src, int pos); /** @@ -92,9 +104,10 @@ typedef struct { /** * Get the predecessor block. */ -static ir_node *get_block_n(const ir_node *irn, int pos) { - if (is_Block(irn)) - return get_Block_cfgpred_block(irn, pos); +static ir_node *get_block_n(const ir_node *block, int pos) +{ + if (is_Block(block)) + return get_Block_cfgpred_block(block, pos); /* might be a Bad */ return NULL; } @@ -105,7 +118,7 @@ static const ir_edge_kind_info_t edge_kind_info[EDGE_KIND_LAST] = { { "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) +#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) #define get_n(irn, pos, kind) (edge_kind_info[kind].get_n(irn, pos)) #define get_kind_str(kind) (edge_kind_info[kind].name) @@ -134,7 +147,11 @@ static int edges_dbg = 0; static long last_edge_num = -1; #endif -static inline long edge_get_id(const ir_edge_t *e) { +/** + * 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 */ @@ -153,7 +170,8 @@ static inline long edge_get_id(const ir_edge_t *e) { * Each user has to remember his given offset and the size of his private data. * To be called before FIRM is initialized. */ -int edges_register_private_data(size_t n) { +int edges_register_private_data(size_t n) +{ int res = edges_private_size; assert(!edges_used && "you cannot register private edge data, if edges have been initialized"); @@ -162,12 +180,13 @@ int edges_register_private_data(size_t n) { return res; } -/** +/* * Reset the user's private data at offset 'offset' * The user has to remember his offset and the size of his data! * Caution: Using wrong values here can destroy other users private data! */ -void edges_reset_private_data(ir_graph *irg, int offset, size_t size) { +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); ir_edge_t *edge; ir_edgeset_iterator_t iter; @@ -187,18 +206,20 @@ void edges_reset_private_data(ir_graph *irg, int offset, size_t size) { * Initialize the out information for a graph. * @note Dead node elimination can call this on an already initialized graph. */ -void edges_init_graph_kind(ir_graph *irg, ir_edge_kind_t kind) { +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); size_t amount = irg->estimated_node_count * 2; edges_used = 1; - if(info->allocated) { + if (info->allocated) { amount = ir_edgeset_size(&info->edges); ir_edgeset_destroy(&info->edges); obstack_free(&info->edges_obst, NULL); } obstack_init(&info->edges_obst); + INIT_LIST_HEAD(&info->free_edges); ir_edgeset_init_size(&info->edges, amount); info->allocated = 1; } @@ -206,9 +227,10 @@ void edges_init_graph_kind(ir_graph *irg, ir_edge_kind_t kind) { /** * Get the edge object of an outgoing edge at a node. - * @param irg The graph, the node is in. - * @param src The node at which the edge originates. - * @param pos The position of the edge. + * @param irg The graph, the node is in. + * @param src The node at which the edge originates. + * @param pos The position of the edge. + * @param kind The kind of the edge. * @return The corresponding edge object or NULL, * if no such edge exists. */ @@ -231,9 +253,10 @@ const ir_edge_t *get_irn_edge_kind(ir_graph *irg, const ir_node *src, int pos, i * Get the edge object of an outgoing edge at a node. * Looks for an edge for all kinds. */ -const ir_edge_t *get_irn_edge(ir_graph *irg, const ir_node *src, int pos) { +const ir_edge_t *get_irn_edge(ir_graph *irg, const ir_node *src, int pos) +{ const ir_edge_t *edge; - if((edge = get_irn_edge_kind(irg, src, pos, EDGE_KIND_NORMAL)) == NULL) + if ((edge = get_irn_edge_kind(irg, src, pos, EDGE_KIND_NORMAL)) == NULL) edge = get_irn_edge_kind(irg, src, pos, EDGE_KIND_BLOCK); return(edge); } @@ -244,11 +267,13 @@ const ir_edge_t *get_irn_edge(ir_graph *irg, const ir_node *src, int pos) { * @param tgt the edge target * @param kind the kind of the edge */ -static inline void edge_change_cnt(ir_node *tgt, ir_edge_kind_t kind, int ofs) { +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); 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 */ @@ -257,12 +282,12 @@ static inline void edge_change_cnt(ir_node *tgt, ir_edge_kind_t kind, int ofs) { 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, current_ir_graph); + 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, current_ir_graph); + edges_notify_edge_kind(tgt, i, NULL, prev, EDGE_KIND_DEP, irg); } } @@ -273,7 +298,8 @@ static inline void edge_change_cnt(ir_node *tgt, ir_edge_kind_t kind, int ofs) { * Verify the edge list of a node, ie. ensure it's a loop: * head -> e_1 -> ... -> e_n -> head */ -static inline void vrfy_list_head(ir_node *irn, ir_edge_kind_t kind) { +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); @@ -302,6 +328,23 @@ static inline void vrfy_list_head(ir_node *irn, ir_edge_kind_t kind) { assert(err == 0); } +void edges_dump_kind(ir_graph *irg, ir_edge_kind_t kind) +{ + irg_edge_info_t *info; + ir_edgeset_t *edges; + ir_edgeset_iterator_t iter; + ir_edge_t *e; + + if (!edges_activated_kind(irg, kind)) + return; + + 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); + } +} + /* The edge from (src, pos) -> old_tgt is redirected to tgt */ void edges_notify_edge_kind(ir_node *src, int pos, ir_node *tgt, ir_node *old_tgt, ir_edge_kind_t kind, @@ -340,6 +383,7 @@ void edges_notify_edge_kind(ir_node *src, int pos, ir_node *tgt, msg = "deleting"; list_del(&edge->list); ir_edgeset_remove(edges, edge); + list_add(&edge->list, &info->free_edges); edge->invalid = 1; edge->pos = -2; edge->src = NULL; @@ -347,21 +391,17 @@ void edges_notify_edge_kind(ir_node *src, int pos, ir_node *tgt, edge->edge_nr = -1; #endif /* DEBUG_libfirm */ edge_change_cnt(old_tgt, kind, -1); - } - - /* If the edge was not found issue a warning on the debug stream */ - else { + } else { + /* If the edge was not found issue a warning on the debug stream */ msg = "edge to delete not found!\n"; } - } /* if */ - - /* - * The target is not NULL and the old target differs - * from the new target, the edge shall be moved (if the - * old target was != NULL) or added (if the old target was - * NULL). - */ - else { + } else { + /* + * The target is not NULL and the old target differs + * from the new target, the edge shall be moved (if the + * old target was != NULL) or added (if the old target was + * NULL). + */ struct list_head *head = _get_irn_outs_head(tgt, kind); assert(head->next && head->prev && @@ -377,33 +417,36 @@ void edges_notify_edge_kind(ir_node *src, int pos, ir_node *tgt, list_move(&edge->list, head); edge_change_cnt(old_tgt, kind, -1); - } - - /* The old target was null, thus, the edge is newly created. */ - else { + } else { + /* The old target was NULL, thus, the edge is newly created. */ ir_edge_t *new_edge; - ir_edge_t *edge - = obstack_alloc(&info->edges_obst, EDGE_SIZE); - memset(edge, 0, EDGE_SIZE); - edge->src = src; - edge->pos = pos; - edge->kind = kind; + ir_edge_t *edge; + + if (list_empty(&info->free_edges)) { + edge = obstack_alloc(&info->edges_obst, EDGE_SIZE); + } else { + edge = list_entry(info->free_edges.next, ir_edge_t, list); + list_del(&edge->list); + } + + edge->src = src; + edge->pos = pos; + edge->invalid = 0; + edge->present = 0; + edge->kind = kind; + 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) { - obstack_free(&info->edges_obst, edge); + if (new_edge != edge) { + panic("new edge exists already"); } - assert(! edge->invalid && "Freshly inserted edge is invalid?!?"); - assert(edge->list.next == NULL && edge->list.prev == NULL && - "New edge must not have list head initialized"); - msg = "adding"; list_add(&edge->list, head); -#ifdef DEBUG_libfirm - edge->edge_nr = ++last_edge_num; -#endif /* DEBUG_libfirm */ + DEBUG_ONLY(edge->edge_nr = ++last_edge_num); } edge_change_cnt(tgt, kind, +1); @@ -413,9 +456,9 @@ void edges_notify_edge_kind(ir_node *src, int pos, ir_node *tgt, /* verify list heads */ if (edges_dbg) { if (tgt) - vrfy_list_head(tgt, kind); + verify_list_head(tgt, kind); if (old_tgt) - vrfy_list_head(old_tgt, kind); + verify_list_head(old_tgt, kind); } #endif @@ -429,17 +472,13 @@ void edges_notify_edge(ir_node *src, int pos, ir_node *tgt, ir_node *old_tgt, ir } if (edges_activated_kind(irg, EDGE_KIND_BLOCK) && is_Block(src)) { - if (pos == -1) { - /* a MacroBlock edge: ignore it here */ - } else { - ir_node *bl_old = old_tgt ? get_nodes_block(skip_Proj(old_tgt)) : NULL; - ir_node *bl_tgt = NULL; + 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)); + 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); - } + edges_notify_edge_kind(src, pos, bl_tgt, bl_old, EDGE_KIND_BLOCK, irg); } } @@ -465,6 +504,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; @@ -475,7 +542,8 @@ struct build_walker { /** * Post-Walker: notify all edges */ -static void build_edges_walker(ir_node *irn, void *data) { +static void build_edges_walker(ir_node *irn, void *data) +{ struct build_walker *w = data; int i, n; ir_edge_kind_t kind = w->kind; @@ -487,18 +555,21 @@ 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; } /** * Pre-Walker: initializes the list-heads and set the out-count * of all nodes to 0. */ -static void init_lh_walker(ir_node *irn, void *data) { +static void init_lh_walker(ir_node *irn, void *data) +{ struct build_walker *w = 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; } /** @@ -512,14 +583,16 @@ static void init_lh_walker(ir_node *irn, void *data) { * b) it might be sufficient to add those stupid NO_REG nodes * to the anchor */ -static void init_lh_walker_dep(ir_node *irn, void *data) { +static void init_lh_walker_dep(ir_node *irn, void *data) +{ struct build_walker *w = data; ir_edge_kind_t kind = w->kind; list_head *head = _get_irn_outs_head(irn, kind); 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); @@ -527,7 +600,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; } } @@ -540,11 +614,14 @@ typedef struct visitor_info_t { * Visitor: initializes the list-heads and set the out-count * of all nodes to 0 of nodes that are not seen so far. */ -static void visitor(ir_node *irn, void *data) { +static void visitor(ir_node *irn, void *data) +{ visitor_info_t *info = data; - if (!irn_visited(irn)) { - mark_irn_visited(irn); + if (is_Deleted(irn)) + return; + + if (!irn_visited_else_mark(irn)) { info->visit(irn, info->data); } } @@ -582,6 +659,8 @@ void edges_activate_kind(ir_graph *irg, ir_edge_kind_t kind) visit.data = &w; + assert(!info->activated); + info->activated = 1; edges_init_graph_kind(irg, kind); if (kind == EDGE_KIND_DEP) { @@ -626,7 +705,7 @@ void edges_reroute_kind(ir_node *from, ir_node *to, ir_edge_kind_t kind, ir_grap { set_edge_func_t *set_edge = edge_kind_info[kind].set_edge; - if(set_edge && edges_activated_kind(irg, kind)) { + if (set_edge && edges_activated_kind(irg, kind)) { struct list_head *head = _get_irn_outs_head(from, kind); DBG((dbg, LEVEL_5, "reroute from %+F to %+F\n", from, to)); @@ -652,7 +731,7 @@ static void verify_set_presence(ir_node *irn, void *data) templ.pos = i; e = ir_edgeset_find(edges, &templ); - if(e != NULL) { + if (e != NULL) { e->present = 1; } else { w->problem_found = 1; @@ -672,7 +751,7 @@ static void verify_list_presence(ir_node *irn, void *data) bitset_set(w->reachable, get_irn_idx(irn)); /* check list heads */ - vrfy_list_head(irn, w->kind); + verify_list_head(irn, w->kind); foreach_out_edge_kind(irn, e, w->kind) { ir_node *tgt; @@ -737,7 +816,8 @@ int edges_verify_kind(ir_graph *irg, ir_edge_kind_t kind) /** * Clear link field of all nodes. */ -static void clear_links(ir_node *irn, void *env) { +static void clear_links(ir_node *irn, void *env) +{ struct build_walker *w = env; bitset_t *bs; @@ -753,7 +833,8 @@ static void clear_links(ir_node *irn, void *env) { /** * Increases count (stored in link field) for all operands of a node. */ -static void count_user(ir_node *irn, void *env) { +static void count_user(ir_node *irn, void *env) +{ int i; int first; (void) env; @@ -771,7 +852,8 @@ static void count_user(ir_node *irn, void *env) { /** * Verifies if collected count, number of edges in list and stored edge count are in sync. */ -static void verify_edge_counter(ir_node *irn, void *env) { +static void verify_edge_counter(ir_node *irn, void *env) +{ struct build_walker *w = env; bitset_t *bs; int list_cnt; @@ -848,7 +930,8 @@ static void verify_edge_counter(ir_node *irn, void *env) { /** * Verifies the out edges of an irg. */ -int edges_verify(ir_graph *irg) { +int edges_verify(ir_graph *irg) +{ struct build_walker w; int problem_found = 0; @@ -866,39 +949,86 @@ int edges_verify(ir_graph *irg) { return problem_found ? 1 : w.problem_found; } -void init_edges(void) { +struct pass_t { + ir_graph_pass_t pass; + unsigned assert_on_problem; +}; + +/** + * Wrapper to edges_verify to be run as an ir_graph pass. + */ +static int edges_verify_wrapper(ir_graph *irg, void *context) +{ + struct pass_t *pass = context; + int problems_found = edges_verify(irg); + /* do NOT rerun the pass if verify is ok :-) */ + assert(problems_found && pass->assert_on_problem); + return 0; +} + +/* Creates an ir_graph pass for edges_verify(). */ +ir_graph_pass_t *irg_verify_edges_pass(const char *name, unsigned assert_on_problem) +{ + struct pass_t *pass = XMALLOCZ(struct pass_t); + + def_graph_pass_constructor( + &pass->pass, name ? name : "edges_verify", edges_verify_wrapper); + + /* neither dump nor verify */ + pass->pass.dump_irg = (DUMP_ON_IRG_FUNC)ir_prog_no_dump; + pass->pass.verify_irg = (RUN_ON_IRG_FUNC)ir_prog_no_verify; + + pass->assert_on_problem = assert_on_problem; + return &pass->pass; +} + +void init_edges(void) +{ FIRM_DBG_REGISTER(dbg, DBG_EDGES); /* firm_dbg_set_mask(dbg, -1); */ } -void edges_init_dbg(int do_dbg) { +void edges_init_dbg(int do_dbg) +{ edges_dbg = do_dbg; } -void edges_activate(ir_graph *irg) { +void edges_activate(ir_graph *irg) +{ edges_activate_kind(irg, EDGE_KIND_NORMAL); edges_activate_kind(irg, EDGE_KIND_BLOCK); if (get_irg_phase_state(irg) == phase_backend) edges_activate_kind(irg, EDGE_KIND_DEP); } -void edges_deactivate(ir_graph *irg) { +void edges_deactivate(ir_graph *irg) +{ if (get_irg_phase_state(irg) == phase_backend) edges_deactivate_kind(irg, EDGE_KIND_DEP); edges_deactivate_kind(irg, EDGE_KIND_BLOCK); edges_deactivate_kind(irg, EDGE_KIND_NORMAL); } -int edges_assure(ir_graph *irg) { - int activated = edges_activated(irg); +int edges_assure(ir_graph *irg) +{ + int activated = 0; - if (!activated) - edges_activate(irg); + if (edges_activated_kind(irg, EDGE_KIND_BLOCK)) { + activated = 1; + } else { + edges_activate_kind(irg, EDGE_KIND_BLOCK); + } + if (edges_activated_kind(irg, EDGE_KIND_NORMAL)) { + activated = 1; + } else { + edges_activate_kind(irg, EDGE_KIND_NORMAL); + } return activated; } -int edges_assure_kind(ir_graph *irg, ir_edge_kind_t kind) { +int edges_assure_kind(ir_graph *irg, ir_edge_kind_t kind) +{ int activated = edges_activated_kind(irg, kind); if (!activated) @@ -907,47 +1037,84 @@ int edges_assure_kind(ir_graph *irg, ir_edge_kind_t kind) { return activated; } -void edges_node_deleted(ir_node *irn, ir_graph *irg) { +void edges_node_deleted(ir_node *irn, ir_graph *irg) +{ edges_node_deleted_kind(irn, EDGE_KIND_NORMAL, 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) { +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); } -const ir_edge_t *(get_irn_out_edge_next)(const ir_node *irn, const ir_edge_t *last) { +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); } -ir_node *(get_edge_src_irn)(const ir_edge_t *edge) { +ir_node *(get_edge_src_irn)(const ir_edge_t *edge) +{ return _get_edge_src_irn(edge); } -int (get_edge_src_pos)(const ir_edge_t *edge) { +int (get_edge_src_pos)(const ir_edge_t *edge) +{ return _get_edge_src_pos(edge); } -int (get_irn_n_edges_kind)(const ir_node *irn, ir_edge_kind_t kind) { +int (get_irn_n_edges_kind)(const ir_node *irn, ir_edge_kind_t kind) +{ return _get_irn_n_edges_kind(irn, kind); } -void dump_all_out_edges(ir_node *irn) { - int i; - for (i = 0; i < EDGE_KIND_LAST; ++i) { - const ir_edge_t *edge; +static void irg_walk_edges2(ir_node *node, irg_walk_func *pre, + irg_walk_func *post, void *env) +{ + const ir_edge_t *edge, *next; - printf("kind \"%s\"\n", get_kind_str(i)); - foreach_out_edge_kind(irn, edge, i) { - ir_printf("\t%+F(%d)\n", edge->src, edge->pos); - } + if (irn_visited(node)) + return; + mark_irn_visited(node); + + if (pre != NULL) + pre(node, env); + + foreach_out_edge_kind_safe(node, edge, next, EDGE_KIND_NORMAL) { + /* find the corresponding successor block. */ + ir_node *pred = get_edge_src_irn(edge); + irg_walk_edges2(pred, pre, post, env); } + + if (post != NULL) + post(node, env); } -static void irg_block_edges_walk2(ir_node *bl, - irg_walk_func *pre, irg_walk_func *post, - void *env) { +void irg_walk_edges(ir_node *node, irg_walk_func *pre, irg_walk_func *post, + void *env) +{ + ir_graph *irg = get_irn_irg(node); + + assert(edges_activated(irg)); + assert(is_Block(node)); + + ir_reserve_resources(irg, IR_RESOURCE_IRN_VISITED); + + inc_irg_visited(irg); + irg_walk_edges2(node, pre, post, env); + + ir_free_resources(irg, IR_RESOURCE_IRN_VISITED); +} + +static void irg_block_edges_walk2(ir_node *bl, irg_walk_func *pre, + irg_walk_func *post, void *env) +{ const ir_edge_t *edge, *next; if (!Block_block_visited(bl)) { @@ -967,17 +1134,18 @@ static void irg_block_edges_walk2(ir_node *bl, } } -void irg_block_edges_walk(ir_node *node, - irg_walk_func *pre, irg_walk_func *post, - void *env) { +void irg_block_edges_walk(ir_node *node, irg_walk_func *pre, + irg_walk_func *post, void *env) +{ + ir_graph *irg = get_irn_irg(node); - assert(edges_activated(current_ir_graph)); + assert(edges_activated(irg)); assert(is_Block(node)); - ir_reserve_resources(current_ir_graph, IR_RESOURCE_BLOCK_VISITED); + ir_reserve_resources(irg, IR_RESOURCE_BLOCK_VISITED); - inc_irg_block_visited(current_ir_graph); + inc_irg_block_visited(irg); irg_block_edges_walk2(node, pre, post, env); - ir_free_resources(current_ir_graph, IR_RESOURCE_BLOCK_VISITED); + ir_free_resources(irg, IR_RESOURCE_BLOCK_VISITED); }