+/**
+ * Store to defer the exchanged of Phi nodes.
+ */
+typedef struct _defer_ex_phi {
+ ir_node *phi_pred; /**< the previous Phi node that will be replaced */
+ ir_node *phi; /**< the new Phi node that replaces phi_pred */
+} defer_ex_phi;
+
+/**
+ * handle pre-optimized table switch Cond's
+ */
+static void handle_switch_cond(ir_node *proj) {
+ ir_node *cond = skip_Proj(proj);
+ ir_node *sel;
+
+ if (! is_Cond(cond))
+ return;
+
+ sel = get_Cond_selector(cond);
+ if (mode_is_int(get_irn_mode(sel))) {
+ /* check for table switch that could be optimized */
+ ir_node *proj1 = get_irn_link(cond);
+ ir_node *proj2 = get_irn_link(proj1);
+ ir_node *jmp, *blk;
+
+ blk = is_Bad(cond) ? cond : get_nodes_block(cond);
+
+ if (! proj2) {
+ /* this Cond has only one Proj: must be the defProj */
+ assert(get_Cond_defaultProj(cond) == get_Proj_proj(proj1));
+ /* convert it into a Jmp */
+ jmp = new_r_Jmp(current_ir_graph, blk);
+ exchange(proj1, jmp);
+ }
+ else if (get_irn_link(proj2) == NULL) {
+ /* We have two Proj's here. Check if the Cond has
+ a constant argument */
+ tarval *tv = value_of(sel);
+
+ if (tv != tarval_bad) {
+ /* we have a constant switch */
+ long num = get_tarval_long(tv);
+ long def_num = get_Cond_defaultProj(cond);
+
+ if (def_num == get_Proj_proj(proj1)) {
+ /* first one is the defProj */
+ if (num == get_Proj_proj(proj2)) {
+ jmp = new_r_Jmp(current_ir_graph, blk);
+ exchange(proj2, jmp);
+ exchange(proj1, new_Bad());
+ }
+ }
+ else if (def_num == get_Proj_proj(proj2)) {
+ /* second one is the defProj */
+ if (num == get_Proj_proj(proj1)) {
+ jmp = new_r_Jmp(current_ir_graph, blk);
+ exchange(proj1, jmp);
+ exchange(proj2, new_Bad());
+ }
+ }
+ else {
+ /* neither: strange, Cond was not optimized so far */
+ if (num == get_Proj_proj(proj1)) {
+ jmp = new_r_Jmp(current_ir_graph, blk);
+ exchange(proj1, jmp);
+ exchange(proj2, new_Bad());
+ }
+ else if (num == get_Proj_proj(proj2)) {
+ jmp = new_r_Jmp(current_ir_graph, blk);
+ exchange(proj2, jmp);
+ exchange(proj1, new_Bad());
+ }
+ }
+ }
+ }
+ }
+}
+
+/**
+ * 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.
+ */