- ir_node* pred = get_irn_n(block, i);
- ir_node* pred_block;
- block_info* info;
- ir_node* phi;
- int pred_arity;
- int arity;
- ir_node** ins;
- int j;
-
- if (get_irn_op(pred) != op_Jmp) return 0;
- pred_block = get_nodes_block(pred);
-
- if (!has_multiple_cdep(pred_block)) return 0;
- if (!can_empty_block(pred_block)) return 0;
-
- ir_fprintf(stderr, "Fissioning block %+F\n", pred_block);
-
- pred_arity = get_irn_arity(pred_block);
- arity = get_irn_arity(block);
- info = get_irn_link(block);
- ins = xmalloc(sizeof(*ins) * (arity + pred_arity - 1));
- for (phi = info->phi; phi != NULL; phi = get_irn_link(phi)) {
- for (j = 0; j < i; ++j) ins[j] = get_irn_n(phi, j);
- for (j = 0; j < pred_arity; ++j) {
- ins[i + j] = copy_to(get_irn_n(phi, i), pred_block, j);
- }
- for (j = i + 1; j < arity; ++j) {
- ins[pred_arity - 1 + j] = get_irn_n(phi, j);
- }
- set_irn_in(phi, arity + pred_arity - 1, ins);
- }
- for (j = 0; j < i; ++j) ins[j] = get_irn_n(block, j);
- for (j = 0; j < pred_arity; ++j) ins[i + j] = get_irn_n(pred_block, j);
- for (j = i + 1; j < arity; ++j) ins[pred_arity - 1 + j] = get_irn_n(block, j);
- set_irn_in(block, arity + pred_arity - 1, ins);
- xfree(ins);
-
- /* Kill all Phis in the fissioned block
- * This is to make sure they're not kept alive
- */
- info = get_irn_link(pred_block);
- phi = info->phi;
- while (phi != NULL) {
- ir_node* next = get_irn_link(phi);
- exchange(phi, new_Bad());
- phi = next;
- }
- return 1;
-}
-
-
-static void if_conv_walker(ir_node* block, void* env)
-{
- ir_node* phi;
- int arity;
- int i;
-
- // Bail out, if there are no Phis at all
- if (get_block_blockinfo(block)->phi == NULL) return;
-
-restart:
- arity = get_irn_arity(block);
- for (i = 0; i < arity; ++i) {
- if (fission_block(block, i)) goto restart;
- }
- //return;
-
- arity = get_irn_arity(block);
- for (i = 0; i < arity; ++i) {
- ir_node* pred;
- ir_node* cond;
- ir_node* projx0;
- int j;
-
- projx0 = walk_to_projx(get_irn_n(block, i));
- if (projx0 == NULL) return;
- pred = get_Proj_pred(projx0);
- if (get_irn_op(pred) != op_Cond || get_irn_mode(get_Cond_selector(pred)) != mode_b) continue;
- cond = pred;
-
- if (!can_empty_block(get_nodes_block(get_irn_n(block, i)))) {
- ir_fprintf(stderr, "Cannot empty block %+F\n",
- get_nodes_block(get_irn_n(block, i))
- );
- continue;
- }
-
- for (j = i + 1; j < arity; ++j) {
- ir_node* projx1;
- ir_node* psi_block;
- ir_node* conds[1];
- ir_node* vals[2];
- ir_node* psi;
-
- projx1 = walk_to_projx(get_irn_n(block, j));
- if (projx1 == NULL) continue;
- pred = get_Proj_pred(projx1);
- if (get_irn_op(pred) != op_Cond || get_irn_mode(get_Cond_selector(pred)) != mode_b) continue;
- if (pred != cond) continue;
- ir_fprintf(stderr, "Found Cond %+F with proj %+F and %+F\n", cond, projx0, projx1);
-
- if (!can_empty_block(get_nodes_block(get_irn_n(block, j)))) {
- ir_fprintf(stderr, "Cannot empty block %+F\n",
- get_nodes_block(get_irn_n(block, j))
- );
- continue;
- }
-
- conds[0] = get_Cond_selector(cond);
-
- psi_block = get_nodes_block(cond);
- phi = get_block_blockinfo(block)->phi;
- do {
- // Don't generate PsiMs
- if (get_irn_mode(phi) == mode_M) {
- /* Something is very fishy if to predecessors of a PhiM point into the
- * block but not at the same memory node
- */
- assert(get_irn_n(phi, i) == get_irn_n(phi, j));
- // fake memory Psi
- psi = get_irn_n(phi, i);
- ir_fprintf(stderr, "Handling memory Phi %+F\n", phi);
- } else {
- if (get_Proj_proj(projx0) == pn_Cond_true) {
- vals[0] = get_irn_n(phi, i);
- vals[1] = get_irn_n(phi, j);
- } else {
- vals[0] = get_irn_n(phi, j);
- vals[1] = get_irn_n(phi, i);
- }
- psi = new_r_Psi(
- current_ir_graph, psi_block, 1, conds, vals, get_irn_mode(phi)
- );
- ir_fprintf(stderr, "Generating %+F for %+F\n", psi, phi);
- }
-
- if (arity == 2) {
- exchange(phi, psi);
- } else {
- ir_node** ins = xmalloc(sizeof(*ins) * (arity - 1));
- int k;
- int l;
-
- l = 0;
- for (k = 0; k < i; ++k) ins[l++] = get_irn_n(phi, k);
- for (++k; k < j; ++k) ins[l++] = get_irn_n(phi, k);
- for (++k; k < arity; ++k) ins[l++] = get_irn_n(phi, k);
- ins[l++] = psi;
- assert(l == arity - 1);
- set_irn_in(phi, l, ins);
-
- xfree(ins);
- }
-
- phi = get_irn_link(phi);
- } while (phi != NULL && get_irn_op(phi) == op_Phi);
-
- exchange(get_nodes_block(get_irn_n(block, i)), psi_block);
- exchange(get_nodes_block(get_irn_n(block, j)), psi_block);
-
- if (arity == 2) {
- ir_fprintf(stderr, "Welding block %+F to %+F\n", block, psi_block);
- get_block_blockinfo(psi_block)->evil |= get_block_blockinfo(block)->evil;
- exchange(block, psi_block);
- return;
- } else {
- ir_node** ins = xmalloc(sizeof(*ins) * (arity - 1));
- int k;
- int l;
-
- l = 0;
- for (k = 0; k < i; ++k) ins[l++] = get_irn_n(block, k);
- for (++k; k < j; ++k) ins[l++] = get_irn_n(block, k);
- for (++k; k < arity; ++k) ins[l++] = get_irn_n(block, k);
- ins[l++] = new_r_Jmp(current_ir_graph, psi_block);
- assert(l == arity - 1);
- set_irn_in(block, l, ins);
-
- xfree(ins);
- goto restart;
- }
- }
- }
-}