-static INLINE void
-init_node (ir_node *n, void *env) {
- set_irn_link (n, new_scc_info());
- clear_backedges(n);
-#if 0
- /* Also init nodes not visible in intraproc_view. */
- /* @@@ init_node is called for too many nodes -- this wastes memory!.
- The mem is not lost as its on the obstack. */
- if (get_irn_op(n) == op_Filter) {
- for (i = 0; i < get_Filter_n_cg_preds(n); i++)
- init_node(get_Filter_cg_pred(n, i), NULL);
- }
- if (get_irn_op(n) == op_Block) {
- for (i = 0; i < get_Block_cg_n_cfgpreds(n); i++) {
- init_node(get_Block_cg_cfgpred(n, i), NULL);
- }
- }
- /* The following pattern matches only after a call from above pattern. */
- if ((get_irn_op(n) == op_Proj) /*&& (get_Proj_proj(n) == 0)*/) {
- /* @@@ init_node is called for every proj -- this wastes memory!.
- The mem is not lost as its on the obstack. */
- ir_node *cb = get_Proj_pred(n);
- if ((get_irn_op(cb) == op_CallBegin) ||
- (get_irn_op(cb) == op_EndReg) ||
- (get_irn_op(cb) == op_EndExcept)) {
- init_node(cb, NULL);
- init_node(get_nodes_Block(cb), NULL);
- }
+
+/*-----------------------------------------------------------*
+ * The core algorithm. *
+ *-----------------------------------------------------------*/
+
+/**
+ * The core algorithm: Find strongly coupled components.
+ *
+ * @param n node to start
+ */
+static void scc(ir_node *n) {
+ 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 i, 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);
+ 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)) {
+ /* 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.
+
+ 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 != NULL) {
+ /* 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
+ again on the subgraph that is 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 {
+ /* No loop head was found, that is we have straight line code.
+ Pop all nodes from the stack to the current loop. */
+ pop_scc_to_loop(n);
+ }
+ }
+}
+
+#ifdef INTERPROCEDURAL_VIEW
+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)) {
+ /* 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.
+
+ 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. */
+
+ 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();