#include <string.h>
#include "irloop_t.h"
-#include "irnode_t.h"
+
+#include "irprog_t.h"
#include "irgraph_t.h"
+#include "irnode_t.h"
+#include "irgwalk.h"
#include "array.h"
#include "pmap.h"
-#include "irgwalk.h"
-#include "irprog_t.h"
+
#include "irdump.h"
-ir_graph *outermost_ir_graph; /* The outermost graph the scc is computed
- for */
+/* A variant of the loop tree that avoids loops without head.
+ This reduces the depth of the loop tree. */
+#define NO_LOOPS_WITHOUT_HEAD 1
+
+
+INLINE void add_loop_son(ir_loop *loop, ir_loop *son);
+
+INLINE void add_loop_node(ir_loop *loop, ir_node *n);
+
+static ir_graph *outermost_ir_graph; /* The outermost graph the scc is computed
+ for */
static ir_loop *current_loop; /* Current loop construction is working
- on. */
+ on. */
static int loop_node_cnt = 0; /* Counts the number of allocated loop nodes.
- Each loop node gets a unique number.
- What for? ev. remove. @@@ */
+ Each loop node gets a unique number.
+ What for? ev. remove. @@@ */
static int current_dfn = 1; /* Counter to generate depth first numbering
- of visited nodes. */
+ of visited nodes. */
+
+static int max_loop_depth = 0;
void link_to_reg_end (ir_node *n, void *env);
void set_projx_link(ir_node *cb_projx, ir_node *end_projx);
/* Node attributes **/
/**********************************************************************/
-/* A map to get from irnodes to loop nodes. */
-static pmap *node_loop_map = NULL;
-
/**********************************************************************/
/* Node attributes needed for the construction. **/
/**********************************************************************/
((scc_info *)n->link)->uplink = uplink;
}
-static INLINE int
+INLINE int
get_irn_uplink (ir_node *n) {
assert(get_irn_link(n));
/* from fast to slow */
((scc_info *)n->link)->dfn = dfn;
}
-static INLINE int
+INLINE int
get_irn_dfn (ir_node *n) {
assert(get_irn_link(n));
/* to slow */
return ((scc_info *)n->link)->dfn;
}
-#if 0
-/* Replaced node loop map by real field as hash access dominates runtime
- * of the algorithm. ! */
-/* Uses temporary information to set the loop */
-INLINE void
-set_irn_loop (ir_node *n, ir_loop* loop) {
- assert(node_loop_map && "not initialized!");
- pmap_insert(node_loop_map, (void *)n, (void *)loop);
-}
-
-/* Uses temporary information to get the loop */
-INLINE ir_loop *
-get_irn_loop (ir_node *n) {
- ir_loop *res = NULL;
- if (!node_loop_map) return NULL;
-
- if (pmap_contains(node_loop_map, (void *)n))
- res = (ir_loop *) pmap_get(node_loop_map, (void *)n);
- return res;
-}
-#else
INLINE void
set_irn_loop (ir_node *n, ir_loop* loop) {
n->loop = loop;
get_irn_loop (ir_node *n) {
return n->loop;
}
-#endif
#if 0
ir_node *m;
int i = 0;
- /*for (;;) {*/
- do
- {
+ do {
m = pop();
+
+ //printf(" dfn: %d, upl %d upl-new %d ", get_irn_dfn(m), get_irn_uplink(m), loop_node_cnt+1); DDMN(m);
+
loop_node_cnt++;
set_irn_dfn(m, loop_node_cnt);
add_loop_node(current_loop, m);
set_irn_loop(m, current_loop);
i++;
/* if (m==n) break;*/
- } while(m != n);
+ } while(m != n);
- if(i > 1)
+ /* i might be bigger than 1 for dead (and that's why bad) loops */
+ /* if(i > 1)
printf("Mehr als eine Iteration!!!!!!!!!!!!!!!!!!!!!!!!!!!!11111\n");
+ */
}
/* GL ??? my last son is my grandson??? Removes loops with no
son->outer_loop = father;
add_loop_son(father, son);
son->depth = father->depth+1;
+ if (son->depth > max_loop_depth) max_loop_depth = son->depth;
} else { /* The root loop */
son->outer_loop = son;
son->depth = 0;
loop_element ln;
ln.node = n;
assert(loop && loop->kind == k_ir_loop);
- assert(get_kind(n) == k_ir_node);
+ assert(get_kind(n) == k_ir_node || get_kind(n) == k_ir_graph); /* used in callgraph.c */
ARR_APP1 (loop_element, loop->children, ln);
loop->n_nodes++;
}
(get_irn_op(cb) == op_EndReg) ||
(get_irn_op(cb) == op_EndExcept)) {
init_node(cb, NULL);
- init_node(get_nodes_Block(cb), NULL);
+ init_node(get_nodes_block(cb), NULL);
}
}
#endif
init_scc_common (void) {
current_dfn = 1;
loop_node_cnt = 0;
- if (!node_loop_map) node_loop_map = pmap_create();
init_stack();
}
if ((get_irn_op(n) == op_Block) &&
(get_Block_n_cfgpreds(n) == 1) &&
(get_irn_op(skip_Proj(get_Block_cfgpred(n, 0))) == op_Start) &&
- (get_nodes_Block(skip_Proj(get_Block_cfgpred(n, 0))) == n)) {
+ (get_nodes_block(skip_Proj(get_Block_cfgpred(n, 0))) == n)) {
return true;
}
#if 0
if (get_irn_op(n) == op_Phi ||
get_irn_op(n) == op_Block ||
(get_irn_op(n) == op_Filter && interprocedural_view) ||
- (get_irg_pinned(get_irn_irg(n)) == floats &&
- get_op_pinned(get_irn_op(n)) == floats))
+ (get_irg_pinned(get_irn_irg(n)) == op_pin_state_floats &&
+ get_op_pinned(get_irn_op(n)) == op_pin_state_floats))
// Here we could test for backedge at -1 which is illegal
return 0;
else
}
-#if 0
-/* Returns current_ir_graph and set 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);
- set_irg_visited(current_ir_graph, get_max_irg_visited());
- }
- }
- }
-
- return old_current;
-}
-
-/* Walks up the stack passing n and then finding the node
- where we walked into the irg n is contained in.
- Here we switch the irg. */
-static ir_graph *
-find_irg_on_stack (ir_node *n) {
- ir_node *m;
- ir_graph *old_current = current_ir_graph;
- int i;
-
- if (interprocedural_view) {
- for (i = tos; i >= 0; i--) {
- if (stack[i] == n) break;
- }
- if (i < 0) i = tos;
-
- assert (i >= 0);
- for (; i >= 0; i--) {
- m = stack[i];
- /*printf(" Visiting %d ", i); DDMN(m);*/
- if (is_ip_cfop(m)) {
- current_ir_graph = get_irn_irg(m);
- break;
- }
- if (get_irn_op(m) == op_Filter) {
- /* Find the corresponding ip_cfop */
- ir_node *pred = stack[i+1];
- int j;
- for (j = 0; j < get_Filter_n_cg_preds(m); j++)
- if (get_Filter_cg_pred(m, j) == pred) break;
- if (j >= get_Filter_n_cg_preds(m))
- /* It is a filter we didn't pass as the predecessors are marked. */
- continue;
- assert(get_Filter_cg_pred(m, j) == pred);
- switch_irg(m, j);
- break;
- }
- }
- }
-
- return old_current;
-}
-#endif
-
#if 0
static void test(ir_node *pred, ir_node *root, ir_node *this) {
int i;
if (!irn_is_in_stack(pred)) {
some_outof_loop = 1;
} else {
- if(get_irn_uplink(pred) < get_irn_uplink(root))
- {
- DDMN(pred); DDMN(root);
- }
- assert(get_irn_uplink(pred) >= get_irn_uplink(root));
+ if(get_irn_uplink(pred) < get_irn_uplink(root)) {
+ DDMN(n); DDMN(pred); DDMN(root);
+ assert(get_irn_uplink(pred) >= get_irn_uplink(root));
+ }
some_in_loop = 1;
}
}
return some_outof_loop && some_in_loop;
}
+/* Returns true if n is possible loop head of an endless loop.
+ I.e., it is a Block, Phi or Filter node and has only predecessors
+ within the loop.
+ @arg root: only needed for assertion. */
+static bool
+is_endless_head (ir_node *n, ir_node *root)
+{
+ int i, arity;
+ int some_outof_loop = 0, some_in_loop = 0;
+
+ /* Test for legal loop header: Block, Phi, ... */
+ if (!is_possible_loop_head(n))
+ return false;
+
+ if (!is_outermost_Start(n)) {
+ arity = get_irn_arity(n);
+ for (i = get_start_index(n); i < arity; i++) {
+ ir_node *pred = get_irn_n(n, i);
+ assert(pred);
+ if (is_backedge(n, i)) { continue; }
+ if (!irn_is_in_stack(pred)) {
+ some_outof_loop = 1; //printf(" some out of loop ");
+ } else {
+ if(get_irn_uplink(pred) < get_irn_uplink(root)) {
+ DDMN(pred); DDMN(root);
+ assert(get_irn_uplink(pred) >= get_irn_uplink(root));
+ }
+ some_in_loop = 1;
+ }
+ }
+ }
+ return !some_outof_loop && some_in_loop;
+}
+
/* Returns index of the predecessor with the smallest dfn number
greater-equal than limit. */
static int
return index;
}
-/* Searches the stack for possible loop heads. Tests these for backedges.
- If it finds a head with an unmarked backedge it marks this edge and
- returns the tail of the loop.
- If it finds no backedge returns NULL.
- ("disable_backedge" in fiasco) */
+/** Searches the stack for possible loop heads. Tests these for backedges.
+ If it finds a head with an unmarked backedge it marks this edge and
+ returns the tail of the loop.
+ If it finds no backedge returns NULL.
+ ("disable_backedge" in fiasco)
+*
+* @param n A node where uplink == dfn.
+**/
static ir_node *
find_tail (ir_node *n) {
/*
if (!icfg && rm_cyclic_phis && remove_cyclic_phis (n)) return NULL;
*/
-
m = stack[tos-1]; /* tos = top of stack */
if (is_head (m, n)) {
res_index = smallest_dfn_pred(m, 0);
(n == m))
return NULL;
} else {
- if (m == n) return NULL;
- for (i = tos-2; ; --i) {
+ if (m == n) return NULL; // Is this to catch Phi - self loops?
+ for (i = tos-2; i >= 0; --i) {
m = stack[i];
+
if (is_head (m, n)) {
res_index = smallest_dfn_pred (m, get_irn_dfn(m) + 1);
if (res_index == -2) /* no smallest dfn pred found. */
res_index = largest_dfn_pred (m);
+
+ if ((m == n) && (res_index == -2)) { /* dont walk past loop head. */
+ i = -1;
+ }
+ break;
+ }
+
+ /* We should not walk past our selves on the stack: The upcoming nodes
+ are not in this loop. We assume a loop not reachable from Start. */
+ if (m == n) {
+ i = -1;
break;
}
+
+ }
+
+ if (i < 0) {
+ /* A dead loop not reachable from Start. */
+ for (i = tos-2; i >= 0; --i) {
+ m = stack[i];
+ if (is_endless_head (m, n)) {
+ res_index = smallest_dfn_pred (m, get_irn_dfn(m) + 1);
+ if (res_index == -2) /* no smallest dfn pred found. */
+ res_index = largest_dfn_pred (m);
+ break;
+ }
+ if (m == n) { break; } /* It's not an unreachable loop, either. */
+ }
+ //assert(0 && "no head found on stack");
+ }
+
+ }
+ if (res_index <= -2) {
+ /* It's a completely bad loop: without Phi/Block nodes that can
+ be a head. I.e., the code is "dying". We break the loop by
+ setting Bad nodes. */
+ int arity = get_irn_arity(n);
+ for (i = -1; i < arity; ++i) {
+ set_irn_n(n, i, get_irg_bad(get_irn_irg(n)));
}
+ return NULL;
}
assert (res_index > -2);
printf("FOUND PROJ!!!!!!!!!!!!!!!!!!!!!!!!!!\n");
ir_node *end_projx = stack[i];
- for(j = 0; j < get_irn_arity(start_block); j++)
+ int arity = get_irn_arity(start_block);
+ for(j = 0; j < arity; j++)
{
- ir_node *begin_projx = get_Block_cfgpred(get_irg_start_block(get_irn_irg(end_projx)), get_Proj_proj(end_projx));
+ ir_node *begin_projx = get_Block_cfgpred(get_irg_start_block(get_irn_irg(end_projx)),
+ get_Proj_proj(end_projx));
DDMN(begin_projx);
if(get_irn_n(start_block, j) == begin_projx)
{
static pmap *projx_link = NULL;
void link_to_reg_end (ir_node *n, void *env) {
- if(get_irn_op(n) == op_Proj && get_irn_mode(n) == mode_X && get_irn_op(get_irn_n(n, 0)) == op_EndReg)
- {
+ if(get_irn_op(n) == op_Proj &&
+ get_irn_mode(n) == mode_X &&
+ get_irn_op(get_irn_n(n, 0)) == op_EndReg) {
/* Reg End Projx -> Find the CallBegin Projx and hash it */
ir_node *end_projx = n;
- ir_node *begin_projx = get_Block_cfgpred(get_irg_start_block(get_irn_irg(end_projx)), get_Proj_proj(end_projx));
+ ir_node *begin_projx = get_Block_cfgpred(get_irg_start_block(get_irn_irg(end_projx)),
+ get_Proj_proj(end_projx));
printf("Linked the following ProjxNodes:\n");
DDMN(begin_projx);
DDMN(end_projx);
#endif
+INLINE static int
+is_outermost_loop(ir_loop *l) {
+ return l == get_loop_outer_loop(l);
+}
/*-----------------------------------------------------------*
if (!is_outermost_Start(n)) {
int arity = get_irn_arity(n);
-#if EXPERIMENTAL_LOOP_TREE
+ for (i = get_start_index(n); i < arity; i++) {
+ ir_node *m;
+ if (is_backedge(n, i)) continue;
+ m = get_irn_n(n, i); /* get_irn_ip_pred(n, i); */
+ /* if ((!m) || (get_irn_op(m) == op_Unknown)) continue; */
+ scc (m);
+ if (irn_is_in_stack(m)) {
+ /* Uplink of m is smaller if n->m is a backedge.
+ Propagate the uplink to mark the loop. */
+ if (get_irn_uplink(m) < get_irn_uplink(n))
+ set_irn_uplink(n, get_irn_uplink(m));
+ }
+ }
+ }
- /* This is meant to be used with the experimenatl code above.
- If the above code is not used any more, this can be deleted, too.... */
+ if (get_irn_dfn(n) == get_irn_uplink(n)) {
+ /* This condition holds for
+ 1) the node with the incoming backedge.
+ That is: We found a loop!
+ 2) Straight line code, because no uplink has been propagated, so the
+ uplink still is the same as the dfn.
- if(interprocedural_view &&
- is_Block(n) &&
- get_irn_op(get_irn_n(n, 0)) == op_Proj &&
- get_irn_op(get_irn_n(get_irn_n(n, 0), 0)) == op_CallBegin)
- {
- /* We are at the start node of a function:
- Walk to the callers in the correct order! */
- DDMN(n);
- DDMN(get_irn_n(get_irn_n(n, 0), 0));
- for(i = 0; i < arity; i++)
- {
- int pred_nr;
- ir_node *m;
-
- pred_nr = search_endproj_in_stack(n);
- assert(pred_nr >= 0);
- if(is_backedge(n, pred_nr))
- continue;
- m = get_irn_n(n, pred_nr);
- scc(m);
-
- if (irn_is_in_stack(m)) {
- /* Uplink of m is smaller if n->m is a backedge.
- Propagate the uplink to mark the loop. */
- if (get_irn_uplink(m) < get_irn_uplink(n))
- set_irn_uplink(n, get_irn_uplink(m));
- }
- }
- }
- else
+ But n might not be a proper loop head for the analysis. Proper loop
+ heads are Block and Phi nodes. find_tail searches the stack for
+ Block's and Phi's and takes those nodes as loop heads for the current
+ loop instead and marks the incoming edge as backedge. */
+
+ ir_node *tail = find_tail(n);
+ if (tail) {
+ /* We have a loop, that is no straight line code,
+ because we found a loop head!
+ Next actions: Open a new loop on the loop tree and
+ try to find inner loops */
+#if NO_LOOPS_WITHOUT_HEAD
+ /* This is an adaption of the algorithm from fiasco / optscc to
+ * avoid loops without Block or Phi as first node. This should
+ * severely reduce the number of evaluations of nodes to detect
+ * a fixpoint in the heap analysis.
+ * Further it avoids loops without firm nodes that cause errors
+ * in the heap analyses.
+ * But attention: don't do it for the outermost loop: This loop
+ * is not iterated. A first block can be a loop head in case of
+ * an endless recursion. */
+
+ ir_loop *l;
+ int close;
+ if ((get_loop_n_elements(current_loop) > 0) || (is_outermost_loop(current_loop))) {
+ l = new_loop();
+ close = 1;
+ } else {
+ l = current_loop;
+ close = 0;
+ }
+#else
+ ir_loop *l = new_loop();
#endif
+ /* Remove the loop from the stack ... */
+ pop_scc_unmark_visit (n);
+
+ /* The current backedge has been marked, that is temporarily eliminated,
+ by find tail. Start the scc algorithm
+ anew on the subgraph thats left (the current loop without the backedge)
+ in order to find more inner loops. */
+ scc (tail);
+
+ assert (irn_visited(n));
+#if NO_LOOPS_WITHOUT_HEAD
+ if (close)
+#endif
+ close_loop(l);
+ }
+ else
{
- for (i = get_start_index(n); i < arity; i++) {
- ir_node *m;
- if (is_backedge(n, i)) continue;
- /* printf("i: %d\n", i); */
- m = get_irn_n(n, i); /* get_irn_ip_pred(n, i); */
- /* if ((!m) || (get_irn_op(m) == op_Unknown)) continue; */
- scc (m);
- if (irn_is_in_stack(m)) {
- /* Uplink of m is smaller if n->m is a backedge.
- Propagate the uplink to mark the loop. */
- if (get_irn_uplink(m) < get_irn_uplink(n))
- set_irn_uplink(n, get_irn_uplink(m));
- }
- }
+ /* No loop head was found, that is we have straightline code.
+ Pop all nodes from the stack to the current loop. */
+ pop_scc_to_loop(n);
+ }
+ }
+}
+
+static void my_scc (ir_node *n) {
+ int i;
+ if (irn_visited(n)) return;
+ mark_irn_visited(n);
+
+ /* Initialize the node */
+ set_irn_dfn(n, current_dfn); /* Depth first number for this node */
+ set_irn_uplink(n, current_dfn); /* ... is default uplink. */
+ set_irn_loop(n, NULL);
+ current_dfn ++;
+ push(n);
+
+ /* AS: get_start_index might return -1 for Control Flow Nodes, and thus a negative
+ array index would be passed to is_backedge(). But CFG Nodes dont't have a backedge array,
+ so is_backedge does not access array[-1] but correctly returns false! */
+
+ if (!is_outermost_Start(n)) {
+ int arity = get_irn_arity(n);
+
+ for (i = get_start_index(n); i < arity; i++) {
+ ir_node *m;
+ if (is_backedge(n, i)) continue;
+ m = get_irn_n(n, i); /* get_irn_ip_pred(n, i); */
+ /* if ((!m) || (get_irn_op(m) == op_Unknown)) continue; */
+ my_scc (m);
+ if (irn_is_in_stack(m)) {
+ /* Uplink of m is smaller if n->m is a backedge.
+ Propagate the uplink to mark the loop. */
+ if (get_irn_uplink(m) < get_irn_uplink(n))
+ set_irn_uplink(n, get_irn_uplink(m));
}
+ }
}
if (get_irn_dfn(n) == get_irn_uplink(n)) {
Next actions: Open a new loop on the loop tree and
try to find inner loops */
-
-#define NO_LOOPS_WITHOUT_HEAD 1
#if NO_LOOPS_WITHOUT_HEAD
-
/* This is an adaption of the algorithm from fiasco / optscc to
* avoid loops without Block or Phi as first node. This should
* severely reduce the number of evaluations of nodes to detect
ir_loop *l;
int close;
- if (get_loop_n_elements(current_loop) > 0) {
+ if ((get_loop_n_elements(current_loop) > 0) || (is_outermost_loop(current_loop))) {
l = new_loop();
close = 1;
} else {
l = current_loop;
close = 0;
}
-
#else
-
ir_loop *l = new_loop();
-
#endif
/* Remove the loop from the stack ... */
pop_scc_unmark_visit (n);
- /* GL @@@ remove experimental stuff rem = find_irg_on_stack(tail); */
-
/* The current backedge has been marked, that is temporarily eliminated,
by find tail. Start the scc algorithm
anew on the subgraph thats left (the current loop without the backedge)
in order to find more inner loops. */
-
- scc (tail);
-
- /* GL @@@ remove experimental stuff current_ir_graph = rem; */
+ my_scc (tail);
assert (irn_visited(n));
#if NO_LOOPS_WITHOUT_HEAD
}
else
{
- /* AS: No loop head was found, that is we have straightline code.
- Pop all nodes from the stack to the current loop. */
+ /* No loop head was found, that is we have straightline code.
+ Pop all nodes from the stack to the current loop. */
pop_scc_to_loop(n);
}
}
/* Constructs backedge information for irg. In interprocedural view constructs
backedges for all methods called by irg, too. */
-void construct_backedges(ir_graph *irg) {
+int construct_backedges(ir_graph *irg) {
ir_graph *rem = current_ir_graph;
ir_loop *head_rem;
assert(!interprocedural_view &&
"not implemented, use construct_ip_backedges");
- current_ir_graph = irg;
+ max_loop_depth = 0;
+ current_ir_graph = irg;
outermost_ir_graph = irg;
init_scc(current_ir_graph);
new_loop(); /* sets current_loop */
head_rem = current_loop; /* Just for assertion */
- if (interprocedural_view) {
- set_irg_visited(current_ir_graph, inc_max_irg_visited());
- init_ip_walk ();
- } else {
- inc_irg_visited(current_ir_graph);
- }
+ inc_irg_visited(current_ir_graph);
scc(get_irg_end(current_ir_graph));
- if (interprocedural_view) finish_ip_walk();
-
assert(head_rem == current_loop);
set_irg_loop(current_ir_graph, current_loop);
set_irg_loopinfo_state(current_ir_graph, loopinfo_consistent);
}
*/
current_ir_graph = rem;
+
+ return max_loop_depth;
}
-#if 0
-void construct_ip_backedges (void) {
+int construct_ip_backedges (void) {
ir_graph *rem = current_ir_graph;
int rem_ipv = interprocedural_view;
- int i, j;
+ int i;
+
+ max_loop_depth = 0;
+ assert(get_irp_ip_view_state() == ip_view_valid);
outermost_ir_graph = get_irp_main_irg();
for (i = 0; i < get_irp_n_irgs(); i++)
set_irg_visited(get_irp_irg(i), get_max_irg_visited());
+ /** We have to start the walk at the same nodes as cg_walk. **/
+ /* Walk starting at unreachable procedures. Only these
+ * have End blocks visible in interprocedural view. */
for (i = 0; i < get_irp_n_irgs(); i++) {
ir_node *sb;
current_ir_graph = get_irp_irg(i);
- /* Find real entry points */
+
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;
- /* Compute scc for this graph */
- outermost_ir_graph = current_ir_graph;
- set_irg_visited(outermost_ir_graph, get_max_irg_visited());
+ (get_nodes_block(get_Block_cfgpred(sb, 0)) != sb)) continue;
+
scc(get_irg_end(current_ir_graph));
- for (j = 0; j < get_End_n_keepalives(get_irg_end(outermost_ir_graph)); j++)
- scc(get_End_keepalive(get_irg_end(outermost_ir_graph), j));
+ }
+
+ /* Check whether we walked all procedures: there could be procedures
+ with cyclic calls but no call from the outside. */
+ for (i = 0; i < get_irp_n_irgs(); i++) {
+ ir_node *sb;
+ current_ir_graph = get_irp_irg(i);
+
+ /* Test start block: if inner procedure end and end block are not
+ * visible and therefore not marked. */
+ sb = get_irg_start_block(current_ir_graph);
+ if (get_irn_visited(sb) < get_irg_visited(current_ir_graph)) scc(sb);
+ }
+
+ /* Walk all endless loops in inner procedures.
+ * We recognize an inner procedure if the End node is not visited. */
+ for (i = 0; i < get_irp_n_irgs(); i++) {
+ ir_node *e;
+ current_ir_graph = get_irp_irg(i);
+
+ e = get_irg_end(current_ir_graph);
+ if (get_irn_visited(e) < get_irg_visited(current_ir_graph)) {
+ int j;
+ /* Don't visit the End node. */
+ for (j = 0; j < get_End_n_keepalives(e); j++) scc(get_End_keepalive(e, j));
+ }
}
set_irg_loop(outermost_ir_graph, current_loop);
current_ir_graph = rem;
interprocedural_view = rem_ipv;
+ return max_loop_depth;
}
-#else
-void construct_ip_backedges (void) {
+
+void my_construct_ip_backedges (void) {
ir_graph *rem = current_ir_graph;
int rem_ipv = interprocedural_view;
int i;
if ((get_Block_n_cfgpreds(sb) > 1) ||
(get_nodes_block(get_Block_cfgpred(sb, 0)) != sb)) continue;
- scc(get_irg_end(current_ir_graph));
+ my_scc(get_irg_end(current_ir_graph));
}
/* Check whether we walked all procedures: there could be procedures
current_ir_graph = rem;
interprocedural_view = rem_ipv;
}
-#endif
static void reset_backedges(ir_node *n) {
if (is_possible_loop_head(n)) {
}
}
+
+/*
static void loop_reset_backedges(ir_loop *l) {
int i;
reset_backedges(get_loop_node(l, 0));
loop_reset_backedges(get_loop_son(l, i));
}
}
+*/
+
+static void loop_reset_node(ir_node *n, void *env) {
+ set_irn_loop(n, NULL);
+ reset_backedges(n);
+}
+
/** Removes all loop information.
Resets all backedges */
void free_loop_information(ir_graph *irg) {
- if (get_irg_loop(irg))
- loop_reset_backedges(get_irg_loop(irg));
+ /* We can not use this recursion, as the loop might contain
+ illegal nodes by now. Why else would we throw away the
+ representation?
+ if (get_irg_loop(irg)) loop_reset_backedges(get_irg_loop(irg));
+ */
+ irg_walk_graph(irg, loop_reset_node, NULL, NULL);
set_irg_loop(irg, NULL);
set_irg_loopinfo_state(current_ir_graph, loopinfo_none);
/* We cannot free the loop nodes, they are on the obstack. */
for (i = 0; i < get_irp_n_irgs(); i++) {
free_loop_information(get_irp_irg(i));
}
- pmap_destroy(node_loop_map);
- node_loop_map = NULL;
interprocedural_view = rem;
}