X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=ir%2Fana%2Firouts.c;h=dcff5fb65ec73b138873bb9564e66c67fbf781e7;hb=e97a86a5e90141c2cb4ccdc34195cab035627c3f;hp=3cc6f30e8d78acadc273a4cb59e808e7e56aa3dd;hpb=6f068af98daa4725d60e5d23a8f98ec2841cfa44;p=libfirm diff --git a/ir/ana/irouts.c b/ir/ana/irouts.c index 3cc6f30e8..dcff5fb65 100644 --- a/ir/ana/irouts.c +++ b/ir/ana/irouts.c @@ -1,20 +1,6 @@ /* - * Copyright (C) 1995-2011 University of Karlsruhe. All right reserved. - * * This file is part of libFirm. - * - * This file may be distributed and/or modified under the terms of the - * GNU General Public License version 2 as published by the Free Software - * Foundation and appearing in the file LICENSE.GPL included in the - * packaging of this file. - * - * Licensees holding valid libFirm Professional Edition licenses may use - * this file in accordance with the libFirm Commercial License. - * Agreement provided with the Software. - * - * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE - * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE. + * Copyright (C) 2012 University of Karlsruhe. */ /** @@ -22,7 +8,6 @@ * @brief Compute and access out edges (also called def-use edges). * @author Goetz Lindenmaier, Michael Beck * @date 1.2002 - * @version $Id$ */ #include "config.h" @@ -34,173 +19,122 @@ #include "irgraph_t.h" #include "irprog_t.h" #include "irgwalk.h" -#include "irtools.h" +#include "util.h" #include "irprintf.h" #include "error.h" +#include "ircons.h" -#ifdef DEBUG_libfirm -/* Note: ir_node.out_valid and ir_graph.n_outs are only present when DEBUG_libfirm is defined */ -/* Accesses to out_valid and n_outs are fenced out to avoid breakage - when compiling with neither DEBUG_libfirm or NDEBUG defined */ -#endif /* defined DEBUG_libfirm */ - -/*--------------------------------------------------------------------*/ -/** Accessing the out datastructures **/ -/*--------------------------------------------------------------------*/ - -#ifdef DEBUG_libfirm -/** Clear the outs of a node */ -static void reset_outs(ir_node *node, void *unused) +unsigned get_irn_n_outs(const ir_node *node) { - (void) unused; - node->out = NULL; - node->out_valid = 0; + return node->o.out->n_edges; } -#endif -int get_irn_outs_computed(const ir_node *node) +ir_node *get_irn_out(const ir_node *def, unsigned pos) { - return node->out != NULL; + assert(pos < get_irn_n_outs(def)); + return def->o.out->edges[pos].use; } -/* returns the number of successors of the node: */ -int get_irn_n_outs(const ir_node *node) +ir_node *get_irn_out_ex(const ir_node *def, unsigned pos, int *in_pos) { - assert(node && node->kind == k_ir_node); -#ifdef DEBUG_libfirm - /* assert(node->out_valid); */ -#endif /* defined DEBUG_libfirm */ - /* we misuse the first for the size info of the out array */ - return node->out[0].pos; + assert(pos < get_irn_n_outs(def)); + *in_pos = def->o.out->edges[pos].pos; + return def->o.out->edges[pos].use; } -/* Access successor n */ -ir_node *get_irn_out(const ir_node *def, int pos) +void set_irn_out(ir_node *def, unsigned pos, ir_node *use, int in_pos) { - assert(pos >= 0 && pos < get_irn_n_outs(def)); -#ifdef DEBUG_libfirm - /* assert(def->out_valid); */ -#endif /* defined DEBUG_libfirm */ - return def->out[pos+1].use; -} - -/* Access successor n */ -ir_node *get_irn_out_ex(const ir_node *def, int pos, int *in_pos) -{ - assert(pos >= 0 && pos < get_irn_n_outs(def)); -#ifdef DEBUG_libfirm - /* assert(def->out_valid); */ -#endif /* defined DEBUG_libfirm */ - *in_pos = def->out[pos+1].pos; - return def->out[pos+1].use; + assert(use != NULL); + assert(pos < get_irn_n_outs(def)); + def->o.out->edges[pos].use = use; + def->o.out->edges[pos].pos = in_pos; } -void set_irn_out(ir_node *def, int pos, ir_node *use, int in_pos) +unsigned get_Block_n_cfg_outs(const ir_node *bl) { - assert(def && use); - assert(pos >= 0 && pos < get_irn_n_outs(def)); -#ifdef DEBUG_libfirm - def->out_valid = 1; /* assume that this function is used correctly */ -#endif /* defined DEBUG_libfirm */ - def->out[pos+1].use = use; - def->out[pos+1].pos = in_pos; -} - -/* Return the number of control flow successors, ignore keep-alives. */ -int get_Block_n_cfg_outs(const ir_node *bl) -{ - int i, n_cfg_outs = 0; - assert(bl && is_Block(bl)); -#ifdef DEBUG_libfirm - assert(bl->out_valid); -#endif /* defined DEBUG_libfirm */ - for (i = 1; i <= bl->out[0].pos; ++i) { - ir_node *succ = bl->out[i].use; - if (get_irn_mode(succ) == mode_X && !is_End(succ) && !is_Bad(succ)) - n_cfg_outs += succ->out[0].pos; + assert(is_Block(bl)); + unsigned n_cfg_outs = 0; + for (unsigned i = 0; i < get_irn_n_outs(bl); ++i) { + const ir_node *succ = get_irn_out(bl, i); + if (get_irn_mode(succ) != mode_X) + continue; + if (is_End(succ) || is_Bad(succ)) + continue; + n_cfg_outs += get_irn_n_outs(succ); } return n_cfg_outs; } -/* Return the number of control flow successors, honor keep-alives. */ -int get_Block_n_cfg_outs_ka(const ir_node *bl) +unsigned get_Block_n_cfg_outs_ka(const ir_node *bl) { - int i, n_cfg_outs = 0; - assert(bl && is_Block(bl)); -#ifdef DEBUG_libfirm - assert(bl->out_valid); -#endif /* defined DEBUG_libfirm */ - for (i = 1; i <= bl->out[0].pos; ++i) { - ir_node *succ = bl->out[i].use; - if (get_irn_mode(succ) == mode_X) { - if (is_Bad(succ)) + assert(is_Block(bl)); + unsigned n_cfg_outs = 0; + for (unsigned i = 0; i < get_irn_n_outs(bl); ++i) { + const ir_node *succ = get_irn_out(bl, i); + if (get_irn_mode(succ) != mode_X) + continue; + if (is_Bad(succ)) + continue; + if (is_End(succ)) { + ir_node *end_bl = get_nodes_block(succ); + if (end_bl == bl) continue; - if (is_End(succ)) { - /* ignore End if we are in the Endblock */ - if (get_nodes_block(succ) == bl) - continue; - else /* count Keep-alive as one */ - n_cfg_outs += 1; - } else - n_cfg_outs += succ->out[0].pos; + ++n_cfg_outs; + continue; } + n_cfg_outs += get_irn_n_outs(succ); } return n_cfg_outs; } -/* Access predecessor n, ignore keep-alives. */ -ir_node *get_Block_cfg_out(const ir_node *bl, int pos) +ir_node *get_Block_cfg_out(const ir_node *bl, unsigned pos) { - int i; - assert(bl && is_Block(bl)); -#ifdef DEBUG_libfirm - assert(bl->out_valid); -#endif /* defined DEBUG_libfirm */ - for (i = 1; i <= bl->out[0].pos; ++i) { - ir_node *succ = bl->out[i].use; - if (get_irn_mode(succ) == mode_X && !is_End(succ) && !is_Bad(succ)) { - int n_outs = succ->out[0].pos; - if (pos < n_outs) - return succ->out[pos + 1].use; - else - pos -= n_outs; - } + assert(is_Block(bl)); + for (unsigned i = 0; i < get_irn_n_outs(bl); ++i) { + const ir_node *succ = get_irn_out(bl, i); + if (get_irn_mode(succ) != mode_X) + continue; + if (is_End(succ) || is_Bad(succ)) + continue; + + unsigned n_outs = get_irn_n_outs(succ); + if (pos < n_outs) + return get_irn_out(succ, pos); + else + pos -= n_outs; } return NULL; } -/* Access predecessor n, honor keep-alives. */ -ir_node *get_Block_cfg_out_ka(const ir_node *bl, int pos) +ir_node *get_Block_cfg_out_ka(const ir_node *bl, unsigned pos) { - int i, n_outs; - assert(bl && is_Block(bl)); -#ifdef DEBUG_libfirm - assert (bl->out_valid); -#endif /* defined DEBUG_libfirm */ - for (i = 1; i <= bl->out[0].pos; ++i) { - ir_node *succ = bl->out[i].use; - if (get_irn_mode(succ) == mode_X) { - if (is_Bad(succ)) + assert(is_Block(bl)); + for (unsigned i = 0; i < get_irn_n_outs(bl); ++i) { + const ir_node *succ = get_irn_out(bl, i); + if (get_irn_mode(succ) != mode_X) + continue; + if (is_Bad(succ)) + continue; + + if (is_End(succ)) { + ir_node *end_bl = get_nodes_block(succ); + if (end_bl == bl) { + /* ignore End if we are in the Endblock */ continue; - if (is_End(succ)) { - ir_node *end_bl = get_nodes_block(succ); - if (end_bl == bl) { - /* ignore End if we are in the Endblock */ - continue; - } - if (pos == 0) { - /* handle keep-alive here: return the Endblock instead of the End node */ - return end_bl; - } else - --pos; + } + if (pos == 0) { + /* handle keep-alive here: return the Endblock instead of the End node */ + return end_bl; } else { - n_outs = succ->out[0].pos; - if (pos < n_outs) - return succ->out[pos + 1].use; - else - pos -= n_outs; + --pos; + continue; } } + unsigned n_outs = get_irn_n_outs(succ); + if (pos < n_outs) + return get_irn_out(succ, pos); + else + pos -= n_outs; } return NULL; } @@ -208,18 +142,15 @@ ir_node *get_Block_cfg_out_ka(const ir_node *bl, int pos) static void irg_out_walk_2(ir_node *node, irg_walk_func *pre, irg_walk_func *post, void *env) { - int i, n; - ir_node *succ; - - assert(node); assert(get_irn_visited(node) < get_irg_visited(current_ir_graph)); set_irn_visited(node, get_irg_visited(current_ir_graph)); if (pre) pre(node, env); - for (i = 0, n = get_irn_n_outs(node); i < n; ++i) { - succ = get_irn_out(node, i); + int n = get_irn_n_outs(node); + for (int i = 0; i < n; ++i) { + ir_node *succ = get_irn_out(node, i); if (get_irn_visited(succ) < get_irg_visited(current_ir_graph)) irg_out_walk_2(succ, pre, post, env); } @@ -231,8 +162,9 @@ void irg_out_walk(ir_node *node, irg_walk_func *pre, irg_walk_func *post, void *env) { assert(node); - if (get_irg_outs_state(current_ir_graph) != outs_none) { - inc_irg_visited (current_ir_graph); + ir_graph *irg = get_irn_irg(node); + if (irg_has_properties(irg, IR_GRAPH_PROPERTY_CONSISTENT_OUTS)) { + inc_irg_visited(irg); irg_out_walk_2(node, pre, post, env); } } @@ -240,47 +172,48 @@ void irg_out_walk(ir_node *node, irg_walk_func *pre, irg_walk_func *post, static void irg_out_block_walk2(ir_node *bl, irg_walk_func *pre, irg_walk_func *post, void *env) { - int i, n; + if (Block_block_visited(bl)) + return; - if (!Block_block_visited(bl)) { - mark_Block_block_visited(bl); + mark_Block_block_visited(bl); - if (pre) - pre(bl, env); + if (pre) + pre(bl, env); - for (i = 0, n = get_Block_n_cfg_outs(bl); i < n; ++i) { - /* find the corresponding predecessor block. */ - ir_node *pred = get_Block_cfg_out(bl, i); - /* recursion */ - irg_out_block_walk2(pred, pre, post, env); - } - - if (post) - post(bl, env); + int n = get_Block_n_cfg_outs(bl); + for (int i = 0; i < n; ++i) { + /* find the corresponding predecessor block. */ + ir_node *pred = get_Block_cfg_out(bl, i); + /* recursion */ + irg_out_block_walk2(pred, pre, post, env); } + + if (post) + post(bl, env); } -/* Walks only over Block nodes in the graph. Has its own visited - flag, so that it can be interleaved with the other walker. */ void irg_out_block_walk(ir_node *node, irg_walk_func *pre, irg_walk_func *post, void *env) { - + ir_graph *irg = get_irn_irg(node); assert(is_Block(node) || (get_irn_mode(node) == mode_X)); - inc_irg_block_visited(current_ir_graph); + ir_graph *rem = current_ir_graph; + current_ir_graph = irg; - if (get_irn_mode(node) == mode_X) { - int i, n; + inc_irg_block_visited(irg); - for (i = 0, n = get_irn_n_outs(node); i < n; ++i) { + if (get_irn_mode(node) == mode_X) { + int n = get_irn_n_outs(node); + for (int i = 0; i < n; ++i) { ir_node *succ = get_irn_out(node, i); irg_out_block_walk2(succ, pre, post, env); } - } - else { + } else { irg_out_block_walk2(node, pre, post, env); } + + current_ir_graph = rem; } /*--------------------------------------------------------------------*/ @@ -304,215 +237,128 @@ void irg_out_block_walk(ir_node *node, irg_walk_func *pre, irg_walk_func *post, /** Returns the amount of out edges for not yet visited successors. */ -static int _count_outs(ir_node *n) +static void count_outs_node(ir_node *n) { - int start, i, res, irn_arity; - - mark_irn_visited(n); - n->out = (ir_def_use_edge*) INT_TO_PTR(1); /* Space for array size. */ - - start = is_Block(n) ? 0 : -1; - irn_arity = get_irn_arity(n); - res = irn_arity - start + 1; /* --1 or --0; 1 for array size. */ - - for (i = start; i < irn_arity; ++i) { - /* Optimize Tuples. They annoy if walking the cfg. */ - ir_node *pred = get_irn_n(n, i); - ir_node *skipped_pred = skip_Tuple(pred); - - if (skipped_pred != pred) { - set_irn_n(n, i, skipped_pred); - } - - /* count Def-Use edges for predecessors */ - if (!irn_visited(skipped_pred)) - res += _count_outs(skipped_pred); - - /*count my Def-Use edges */ - skipped_pred->out = (ir_def_use_edge*) INT_TO_PTR(PTR_TO_INT(skipped_pred->out) + 1); + if (irn_visited_else_mark(n)) + return; + + /* initialize our counter */ + n->o.n_outs = 0; + + int start = is_Block(n) ? 0 : -1; + int irn_arity = get_irn_arity(n); + for (int i = start; i < irn_arity; ++i) { + ir_node *def = get_irn_n(n, i); + /* optimize Tuples */ + ir_node *skipped = skip_Tuple(def); + if (skipped != def) + set_irn_n(n, i, skipped); + + count_outs_node(skipped); + ++skipped->o.n_outs; } - return res; } /** Returns the amount of out edges for not yet visited successors. - * This version handles some special nodes like irg_frame, irg_args etc. - */ -static int count_outs(ir_graph *irg) + * This version handles some special nodes like irg_frame, irg_args etc. */ +static void count_outs(ir_graph *irg) { - ir_node *n; - int i, res; - inc_irg_visited(irg); - res = _count_outs(get_irg_end(irg)); - - /* Now handle anchored nodes. We need the out count of those - even if they are not visible. */ - for (i = anchor_last - 1; i >= 0; --i) { - n = get_irg_anchor(irg, i); - if (!irn_visited_else_mark(n)) { - n->out = (ir_def_use_edge*) INT_TO_PTR(1); - ++res; - } + count_outs_node(get_irg_end(irg)); + for (int i = anchor_first; i <= anchor_last; ++i) { + ir_node *n = get_irg_anchor(irg, i); + if (irn_visited_else_mark(n)) + continue; + n->o.n_outs = 0; } - return res; } -/** - * Enter memory for the outs to a node. - * - * @param use current node - * @param free current free address in the chunk allocated for the outs - * - * @return The next free address - */ -static ir_def_use_edge *_set_out_edges(ir_node *use, ir_def_use_edge *free) +static void set_out_edges_node(ir_node *node, struct obstack *obst) { - int start, i, irn_arity, pos; - size_t n_outs; - - mark_irn_visited(use); + if (irn_visited_else_mark(node)) + return; /* Allocate my array */ - n_outs = PTR_TO_INT(use->out); - use->out = free; -#ifdef DEBUG_libfirm - use->out_valid = 1; -#endif /* defined DEBUG_libfirm */ - free += n_outs; - /* We count the successors again, the space will be sufficient. - We use this counter to remember the position for the next back - edge. */ - use->out[0].pos = 0; - - start = is_Block(use) ? 0 : -1; - irn_arity = get_irn_arity(use); + unsigned n_outs = node->o.n_outs; + node->o.out = OALLOCF(obst, ir_def_use_edges, edges, n_outs); + node->o.out->n_edges = 0; - for (i = start; i < irn_arity; ++i) { - ir_node *def = get_irn_n(use, i); + /* add def->use edges from my predecessors to me */ + int start = is_Block(node) ? 0 : -1; + int irn_arity = get_irn_arity(node); + for (int i = start; i < irn_arity; ++i) { + ir_node *def = get_irn_n(node, i); - /* Recursion */ - if (!irn_visited(def)) - free = _set_out_edges(def, free); + /* recurse, ensures that out array of pred is already allocated */ + set_out_edges_node(def, obst); /* Remember this Def-Use edge */ - pos = def->out[0].pos + 1; - def->out[pos].use = use; - def->out[pos].pos = i; - - /* increase the number of Def-Use edges so far */ - def->out[0].pos = pos; + unsigned pos = def->o.out->n_edges++; + def->o.out->edges[pos].use = node; + def->o.out->edges[pos].pos = i; } - return free; } -/** - * Enter memory for the outs to a node. Handles special nodes - * - * @param irg the graph - * @param free current free address in the chunk allocated for the outs - * - * @return The next free address - */ -static ir_def_use_edge *set_out_edges(ir_graph *irg, ir_def_use_edge *free) +static void set_out_edges(ir_graph *irg) { - ir_node *n; - int i; + struct obstack *obst = &irg->out_obst; + + obstack_init(obst); + irg->out_obst_allocated = true; inc_irg_visited(irg); - free = _set_out_edges(get_irg_end(irg), free); - - /* handle anchored nodes */ - for (i = anchor_last - 1; i >= 0; --i) { - n = get_irg_anchor(irg, i); - if (!irn_visited_else_mark(n)) { - size_t n_outs = PTR_TO_INT(n->out); - n->out = free; -#ifdef DEBUG_libfirm - n->out_valid = 1; -#endif /* defined DEBUG_libfirm */ - free += n_outs; - } + set_out_edges_node(get_irg_end(irg), obst); + for (int i = anchor_first; i <= anchor_last; ++i) { + ir_node *n = get_irg_anchor(irg, i); + if (irn_visited_else_mark(n)) + continue; + n->o.out = OALLOCF(obst, ir_def_use_edges, edges, 0); + n->o.out->n_edges = 0; } - - return free; } -/* compute the outs for a given graph */ void compute_irg_outs(ir_graph *irg) { - ir_graph *rem = current_ir_graph; - int n_out_edges = 0; - ir_def_use_edge *end = NULL; /* Only for debugging */ - - current_ir_graph = irg; - - /* Update graph state */ - assert(get_irg_phase_state(current_ir_graph) != phase_building); - - if (current_ir_graph->outs_state != outs_none) - free_irg_outs(current_ir_graph); + free_irg_outs(irg); /* This first iteration counts the overall number of out edges and the number of out edges for each node. */ - n_out_edges = count_outs(irg); - - /* allocate memory for all out edges. */ - irg->outs = XMALLOCNZ(ir_def_use_edge, n_out_edges); -#ifdef DEBUG_libfirm - irg->n_outs = n_out_edges; -#endif /* defined DEBUG_libfirm */ + count_outs(irg); /* The second iteration splits the irg->outs array into smaller arrays for each node and writes the back edges into this array. */ - end = set_out_edges(irg, irg->outs); - - /* Check how much memory we have used */ - assert (end == (irg->outs + n_out_edges)); + set_out_edges(irg); - current_ir_graph->outs_state = outs_consistent; - current_ir_graph = rem; + add_irg_properties(irg, IR_GRAPH_PROPERTY_CONSISTENT_OUTS + | IR_GRAPH_PROPERTY_NO_TUPLES); } void assure_irg_outs(ir_graph *irg) { - if (get_irg_outs_state(irg) != outs_consistent) + if (!irg_has_properties(irg, IR_GRAPH_PROPERTY_CONSISTENT_OUTS)) compute_irg_outs(irg); } -void compute_irp_outs(void) -{ - size_t i, n; - for (i = 0, n = get_irp_n_irgs(); i < n; ++i) - compute_irg_outs(get_irp_irg(i)); -} - -void free_irp_outs(void) +#ifdef DEBUG_libfirm +/** Clear the outs of a node */ +static void reset_outs(ir_node *node, void *unused) { - size_t i, n; - for (i = 0, n = get_irp_n_irgs(); i < n; ++i) - free_irg_outs(get_irp_irg(i)); + (void) unused; + node->o.out = NULL; } +#endif void free_irg_outs(ir_graph *irg) { - /* current_ir_graph->outs_state = outs_none; */ - irg->outs_state = outs_none; - - if (irg->outs) { -#ifdef DEBUG_libfirm - memset(irg->outs, 0, irg->n_outs); -#endif /* defined DEBUG_libfirm */ - free(irg->outs); - irg->outs = NULL; -#ifdef DEBUG_libfirm - irg->n_outs = 0; -#endif /* defined DEBUG_libfirm */ + if (irg->out_obst_allocated) { + obstack_free(&irg->out_obst, NULL); + irg->out_obst_allocated = false; } #ifdef DEBUG_libfirm /* when debugging, *always* reset all nodes' outs! irg->outs might have been lying to us */ irg_walk_graph (irg, reset_outs, NULL, NULL); -#endif /* defined DEBUG_libfirm */ +#endif }