From: Sebastian Hack Date: Mon, 28 Aug 2006 13:48:54 +0000 (+0000) Subject: Added dependency edges X-Git-Url: http://nsz.repo.hu/git/?a=commitdiff_plain;h=a953ba0dad38aea06301d00e215829a909c1ffe7;p=libfirm Added dependency edges Adapted out edges to the new dependency edges [r8135] --- diff --git a/ir/ir/irdump.c b/ir/ir/irdump.c index d11ba5dd4..386d9eb40 100644 --- a/ir/ir/irdump.c +++ b/ir/ir/irdump.c @@ -1438,34 +1438,54 @@ print_edge_vcgattr(FILE *F, ir_node *from, int to) { /* dump edges to our inputs */ static void dump_ir_data_edges(FILE *F, ir_node *n) { - int i; - unsigned long visited = get_irn_visited(n); - - if ((get_irn_op(n) == op_End) && (!dump_keepalive)) - return; - - for (i = 0; i < get_irn_arity(n); i++) { - ir_node * pred = get_irn_n(n, i); - assert(pred); - - if ((get_interprocedural_view() && get_irn_visited(pred) < visited)) - continue; /* pred not dumped */ - - if (dump_backedge_information_flag && is_backedge(n, i)) - fprintf (F, "backedge: {sourcename: \""); - else - fprintf (F, "edge: {sourcename: \""); - PRINT_NODEID(n); - fprintf (F, "\" targetname: "); - if ((get_opt_dump_const_local()) && is_constlike_node(pred)) { - PRINT_CONSTID(n, pred); - } else { - fprintf(F, "\""); PRINT_NODEID(pred); fprintf(F, "\""); - } - fprintf (F, " label: \"%d\" ", i); - print_edge_vcgattr(F, n, i); - fprintf (F, "}\n"); - } + int i; + unsigned long visited = get_irn_visited(n); + + if ((get_irn_op(n) == op_End) && (!dump_keepalive)) + return; + + /* dump the dependency edges. */ + for (i = 0; i < get_irn_deps(n); ++i) { + ir_node *dep = get_irn_dep(n, i); + + if(dep) { + fprintf(F, "edge: {sourcename: \""); + PRINT_NODEID(n); + fprintf(F, "\" targetname: "); + if ((get_opt_dump_const_local()) && is_constlike_node(dep)) { + PRINT_CONSTID(n, dep); + } else { + fprintf(F, "\""); + PRINT_NODEID(dep); + fprintf(F, "\""); + } + fprintf(F, " label: \"%d\" ", i); + fprintf(F, " color: darkgreen}\n"); + } + } + + for (i = 0; i < get_irn_arity(n); i++) { + ir_node * pred = get_irn_n(n, i); + assert(pred); + + if ((get_interprocedural_view() && get_irn_visited(pred) < visited)) + continue; /* pred not dumped */ + + if (dump_backedge_information_flag && is_backedge(n, i)) + fprintf (F, "backedge: {sourcename: \""); + else + fprintf (F, "edge: {sourcename: \""); + PRINT_NODEID(n); + fprintf (F, "\" targetname: "); + if ((get_opt_dump_const_local()) && is_constlike_node(pred)) { + PRINT_CONSTID(n, pred); + } else { + fprintf(F, "\""); PRINT_NODEID(pred); fprintf(F, "\""); + } + fprintf (F, " label: \"%d\" ", i); + print_edge_vcgattr(F, n, i); + fprintf (F, "}\n"); + } } /** Dumps a node and its edges but not the block edge diff --git a/ir/ir/iredges.c b/ir/ir/iredges.c index 8f626940f..886cc438a 100644 --- a/ir/ir/iredges.c +++ b/ir/ir/iredges.c @@ -29,6 +29,7 @@ #include "irnode_t.h" #include "iropt_t.h" +#include "iredgekinds.h" #include "iredges_t.h" #include "irgwalk.h" #include "irdump_t.h" @@ -37,6 +38,55 @@ #include "debug.h" #include "set.h" +/** +* A function that allows for setting an edge. +* This abstraction is necessary since different edge kind have +* different methods of setting edges. +*/ +typedef void (set_edge_func_t)(ir_node *src, int pos, ir_node *tgt); + +typedef int (get_edge_src_arity_func_t)(const ir_node *src); + +typedef int (get_edge_src_first_func_t)(const ir_node *src); + +typedef ir_node *(get_edge_src_n_func_t)(const ir_node *src, int pos); + +/** +* Additional data for an edge kind. +*/ +typedef struct { + const char *name; + set_edge_func_t *set_edge; + get_edge_src_first_func_t *get_first; + get_edge_src_arity_func_t *get_arity; + get_edge_src_n_func_t *get_n; +} ir_edge_kind_info_t; + +static int get_zero(const ir_node *irn) +{ + return 0; +} + +static int get_irn_first(const ir_node *irn) +{ + return 0 - !is_Block(irn); +} + +static ir_node *get_block_n(const ir_node *irn, int pos) +{ + return is_Block(irn) ? get_Block_cfgpred_block((ir_node *) irn, pos) : 0; +} + +static const ir_edge_kind_info_t edge_kind_info[EDGE_KIND_LAST] = { + { "normal" , set_irn_n, get_irn_first, get_irn_arity, get_irn_n }, + { "block succs", NULL, get_zero, get_irn_arity, get_block_n }, + { "dependency", set_irn_dep, get_zero, get_irn_deps, get_irn_dep } +}; + +#define foreach_tgt(irn, i, n, kind) for(i = edge_kind_info[kind].get_first(irn), 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) + DEBUG_ONLY(static firm_dbg_module_t *dbg;) /** @@ -76,27 +126,21 @@ static int edge_cmp(const void *p1, const void *p2, size_t len) * Initialize the out information for a graph. * @note Dead node elimination can call this on an already initialized graph. */ -void edges_init_graph(ir_graph *irg) +void edges_init_graph_kind(ir_graph *irg, ir_edge_kind_t kind) { - if(edges_activated(irg)) { - irg_edge_info_t *info = _get_irg_edge_info(irg); + if(edges_activated_kind(irg, kind)) { + irg_edge_info_t *info = _get_irg_edge_info(irg, kind); int amount = 2048; edges_used = 1; - if(info->edges) { amount = set_count(info->edges); del_set(info->edges); } - info->edges = new_set(edge_cmp, amount); } } -#define EDGE_SIZE(src) \ - (edges_private_size + (is_Block(src) ? sizeof(ir_block_edge_t) : sizeof(ir_edge_t))) - - /** * Get the edge object of an outgoing edge at a node. * @param irg The graph, the node is in. @@ -105,16 +149,15 @@ void edges_init_graph(ir_graph *irg) * @return The corresponding edge object or NULL, * if no such edge exists. */ -const ir_edge_t *get_irn_edge(ir_graph *irg, const ir_node *src, int pos) +const ir_edge_t *get_irn_edge_kind(ir_graph *irg, const ir_node *src, int pos, ir_edge_kind_t kind) { - if(edges_activated(irg)) { - irg_edge_info_t *info = _get_irg_edge_info(irg); - size_t size = EDGE_SIZE(src); + if(edges_activated_kind(irg, kind)) { + irg_edge_info_t *info = _get_irg_edge_info(irg, kind); ir_edge_t key; key.src = (ir_node *) src; key.pos = pos; - return set_find(info->edges, &key, size, edge_hash(&key)); + return set_find(info->edges, &key, sizeof(key), edge_hash(&key)); } return NULL; @@ -123,50 +166,35 @@ const ir_edge_t *get_irn_edge(ir_graph *irg, const ir_node *src, int pos) /** * Change the out count */ -static INLINE void edge_change_cnt(ir_node *tgt, int ofs) { - irn_edge_info_t *info = _get_irn_edge_info(tgt); +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; } /* The edge from (src, pos) -> old_tgt is redirected to tgt */ -void edges_notify_edge(ir_node *src, int pos, ir_node *tgt, ir_node *old_tgt, ir_graph *irg) +void edges_notify_edge_kind(ir_node *src, int pos, ir_node *tgt, ir_node *old_tgt, ir_edge_kind_t kind, ir_graph *irg) { const char *msg = ""; - if(!edges_activated(irg)) + if(!edges_activated_kind(irg, kind)) return; -#if 0 - assert(node_is_in_irgs_storage(irg, src) && "source not in irg"); -#endif - /* * Only do something, if the old and new target differ. */ if(tgt != old_tgt) { - int is_block_edge = is_Block(src); - set *edges = _get_irg_edge_info(irg)->edges; + irg_edge_info_t *info = _get_irg_edge_info(irg, kind); + set *edges = info->edges; + ir_edge_t *templ = alloca(sizeof(templ[0])); ir_edge_t *edge; - /* - * This is scary, but: - * If two entries in a set do not have the same size, they are - * treated as unequal, ignoring the comparison function. - * So, edges from blocks have extra storage (they are - * ir_block_edge_t's). - * - * Also add the amount of registered private data to the - * size of the edge. - */ - size_t size = EDGE_SIZE(src); - ir_edge_t *templ = alloca(size); - /* Initialize the edge template to search in the set. */ - memset(templ, 0, size); - templ->src = src; - templ->pos = pos; + memset(templ, 0, sizeof(templ[0])); + templ->src = src; + templ->pos = pos; templ->invalid = 0; templ->present = 0; + templ->kind = kind; DEBUG_ONLY(templ->src_nr = get_irn_node_nr(src)); /* @@ -174,7 +202,7 @@ void edges_notify_edge(ir_node *src, int pos, ir_node *tgt, ir_node *old_tgt, ir */ if (tgt == NULL) { /* search the edge in the set. */ - edge = set_find(edges, templ, size, edge_hash(templ)); + edge = set_find(edges, templ, sizeof(templ[0]), edge_hash(templ)); /* mark the edge invalid if it was found */ if(edge) { @@ -185,15 +213,6 @@ void edges_notify_edge(ir_node *src, int pos, ir_node *tgt, ir_node *old_tgt, ir edge->invalid = 1; edge->pos = -2; edge->src = NULL; - - /* - * If the edge is a cf edge, we delete it also - * from the list of all block successor edges. - */ - if(is_block_edge) { - list_del(&block_edge->succ_list); - edge_change_cnt(old_tgt, -1); - } } /* If the edge was not found issue a warning on the debug stream */ @@ -209,22 +228,8 @@ void edges_notify_edge(ir_node *src, int pos, ir_node *tgt, ir_node *old_tgt, ir * NULL). */ else { - struct list_head *head = _get_irn_outs_head(tgt); - - /* - * The list head in the block of the edges target. - * Therein all control flow edges directed at that block - * are recorded. - */ - struct list_head *succ_head = - is_block_edge ? _get_block_succ_head(get_nodes_block(tgt)) : NULL; - - ir_block_edge_t *block_edge; + struct list_head *head = _get_irn_outs_head(tgt, kind); -#if 0 - if(!node_is_in_irgs_storage(irg, tgt)) - return; -#endif assert(head->next && head->prev && "target list head must have been initialized"); @@ -232,8 +237,7 @@ void edges_notify_edge(ir_node *src, int pos, ir_node *tgt, ir_node *old_tgt, ir * insert the edge, if it is not yet in the set or return * the instance in the set. */ - edge = set_insert(edges, templ, size, edge_hash(templ)); - block_edge = (ir_block_edge_t *) edge; + edge = set_insert(edges, templ, sizeof(templ[0]), edge_hash(templ)); #ifdef DEBUG_libfirm assert(!edge->invalid && "Invalid edge encountered"); @@ -244,68 +248,63 @@ void edges_notify_edge(ir_node *src, int pos, ir_node *tgt, ir_node *old_tgt, ir msg = "redirecting"; list_move(&edge->list, head); - - /* If the edge is a cf edge, move it from the successor list. */ - if(is_block_edge) - list_move(&block_edge->succ_list, succ_head); - - edge_change_cnt(old_tgt, -1); + edge_change_cnt(old_tgt, kind, -1); } /* The old target was null, thus, the edge is newly created. */ else { msg = "adding"; list_add(&edge->list, head); - - /* - * If the edge is cf edge, enter it into the successor list - * of the target node's block. - */ - if(is_block_edge) - list_add(&block_edge->succ_list, succ_head); } - edge_change_cnt(tgt, +1); + edge_change_cnt(tgt, kind, +1); } /* else */ } /* If the target and the old target are equal, nothing is done. */ - DBG((dbg, LEVEL_5, "announce out edge: %+F %d-> %+F(%+F): %s\n", - src, pos, tgt, old_tgt, msg)); + DBG((dbg, LEVEL_5, "announce out edge: %+F %d-> %+F(%+F): %s\n", src, pos, tgt, old_tgt, msg)); } -void edges_node_deleted(ir_node *old, 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(irg)) { - int not_a_block = !is_Block(old); + edges_notify_edge_kind(src, pos, tgt, old_tgt, EDGE_KIND_NORMAL, irg); + if(is_Block(src)) { + ir_node *bl_tgt = tgt ? get_nodes_block(skip_Proj(tgt)) : NULL; + // ir_node *bl_old = old_tgt ? old_tgt : NULL; + ir_node *bl_old = old_tgt ? get_nodes_block(skip_Proj(old_tgt)) : NULL; + edges_notify_edge_kind(src, pos, bl_tgt, bl_old, EDGE_KIND_BLOCK, irg); + } +} + + +void edges_node_deleted_kind(ir_node *old, ir_edge_kind_t kind, ir_graph *irg) +{ + if(edges_activated_kind(irg, kind)) { int i, n; - DBG((dbg, LEVEL_5, "node deleted: %+F\n", old)); + DBG((dbg, LEVEL_5, "node deleted (kind: %s): %+F\n", get_kind_str(kind), old)); - /* Change to get_irn_n */ - for(i = -not_a_block, n = get_irn_arity(old); i < n; ++i) { - ir_node *old_tgt = get_irn_n(old, i); - DBG((dbg, LEVEL_5, "\tdelete to old target %+F\n", old_tgt)); - edges_notify_edge(old, i, NULL, old_tgt, irg); + foreach_tgt(old, i, n, kind) { + ir_node *old_tgt = get_n(old, i, kind); + edges_notify_edge_kind(old, i, NULL, old_tgt, kind, irg); } - } } -void edges_invalidate(ir_node *irn, ir_graph *irg) { - edges_node_deleted(irn, irg); -} +struct build_walker { + ir_graph *irg; + ir_edge_kind_t kind; +}; /** * Post-Walker: notify all edges */ static void build_edges_walker(ir_node *irn, void *data) { - ir_graph *irg = data; - int not_a_block = !is_Block(irn); + struct build_walker *w = data; int i, n; - for (i = -not_a_block, n = get_irn_arity(irn); i < n; ++i) - edges_notify_edge(irn, i, get_irn_n(irn, i), NULL, irg); + foreach_tgt(irn, i, n, w->kind) + edges_notify_edge_kind(irn, i, get_n(irn, i, w->kind), NULL, w->kind, w->irg); } /** @@ -313,10 +312,9 @@ static void build_edges_walker(ir_node *irn, void *data) { * of all nodes to 0. */ static void init_lh_walker(ir_node *irn, void *data) { - INIT_LIST_HEAD(_get_irn_outs_head(irn)); - if (is_Block(irn)) - INIT_LIST_HEAD(_get_block_succ_head(irn)); - _get_irn_edge_info(irn)->out_count = 0; + struct build_walker *w = data; + INIT_LIST_HEAD(_get_irn_outs_head(irn, w->kind)); + _get_irn_edge_info(irn, w->kind)->out_count = 0; } /** @@ -348,24 +346,28 @@ static void visitor(ir_node *irn, void *data) { * Solves the revival problem, but may increase the memory consumption, as * nodes cannot be revivaled at all. * - Manually iterate over the identities root set. This did not consume more memory - * but increase the computation time because the |identies| >= |V| + * but increase the computation time because the |identities| >= |V| * * Currently, we use the last option. */ -void edges_activate(ir_graph *irg) +void edges_activate_kind(ir_graph *irg, ir_edge_kind_t kind) { - irg_edge_info_t *info = _get_irg_edge_info(irg); + struct build_walker w; + irg_edge_info_t *info = _get_irg_edge_info(irg, kind); + + w.irg = irg; + w.kind = kind; info->activated = 1; - edges_init_graph(irg); - irg_walk_graph(irg, init_lh_walker, build_edges_walker, irg); - irg_walk_anchors(irg, init_lh_walker, NULL, irg); - visit_all_identities(irg, visitor, irg); + edges_init_graph_kind(irg, kind); + irg_walk_graph(irg, init_lh_walker, build_edges_walker, &w); + irg_walk_anchors(irg, init_lh_walker, NULL, &w); + visit_all_identities(irg, visitor, &w); } -void edges_deactivate(ir_graph *irg) +void edges_deactivate_kind(ir_graph *irg, ir_edge_kind_t kind) { - irg_edge_info_t *info = _get_irg_edge_info(irg); + irg_edge_info_t *info = _get_irg_edge_info(irg, kind); info->activated = 0; if (info->edges) { @@ -374,9 +376,9 @@ void edges_deactivate(ir_graph *irg) } } -int (edges_activated)(const ir_graph *irg) +int (edges_activated_kind)(const ir_graph *irg, ir_edge_kind_t kind) { - return _edges_activated(irg); + return _edges_activated_kind(irg, kind); } @@ -387,70 +389,70 @@ int (edges_activated)(const ir_graph *irg) * sent to. * @param irg The graph. */ -void edges_reroute(ir_node *from, ir_node *to, ir_graph *irg) +void edges_reroute_kind(ir_node *from, ir_node *to, ir_edge_kind_t kind, ir_graph *irg) { - if(edges_activated(irg)) { - struct list_head *head = _get_irn_outs_head(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); - DBG((dbg, LEVEL_5, - "reroute from %+F to %+F\n", from, to)); + DBG((dbg, LEVEL_5, "reroute from %+F to %+F\n", from, to)); while(head != head->next) { ir_edge_t *edge = list_entry(head->next, ir_edge_t, list); - // DBG((dbg, LEVEL_5, "\t%n %d\n", edge->src, edge->pos)); assert(edge->pos >= -1); - set_irn_n(edge->src, edge->pos, to); + set_edge(edge->src, edge->pos, to); } } } static void verify_set_presence(ir_node *irn, void *data) { - ir_graph *irg = data; - set *edges = _get_irg_edge_info(irg)->edges; - int not_a_block = !is_Block(irn); + struct build_walker *w = data; + set *edges = _get_irg_edge_info(w->irg, w->kind)->edges; + int not_a_block = !is_Block(irn); int i, n; - for(i = 0, n = get_irn_arity(irn) + not_a_block; i < n; ++i) { - ir_block_edge_t space; - ir_edge_t *templ = (ir_edge_t *) &space; - ir_edge_t *e; - size_t size = not_a_block ? sizeof(ir_edge_t) : sizeof(ir_block_edge_t); + foreach_tgt(irn, i, n, w->kind) { + ir_edge_t templ, *e; - templ->src = irn; - templ->pos = i - not_a_block; + templ.src = irn; + templ.pos = i; - e = set_find(edges, templ, size, edge_hash(templ)); + e = set_find(edges, &templ, sizeof(templ), edge_hash(&templ)); if(e != NULL) e->present = 1; else - DBG((dbg, LEVEL_DEFAULT, "edge %+F,%d is missing\n", irn, templ->pos)); + DBG((dbg, LEVEL_DEFAULT, "edge %+F,%d (kind: \"%s\") is missing\n", irn, i, get_kind_str(w->kind))); } } static void verify_list_presence(ir_node *irn, void *data) { + struct build_walker *w = data; const ir_edge_t *e; - foreach_out_edge(irn, e) { - ir_node *tgt = get_irn_n(e->src, e->pos); + foreach_out_edge_kind(irn, e, w->kind) { + ir_node *tgt = get_n(e->src, e->pos, w->kind); if(irn != tgt) - DBG((dbg, LEVEL_DEFAULT, "edge %+F,%d is no out edge of %+F but of %+F\n", - e->src, e->pos, irn, tgt)); + DBG((dbg, LEVEL_DEFAULT, "edge %+F,%d (kind \"%s\") is no out edge of %+F but of %+F\n", e->src, e->pos, get_kind_str(w->kind), irn, tgt)); } - } -void edges_verify(ir_graph *irg) +void edges_verify_kind(ir_graph *irg, ir_edge_kind_t kind) { - set *edges = _get_irg_edge_info(irg)->edges; + struct build_walker w; + set *edges = _get_irg_edge_info(irg, kind)->edges; ir_edge_t *e; + w.irg = irg; + w.kind = kind; + /* Clear the present bit in all edges available. */ for(e = set_first(edges); e; e = set_next(edges)) e->present = 0; - irg_walk_graph(irg, verify_set_presence, verify_list_presence, irg); + irg_walk_graph(irg, verify_set_presence, verify_list_presence, &w); /* * Dump all edges which are not invalid and not present. @@ -469,10 +471,38 @@ void init_edges(void) /* firm_dbg_set_mask(dbg, -1); */ } +void edges_activate(ir_graph *irg) +{ + edges_activate_kind(irg, EDGE_KIND_NORMAL); + edges_activate_kind(irg, EDGE_KIND_BLOCK); +} + +void edges_deactivate(ir_graph *irg) +{ + edges_deactivate_kind(irg, EDGE_KIND_NORMAL); + edges_deactivate_kind(irg, EDGE_KIND_BLOCK); +} + +int edges_assure(ir_graph *irg) +{ + int activated = edges_activated(irg); + + if(!activated) + edges_activate(irg); + + return activated; +} + +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); +} + -const ir_edge_t *(get_irn_out_edge_first)(const ir_node *irn) +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(irn); + 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) @@ -490,7 +520,20 @@ int (get_edge_src_pos)(const ir_edge_t *edge) return _get_edge_src_pos(edge); } -int (get_irn_n_edges)(const ir_node *irn) +int (get_irn_n_edges_kind)(const ir_node *irn, ir_edge_kind_t kind) { - return _get_irn_n_edges(irn); + 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; + + 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); + } + } } diff --git a/ir/ir/iredges.h b/ir/ir/iredges.h index 57b52e597..38fd33995 100644 --- a/ir/ir/iredges.h +++ b/ir/ir/iredges.h @@ -19,15 +19,18 @@ #define _FIRM_IR_EDGES_H #include "firm_types.h" +#include "iredgekinds.h" #ifndef _IR_EDGE_TYPEDEF_ #define _IR_EDGE_TYPEDEF_ typedef struct _ir_edge_t ir_edge_t; #endif -#ifndef _IR_BLOCK_EDGE_TYPEDEF_ -#define _IR_BLOCK_EDGE_TYPEDEF_ -typedef struct _ir_block_edge_t ir_block_edge_t; +#if 0 +#ifndef _IR_EDGE_KIND_TYPEDEF_ +#define _IR_EDGE_KIND_TYPEDEF_ +typedef enum _ir_edge_kind_t ir_edge_kind_t; +#endif /* _IR_EDGE_KIND_TYPEDEF_ */ #endif /** @@ -35,9 +38,10 @@ typedef struct _ir_block_edge_t ir_block_edge_t; * @note There is no order on out edges. First in this context only * means, that you get some starting point into the list of edges. * @param irn The node. + * @param kind The kind of the edge. * @return The first out edge that points to this node. */ -const ir_edge_t *get_irn_out_edge_first(const ir_node *irn); +const ir_edge_t *get_irn_out_edge_first_kind(const ir_node *irn, ir_edge_kind_t kind); /** * Get the next edge in the out list of some node. @@ -45,44 +49,44 @@ const ir_edge_t *get_irn_out_edge_first(const ir_node *irn); * @param last The last out edge you have seen. * @return The next out edge in @p irn 's out list after @p last. */ -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); /** * A convenience iteration macro over all out edges of a node. * @param irn The node. + * @param kind The edge's kind. * @param edge An ir_edge_t pointer which shall be set to the current * edge. */ -#define foreach_out_edge(irn,edge) \ - for(edge = get_irn_out_edge_first(irn); edge; edge = get_irn_out_edge_next(irn, edge)) +#define foreach_out_edge_kind(irn, edge, kind) \ + for(edge = get_irn_out_edge_first_kind(irn, kind); edge; edge = get_irn_out_edge_next(irn, edge)) /** * A convenience iteration macro over all out edges of a node, which is safe * against alteration of the current edge. * * @param irn The node. - * @param edge An ir_edge_t pointer which shall be set to the current - * edge. + * @param edge An ir_edge_t pointer which shall be set to the current edge. * @param ne The next edge, enables alteration safe edge processing. */ -#define foreach_out_edge_safe(irn,edge,ne) \ - for( \ - (edge) = (get_irn_out_edge_first(irn)), \ - (ne) = ((edge) ? (get_irn_out_edge_next(irn, edge)) : NULL); \ - edge; \ - (edge) = (ne), (ne) = ((edge) ? (get_irn_out_edge_next(irn, edge)) : NULL) \ - ) +#define foreach_out_edge_kind_safe(irn, edge, ne, kind) \ + for((edge) = (get_irn_out_edge_first_kind(irn, kind)), (ne) = ((edge) ? (get_irn_out_edge_next(irn, edge)) : NULL); \ + edge; (edge) = (ne), (ne) = ((edge) ? (get_irn_out_edge_next(irn, edge)) : NULL)) +/** + * Convenience macro for normal out edges. + */ +#define foreach_out_edge(irn, edge) foreach_out_edge_kind(irn, edge, EDGE_KIND_NORMAL) /** - * A convenience iteration macro for all control flow edges - * leaving a block, and thus are cf successor edges. - * @param bl The block. - * @param edge An @c ir_edge_t pointer which is set to the current edge. + * Convenience macro for normal out edges. */ -#define foreach_block_succ(bl,edge) \ - for(edge = get_block_succ_first(bl); edge; edge = get_block_succ_next(bl, edge)) +#define foreach_out_edge_safe(irn, edge, tmp) foreach_out_edge_kind_safe(irn, edge, tmp, EDGE_KIND_NORMAL) + +/** + * A convenience iteration macro for all control flow edges. + */ +#define foreach_block_succ(bl, edge) foreach_out_edge_kind(bl, edge, EDGE_KIND_BLOCK) /* * Get the source node of an edge. @@ -113,25 +117,85 @@ extern int get_edge_src_pos(const ir_edge_t *edge); * @return The corresponding edge object or NULL, * if no such edge exists. */ -const ir_edge_t *get_irn_edge(ir_graph *irg, const ir_node *irn, int pos); +const ir_edge_t *get_irn_edge_kind(ir_graph *irg, const ir_node *irn, int pos, ir_edge_kind_t kind); + +/** + * Get the number of registered out edges for a specific kind. + * @param irn The node. + * @param kind The kind. + */ +extern int get_irn_n_edges_kind(const ir_node *irn, ir_edge_kind_t kind); + /** * Check, if the out edges are activated. * @param irg The graph. + * @param kind The edge kind. * @return 1, if the edges are present for the given irg, 0 if not. */ -extern int edges_activated(const ir_graph *irg); +extern int edges_activated_kind(const ir_graph *irg, ir_edge_kind_t kind); /** * Activate the edges for an irg. * @param irg The graph to activate the edges for. - **/ -extern void edges_activate(ir_graph *irg); + * @param kind The edge kind. + */ +extern void edges_activate_kind(ir_graph *irg, ir_edge_kind_t kind); /** * Deactivate the edges for an irg. * @param irg The graph. + * @param kind The edge kind. */ +extern void edges_deactivate_kind(ir_graph *irg, ir_edge_kind_t kind); + +/************************************************************************/ +/* Begin Old Interface */ +/************************************************************************/ + +#define edges_reroute(old, nw, irg) edges_reroute_kind(old, nw, EDGE_KIND_NORMAL, irg) +#define edges_activated(irg) (edges_activated_kind(irg, EDGE_KIND_NORMAL) && edges_activated_kind(irg, EDGE_KIND_BLOCK)) + +#ifndef get_irn_n_edges +#define get_irn_n_edges(irn) get_irn_n_edges_kind(irn, EDGE_KIND_NORMAL) +#endif + +#ifndef get_irn_out_edge_first +#define get_irn_out_edge_first(irn) get_irn_out_edge_first_kind(irn, EDGE_KIND_NORMAL) +#endif + +#ifndef get_block_succ_first +#define get_block_succ_first(irn) get_irn_out_edge_first_kind(irn, EDGE_KIND_BLOCK) +#endif + +#ifndef get_block_succ_next +#define get_block_succ_next(irn, last) get_irn_out_edge_next(irn, last) +#endif + +/** +* Activate all the edges for an irg. +* @param irg The graph to activate the edges for. +*/ +extern void edges_activate(ir_graph *irg); + +/** +* Deactivate all the edges for an irg. +* @param irg The graph. +*/ extern void edges_deactivate(ir_graph *irg); +extern int edges_assure(ir_graph *irg); + +extern void edges_node_deleted(ir_node *irn, ir_graph *irg); + +/** +* Notify normal and block edges. +*/ +extern void edges_notify_edge(ir_node *src, int pos, ir_node *tgt, ir_node *old_tgt, ir_graph *irg); + +/************************************************************************/ +/* End Old Interface */ +/************************************************************************/ + + #endif /* _FIRM_IR_EDGES_H */ diff --git a/ir/ir/iredges_t.h b/ir/ir/iredges_t.h index 8a30b124c..40ab9ddf1 100644 --- a/ir/ir/iredges_t.h +++ b/ir/ir/iredges_t.h @@ -27,6 +27,7 @@ #include "irnode_t.h" #include "irgraph_t.h" +#include "iredgekinds.h" #include "iredges.h" #define DBG_EDGES "firm.ir.edges" @@ -39,136 +40,62 @@ struct _ir_edge_t { int pos; /**< The position of the edge at @p src. */ unsigned invalid : 1; /**< edges that are removed are marked invalid. */ unsigned present : 1; /**< Used by the verifier. Don't rely on its content. */ + unsigned kind : 4; /**< The kind of the edge. */ struct list_head list; /**< The list head to queue all out edges at a node. */ #ifdef DEBUG_libfirm long src_nr; /**< The node number of the source node. */ #endif }; -/** - * A block edge inherits from a normal edge. - * They represent edges leading from a block to a control flow node - * and are used to quickly find all control flow successors of - * a block. - */ -struct _ir_block_edge_t { - struct _ir_edge_t edge; /**< The inherited data. */ - struct list_head succ_list; /**< List element listing all - control flow edges to the - successors of a block. */ -}; /** Accessor for private irn info. */ -#define _get_irn_edge_info(irn) (&(irn)->edge_info) +#define _get_irn_edge_info(irn, kind) (&(((irn)->edge_info)[kind])) /** Accessor for private irg info. */ -#define _get_irg_edge_info(irg) (&(irg)->edge_info) +#define _get_irg_edge_info(irg, kind) (&(((irg)->edge_info)[kind])) /** - * Convenience macro to get the outs_head from a irn_edge_info_t - * struct. - */ -#define _get_irn_outs_head(irn) (&_get_irn_edge_info(irn)->outs_head) - -/** - * Convenience macro to get the succ_head from a block_attr - * struct. - */ -#define _get_block_succ_head(bl) (&((bl)->attr.block.succ_head)) +* Convenience macro to get the outs_head from a irn_edge_info_t +* struct. +*/ +#define _get_irn_outs_head(irn, kind) (&_get_irn_edge_info(irn, kind)->outs_head) /** - * Get the first edge pointing to some node. - * @note There is no order on out edges. First in this context only - * means, that you get some starting point into the list of edges. - * @param irn The node. - * @return The first out edge that points to this node. - */ -static INLINE const ir_edge_t *_get_irn_out_edge_first(const ir_node *irn) +* Get the first edge pointing to some node. +* @note There is no order on out edges. First in this context only +* means, that you get some starting point into the list of edges. +* @param irn The node. +* @return The first out edge that points to this node. +*/ +static INLINE const ir_edge_t *_get_irn_out_edge_first_kind(const ir_node *irn, ir_edge_kind_t kind) { - const struct list_head *head = _get_irn_outs_head(irn); - return list_empty(head) ? NULL : list_entry(head->next, ir_edge_t, list); + const struct list_head *head = _get_irn_outs_head(irn, kind); + return list_empty(head) ? NULL : list_entry(head->next, ir_edge_t, list); } /** - * Get the next edge in the out list of some node. - * @param irn The node. - * @param last The last out edge you have seen. - * @return The next out edge in @p irn 's out list after @p last. - */ +* Get the next edge in the out list of some node. +* @param irn The node. +* @param last The last out edge you have seen. +* @return The next out edge in @p irn 's out list after @p last. +*/ static INLINE const ir_edge_t *_get_irn_out_edge_next(const ir_node *irn, const ir_edge_t *last) { - struct list_head *next = last->list.next; - return next == _get_irn_outs_head(irn) ? NULL : list_entry(next, ir_edge_t, list); -} - -/** - * Get the first successor edge of a block. - * A successor edge is an edge originated from another block, pointing - * to a mode_X node in the given block and is thus a control flow - * successor edge. - * @param irn The block. - * @return The first successor edge of the block. - */ -static INLINE const ir_edge_t *_get_block_succ_first(const ir_node *irn) -{ - const struct list_head *head; - - assert(is_Block(irn) && "Node must be a block here"); - head = _get_block_succ_head(irn); - return (ir_edge_t *) (list_empty(head) ? NULL : - list_entry(head->next, ir_block_edge_t, succ_list)); -} - -/** - * Get the next block successor edge. - * @see See _get_block_succ_first() for details. - * @param irn The block. - * @param last The last edge. - * @return The next edge, or NULL if there is no further. - */ -static INLINE const ir_edge_t *_get_block_succ_next(const ir_node *irn, const ir_edge_t *last) -{ - const ir_block_edge_t *block_edge; - struct list_head *next; - - assert(is_Block(irn) && "Node must be a block here"); - block_edge = (const ir_block_edge_t *) last; - next = block_edge->succ_list.next; - return (ir_edge_t *) (next == _get_block_succ_head(irn) ? NULL : - list_entry(next, ir_block_edge_t, succ_list)); -} - -/** - * Get the source node of an edge. - * @param edge The edge. - * @return The source node of that edge. - */ -static INLINE ir_node *_get_edge_src_irn(const ir_edge_t *edge) -{ - return edge ? edge->src : NULL; + struct list_head *next = last->list.next; + return next == _get_irn_outs_head(irn, last->kind) ? NULL : list_entry(next, ir_edge_t, list); } /** - * Get the position of an edge. - * @param edge The edge. - * @return The position in the in array of that edges source. - */ -static INLINE int _get_edge_src_pos(const ir_edge_t *edge) +* Get the number of edges pointing to a node. +* @param irn The node. +* @return The number of edges pointing to this node. +*/ +static INLINE int _get_irn_n_edges_kind(const ir_node *irn, int kind) { - return edge ? edge->pos : -1; -} - -/** - * Get the number of edges pointing to a node. - * @param irn The node. - * @return The number of edges pointing to this node. - */ -static INLINE int _get_irn_n_edges(const ir_node *irn) -{ -/* Perhaps out_count was buggy. This code does it more safely. */ + /* Perhaps out_count was buggy. This code does it more safely. */ #if 1 int res = 0; - const struct list_head *pos, *head = _get_irn_outs_head(irn); + const struct list_head *pos, *head = _get_irn_outs_head(irn, kind); list_for_each(pos, head) res++; return res; @@ -177,78 +104,100 @@ static INLINE int _get_irn_n_edges(const ir_node *irn) #endif } -static INLINE int _edges_activated(const ir_graph *irg) +static INLINE int _edges_activated_kind(const ir_graph *irg, ir_edge_kind_t kind) { - return _get_irg_edge_info(irg)->activated; + return _get_irg_edge_info(irg, kind)->activated; } /** - * Assure, that the edges information is present for a certain graph. - * @param irg The graph. - */ -static INLINE void _edges_assure(ir_graph *irg) +* Assure, that the edges information is present for a certain graph. +* @param irg The graph. +*/ +static INLINE void _edges_assure_kind(ir_graph *irg, int kind) { - if(!_edges_activated(irg)) - edges_activate(irg); + if(!_edges_activated_kind(irg, kind)) + edges_activate_kind(irg, kind); } -void edges_reroute(ir_node *old, ir_node *nw, ir_graph *irg); +void edges_reroute_kind(ir_node *old, ir_node *nw, ir_edge_kind_t kind, ir_graph *irg); -void edges_init_graph(ir_graph *irg); +void edges_init_graph_kind(ir_graph *irg, ir_edge_kind_t kind); /** - * Notify of a edge change. - * The edge from (src, pos) -> old_tgt is redirected to tgt - */ -void edges_notify_edge(ir_node *src, int pos, ir_node *tgt, ir_node *old_tgt, ir_graph *irg); +* Notify of a edge change. +* 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, ir_graph *irg); /** - * A node is deleted. - */ +* A node is deleted. +*/ void edges_node_deleted(ir_node *old, ir_graph *irg); -void edges_invalidate(ir_node *irn, ir_graph *irg); +void edges_invalidate_kind(ir_node *irn, ir_edge_kind_t kind, ir_graph *irg); /** - * Register additional memory in an edge. - * This must be called before Firm is initialized. - * @param n Number of bytes you need. - * @return A number you have to keep and to pass - * edges_get_private_data() - * to get a pointer to your data. - */ +* Register additional memory in an edge. +* This must be called before Firm is initialized. +* @param n Number of bytes you need. +* @return A number you have to keep and to pass +* edges_get_private_data() +* to get a pointer to your data. +*/ int edges_register_private_data(size_t n); /** - * Get a pointer to the private data you registered. - * @param edge The edge. - * @param ofs The number, you obtained with - * edges_register_private_data(). - * @return A pointer to the private data. - */ +* Get a pointer to the private data you registered. +* @param edge The edge. +* @param ofs The number, you obtained with +* edges_register_private_data(). +* @return A pointer to the private data. +*/ static INLINE void *_get_edge_private_data(const ir_edge_t *edge, int ofs) { - /* Get the size of the edge. */ - size_t size = - is_Block(edge->src) ? sizeof(ir_block_edge_t) : sizeof(ir_edge_t); + return (void *) ((char *) edge + sizeof(edge[0]) + ofs); +} - return (void *) ((char *) edge + size + ofs); +static INLINE ir_node *_get_edge_src_irn(const ir_edge_t *edge) +{ + return edge->src; +} + +static INLINE int _get_edge_src_pos(const ir_edge_t *edge) +{ + return edge->pos; } /** - * Initialize the out edges. - * This must be called before firm is initialized. - */ +* Initialize the out edges. +* This must be called before firm is initialized. +*/ extern void init_edges(void); -#define get_irn_out_edge_first(irn) _get_irn_out_edge_first(irn) -#define get_irn_out_edge_next(irn,last) _get_irn_out_edge_next(irn, last) -#define get_block_succ_first(irn) _get_block_succ_first(irn) -#define get_block_succ_next(irn,last) _get_block_succ_next(irn, last) -#define get_edge_src_irn(edge) _get_edge_src_irn(edge) -#define get_edge_src_pos(edge) _get_edge_src_pos(edge) -#define get_edge_private_data(edge,ofs) _get_edge_private_data(edge,ofs) -#define edges_activated(irg) _edges_activated(irg) -#define edges_assure(irg) _edges_assure(irg) +void edges_invalidate_all(ir_node *irn, ir_graph *irg); + +#define get_irn_n_edges_kind(irn, kind) _get_irn_n_edges_kind(irn, kind) +#define get_edge_src_irn(edge) _get_edge_src_irn(edge) +#define get_edge_src_pos(edge) _get_edge_src_pos(edge) +#define get_edge_private_data(edge, ofs) _get_edge_private_data(edge,ofs) +#define get_irn_out_edge_next(irn, last) _get_irn_out_edge_next(irn, last) + +#ifndef get_irn_n_edges +#define get_irn_n_edges(irn) _get_irn_n_edges_kind(irn, EDGE_KIND_NORMAL) +#endif + +#ifndef get_irn_out_edge_first +#define get_irn_out_edge_first(irn) _get_irn_out_edge_first_kind(irn, EDGE_KIND_NORMAL) +#endif + +#ifndef get_block_succ_first +#define get_block_succ_first(irn) _get_irn_out_edge_first_kind(irn, EDGE_KIND_BLOCK) +#endif + +#ifndef get_block_succ_next +#define get_block_succ_next(irn, last) _get_irn_out_edge_next(irn, last) +#endif + + #endif /* _FIRM_EDGES_T_H */ diff --git a/ir/ir/irgmod.c b/ir/ir/irgmod.c index 47abfa32c..2c57fe18b 100644 --- a/ir/ir/irgmod.c +++ b/ir/ir/irgmod.c @@ -40,7 +40,7 @@ turn_into_tuple (ir_node *node, int arity) } else { /* Allocate new array, don't free old in_array, it's on the obstack. */ ir_node *block = get_nodes_block(node); - edges_invalidate(node, current_ir_graph); + edges_node_deleted(node, current_ir_graph); node->in = NEW_ARR_D(ir_node *, current_ir_graph->obst, arity+1); /* clear the new in array, else edge_notify tries to delete garbage */ memset(node->in, 0, (arity+1) * sizeof(node->in[0])); diff --git a/ir/ir/irgraph.c b/ir/ir/irgraph.c index 0b033a1c5..325837671 100644 --- a/ir/ir/irgraph.c +++ b/ir/ir/irgraph.c @@ -139,7 +139,8 @@ new_r_ir_graph (entity *ent, int n_loc) res = alloc_graph(); res->kind = k_ir_graph; - edges_init_graph(res); + //edges_init_graph_kind(res, EDGE_KIND_NORMAL); + //edges_init_graph_kind(res, EDGE_KIND_BLOCK); /* initialize the idx->node map. */ res->idx_irn_map = NEW_ARR_F(ir_node *, INITIAL_IDX_IRN_MAP_SIZE); diff --git a/ir/ir/irgraph_t.h b/ir/ir/irgraph_t.h index 454ed8b10..9190df097 100644 --- a/ir/ir/irgraph_t.h +++ b/ir/ir/irgraph_t.h @@ -29,6 +29,7 @@ #include "entity_t.h" #include "typegmod.h" #include "tr_inheritance.h" +#include "iredgekinds.h" #include "irloop.h" #include "execution_frequency.h" @@ -48,6 +49,8 @@ typedef struct _irg_edge_info_t { unsigned activated : 1; /**< set if edges are activated for the graph. */ } irg_edge_info_t; +typedef irg_edge_info_t irg_edges_info_t[EDGE_KIND_LAST]; + /** * Index constants for nodes that can be accessed through the graph itself. */ @@ -142,7 +145,7 @@ struct ir_graph { unsigned long block_visited; /**< same as visited, for a complete block */ unsigned estimated_node_count; /**< estimated number of nodes in this graph, updated after every walk */ - irg_edge_info_t edge_info; /**< edge info for automatic outs */ + irg_edges_info_t edge_info; /**< edge info for automatic outs */ ir_node **idx_irn_map; /**< Array mapping node indexes to nodes. */ #ifdef DEBUG_libfirm diff --git a/ir/ir/irnode.c b/ir/ir/irnode.c index b6ca127e5..414b8a260 100644 --- a/ir/ir/irnode.c +++ b/ir/ir/irnode.c @@ -27,6 +27,7 @@ #include "irdump.h" #include "irop_t.h" #include "irprog_t.h" +#include "iredgekinds.h" #include "iredges_t.h" #include "irhooks.h" @@ -144,6 +145,8 @@ new_ir_node (dbg_info *db, ir_graph *irg, ir_node *block, ir_op *op, ir_mode *mo res->visited = 0; res->node_idx = irg_register_node_idx(irg, res); res->link = NULL; + res->deps = NULL; + if (arity < 0) { res->in = NEW_ARR_F (ir_node *, 1); /* 1: space for block */ } else { @@ -159,12 +162,10 @@ new_ir_node (dbg_info *db, ir_graph *irg, ir_node *block, ir_op *op, ir_mode *mo res->node_nr = get_irp_new_node_nr(); #endif - INIT_LIST_HEAD(&res->edge_info.outs_head); - is_bl = is_Block(res); - if (is_bl) - INIT_LIST_HEAD(&res->attr.block.succ_head); - + for(i = 0; i < EDGE_KIND_LAST; ++i) + INIT_LIST_HEAD(&res->edge_info[i].outs_head); + is_bl = is_Block(res); for (i = is_bl; i <= arity; ++i) edges_notify_edge(res, i - 1, res->in[i], NULL, irg); @@ -309,6 +310,69 @@ set_irn_n (ir_node *node, int n, ir_node *in) { node->in[n + 1] = in; } +int +(get_irn_deps)(const ir_node *node) +{ + return _get_irn_deps(node); +} + +ir_node * +(get_irn_dep)(const ir_node *node, int pos) +{ + return _get_irn_dep(node, pos); +} + +void +(set_irn_dep)(ir_node *node, int pos, ir_node *dep) +{ + _set_irn_dep(node, pos, dep); +} + +int add_irn_dep(ir_node *node, ir_node *dep) +{ + int res = 0; + + if (node->deps == NULL) { + node->deps = NEW_ARR_F(ir_node *, 1); + node->deps[0] = dep; + } + else { + int i, n; + int first_zero = -1; + + for(i = 0, n = ARR_LEN(node->deps); i < n; ++i) { + if(node->deps[i] == NULL) + first_zero = i; + + if(node->deps[i] == dep) + return i; + } + + if(first_zero >= 0) { + node->deps[first_zero] = dep; + res = first_zero; + } + + else { + ARR_APP1(ir_node *, node->deps, dep); + res = n; + } + } + + edges_notify_edge_kind(node, res, dep, NULL, EDGE_KIND_DEP, get_irn_irg(node)); + + return res; +} + +void add_irn_deps(ir_node *tgt, ir_node *src) +{ + int i, n; + + for(i = 0, n = get_irn_deps(src); i < n; ++i) + add_irn_dep(tgt, get_irn_dep(src, i)); +} + + ir_mode * (get_irn_mode)(const ir_node *node) { return _get_irn_mode(node); diff --git a/ir/ir/irnode.h b/ir/ir/irnode.h index cea3c61d1..1d531babc 100644 --- a/ir/ir/irnode.h +++ b/ir/ir/irnode.h @@ -109,6 +109,46 @@ void set_irn_in (ir_node *node, int arity, ir_node *in[]); */ ir_node *get_irn_n (const ir_node *node, int n); +/** +* Add a artificial dependency to the node. +* The dependency is only inserted if it is not there already. +* @param node The node. +* @param dep The dependency target. +* @return The index in the array (get_irn_dep() with that index returns @p dep). +*/ +int add_irn_dep(ir_node *node, ir_node *dep); + +/** + * Copy all dependencies from a node to another. + * @param tgt The node which sould be enriched. + * @param src The node whose dependencies shall be copied. + */ +void add_irn_deps(ir_node *tgt, ir_node *src); + +/** +* Get the length of the dependency array. +* @param node The node. +* @return The length of the dependency array or 0 if it has not yet been allocated. +*/ +int get_irn_deps(const ir_node *node); + +/** +* Get an entry of the dependency array. +* @param node The node. +* @param pos The position. +* @return The node at that position. +*/ +ir_node *get_irn_dep(const ir_node *node, int pos); + +/** +* Set an entry of the dependency array. +* @param node The node. +* @param pos The position. +* @param dep The dependency target. +*/ +void set_irn_dep(ir_node *node, int pos, ir_node *dep); + + /** * Get the n-th predecessor of a node in intraprocedural view. * Can be used always if it's know that node is not a split one. diff --git a/ir/ir/irnode_t.h b/ir/ir/irnode_t.h index a492622d4..d802c7f91 100644 --- a/ir/ir/irnode_t.h +++ b/ir/ir/irnode_t.h @@ -29,6 +29,7 @@ #include "irdom_t.h" /* For size of struct dom_info. */ #include "dbginfo.h" #include "irloop.h" +#include "iredgekinds.h" #include "array.h" #include "set.h" @@ -185,15 +186,6 @@ typedef struct { char strict; /**< If set, this is a strict Conv that cannot be removed. */ } conv_attr; -/** - * Edge info to put into an irn. - */ -typedef struct _irn_edge_info_t { - struct list_head outs_head; /**< The list of all outs. */ - int out_count; /**< Number of outs in the list. */ -} irn_edge_info_t; - - /** Some IR-nodes just have one attribute, these are stored here, some have more. Their name is 'irnodename_attr' */ typedef union { @@ -229,6 +221,15 @@ typedef union { conv_attr conv; /**< For Conv operation */ } attr; +/** +* Edge info to put into an irn. +*/ +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. */ +} irn_edge_info_t; + +typedef irn_edge_info_t irn_edges_info_t[EDGE_KIND_LAST]; /** common structure of an irnode if the node has some attributes, they are stored in attr */ @@ -259,7 +260,8 @@ struct ir_node { struct abstval *av; /**< the abstract value of this node */ struct section *sec; #endif - irn_edge_info_t edge_info; /**< everlasting out edges */ + struct ir_node **deps; /**< Additional dependencies induced by state. */ + irn_edges_info_t edge_info; /**< everlasting out edges */ /* ------- Opcode depending fields -------- */ attr attr; /**< attribute of this node. Depends on opcode. Must be last field of struct ir_node. */ @@ -455,6 +457,44 @@ _get_irn_inter_n(const ir_node *node, int n) { */ extern ir_node *(*_get_irn_n)(const ir_node *node, int n); +static INLINE int _get_irn_deps(const ir_node *node) +{ + return node->deps ? ARR_LEN(node->deps) : 0; +} + +static INLINE ir_node *_get_irn_dep(const ir_node *node, int pos) +{ + assert(node->deps && "dependency array node yet allocated. use add_irn_dep()"); + assert(pos >= 0 && pos < ARR_LEN(node->deps) && "dependency index out of range"); + return node->deps[pos]; +} + +static INLINE void +_set_irn_dep(ir_node *node, int pos, ir_node *dep) +{ + ir_node *old; + + assert(node->deps && "dependency array node yet allocated. use add_irn_dep()"); + assert(pos >= 0 && pos < ARR_LEN(node->deps) && "dependency index out of range"); + old = node->deps[pos]; + node->deps[pos] = dep; + edges_notify_edge_kind(node, pos, dep, old, EDGE_KIND_DEP, get_irn_irg(node)); +} + + +static INLINE int +_get_irn_ins_or_deps(const ir_node *irn) +{ + return _get_irn_deps(irn) + _get_irn_arity(irn); +} + +static INLINE ir_node * +_get_irn_in_or_dep(const ir_node *irn, int pos) +{ + int n_in = get_irn_arity(irn); + return pos < n_in ? get_irn_n(irn, pos) : get_irn_dep(irn, pos - n_in); +} + /** * Gets the mode of a node. * Intern version for libFirm. @@ -906,4 +946,11 @@ static INLINE unsigned _get_irn_idx(const ir_node *node) { #define get_Psi_n_conds(node) _get_Psi_n_conds(node) #define get_irn_idx(node) _get_irn_idx(node) +#define get_irn_deps(node) _get_irn_deps(node) +#define set_irn_dep(node, pos, dep) _set_irn_dep(node, pos, dep) +#define get_irn_dep(node, pos) _get_irn_dep(node, pos) + +#define get_irn_ins_or_deps(node) _get_irn_ins_or_deps(node) +#define get_irn_in_or_dep(node, pos) _get_irn_in_or_dep(node, pos) + #endif /* _IRNODE_T_H_ */