+ int i, j, n_preds = 1;
+ ir_node *pred = get_Block_cfgpred_block(b, pos);
+
+ /* Bad blocks will be optimized away, so we don't need space for them */
+ if (is_Block_dead(pred))
+ return 0;
+
+ if (is_Block_removable(pred)) {
+ if (!get_opt_optimize() || !get_opt_control_flow_strong_simplification()) {
+ /* Mark block so that is will not be removed: optimization is turned off. */
+ set_Block_non_removable(pred);
+ return 1;
+ }
+
+ /* Seems to be empty. At least we detected this in collect_nodes. */
+ if (get_irn_link(b) == NULL) {
+ /* There are no Phi nodes ==> all predecessors are dispensable. */
+ n_preds = get_Block_n_cfgpreds(pred);
+ } else {
+ /* b's pred blocks and pred's pred blocks must be pairwise disjunct.
+ Handle all pred blocks with preds < pos as if they were already removed. */
+ for (i = 0; i < pos; i++) {
+ ir_node *b_pred = get_Block_cfgpred_block(b, i);
+ if (! is_Block_dead(b_pred) && is_Block_removable(b_pred)) {
+ for (j = get_Block_n_cfgpreds(b_pred) - 1; j >= 0; --j) {
+ ir_node *b_pred_pred = get_Block_cfgpred_block(b_pred, j);
+ if (is_pred_of(b_pred_pred, pred))
+ goto non_dispensable;
+ }
+ } else {
+ if (is_pred_of(b_pred, pred))
+ goto non_dispensable;
+ }
+ }
+ for (i = pos +1; i < get_Block_n_cfgpreds(b); i++) {
+ ir_node *b_pred = get_Block_cfgpred_block(b, i);
+ if (is_pred_of(b_pred, pred))
+ goto non_dispensable;
+ }
+ /* if we get here, the block is dispensable */
+ n_preds = get_Block_n_cfgpreds(pred);
+ }
+ }
+
+ return n_preds;
+
+non_dispensable:
+ set_Block_non_removable(pred);
+ return 1;
+}
+
+/**
+ * This method removed Bad cf predecessors from Blocks and Phis, and removes
+ * empty blocks. A block is empty if it only contains Phi and Jmp nodes.
+ *
+ * We first adapt Phi nodes, then Block nodes, as we need the old ins
+ * of the Block to adapt the Phi nodes. We do this by computing new
+ * in arrays, and then replacing the old ones. So far we compute new in arrays
+ * for all nodes, not regarding whether there is a possibility for optimization.
+ *
+ * For each predecessor p of a Block b there are three cases:
+ * -1. The predecessor p is a Bad node: just skip it. The in array of b shrinks by one.
+ * -2. The predecessor p is empty. Remove p. All predecessors of p are now
+ * predecessors of b.
+ * -3. The predecessor p is a block containing useful code. Just keep p as is.
+ *
+ * For Phi nodes f we have to check the conditions at the Block of f.
+ * For cases 1 and 3 we proceed as for Blocks. For case 2 we can have two
+ * cases:
+ * -2a: The old predecessor of the Phi f is a Phi pred_f IN THE BLOCK REMOVED. In this
+ * case we proceed as for blocks. We remove pred_f. All
+ * predecessors of pred_f now are predecessors of f.
+ * -2b: The old predecessor of f is NOT in the block removed. It might be a Phi, too.
+ * We have to replicate f for each predecessor of the removed block. Or, with
+ * other words, the removed predecessor block has exactly one predecessor.
+ *
+ * Further there is a special case for self referencing blocks:
+ * @verbatim
+ *
+ * then_b else_b then_b else_b
+ * \ / \ /
+ * \ / | /
+ * pred_b | /
+ * | ____ | / ____
+ * | | | | | | |
+ * | | | === optimized to ===> \ | | |
+ * loop_b | loop_b |
+ * | | | | | |
+ * | |____| | |____|
+ * | |
+ * @endverbatim
+ *
+ * If there is a Phi in pred_b, but we remove pred_b, we have to generate a
+ * Phi in loop_b, that has the ins of the Phi in pred_b and a self referencing
+ * backedge.
+ * @@@ It is negotiable whether we should do this ... there might end up a copy
+ * from the Phi in the loop when removing the Phis.
+ */
+static void optimize_blocks(ir_node *b, void *ctx) {
+ int i, j, k, n, max_preds, n_preds, p_preds = -1;
+ ir_node *pred, *phi;
+ ir_node **in;
+ merge_env *env = ctx;
+
+ /* Count the number of predecessor if this block is merged with pred blocks
+ that are empty. */
+ max_preds = 0;
+ for (i = 0, k = get_Block_n_cfgpreds(b); i < k; ++i) {
+ max_preds += test_whether_dispensable(b, i);
+ }
+ in = xmalloc(max_preds * sizeof(*in));
+
+ /*- Fix the Phi nodes of the current block -*/
+ for (phi = get_irn_link(b); phi; ) {
+ assert(get_irn_op(phi) == op_Phi);
+
+ /* Find the new predecessors for the Phi */
+ p_preds = 0;
+ for (i = 0, n = get_Block_n_cfgpreds(b); i < n; ++i) {
+ pred = get_Block_cfgpred_block(b, i);
+
+ if (is_Block_dead(pred)) {
+ /* case Phi 1: Do nothing */
+ }
+ else if (is_Block_removable(pred) && Block_not_block_visited(pred)) {
+ /* case Phi 2: It's an empty block and not yet visited. */
+ ir_node *phi_pred = get_Phi_pred(phi, i);
+
+ for (j = 0, k = get_Block_n_cfgpreds(pred); j < k; j++) {
+ /* because of breaking loops, not all predecessors are Bad-clean,
+ * so we must check this here again */
+ if (! is_Bad(get_Block_cfgpred(pred, j))) {
+ if (get_nodes_block(phi_pred) == pred) {
+ /* case Phi 2a: */
+ assert(get_irn_op(phi_pred) == op_Phi); /* Block is empty!! */
+
+ in[p_preds++] = get_Phi_pred(phi_pred, j);
+ } else {
+ /* case Phi 2b: */
+ in[p_preds++] = phi_pred;
+ }
+ }
+ }
+ } else {
+ /* case Phi 3: */
+ in[p_preds++] = get_Phi_pred(phi, i);
+ }
+ }
+ assert(p_preds <= max_preds);
+
+ /* Fix the node */
+ if (p_preds == 1)
+ /* By removal of Bad ins the Phi might be degenerated. */
+ exchange(phi, in[0]);
+ else
+ set_irn_in(phi, p_preds, in);
+ env->changed = 1;
+
+ phi = get_irn_link(phi);
+ }
+
+ /*- This happens only if merge between loop backedge and single loop entry.
+ Moreover, it is only needed if predb is the direct dominator of b, else there can be no uses
+ of the Phi's in predb ... -*/
+ for (k = 0, n = get_Block_n_cfgpreds(b); k < n; ++k) {
+ ir_node *predb = get_nodes_block(get_Block_cfgpred(b, k));
+
+ if (is_Block_removable(predb) && Block_not_block_visited(predb)) {
+ ir_node *next_phi;
+
+ /* we found a predecessor block at position k that will be removed */
+ for (phi = get_irn_link(predb); phi; phi = next_phi) {
+ int q_preds = 0;
+ next_phi = get_irn_link(phi);
+
+ assert(is_Phi(phi));
+
+ if (get_Block_idom(b) != predb) {
+ /* predb is not the dominator. There can't be uses of pred's Phi nodes, kill them .*/
+ exchange(phi, new_Bad());
+ } else {
+ /* predb is the direct dominator of b. There might be uses of the Phi nodes from
+ predb in further block, so move this phi from the predecessor into the block b */
+ set_nodes_block(phi, b);
+ set_irn_link(phi, get_irn_link(b));
+ set_irn_link(b, phi);
+ env->phis_moved = 1;
+
+ /* first, copy all 0..k-1 predecessors */
+ for (i = 0; i < k; i++) {
+ pred = get_Block_cfgpred_block(b, i);
+
+ if (is_Block_dead(pred)) {
+ /* Do nothing */
+ } else if (is_Block_removable(pred) && Block_not_block_visited(pred)) {
+ /* It's an empty block and not yet visited. */
+ for (j = 0; j < get_Block_n_cfgpreds(pred); j++) {
+ if (! is_Bad(get_Block_cfgpred(pred, j)))
+ in[q_preds++] = phi;
+ }
+ } else {
+ in[q_preds++] = phi;
+ }
+ }
+
+ /* now we are at k, copy the phi predecessors */
+ pred = get_nodes_block(get_Block_cfgpred(b, k));
+ for (i = 0; i < get_Phi_n_preds(phi); i++) {
+ if (! is_Bad(get_Block_cfgpred(pred, i)))
+ in[q_preds++] = get_Phi_pred(phi, i);
+ }
+
+ /* and now all the rest */
+ for (i = k+1; i < get_Block_n_cfgpreds(b); i++) {
+ pred = get_Block_cfgpred_block(b, i);
+
+ if (is_Block_dead(pred)) {
+ /* Do nothing */
+ } else if (is_Block_removable(pred) && Block_not_block_visited(pred)) {
+ /* It's an empty block and not yet visited. */
+ for (j = 0; j < get_Block_n_cfgpreds(pred); j++) {
+ if (! is_Bad(get_Block_cfgpred(pred, j)))
+ in[q_preds++] = phi;
+ }
+ } else {
+ in[q_preds++] = phi;
+ }
+ }
+
+ /* Fix the node */
+ if (q_preds == 1)
+ exchange(phi, in[0]);
+ else
+ set_irn_in(phi, q_preds, in);
+ env->changed = 1;
+
+ assert(q_preds <= max_preds);
+ // assert(p_preds == q_preds && "Wrong Phi Fix");
+ }
+ }
+ }
+ }
+
+ /*- Fix the block -*/
+ n_preds = 0;
+ for (i = 0; i < get_Block_n_cfgpreds(b); i++) {
+ pred = get_Block_cfgpred_block(b, i);
+
+ if (is_Block_dead(pred)) {
+ /* case 1: Do nothing */
+ } else if (is_Block_removable(pred) && Block_not_block_visited(pred)) {
+ /* case 2: It's an empty block and not yet visited. */
+ assert(get_Block_n_cfgpreds(b) > 1);
+ /* Else it should be optimized by equivalent_node. */
+ for (j = 0; j < get_Block_n_cfgpreds(pred); j++) {
+ ir_node *pred_X = get_Block_cfgpred(pred, j);
+
+ /* because of breaking loops, not all predecessors are Bad-clean,
+ * so we must check this here again */
+ if (! is_Bad(pred_X))
+ in[n_preds++] = pred_X;
+ }
+ /* Remove block as it might be kept alive. */
+ exchange(pred, b/*new_Bad()*/);
+ } else {
+ /* case 3: */
+ in[n_preds++] = get_Block_cfgpred(b, i);
+ }
+ }
+ assert(n_preds <= max_preds);
+
+ set_irn_in(b, n_preds, in);
+ env->changed = 1;
+
+ assert(get_irn_link(b) == NULL || p_preds == -1 || (n_preds == p_preds && "Wrong Phi Fix"));
+ xfree(in);
+}
+
+/**
+ * Block walker: optimize all blocks using the default optimizations.
+ * This removes Blocks that with only a Jmp predecessor.
+ */
+static void remove_simple_blocks(ir_node *block, void *ctx) {
+ ir_node *new_blk = equivalent_node(block);
+ merge_env *env = ctx;
+
+ if (new_blk != block) {
+ exchange(block, new_blk);
+ env->changed = 1;
+ }