+
+ mode = get_irn_mode(loop_info.end_val);
+ const_null = new_Const(get_mode_null(mode));
+
+ /* TODO naming
+ * 1. Calculate first approach to count.
+ * Condition: (end - start) % step == 0 */
+ block1 = clone_block_sans_bes(loop_head, loop_head);
+ DB((dbg, LEVEL_4, "Duff block 1 %N\n", block1));
+
+ /* Create loop entry phis in first duff block
+ * as it becomes the loops preheader */
+ for_each_phi(loop_head, phi) {
+ /* Returns phis pred if phi would have arity 1*/
+ ir_node *new_phi = clone_phis_sans_bes(phi, loop_head, block1);
+
+ DB((dbg, LEVEL_4, "HEAD %N phi %N\n", loop_head, phi));
+ DB((dbg, LEVEL_4, "BLOCK1 %N phi %N\n", block1, new_phi));
+ }
+
+ ems = new_r_Sub(block1, loop_info.end_val, loop_info.start_val,
+ get_irn_mode(loop_info.end_val));
+ DB((dbg, LEVEL_4, "BLOCK1 sub %N\n", ems));
+
+
+ ems = new_Sub(loop_info.end_val, loop_info.start_val,
+ get_irn_mode(loop_info.end_val));
+
+ DB((dbg, LEVEL_4, "mod ins %N %N\n", ems, loop_info.step));
+ ems_mod = new_r_Mod(block1,
+ new_NoMem(),
+ ems,
+ loop_info.step,
+ mode,
+ op_pin_state_pinned);
+ ems_div = new_r_Div(block1,
+ new_NoMem(),
+ ems,
+ loop_info.step,
+ mode,
+ op_pin_state_pinned);
+
+ DB((dbg, LEVEL_4, "New module node %N\n", ems_mod));
+
+ ems_mod_proj = new_r_Proj(ems_mod, mode_Iu, pn_Mod_res);
+ cmp_null = new_r_Cmp(block1, ems_mod_proj, const_null, ir_relation_less);
+ ems_mode_cond = new_r_Cond(block1, cmp_null);
+
+ /* ems % step == 0 */
+ x_true = new_r_Proj(ems_mode_cond, mode_X, pn_Cond_true);
+ /* ems % step != 0 */
+ x_false = new_r_Proj(ems_mode_cond, mode_X, pn_Cond_false);
+
+ /* 2. Second block.
+ * Assures, duffs device receives a valid count.
+ * Condition:
+ * decreasing: count < 0
+ * increasing: count > 0
+ */
+ ins[0] = x_true;
+ ins[1] = x_false;
+
+ count_block = new_Block(2, ins);
+ DB((dbg, LEVEL_4, "Duff block 2 %N\n", count_block));
+
+
+ /* Increase loop-taken-count depending on the loop condition
+ * uses the latest iv to compare to. */
+ if (loop_info.latest_value == 1) {
+ /* ems % step == 0 : +0 */
+ true_val = new_Const(get_mode_null(mode));
+ /* ems % step != 0 : +1 */
+ false_val = new_Const(get_mode_one(mode));
+ } else {
+ ir_tarval *tv_two = new_tarval_from_long(2, mode);
+ /* ems % step == 0 : +1 */
+ true_val = new_Const(get_mode_one(mode));
+ /* ems % step != 0 : +2 */
+ false_val = new_Const(tv_two);
+ }
+
+ ins[0] = true_val;
+ ins[1] = false_val;
+
+ correction = new_r_Phi(count_block, 2, ins, mode);
+
+ count = new_r_Proj(ems_div, mode, pn_Div_res);
+
+ /* (end - start) / step + correction */
+ count = new_Add(count, correction, mode);
+
+ /* We preconditioned the loop to be tail-controlled.
+ * So, if count is something 'wrong' like 0,
+ * negative/positive (depending on step direction),
+ * we may take the loop once (tail-contr.) and leave it
+ * to the existing condition, to break; */
+
+ /* Depending on step direction, we have to check for > or < 0 */
+ if (loop_info.decreasing == 1) {
+ cmp_bad_count = new_r_Cmp(count_block, count, const_null,
+ ir_relation_less);
+ } else {
+ cmp_bad_count = new_r_Cmp(count_block, count, const_null,
+ ir_relation_greater);
+ }
+
+ bad_count_neg = new_r_Cond(count_block, cmp_bad_count);
+ good_count = new_Proj(bad_count_neg, mode_X, pn_Cond_true);
+ bad_count = new_Proj(ems_mode_cond, mode_X, pn_Cond_false);
+
+ /* 3. Duff Block
+ * Contains module to decide which loop to start from. */
+
+ ins[0] = good_count;
+ ins[1] = bad_count;
+ duff_block = new_Block(2, ins);
+ DB((dbg, LEVEL_4, "Duff block 3 %N\n", duff_block));
+
+ /* Get absolute value */
+ ins[0] = new_Abs(count, mode);
+ /* Manually feed the aforementioned count = 1 (bad case)*/
+ ins[1] = new_Const(get_mode_one(mode));
+ count_phi = new_r_Phi(duff_block, 2, ins, mode);
+
+ unroll_c = new_Const(new_tarval_from_long((long)unroll_nr, mode));
+
+ /* count % unroll_nr */
+ duff_mod = new_r_Mod(duff_block,
+ new_NoMem(),
+ count_phi,
+ unroll_c,
+ mode,
+ op_pin_state_pinned);
+
+
+ proj = new_Proj(duff_mod, mode, pn_Mod_res);
+ /* condition does NOT create itself in the block of the proj! */
+ cond = new_r_Cond(duff_block, proj);
+
+ loop_info.duff_cond = cond;
+}
+
+/* Returns 1 if given node is not in loop,
+ * or if it is a phi of the loop head with only loop invariant defs.
+ */
+static unsigned is_loop_invariant_def(ir_node *node)
+{