+ list_for_each_entry(block_t, bl, &part->blocks, block_list) {
+ block = bl->block;
+
+ DB((dbg, LEVEL_1, "%+F, ", block));
+
+ /* first step: kill any keep-alive from this block */
+ for (i = get_End_n_keepalives(end) - 1; i >= 0; --i) {
+ ir_node *ka = get_End_keepalive(end, i);
+
+ if (is_Block(ka)) {
+ if (ka == block)
+ remove_End_keepalive(end, ka);
+ } else {
+ if (get_nodes_block(ka) == block)
+ remove_End_keepalive(end, ka);
+ }
+ }
+
+ /* second step: update control flow */
+ n = get_Block_n_cfgpreds(block);
+ for (i = 0; i < n; ++i) {
+ ir_node *pred = get_Block_cfgpred(block, i);
+ ARR_APP1(ir_node *, ins, pred);
+ }
+
+ /* third step: update Phis */
+ for (repr_phi = repr->phis, phi = bl->phis;
+ repr_phi != NULL;
+ repr_phi = repr_phi->next, phi = phi->next) {
+ for (i = 0; i < n; ++i) {
+ ir_node *pred = get_Phi_pred(phi->phi, i);
+ ARR_APP1(ir_node *, repr_phi->ins, pred);
+ }
+ }
+
+ /* fourth step: update inputs for new Phis */
+ for (repr_pair = repr->input_pairs, pair = bl->input_pairs;
+ repr_pair != NULL;
+ repr_pair = repr_pair->next, pair = pair->next) {
+ ir_node *input = get_irn_n(pair->irn, pair->index);
+
+ for (i = 0; i < n; ++i)
+ ARR_APP1(ir_node *, repr_pair->ins, input);
+ }
+ }
+
+ DB((dbg, LEVEL_1, "by %+F\n", repr->block));
+
+ /* rewire block input ... */
+ n = ARR_LEN(ins);
+
+ /*
+ * Some problem here. For:
+ * if (x) y = 1; else y = 2;
+ *
+ * the following code is constructed:
+ *
+ * b0: if (x) goto b1; else goto b1;
+ * b1: y = Phi(1,2)
+ *
+ * However, both predecessors of b1 are b0, making the Phi
+ * "wrong".
+ *
+ * We solve this by fixing critical edges.
+ */
+ for (i = 0; i < n; ++i) {
+ ir_node *pred = ins[i];
+ const ir_op *cfop;
+
+ if (is_Bad(pred))
+ continue;
+
+ cfop = get_irn_op(skip_Proj(pred));
+ if (is_op_fragile(cfop)) {
+ /* ignore exception flow */
+ continue;
+ }
+ if (is_op_forking(cfop)) {
+ /* a critical edge */
+ ir_node *block = new_r_Block(irg, 1, &ins[i]);
+ ir_node *jmp = new_r_Jmp(block);
+ ins[i] = jmp;
+ }
+ }
+
+ block = repr->block;
+ set_irn_in(block, n, ins);
+ DEL_ARR_F(ins);
+
+ /* ... existing Phis ... */
+ for (repr_phi = repr->phis; repr_phi != NULL; repr_phi = repr_phi->next) {
+ set_irn_in(repr_phi->phi, n, repr_phi->ins);
+ DEL_ARR_F(repr_phi->ins);
+ }
+
+ /* ... and all inputs by creating new Phis ... */
+ for (repr_pair = repr->input_pairs; repr_pair != NULL; repr_pair = repr_pair->next) {
+ ir_node *input = get_irn_n(repr_pair->irn, repr_pair->index);
+ ir_mode *mode = get_irn_mode(input);
+ ir_node *phi = new_r_Phi(block, n, repr_pair->ins, mode);
+
+ set_irn_n(repr_pair->irn, repr_pair->index, phi);
+ DEL_ARR_F(repr_pair->ins);
+
+ /* might be optimized away */
+ if (is_Phi(phi))
+ add_Block_phi(block, phi);
+ }
+
+ /* ... finally rewire the meet block and fix its Phi-nodes */
+ meet_block = part->meet_block;
+ n = get_Block_n_cfgpreds(meet_block);
+
+ ins = NEW_ARR_F(ir_node *, n);
+
+ n_phis = 0;
+ for (p = get_Block_phis(meet_block); p != NULL; p = get_Phi_next(p)) {
+ ++n_phis;
+ }
+
+ phi_ins = NEW_ARR_F(ir_node *, n_phis * n);
+
+ for (i = j = 0; i < n; ++i) {
+ ir_node *pred = get_Block_cfgpred(meet_block, i);
+
+ list_for_each_entry(block_t, bl, &part->blocks, block_list) {
+ if (bl->cf_root->node == pred)
+ goto continue_outer;
+ }
+ ins[j] = pred;
+
+ for (k = 0, p = get_Block_phis(meet_block); p != NULL; p = get_Phi_next(p), ++k) {
+ phi_ins[k * n + j] = get_Phi_pred(p, i);
+ }
+ ++j;
+
+continue_outer:
+ ;
+ }
+
+ /* fix phis */
+ if (j == 1) {
+ for (k = 0, p = get_Block_phis(meet_block); p != NULL; p = next, ++k) {
+ next = get_Phi_next(p);
+
+ exchange(p, phi_ins[k * n]);
+ }
+ /* all Phis killed */
+ set_Block_phis(meet_block, NULL);
+ } else {
+ for (k = 0, p = get_Block_phis(meet_block); p != NULL; p = next, ++k) {
+ next = get_Phi_next(p);
+
+ set_irn_in(p, j, &phi_ins[k * n]);
+ }
+ }
+ DEL_ARR_F(phi_ins);
+
+ /* fix inputs of the meet block */
+ set_irn_in(meet_block, j, ins);
+ DEL_ARR_F(ins);
+} /* apply */
+
+/**
+ * Create a partition for a the end block.
+ *
+ * @param end_block the end block
+ * @param env the environment
+ */
+static void partition_for_end_block(ir_node *end_block, environment_t *env)
+{
+ partition_t *part = create_partition(end_block, env);
+ ir_node *end;
+ int i;
+
+ /* collect normal blocks */
+ for (i = get_Block_n_cfgpreds(end_block) - 1; i >= 0; --i) {
+ ir_node *pred = get_Block_cfgpred(end_block, i);
+ ir_node *block;
+ block_t *bl;
+ node_t *node;
+
+ mark_irn_visited(pred);
+
+ block = get_nodes_block(pred);
+ bl = create_block(block, i, part, env);
+ node = create_node(pred, bl, env);
+
+ bl->cf_root = node;
+ }
+
+ /* collect all no-return blocks */
+ end = get_irg_end(get_irn_irg(end_block));