/* 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
#include "irnode_t.h"
#include "iropt_t.h"
+#include "iredgekinds.h"
#include "iredges_t.h"
#include "irgwalk.h"
#include "irdump_t.h"
#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;)
/**
* 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.
* @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;
/**
* 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));
/*
*/
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) {
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 */
* 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");
* 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");
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);
}
/**
* 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;
}
/**
* 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) {
}
}
-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);
}
* 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.
/* 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)
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);
+ }
+ }
}
#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
/**
* @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.
* @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.
* @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 */
#include "irnode_t.h"
#include "irgraph_t.h"
+#include "iredgekinds.h"
#include "iredges.h"
#define DBG_EDGES "firm.ir.edges"
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;
#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 */
} 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]));
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);
#include "entity_t.h"
#include "typegmod.h"
#include "tr_inheritance.h"
+#include "iredgekinds.h"
#include "irloop.h"
#include "execution_frequency.h"
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.
*/
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
#include "irdump.h"
#include "irop_t.h"
#include "irprog_t.h"
+#include "iredgekinds.h"
#include "iredges_t.h"
#include "irhooks.h"
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 {
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);
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);
*/
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.
#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"
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 {
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 */
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. */
*/
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.
#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_ */