X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=ir%2Fir%2Firedges.c;h=c42dda2022941072770b2e7b02edbfbf80b5abdd;hb=de8269f08de3f68e62dfc6fe7f0c29c976489fdd;hp=13c568d48e4a94041330efae53ef0e8f5453292e;hpb=f80038cac193258c1111b058a1987231c5781929;p=libfirm diff --git a/ir/ir/iredges.c b/ir/ir/iredges.c index 13c568d48..c42dda202 100644 --- a/ir/ir/iredges.c +++ b/ir/ir/iredges.c @@ -8,8 +8,16 @@ #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 "irgwalk.h" #include "irdump_t.h" #include "irprintf.h" #include "irhooks.h" @@ -20,6 +28,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 +59,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 +71,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 +82,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,7 +117,9 @@ 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. @@ -74,22 +127,23 @@ void edges_notify_edge(ir_node *src, int pos, ir_node *tgt, ir_node *old_tgt, ir if(tgt != old_tgt) { 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 +161,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 +169,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 +192,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 +214,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 +225,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 +237,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; @@ -236,9 +291,9 @@ static void build_edges_walker(ir_node *irn, void *data) 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)); + 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)