+static void
+new_after_loop_node(set *l_n, set *loop_outs, ir_node *node, copies_t *loop_in, int unroll_factor)
+{
+ ir_node *pred, *block_pred = NULL, *node_block, *new_phi;
+ int phi = 0, old_preds, new_preds, all_new_preds, p, q, i, s;
+ copies_t key, *value = NULL;
+ ir_node **all_in;
+
+ old_preds = get_irn_arity(node); /* All old predecessors of this node. */
+ new_preds =old_preds * (unroll_factor - 1); /* All new predecessors of this block. */
+ all_new_preds = old_preds + new_preds; /* All predecessors of this block. */
+
+ all_in = alloca(sizeof(*all_in) * all_new_preds); /* An array with size for all predecessors of this block. */
+
+ /* Verification Predecessors, successors and operation of node and loop_in.
+ * loop_in must be a Proj node.
+ */
+ if (loop_in->irn->op != op_Proj) return;
+ /* Node must be operation Phi with mode memory or a Call node. */
+ if (get_irn_op(node) == op_Phi &&
+ get_irn_mode(node) == mode_M){
+ /* If node is a Phi node,then must have a Call node as successor. */
+ for (i = 0; i < get_irn_n_outs(node); i++)
+ if (get_irn_op(get_irn_out(node, i)) == op_Call) {
+ phi = 1;
+ break;
+ }
+
+ if (!phi) return;
+ }
+
+ /* The predecessor of loop_in must not be a loop invariant. */
+ pred = get_Proj_pred(loop_in->irn);
+ key.irn = pred;
+ value = set_find( l_n, &key, sizeof(key), HASH_PTR(key.irn));
+ if (! value) return;
+
+ node_block = get_nodes_block(node);
+
+ /* The block of node must also have a (Proj) predecessor from the unrolling loop. */
+ for (i = 0; i < get_Block_n_cfgpreds(node_block); i++) {
+ block_pred = get_Block_cfgpred(node_block, i);
+
+ if (get_irn_op(block_pred) == op_Proj) {
+ if (get_Proj_pred(block_pred) == pred)
+ break;
+ }
+ else {
+ block_pred = NULL;
+ }
+ }
+
+ if (! block_pred) return;
+
+ key.irn = block_pred;
+ value = set_find(l_n, &key, sizeof(key), HASH_PTR(key.irn));
+
+ if (! value)
+ return;
+ else
+ new_after_loop_block(l_n, node_block, value, unroll_factor);
+
+ for (i = 0; i < old_preds; ++i)
+ all_in[i] = get_irn_n(node, i); /* The old predecessors. */
+
+ q = old_preds;
+ for (i = 0; i < old_preds; ++i) {
+ key.irn = all_in[i];
+ value = set_find( l_n, &key, sizeof(key), HASH_PTR(key.irn));
+ p = 0;
+ for (s = 0; s < (unroll_factor - 1); ++s) {
+ all_in[q] = value->copy[p]; /* The new predecessors. */
+ p++;
+ q++;
+ }
+ }
+ /* A new phi node with the new predecessors. */
+ new_phi = new_r_Phi(current_ir_graph, get_nodes_block(node), all_new_preds,all_in,
+ get_irn_mode(node));
+
+ if (phi)
+ exchange(node, new_phi);
+ else{
+ for (i = 0; i < get_irn_arity(node); ++i)
+ if (get_irn_n(node, i) == pred)
+ set_irn_n(node, i, new_phi);
+ }
+
+ /* The set loop_outs contains the visited nodes and their blocks. */
+ key.irn = node;
+ value = set_insert(loop_outs, &key, sizeof(key), HASH_PTR(key.irn));
+ key.irn = get_nodes_block(node);
+ value = set_insert(loop_outs, &key, sizeof(key), HASH_PTR(key.irn));
+}
+