From: Götz Lindenmaier Date: Wed, 11 Sep 2002 16:41:18 +0000 (+0000) Subject: walker for complete interprocedural graph X-Git-Url: http://nsz.repo.hu/git/?a=commitdiff_plain;ds=sidebyside;h=c2e377ee1536c04c8b00d241fb2d63a4061732bc;p=libfirm walker for complete interprocedural graph dump const nodes local access routines of ip_cfop nodes [r474] --- diff --git a/ir/ir/irdump.c b/ir/ir/irdump.c index 59d43cc31..dc6b74961 100644 --- a/ir/ir/irdump.c +++ b/ir/ir/irdump.c @@ -92,6 +92,13 @@ int dump_keepalive = 0; int dump_out_edge_flag = 0; int dump_dominator_information_flag = 0; int dump_loop_information_flag = 0; +int dump_const_local = 0; +static INLINE bool dump_const_local_set() { + if (!dump_out_edge_flag && !dump_loop_information_flag) + return dump_const_local; + else + return false; +} /* A global variable to record output of the Bad node. */ int Bad_dumped; @@ -227,15 +234,66 @@ dump_node_vcgattr (ir_node *n) } } +bool pred_in_wrong_graph(ir_node *n, int pos, pmap *irgmap) { + ir_node *block = (is_Block(n)) ? n : get_nodes_Block(n); + + if (irgmap && + ((get_irn_op(n) == op_Filter) || (get_irn_op(n) == op_Block))) { + ir_node *pred = skip_Proj(get_Block_cfgpred(block, pos)); + if (is_ip_cfop(pred)) { + ir_graph *irg = get_ip_cfop_irg(pred); + if (pmap_find(irgmap, irg) == NULL) return true; + } + } + + return false; +} + + +void dump_const_node_local(ir_node *n, pmap *irgmap) { + int i; + if (!dump_const_local_set()) return; + /* Use visited flag to avoid outputting nodes twice. + initialize it first. */ + for (i = 0; i < get_irn_arity(n); i++) { + ir_node *con = get_irn_n(n, i); + if (get_irn_op(con) == op_Const) { + if (pred_in_wrong_graph(n, i, irgmap)) continue; /* pred not dumped */ + set_irn_visited(con, get_irg_visited(current_ir_graph)-1); + } + } + for (i = 0; i < get_irn_arity(n); i++) { + ir_node *con = get_irn_n(n, i); + if ((get_irn_op(con) == op_Const) && irn_not_visited(con)) { + if (pred_in_wrong_graph(n, i, irgmap)) continue; /* pred not dumped */ + mark_irn_visited(con); + /* Generate a new name for the node by appending the names of + n and const. */ + xfprintf (F, "node: {title: \""); PRINT_NODEID(n); PRINT_NODEID(con); + fprintf(F, "\" label: \""); + dump_node_opcode(con); + dump_node_mode (con); + xfprintf (F, " "); + dump_node_nodeattr(con); +#ifdef DEBUG_libfirm + xfprintf (F, " %ld", get_irn_node_nr(con)); +#endif + xfprintf (F, "\" "); + dump_node_vcgattr(con); + xfprintf (F, "}\n"); + } + } +} + void -dump_node (ir_node *n) { +dump_node (ir_node *n, pmap * map) { + if (dump_const_local_set() && (get_irn_op(n) == op_Const)) return; /* dump this node */ xfprintf (F, "node: {title: \""); PRINT_NODEID(n); fprintf(F, "\" label: \""); dump_node_opcode(n); dump_node_mode (n); - //if (dump_loop_information_flag) dump_node_loop_info(n); xfprintf (F, " "); dump_node_nodeattr(n); #ifdef DEBUG_libfirm @@ -244,6 +302,7 @@ dump_node (ir_node *n) { xfprintf (F, "\" "); dump_node_vcgattr(n); xfprintf (F, "}\n"); + dump_const_node_local(n, map); } void @@ -443,6 +502,7 @@ dump_ir_node (ir_node *n) /* dump the edge to the block this node belongs to */ void dump_ir_block_edge(ir_node *n) { + if (dump_const_local_set() && (get_irn_op(n) == op_Const)) return; if (is_no_Block(n)) { xfprintf (F, "edge: { sourcename: \""); PRINT_NODEID(n); @@ -549,7 +609,7 @@ dump_ir_data_edges(ir_node *n) { for (i = 0; i < get_irn_arity(n); i++) { ir_node * pred = get_irn_n(n, i); assert(pred); - if (interprocedural_view && get_irn_visited(pred) < visited) + if ((interprocedural_view && get_irn_visited(pred) < visited)) continue; /* pred not dumped */ if (is_backedge(n, i)) fprintf (F, "backedge: {sourcename: \""); @@ -557,6 +617,8 @@ dump_ir_data_edges(ir_node *n) { fprintf (F, "edge: {sourcename: \""); PRINT_NODEID(n); fprintf (F, "\" targetname: \""); + if ((dump_const_local_set()) && (get_irn_op(pred) == op_Const)) + PRINT_NODEID(n); PRINT_NODEID(pred); fprintf (F, "\""); fprintf (F, " label: \"%d\" ", i); @@ -1015,7 +1077,7 @@ int node_floats(ir_node *n) { void dump_whole_node (ir_node *n, void* env) { - dump_node(n); + dump_node(n, NULL); if (!node_floats(n)) dump_ir_block_edge(n); dump_ir_data_edges(n); } @@ -1052,7 +1114,7 @@ dump_ir_blocks_nodes (ir_node *n, void *env) { ir_node *block = (ir_node *)env; if (is_no_Block(n) && get_nodes_Block(n) == block && !node_floats(n)) { - dump_node(n); + dump_node(n, NULL); dump_ir_data_edges(n); } if (get_irn_op(n) == op_Bad) @@ -1094,14 +1156,14 @@ dump_ir_block (ir_node *block, void *env) { void dump_blockless_nodes (ir_node *n, void *env) { if (is_no_Block(n) && get_irn_op(get_nodes_Block(n)) == op_Bad) { - dump_node(n); + dump_node(n, NULL); dump_ir_data_edges(n); dump_ir_block_edge(n); if (get_irn_op(n) == op_Bad) Bad_dumped = 1; return; } if (node_floats(n)) { - dump_node(n); + dump_node(n, NULL); dump_ir_data_edges(n); if (get_irn_op(n) == op_Bad) Bad_dumped = 1; } @@ -1118,7 +1180,7 @@ void dump_ir_block_graph_2 (ir_graph *irg) /* dump the Bad node */ if (!Bad_dumped) - dump_node(get_irg_bad(irg)); + dump_node(get_irg_bad(irg), NULL); } void @@ -1317,6 +1379,11 @@ void turn_off_edge_labels() { edge_label = 0; } + +void dump_consts_local(bool b) { + dump_const_local = b; +} + void turn_off_constant_entity_values() { const_entities = 0; } @@ -1345,12 +1412,6 @@ static void clear_link(ir_node * node, void * env) { set_irn_link(node, NULL); } - -static INLINE bool is_Block(ir_node * node) { - return !is_no_Block(node); -} - - static void collect_blocks_floats_cg(ir_node * node, pmap * map) { if (is_Block(node) || node_floats(node) @@ -1372,29 +1433,31 @@ static void collect_blocks_floats_cg(ir_node * node, pmap * map) { } -static void dump_cg_ir_block(ir_node * node, void * env) { - assert(is_Block(node)); +static void dump_cg_ir_block(ir_node * block, void * env) { + ir_node *node; + pmap *irgmap = (pmap *)env; + assert(is_Block(block)); xfprintf(F, "graph: { title: \""); - PRINT_NODEID(node); + PRINT_NODEID(block); fprintf(F, "\" label: \""); #ifdef DEBUG_libfirm - xfprintf (F, "%ld", get_irn_node_nr(node)); + xfprintf (F, "%ld", get_irn_node_nr(block)); #else - xfprintf (F, "%I", node->op->name); + xfprintf (F, "%I", block->op->name); #endif - if (exc_normal != get_Block_exc(node)) { - fprintf (F, " (%s)", exc_to_string (get_Block_exc(node))); + if (exc_normal != get_Block_exc(block)) { + fprintf (F, " (%s)", exc_to_string (get_Block_exc(block))); } xfprintf(F, "\" status:clustered color:%s \n", - get_Block_matured(node) ? "yellow" : "red"); + get_Block_matured(block) ? "yellow" : "red"); /* dump the blocks edges */ - dump_ir_data_edges(node); + dump_ir_data_edges(block); /* dump the nodes that go into the block */ for (node = get_irn_link(node); node; node = get_irn_link(node)) { - dump_node(node); + dump_node(node, irgmap); dump_ir_data_edges(node); } @@ -1402,58 +1465,112 @@ static void dump_cg_ir_block(ir_node * node, void * env) { xfprintf(F, "}\n\n"); } +void d_cg_block_graph(ir_graph *irg, ir_node **arr, pmap *irgmap) { + int i; + + xfprintf(F, "graph: { title: \"%p\" label: \"%I\" status:clustered color:white \n", + irg, get_entity_ident(get_irg_ent(irg))); + + for (i = ARR_LEN(arr) - 1; i >= 0; --i) { + ir_node * node = arr[i]; + if (is_Block(node)) { + /* Dumps the block and all the nodes in the block , which are to + be found in Block->link. */ + dump_cg_ir_block(node, irgmap); + } else { + /* Nodes that are not in a Block. */ + dump_node(node, NULL); + dump_ir_data_edges(node); + } + } + /* Close the vcg information for the irg */ + xfprintf(F, "}\n\n"); +} /* dump interprocedural graph with surrounding methods */ void dump_cg_block_graph(ir_graph * irg) { pmap * map = pmap_create(); + pmap * map2 = pmap_create(); pmap_entry * entry; + vcg_open(irg, ""); irg_walk_graph(irg, clear_link, (irg_walk_func) collect_blocks_floats_cg, map); + for (entry = pmap_first(map); entry; entry = pmap_next(map)) + pmap_insert(map2, entry->key, entry->value); for (entry = pmap_first(map); entry; entry = pmap_next(map)) { - ir_node ** arr = entry->value; - int i; - - xfprintf(F, "graph: { title: \"%I\" label: \"%I\" status:clustered color:white \n", - get_entity_ident(get_irg_ent(entry->key)), - get_entity_ident(get_irg_ent(entry->key))); + d_cg_block_graph(entry->key, entry->value, map2); + DEL_ARR_F(entry->value); + } - for (i = ARR_LEN(arr) - 1; i >= 0; --i) { - ir_node * node = arr[i]; - if (is_Block(node)) { - /* Dumps the block and all the nodes in the block , with are to be found in - Block->link. */ - dump_cg_ir_block(node, NULL); - } else { - /* Node that are not in a Block. */ - dump_node(node); - dump_ir_data_edges(node); - } - } + pmap_destroy(map); + pmap_destroy(map2); - DEL_ARR_F(arr); + if (dump_loop_information_flag) dump_loop_info(irg); + vcg_close(); +} - /* Close the vcg information for the irg */ - xfprintf(F, "}\n\n"); +static void collect_node(ir_node * node, void *env) { + if (is_Block(node) + || node_floats(node) + || get_irn_op(node) == op_Bad + || get_irn_op(node) == op_Unknown) { + ir_node ** arr = (ir_node **) get_irg_link(current_ir_graph); + ARR_APP1(ir_node *, arr, node); + set_irg_link(current_ir_graph, arr); /* arr is an l-value, APP_ARR might change it! */ + } else { + ir_node * block = get_nodes_Block(node); + set_irn_link(node, get_irn_link(block)); + set_irn_link(block, node); } +} - pmap_destroy(map); +/* Links all nodes that have the block field set in the link field of + the block. Adds all blocks and nodes not associated with a block + in a array in irg->link. */ +static void collect_nodes() { + int i; + for (i = 0; i < get_irp_n_irgs(); i++) + set_irg_link(get_irp_irg(i), NEW_ARR_F(ir_node *, 0)); + cg_walk(clear_link, collect_node, NULL); +} - if (dump_loop_information_flag) { - dump_loop_info(irg); +static void dump_graphs() { + int i; + for (i = 0; i < get_irp_n_irgs(); i++) { + current_ir_graph = get_irp_irg(i); + d_cg_block_graph(current_ir_graph, get_irg_link(current_ir_graph), NULL); } +} + +/* Dump all irgs in interprocedural view to a single file. */ +void dump_all_cg_block_graph() { + int i; + int rem_view = interprocedural_view; + interprocedural_view = 1; + vcg_open_name ("All_graphs"); + + collect_nodes(); + dump_graphs(); + + if (dump_loop_information_flag) + for (i = 0; i < get_irp_n_irgs(); i++) + dump_loop_info(get_irp_irg(i)); vcg_close(); + interprocedural_view = rem_view; } - /* dump interprocedural block graph with surrounding methods */ void dump_cg_graph(ir_graph * irg) { pmap * map = pmap_create(); + pmap * map2 = pmap_create(); /* We can not iterate in the same map twice! */ pmap_entry * entry; vcg_open(irg, ""); irg_walk_graph(irg, clear_link, (irg_walk_func) collect_blocks_floats_cg, map); + for (entry = pmap_first(map); entry; entry = pmap_next(map)) + pmap_insert(map2, entry->key, entry->value); for (entry = pmap_first(map); entry; entry = pmap_next(map)) { ir_node ** arr = entry->value; int i; @@ -1464,11 +1581,11 @@ void dump_cg_graph(ir_graph * irg) { for (i = ARR_LEN(arr) - 1; i >= 0; --i) { ir_node * node = arr[i]; - dump_node(node); + dump_node(node, map2); dump_ir_data_edges(node); if (is_Block(node)) { for (node = get_irn_link(node); node; node = get_irn_link(node)) { - dump_node(node); + dump_node(node, map2); dump_ir_block_edge(node); dump_ir_data_edges(node); } @@ -1482,6 +1599,7 @@ void dump_cg_graph(ir_graph * irg) { } pmap_destroy(map); + pmap_destroy(map2); vcg_close(); } diff --git a/ir/ir/irdump.h b/ir/ir/irdump.h index b8a45011b..7f91c130f 100644 --- a/ir/ir/irdump.h +++ b/ir/ir/irdump.h @@ -232,6 +232,9 @@ void dump_cg_graph(ir_graph * irg); */ void dump_cg_block_graph(ir_graph * irg); + +void dump_all_cg_block_graph(); + /****m* irdump/dump_all_ir_graphs * * NAME @@ -276,6 +279,27 @@ void dump_all_ir_graphs (void dump_graph(ir_graph*)); */ void turn_off_edge_labels(); +/****m* irdump/dump_consts_local + * + * NAME + * dump_consts_local + * SYNOPSIS + * void dump_consts_local(bool b); + * FUNCTION + * If set to true constants will be replicated for every use. In non blocked + * view edges from constant to block are scipped. Vcg + * then layouts the graphs more compact, this makes them better readable. + * The flag is automatically and temporarily set to false if other + * edges are dumped, as outs, loop, ... + * Default setting: false. + * INPUTS + * RESULT + * SEE ALSO + * + *** + */ +void dump_consts_local(bool b); + /****m* irdump/turn_off_constant_entity_values * @@ -351,6 +375,25 @@ void dump_out_edges(); */ void dump_dominator_information(); + +/****m* irdump/dump_loop_information + * + * NAME + * dump_loop_information + * SYNOPSIS + * void dump_loop_information() + * FUNCTION + * If this flag is set the dumper dumps loop nodes and edges from + * these nodes to the contained ir nodes. + * Can be turned off with dont_dump_loop_information(). + * If the loops are interprocedural nodes can be missing. + * INPUTS + * No inputs + * RESULT + * SEE ALSO + * + *** + */ void dump_loop_information(); void dont_dump_loop_information(); diff --git a/ir/ir/irgopt.c b/ir/ir/irgopt.c index 1e1893de8..c7a3cc9a0 100644 --- a/ir/ir/irgopt.c +++ b/ir/ir/irgopt.c @@ -743,7 +743,7 @@ void inline_small_irgs(ir_graph *irg, int size) { if (!(get_optimize() && get_opt_inline())) return; - /*DDME(get_irg_ent(current_ir_graph));*/ + //DDME(get_irg_ent(current_ir_graph)); current_ir_graph = irg; /* Handle graph state */ @@ -766,7 +766,6 @@ void inline_small_irgs(ir_graph *irg, int size) { tv = get_Const_tarval(get_Call_ptr(calls[i])); callee = get_entity_irg(tv->u.p.ent); if ((_obstack_memory_used(callee->obst) - obstack_room(callee->obst)) < size) { - /*printf(" inlineing "); DDME(tv->u.p.ent);*/ inline_method(calls[i], callee); } } @@ -904,7 +903,7 @@ consumer_dom_dca (ir_node *dca, ir_node *consumer, ir_node *producer) return dca; } -int get_irn_loop_depth(ir_node *n) { +INLINE int get_irn_loop_depth(ir_node *n) { return get_loop_depth(get_irn_loop(n)); } @@ -988,9 +987,8 @@ place_floats_late (ir_node *n) dca = consumer_dom_dca (dca, get_irn_out(n, i), n); } set_nodes_Block(n, dca); -#if 1 + move_out_of_loops (n, early); -#endif } } @@ -1018,8 +1016,6 @@ INLINE void place_late() { } } -#include "irdump.h" - void place_code(ir_graph *irg) { ir_graph *rem = current_ir_graph; current_ir_graph = irg; diff --git a/ir/ir/irgraph.c b/ir/ir/irgraph.c index f7bf56af1..4b5c340ce 100644 --- a/ir/ir/irgraph.c +++ b/ir/ir/irgraph.c @@ -456,17 +456,21 @@ unsigned long get_max_irg_visited(void) { int i; - for(i = 0; i < get_irp_n_irgs(); i++) - assert(max_irg_visited >= get_irg_visited(get_irp_irg(i))); + //for(i = 0; i < get_irp_n_irgs(); i++) + // assert(max_irg_visited >= get_irg_visited(get_irp_irg(i))); return max_irg_visited; } +void set_max_irg_visited(int val) { + max_irg_visited = val; +} + unsigned long inc_max_irg_visited(void) { int i; - for(i = 0; i < get_irp_n_irgs(); i++) - assert(max_irg_visited >= get_irg_visited(get_irp_irg(i))); + // for(i = 0; i < get_irp_n_irgs(); i++) + //assert(max_irg_visited >= get_irg_visited(get_irp_irg(i))); max_irg_visited++; return max_irg_visited; } diff --git a/ir/ir/irgraph.h b/ir/ir/irgraph.h index 913055cef..c77251db8 100644 --- a/ir/ir/irgraph.h +++ b/ir/ir/irgraph.h @@ -226,6 +226,7 @@ void inc_irg_visited(ir_graph *irg); unsigned long get_irg_visited (ir_graph *irg); void set_irg_visited(ir_graph *irg, unsigned long i); unsigned long get_max_irg_visited(void); +void set_max_irg_visited(int val); unsigned long inc_max_irg_visited(void); /* increments block_visited by one */ diff --git a/ir/ir/irgwalk.c b/ir/ir/irgwalk.c index 8b84a24a3..7221ba3cb 100644 --- a/ir/ir/irgwalk.c +++ b/ir/ir/irgwalk.c @@ -45,7 +45,8 @@ static void irg_walk_cg(ir_node * node, int visited, eset * irg_set, if (pre) pre(node, env); - if (is_no_Block(node)) irg_walk_cg(get_nodes_Block(node), visited, irg_set, pre, post, env); + if (is_no_Block(node)) + irg_walk_cg(get_nodes_Block(node), visited, irg_set, pre, post, env); if (get_irn_op(node) == op_Block) { /* block */ for (i = get_irn_arity(node) - 1; i >= 0; --i) { @@ -103,37 +104,22 @@ static void collect_irgs(ir_node * node, eset * irg_set) { } } - void irg_walk_2(ir_node *node, irg_walk_func pre, irg_walk_func post, void * env) { int i; - - assert(node); - /* printf(" - "); DDMSG2(node); */ if (get_irn_visited(node) < get_irg_visited(current_ir_graph)) { - -/* printf(" -> "); DDMSG2(node); */ set_irn_visited(node, get_irg_visited(current_ir_graph)); - if (pre) { - pre(node, env); - } + if (pre) pre(node, env); - if (is_no_Block(node)) { + if (is_no_Block(node)) irg_walk_2(get_nodes_Block(node), pre, post, env); - } - for (i = get_irn_arity(node) - 1; i >= 0; --i) { - /* printf(" "); DDMSG2(node); - printf(" "); DDMSG2(get_irn_n(node, i)); */ - + for (i = get_irn_arity(node) - 1; i >= 0; --i) irg_walk_2(get_irn_n(node, i), pre, post, env); - } -/* printf(" <- "); DDMSG2(node); */ - if (post) - post(node, env); + if (post) post(node, env); } return; } @@ -171,9 +157,6 @@ void irg_walk_graph(ir_graph *irg, irg_walk_func pre, irg_walk_func post, void * current_ir_graph = rem; } - -/***************************************************************************/ - /* Executes irg_walk(end, pre, post, env) for all irgraphs in irprog. Sets current_ir_graph properly for each walk. Conserves current current_ir_graph. */ @@ -191,6 +174,84 @@ void all_irg_walk(irg_walk_func pre, irg_walk_func post, void *env) { current_ir_graph = rem; } +/***************************************************************************/ + +/* Returns current_ir_graph and sets it to the irg of predecessor index + of node n. */ +static INLINE ir_graph * +switch_irg (ir_node *n, int index) { + ir_graph *old_current = current_ir_graph; + + if (interprocedural_view) { + /* Only Filter and Block nodes can have predecessors in other graphs. */ + if (get_irn_op(n) == op_Filter) + n = get_nodes_Block(n); + if (get_irn_op(n) == op_Block) { + ir_node *cfop = skip_Proj(get_Block_cfgpred(n, index)); + if (is_ip_cfop(cfop)) { + current_ir_graph = get_irn_irg(cfop); + } + } + } + + return old_current; +} + +void cg_walk_2(ir_node *node, irg_walk_func pre, irg_walk_func post, void * env) +{ + int i; + ir_graph *rem = NULL; + assert(node); + + if (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); + + if (is_no_Block(node)) + cg_walk_2(get_nodes_Block(node), pre, post, env); + for (i = get_irn_arity(node) - 1; i >= 0; --i) { + rem = switch_irg(node, i); + cg_walk_2(get_irn_n(node, i), pre, post, env); + current_ir_graph = rem; + } + + if (post) post(node, env); + } + return; +} + + +/* Walks all irgs in interprocedural view. Visits each node only once. */ +void cg_walk(irg_walk_func pre, irg_walk_func post, void *env) { + int i; + ir_graph *rem = current_ir_graph; + int rem_view = interprocedural_view; + + interprocedural_view = true; + + inc_max_irg_visited(); + /* Fix all irg_visited flags */ + for (i = 0; i < get_irp_n_irgs(); i++) + set_irg_visited(get_irp_irg(i), get_max_irg_visited()); + + /* Walk starting at unreachable procedures. */ + for (i = 0; i < get_irp_n_irgs(); i++) { + ir_node *sb; + current_ir_graph = get_irp_irg(i); + + sb = get_irg_start_block(current_ir_graph); + if ((get_Block_n_cfgpreds(sb) > 1) || + (get_nodes_Block(get_Block_cfgpred(sb, 0)) != sb)) continue; + + cg_walk_2(get_irg_end(current_ir_graph), pre, post, env); + } + + interprocedural_view = rem_view; + current_ir_graph = rem; +} + + /***************************************************************************/ /* Walks back from n until it finds a real cf op. */ @@ -210,38 +271,27 @@ ir_node *get_cf_op(ir_node *n) { void irg_block_walk_2(ir_node *node, irg_walk_func pre, irg_walk_func post, void *env) { int i; - assert(get_irn_opcode(node) == iro_Block); if(get_Block_block_visited(node) < get_irg_block_visited(current_ir_graph)) { set_Block_block_visited(node, get_irg_block_visited(current_ir_graph)); - if(pre) - pre(node, env); + if(pre) pre(node, env); for(i = get_Block_n_cfgpreds(node) - 1; i >= 0; --i) { - /* find the corresponding predecessor block. */ ir_node *pred = get_cf_op(get_Block_cfgpred(node, i)); - /* GL: I'm not sure whether this assert must go through. There - could be Id chains?? Tuple/Proj .... */ - - assert(is_cfop(pred) - || is_fragile_op(pred) - || (get_irn_op(pred) == op_Bad)); - pred = get_nodes_Block(pred); if(get_irn_opcode(pred) == iro_Block) { /* recursion */ irg_block_walk_2(pred, pre, post, env); } else { - assert(get_irn_opcode(pred) == iro_Bad); + assert(get_irn_opcode(pred) == iro_Bad); } } - if(post) - post(node, env); + if(post) post(node, env); } return; } @@ -273,7 +323,8 @@ void irg_block_walk(ir_node *node, irg_walk_func pre, irg_walk_func post, void * } -void irg_block_walk_graph(ir_graph *irg, irg_walk_func pre, irg_walk_func post, void *env) { +void irg_block_walk_graph(ir_graph *irg, irg_walk_func pre, + irg_walk_func post, void *env) { ir_graph * rem = current_ir_graph; current_ir_graph = irg; irg_block_walk(get_irg_end(irg), pre, post, env); @@ -340,6 +391,58 @@ void walk_const_code(irg_walk_func pre, irg_walk_func post, void *env) { current_ir_graph = rem; } + +/********************************************************************/ +/** Walking support for interprocedural analysis **/ +/** **/ +/** @@@ Don't use, not operational yet, doesn't grok recursions!! **/ +/** @@@ Header for irgwalk.h, here until it works. **/ +/** **/ +/** Interprocedural walking should not walk all predecessors of **/ +/** all nodes. When leaving a procedure the walker should only **/ +/** follow the edge corresponding to the most recent entry of the **/ +/** procedure. The following functions use an internal stack to **/ +/** remember the current call site of a procedure. **/ +/** They also set current_ir_graph correctly. **/ +/** **/ +/** Usage example: **/ +/** **/ +/** void init_ip_walk (); **/ +/** work_on_graph(some_end_node); **/ +/** void finish_ip_walk(); **/ +/** **/ +/** work_on_graph(ir_node *n) { **/ +/** for (i = 0; i < get_irn_arity(n); i++) { **/ +/** if (...) continue; **/ +/** ir_node *m = get_irn_ip_pred(n, i); **/ +/** if !m continue; **/ +/** work_on_graph(m); **/ +/** return_recur(n, i); **/ +/** } **/ +/** } **/ +/********************************************************************/ + +/* Allocates some necessary datastructures. */ +void init_ip_walk (); +/* Frees some necessary datastructures. */ +void finish_ip_walk(); + +/* Call for i in {0|-1 ... get_irn_arity(n)}. + If n is a conventional node returns the same node as get_irn_n(n, i). + If the predecessors of n are in the callee of the procedure n belongs + to, returns get_irn_n(n, i) if this node is in the callee on the top + of the stack, else returns NULL. + If the predecessors of n are in a procedure called by the procedure n + belongs to pushes the caller on the caller stack in the callee. + Sets current_ir_graph to the graph the node returned is in. */ +ir_node *get_irn_ip_pred(ir_node *n, int pos); + +/* If get_irn_ip_pred() returned a node (not NULL) this must be + called to clear up the stacks. + Sets current_ir_graph to the graph n is in. */ +void return_recur(ir_node *n, int pos); + + /********************************************************************/ /** Walking support for interprocedural analysis **/ /********************************************************************/ diff --git a/ir/ir/irgwalk.h b/ir/ir/irgwalk.h index 3d217fa12..71f6ee722 100644 --- a/ir/ir/irgwalk.h +++ b/ir/ir/irgwalk.h @@ -37,9 +37,13 @@ void irg_walk_graph(ir_graph *irg, irg_walk_func pre, irg_walk_func post, void * /* Executes irg_walk(end, pre, post, env) for all irgraphs in irprog. Sets current_ir_graph properly for each walk. Conserves current - current_ir_graph. */ + current_ir_graph. In interprocedural view nodes can be visited several + times. */ void all_irg_walk(irg_walk_func pre, irg_walk_func post, void *env); +/* Walks all irgs in interprocedural view. Visits each node only once. + Sets current_ir_graph properly. */ +void cg_walk(irg_walk_func pre, irg_walk_func post, void *env); /* Walks only over Block nodes in the graph. Has it's own visited flag, so that it can be interleaved with the other walker. @@ -55,54 +59,5 @@ void irg_block_walk_graph(ir_graph *irg, irg_walk_func pre, irg_walk_func post, Uses visited flag in const_code_irg. */ void walk_const_code(irg_walk_func pre, irg_walk_func post, void *env); -/********************************************************************/ -/** Walking support for interprocedural analysis **/ -/** **/ -/** @@@ Don't use, not operational yet, doesn't grok recursions!! **/ -/** **/ -/** Interprocedural walking should not walk all predecessors of **/ -/** all nodes. When leaving a procedure the walker should only **/ -/** follow the edge corresponding to the most recent entry of the **/ -/** procedure. The following functions use an internal stack to **/ -/** remember the current call site of a procedure. **/ -/** They also set current_ir_graph correctly. **/ -/** **/ -/** Usage example: **/ -/** **/ -/** void init_ip_walk (); **/ -/** work_on_graph(some_end_node); **/ -/** void finish_ip_walk(); **/ -/** **/ -/** work_on_graph(ir_node *n) { **/ -/** for (i = 0; i < get_irn_arity(n); i++) { **/ -/** if (...) continue; **/ -/** ir_node *m = get_irn_ip_pred(n, i); **/ -/** if !m continue; **/ -/** work_on_graph(m); **/ -/** return_recur(n, i); **/ -/** } **/ -/** } **/ -/********************************************************************/ - -/* Allocates some necessary datastructures. */ -void init_ip_walk (); -/* Frees some necessary datastructures. */ -void finish_ip_walk(); - -/* Call for i in {0|-1 ... get_irn_arity(n)}. - If n is a conventional node returns the same node as get_irn_n(n, i). - If the predecessors of n are in the callee of the procedure n belongs - to, returns get_irn_n(n, i) if this node is in the callee on the top - of the stack, else returns NULL. - If the predecessors of n are in a procedure called by the procedure n - belongs to pushes the caller on the caller stack in the callee. - Sets current_ir_graph to the graph the node returned is in. */ -ir_node *get_irn_ip_pred(ir_node *n, int pos); - -/* If get_irn_ip_pred() returned a node (not NULL) this must be - called to clear up the stacks. - Sets current_ir_graph to the graph n is in. */ -void return_recur(ir_node *n, int pos); - # endif /* _IRGWALK_H_ */ diff --git a/ir/ir/irmode.h b/ir/ir/irmode.h index 76bf8fa75..ffdd0b8ab 100644 --- a/ir/ir/irmode.h +++ b/ir/ir/irmode.h @@ -123,7 +123,6 @@ unsigned get_mode_ffloat (ir_mode *mode); int mode_is_signed (ir_mode *mode); int mode_is_float (ir_mode *mode); int mode_is_int (ir_mode *mode); -# define is_chilCHIL(m) ((m) <= irm_L && (m) >= irm_c) /* old */ int mode_is_num (ir_mode *mode); int mode_is_data (ir_mode *mode); int mode_is_datab (ir_mode *mode); diff --git a/ir/ir/irnode.c b/ir/ir/irnode.c index 78e7a9b97..036ee9e0a 100644 --- a/ir/ir/irnode.c +++ b/ir/ir/irnode.c @@ -258,11 +258,11 @@ set_irn_in (ir_node *node, int arity, ir_node **in) { If it is a block, the entry -1 is NULL. */ INLINE ir_node * get_irn_n (ir_node *node, int n) { - /* debug @@@ */ + /* debug @@@ if (-1 > n || get_irn_arity(node) <= n) { printf("pos: %d, arity: %d ", n, get_irn_arity(node)); DDMN(node); - } + } */ assert(node); assert(-1 <= n && n < get_irn_arity(node)); if (interprocedural_view) { /* handle Filter and Block specially */ if (get_irn_opcode(node) == iro_Filter) { @@ -511,13 +511,13 @@ get_Block_n_cfgpreds (ir_node *node) { INLINE ir_node * get_Block_cfgpred (ir_node *node, int pos) { - /* debug @@@ */ assert (node->op == op_Block); + /* debug @@@ if (-1 > pos || get_irn_arity(node) <= pos) { dump_ir_block_graph(current_ir_graph); printf("pos: %d, arity: %d ", pos, get_irn_arity(node)); DDMN(node); - } + } */ assert(node); assert(-1 <= pos && pos < get_irn_arity(node)); return get_irn_n(node, pos); } @@ -645,8 +645,8 @@ ir_node ** get_Block_cg_cfgpred_arr(ir_node * node) { } int get_Block_cg_n_cfgpreds(ir_node * node) { - assert(node->op == op_Block && node->attr.block.in_cg); - return ARR_LEN(node->attr.block.in_cg) - 1; + assert(node->op == op_Block); + return node->attr.block.in_cg == NULL ? 0 : ARR_LEN(node->attr.block.in_cg) - 1; } ir_node * get_Block_cg_cfgpred(ir_node * node, int pos) { @@ -2212,6 +2212,12 @@ is_no_Block (ir_node *node) { return (get_irn_opcode(node) != iro_Block); } +INLINE int +is_Block (ir_node *node) { + assert(node); + return (get_irn_opcode(node) == iro_Block); +} + INLINE int is_Proj (ir_node *node) { assert(node); @@ -2227,10 +2233,23 @@ is_cfop(ir_node *node) { /* Returns true if the operation manipulates interprocedural control flow: CallBegin, EndReg, EndExcept */ -int is_ip_cfop(ir_node *node) { +INLINE int is_ip_cfop(ir_node *node) { return is_ip_cfopcode(get_irn_op(node)); } +ir_graph *get_ip_cfop_irg(ir_node *n) { + switch (get_irn_opcode(n)) { + case iro_EndReg: + return get_EndReg_irg(n); + case iro_EndExcept: + return get_EndExcept_irg(n); + case iro_CallBegin: + return get_CallBegin_irg(n); + default: + assert(is_ip_cfop(n)); + } +} + /* Returns true if the operation can change the control flow because of an exception. */ int diff --git a/ir/ir/irnode.h b/ir/ir/irnode.h index cf4c98b78..b1810cccb 100644 --- a/ir/ir/irnode.h +++ b/ir/ir/irnode.h @@ -160,13 +160,16 @@ INLINE int Block_not_block_visited(ir_node *node); /* Set and remove interprocedural predecessors. If the interprocedural * predecessors are removed, the node has the same predecessors in - * both views. */ + * both views. + * @@@ Maybe better: arity is zero if no cg preds. */ void set_Block_cg_cfgpred_arr(ir_node * node, int arity, ir_node ** in); void set_Block_cg_cfgpred(ir_node * node, int pos, ir_node * pred); /* @@@ not supported */ ir_node ** get_Block_cg_cfgpred_arr(ir_node * node); +/* Returns the number of interproc predecessors. 0 if none. */ int get_Block_cg_n_cfgpreds(ir_node * node); ir_node * get_Block_cg_cfgpred(ir_node * node, int pos); +/* frees the memory. */ void remove_Block_cg_cfgpred_arr(ir_node * node); /* exc handling @@@ ajacs specific -- not supported */ @@ -193,7 +196,6 @@ INLINE void set_End_keepalive(ir_node *end, int pos, ir_node *ka); INLINE void free_End (ir_node *end); ir_graph *get_EndReg_irg (ir_node *end); - ir_graph *get_EndExcept_irg (ir_node *end); /* We distinguish three kinds of Cond nodes. These can be distinguished @@ -452,7 +454,8 @@ INLINE ir_node *get_Filter_pred(ir_node *node); INLINE void set_Filter_pred(ir_node *node, ir_node *pred); INLINE long get_Filter_proj(ir_node *node); INLINE void set_Filter_proj(ir_node *node, long proj); -/* set the interprocedural predecessors, ...d_arr uses current_ir_graph. */ +/* set the interprocedural predecessors, ...d_arr uses current_ir_graph. + * @@@ Maybe better: arity is zero if no cg preds. */ void set_Filter_cg_pred_arr(ir_node * node, int arity, ir_node ** in); void set_Filter_cg_pred(ir_node * node, int pos, ir_node * pred); int get_Filter_n_cg_preds(ir_node *node); @@ -533,6 +536,8 @@ INLINE ir_node *skip_Tuple (ir_node *node); INLINE int is_Bad (ir_node *node); /* returns true if the node is not a Block */ INLINE int is_no_Block (ir_node *node); +/* returns true if the node is a Block */ +INLINE int is_Block (ir_node *node); /* returns true if node is a Proj node or a Filter node in * intraprocedural view */ INLINE int is_Proj (ir_node *node); @@ -546,6 +551,8 @@ int is_ip_cfop(ir_node *node); /* Returns true if the operation can change the control flow because of an exception: Call, Quot, DivMod, Div, Mod, Load, Store, Alloc, Bad. */ +ir_graph *get_ip_cfop_irg(ir_node *n); + int is_fragile_op(ir_node *node); /* Returns the memory operand of fragile operations. */ ir_node *get_fragile_op_mem(ir_node *node); diff --git a/ir/ir/iropt.c b/ir/ir/iropt.c index 84e8bacdc..e2ed9e229 100644 --- a/ir/ir/iropt.c +++ b/ir/ir/iropt.c @@ -180,8 +180,8 @@ computed_value (ir_node *n) only 1 is used. There are several case where we can evaluate a Cmp node: 1. The nodes compared are both the same. If we compare for - equal, this will return true, else it will return false. - This step relies on cse. + equal, greater equal, ... this will return true, else it + will return false. This step relies on cse. 2. The predecessors of Cmp are target values. We can evaluate the Cmp. 3. The predecessors are Allocs or void* constants. Allocs never @@ -322,7 +322,8 @@ equivalent_node (ir_node *n) if ((get_irn_op(a) == op_Proj) && (get_irn_op(b) == op_Proj) && (get_Proj_pred(a) == get_Proj_pred(b)) && - (get_irn_op(get_Proj_pred(a)) == op_Cond)) { + (get_irn_op(get_Proj_pred(a)) == op_Cond) && + (get_irn_mode(get_Cond_selector(get_Proj_pred(a))) == mode_b)) { /* Also a single entry Block following a single exit Block. Phis have twice the same operand and will be optimized away. */ n = get_nodes_Block(a); DBG_OPT_IFSIM; @@ -407,10 +408,11 @@ equivalent_node (ir_node *n) set_Tuple_pred(n, 2, a); } break; - /* GL: Why are they skipped? DivMod allocates new nodes --> it's - treated in transform node. - case iro_Mod, Quot, DivMod - */ + /* + case iro_Mod, Quot, DivMod + DivMod allocates new nodes --> it's treated in transform node. + What about Quot, DivMod? + */ case iro_And: if (a == b) { n = a; /* And has it's own neutral element */ @@ -574,7 +576,7 @@ equivalent_node (ir_node *n) } } else if (get_irn_mode(n) == mode_X && is_Bad(get_nodes_Block(n))) { - /* Remove dead control flow. */ + /* Remove dead control flow -- early gigo. */ n = new_Bad(); } }