X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=ir%2Fir%2Firedges.c;h=2619a14a8d01905619ef1b394aecd02eb41cb553;hb=2adf5813e8575dd3c7a06433cdcaa3b045202d7f;hp=51a39322b46b5ec489d43d7095967c237ee28817;hpb=534e2c2936a1d091043b8b9f94ca0a2df5fe7145;p=libfirm diff --git a/ir/ir/iredges.c b/ir/ir/iredges.c index 51a39322b..2619a14a8 100644 --- a/ir/ir/iredges.c +++ b/ir/ir/iredges.c @@ -8,6 +8,13 @@ #include "config.h" #endif +#ifdef HAVE_ALLOCA_H +#include +#endif +#ifdef HAVE_MALLOC_H +#include +#endif + #include "irnode_t.h" #include "iredges_t.h" #include "irdump_t.h" @@ -20,6 +27,24 @@ static firm_dbg_module_t *dbg; #if FIRM_EDGES_INPLACE +/** + * This flag is set to 1, if the edges get initialized for an irg. + * Then register additional data is forbidden. + */ +static int edges_used = 0; + +static int edges_private_size = 0; + +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"); + + edges_private_size += n; + return res; +} + #define TIMES37(x) (((x) << 5) + ((x) << 2) + (x)) #define get_irn_out_list_head(irn) (&get_irn_out_info(irn)->outs) @@ -33,12 +58,7 @@ static int edge_cmp(const void *p1, const void *p2, size_t len) return !res; } -static INLINE unsigned edge_hash(const ir_edge_t *edge) -{ - unsigned result = HASH_PTR(edge->src); - result = TIMES37(result) + edge->pos; - return result; -} +#define edge_hash(edge) (TIMES37((edge)->pos) + HASH_PTR((edge)->src)) /** * Initialize the out information for a graph. @@ -50,6 +70,8 @@ void edges_init_graph(ir_graph *irg) irg_edge_info_t *info = _get_irg_edge_info(irg); int amount = 2048; + edges_used = 1; + if(info->edges) { amount = set_count(info->edges); del_set(info->edges); @@ -59,6 +81,34 @@ void edges_init_graph(ir_graph *irg) } } +#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. + * @param src The node at which the edge originates. + * @param pos The position of the 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 *src, int pos) +{ + if(edges_activated(irg)) { + irg_edge_info_t *info = _get_irg_edge_info(irg); + size_t size = EDGE_SIZE(src); + ir_edge_t *templ = alloca(size); + + memset(templ, 0, size); + templ->src = (ir_node *) src; + templ->pos = pos; + return set_find(info->edges, templ, size, edge_hash(templ)); + } + + return NULL; +} + void edges_notify_edge(ir_node *src, int pos, ir_node *tgt, ir_node *old_tgt, ir_graph *irg) { const char *msg = ""; @@ -66,30 +116,33 @@ void edges_notify_edge(ir_node *src, int pos, ir_node *tgt, ir_node *old_tgt, ir if(!edges_activated(irg)) 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); + int is_block_edge = is_Block(src); set *edges = _get_irg_edge_info(irg)->edges; - ir_block_edge_t space; - ir_edge_t *templ = (ir_edge_t *) &space; ir_edge_t *edge; - size_t size; - /* - * This is scray, 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). - */ - size = is_block_edge ? sizeof(ir_block_edge_t) : sizeof(ir_edge_t); + /* + * This is scray, 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); + memset(templ, 0, size); #ifdef DEBUG_libfirm templ->src_nr = get_irn_node_nr(src); #endif @@ -107,7 +160,7 @@ void edges_notify_edge(ir_node *src, int pos, ir_node *tgt, ir_node *old_tgt, ir /* mark the edge invalid if it was found */ if(edge) { - ir_block_edge_t *block_edge = (ir_block_edge_t *) edge; + ir_block_edge_t *block_edge = (ir_block_edge_t *) edge; msg = "deleting"; list_del(&edge->list); @@ -115,12 +168,12 @@ void edges_notify_edge(ir_node *src, int pos, ir_node *tgt, ir_node *old_tgt, ir 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); + /* + * 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); } /* If the edge was not found issue a warning on the debug stream */ @@ -138,19 +191,20 @@ void edges_notify_edge(ir_node *src, int pos, ir_node *tgt, ir_node *old_tgt, ir 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; + /* + * 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; + ir_block_edge_t *block_edge; +#if 0 if(!node_is_in_irgs_storage(irg, tgt)) return; - +#endif assert(head->next && head->prev && "target list head must have been initialized"); @@ -159,7 +213,7 @@ void edges_notify_edge(ir_node *src, int pos, ir_node *tgt, ir_node *old_tgt, ir * the instance in the set. */ edge = set_insert(edges, templ, size, edge_hash(templ)); - block_edge = (ir_block_edge_t *) edge; + block_edge = (ir_block_edge_t *) edge; #ifdef DEBUG_libfirm assert(!edge->invalid && "Invalid edge encountered"); @@ -170,9 +224,9 @@ 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); + /* 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); _get_irn_edge_info(old_tgt)->out_count -= 1; } @@ -182,12 +236,12 @@ void edges_notify_edge(ir_node *src, int pos, ir_node *tgt, ir_node *old_tgt, ir 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); + /* + * 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); } _get_irn_edge_info(tgt)->out_count += 1; @@ -234,13 +288,20 @@ static void build_edges_walker(ir_node *irn, void *data) edges_notify_edge(irn, i, get_irn_n(irn, i), NULL, irg); } +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)); +} + void edges_activate(ir_graph *irg) { irg_edge_info_t *info = _get_irg_edge_info(irg); info->activated = 1; edges_init_graph(irg); - irg_walk_graph(irg, NULL, build_edges_walker, irg); + irg_walk_graph(irg, init_lh_walker, build_edges_walker, irg); } void edges_deactivate(ir_graph *irg)