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;
}
}
+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
xfprintf (F, "\" ");
dump_node_vcgattr(n);
xfprintf (F, "}\n");
+ dump_const_node_local(n, map);
}
void
/* 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);
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: \"");
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);
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);
}
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)
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;
}
/* dump the Bad node */
if (!Bad_dumped)
- dump_node(get_irg_bad(irg));
+ dump_node(get_irg_bad(irg), NULL);
}
void
edge_label = 0;
}
+
+void dump_consts_local(bool b) {
+ dump_const_local = b;
+}
+
void turn_off_constant_entity_values() {
const_entities = 0;
}
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)
}
-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);
}
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;
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);
}
}
pmap_destroy(map);
+ pmap_destroy(map2);
vcg_close();
}
*/
void dump_cg_block_graph(ir_graph * irg);
+
+void dump_all_cg_block_graph();
+
/****m* irdump/dump_all_ir_graphs
*
* NAME
*/
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
*
*/
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();
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 */
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);
}
}
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));
}
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
}
}
}
}
-#include "irdump.h"
-
void place_code(ir_graph *irg) {
ir_graph *rem = current_ir_graph;
current_ir_graph = irg;
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;
}
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 */
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) {
}
}
-
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;
}
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. */
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. */
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;
}
}
-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);
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 **/
/********************************************************************/
/* 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.
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_ */
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);
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) {
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);
}
}
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) {
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);
/* 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
/* 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 */
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
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);
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);
/* 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);
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
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;
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 */
}
} 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();
}
}