+ /* Rewires the 2 heads */
+ peel_fix_heads();
+
+ /* Generate phis for values from peeled code and original loop */
+ construct_ssa_foreach(entry_buffer, entry_c);
+ /*for (i = 0; i < entry_c; i++)
+ {
+ ir_node *cppred, *block, *cpblock, *pred;
+
+ pred = entry_buffer[i];
+ cppred = get_copy(pred);
+ block = get_nodes_block(pred);
+ cpblock = get_nodes_block(cppred);
+ construct_ssa(block, pred, cpblock, cppred);
+ }*/
+}
+
+/**
+ * Populates head_entries with (node, pred_pos) tuple
+ * whereas the node's pred at pred_pos is in the head but not the node itself.
+ * Head and condition chain blocks must be marked.
+ */
+static void get_head_outs(ir_node *node, void *env)
+{
+ int i;
+ int arity = get_irn_arity(node);
+ (void) env;
+
+ DB((dbg, LEVEL_5, "get head entries %N \n", node));
+
+ for (i = 0; i < arity; ++i) {
+ /* node is not in the head, but the predecessor is.
+ * (head or loop chain nodes are marked) */
+
+ DB((dbg, LEVEL_5, "... "));
+ DB((dbg, LEVEL_5, "node %N marked %d (0) pred %d marked %d (1) \n",
+ node->node_nr, is_nodesblock_marked(node),i, is_nodesblock_marked(get_irn_n(node, i))));
+
+ if (!is_nodesblock_marked(node) && is_nodesblock_marked(get_irn_n(node, i))) {
+ out_edge entry;
+ entry.node = node;
+ entry.pred_irn_n = i;
+ DB((dbg, LEVEL_5,
+ "Found head chain entry %N @%d because !inloop %N and inloop %N\n",
+ node, i, node, get_irn_n(node, i)));
+ ARR_APP1(out_edge, cur_head_outs, entry);
+ }
+ }
+}
+
+/**
+ * Find condition chains, and add them to be inverted, until the node count exceeds the limit.
+ * A block belongs to the chain if a condition branches out of the loop.
+ * Returns 1 if the given block belongs to the condition chain.
+ */
+static unsigned find_condition_chains(ir_node *block)
+{
+ const ir_edge_t *edge;
+ unsigned mark = 0;
+ int nodes_n = 0;
+
+ DB((dbg, LEVEL_5, "condition_chains for block %N\n", block));
+
+ /* Collect all outs, including keeps.
+ * (TODO firm function for number of out edges?) */
+ foreach_out_edge_kind(block, edge, EDGE_KIND_NORMAL) {
+ ++nodes_n;
+ }
+
+ /* We do not want to collect more nodes from condition chains, than the limit allows us to.
+ * Also, leave at least one block as body. */
+ if (head_inversion_node_count + nodes_n > inversion_head_node_limit
+ || head_inversion_block_count + 1 == loop_info.blocks) {
+ set_Block_mark(block, 0);
+
+ return 0;
+ }
+
+ /* First: check our successors, and add all succs that are outside of the loop to the list */
+ foreach_block_succ(block, edge) {
+ ir_node *src = get_edge_src_irn( edge );
+ int pos = get_edge_src_pos( edge );
+
+ if (!is_in_loop(src)) {
+ out_edge entry;
+
+ mark = 1;
+ entry.node = src;
+ entry.pred_irn_n = pos;
+ ARR_APP1(out_edge, cond_chain_entries, entry);
+ mark_irn_visited(src);
+ }
+ }
+
+ if (mark == 0) {
+ /* this block is not part of the chain,
+ * because the chain would become too long or we have no successor outside of the loop */
+
+ set_Block_mark(block, 0);
+ return 0;
+ } else {
+ set_Block_mark(block, 1);
+ ++head_inversion_block_count;
+ DB((dbg, LEVEL_5, "block %N is part of condition chain\n", block));
+ head_inversion_node_count += nodes_n;
+ }
+
+ /* Second: walk all successors, and add them to the list if they are not part of the chain */
+ foreach_block_succ(block, edge) {
+ unsigned inchain;
+ ir_node *src = get_edge_src_irn( edge );
+ int pos = get_edge_src_pos( edge );
+
+ /* already done cases */
+ if (!is_in_loop( src ) || (get_irn_visited(src) >= get_irg_visited(current_ir_graph))) {
+ continue;
+ }
+
+ mark_irn_visited(src);
+ DB((dbg, LEVEL_5, "condition chain walk %N\n", src));
+ inchain = find_condition_chains(src);
+
+ /* if successor is not part of chain we need to collect its outs */
+ if (!inchain) {
+ out_edge entry;
+ entry.node = src;
+ entry.pred_irn_n = pos;
+ ARR_APP1(out_edge, cond_chain_entries, entry);
+ }
+ }
+ return mark;
+}
+
+/**
+ * Rewire the loop head and inverted head for loop inversion.
+ */
+static void inversion_fix_heads(void)
+{
+ ir_node **loopheadnins, **invheadnins;
+ ir_node *loophead = loop_cf_head;
+ ir_node *invhead = get_copy(loophead);
+
+ int headarity = get_irn_arity(loophead);
+ ir_node *phi;
+ int i;
+
+ int lheadin_c = 0;
+ int iheadin_c = 0;
+
+ int backedges_n = get_backedge_n(loophead, 0);
+ int lhead_arity = backedges_n;
+ int ihead_arity = headarity - backedges_n;
+
+ assert(lhead_arity != 0 && "Loophead has arity 0. Probably wrong backedge informations.");
+ assert(ihead_arity != 0 && "Inversionhead has arity 0. Probably wrong backedge informations.");
+
+ /* new in arrays for all phis in the head blocks */
+ NEW_ARR_A(ir_node *, loopheadnins, lhead_arity);
+ NEW_ARR_A(ir_node *, invheadnins, ihead_arity);
+
+ for_each_phi(loophead, phi) {
+ NEW_ARR_A(ir_node *, get_node_info(phi)->ins, lhead_arity);
+ }
+ for_each_phi(invhead, phi) {
+ NEW_ARR_A(ir_node *, get_node_info(phi)->ins, ihead_arity);
+ }
+
+ for (i = 0; i < headarity; i++) {
+ ir_node *pred = get_irn_n(loophead, i);
+
+ /**
+ * Rewire the head blocks ins and their phi ins.
+ * Requires phi list per block.
+ */
+ if (is_backedge(loophead, i) && !is_alien_edge(loophead, i)) {
+ /* just copy these edges */
+ loopheadnins[lheadin_c] = pred;
+ for_each_phi(loophead, phi) {
+ get_node_info(phi)->ins[lheadin_c] = get_irn_n(phi, i);
+ }
+ ++lheadin_c;