+ /* 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));
+}
+
+
+/* Set the outs of the unrolling loop. All loop outs of a node muss now
+ * point to the last copy of it. Just phi nodes in the loop head and proj
+ * nodes save it outs. The all copies of some Projs have too outs.
+ *
+ * @param l_n Contains all nodes of the loop.
+ * @param loop_outs The set contains the visited and changed loop outs.
+ * @param loop_endblock_outs The set loop_endblock_outs contains all predecessors
+ * of the end block from the unrolling loop.
+ * @param info Contains the loop information.
+ * @param unroll_factor A integer 2 <= unroll_factor <= 4.
+ */
+static void
+set_loop_outs(set *l_n, set *loop_outs, set *loop_endblock_outs, induct_var_info *info, int unroll_factor)
+{
+ copies_t *value, key;
+ int i, p;
+ ir_node *loop_head = get_loop_node(info->l_itervar_phi, 0);
+ ir_node *end_block = get_irg_end_block(current_ir_graph);
+
+ for (value = set_first(l_n); value != NULL; value = set_next(l_n))
+ if (! is_Phi_in_loop_head(value->irn, loop_head) &&
+ (get_irn_opcode(value->irn) == iro_Proj && value->copy[0] != NULL))
+ for (i = 0; i < get_irn_n_outs(value->irn); ++i) {
+ key.irn = get_irn_out(value->irn, i);
+
+ /* Search for loop outs. */
+ if (set_find( l_n, &key, sizeof(key), HASH_PTR(key.irn)) == NULL)
+ if ((key.irn->op == op_Block && get_Block_dom_depth(key.irn) >
+ get_Block_dom_depth(loop_head)) ||
+ (key.irn->op != op_Block && get_Block_dom_depth(get_nodes_block(key.irn)) >
+ get_Block_dom_depth(loop_head))) {
+
+ for (p = 0; p < get_irn_arity(key.irn); p++)
+ if (value->irn == get_irn_n(key.irn, p)) {
+ if (get_irn_op(value->irn) == op_Proj && is_exception_possible(value->irn)) {
+ if (set_find(loop_outs, &key, sizeof(key), HASH_PTR(key.irn)) == NULL) {
+ /* If the loop out is for exceptions in the loop. */
+ if ((get_irn_op(key.irn) == op_Phi && get_irn_mode(key.irn) == mode_M) ||
+ get_irn_op(key.irn) == op_Call)
+ new_after_loop_node(l_n,loop_outs, key.irn, value, unroll_factor);
+ else
+ continue;
+ } else
+ continue;
+ } else
+ set_irn_n(key.irn, p, value->copy[unroll_factor-2]);
+ }
+ }
+ }
+ /* This function searches for loop outs associated with function call in the unrolling loop. */
+ new_end_block (end_block, loop_head, l_n, loop_endblock_outs, unroll_factor);
+}
+
+/**
+ * Unroll the loop body with a factor that must be power of two.
+ * Called from a post walker.
+ *
+ * @param n An IR node.
+ * @param env points to a result
+ */
+static void do_loop_unroll(ir_node *n, void *env)
+{
+ int *unroll_done = env;