-/**
- * Make the mux for a given cond.
- *
- * @param phi The phi node which shall be replaced by a mux.
- * @param dom The block where the muxes shall be placed.
- * @param cond The cond information.
- * @param info The options for createing Mux nodes.
- * @return The mux node made for this cond.
- */
-static ir_node *make_mux_on_demand(ir_node *phi, ir_node *dom, cond_t *cond,
- const opt_if_conv_info_t *info, ir_node **mux, bitset_t *positions,
- int *muxes_made, long visited_nr)
-{
- int i, can_move[2];
- ir_node *projb = get_Cond_selector(cond->cond);
- ir_node *bl = get_nodes_block(cond->cond);
- ir_node *operands[2];
- int set[2];
-
- cond->visited_nr = visited_nr;
- DBG((dbg, LEVEL_2, "%n\n", cond->cond));
- for(i = 0; i < 2; ++i) {
- cond_t *masked_by = cond->cases[i].masked_by;
- int pos = cond->cases[i].pos;
-
- operands[i] = NULL;
- set[i] = -1;
-
- /*
- * If this Cond branch is masked by another cond, make the mux
- * for that Cond first, since the Mux for this cond takes
- * it as an operand.
- */
- if(masked_by) {
- assert(pos < 0);
- DBG((dbg, LEVEL_2, "\tmasked by: %n\n", masked_by->cond));
- if(masked_by->visited_nr < visited_nr)
- operands[i] = make_mux_on_demand(phi, dom, masked_by, info, mux, positions, muxes_made, visited_nr);
- }
-
- /*
- * If this cond branch is not masked by another cond, take
- * the corresponding phi operand as an operand to the mux.
- */
- else if(pos >= 0) {
- operands[i] = get_irn_n(phi, pos);
- set[i] = pos;
- }
- }
-
- /*
- * Move the operands to the dominator block if the cond
- * made sense. Some Conds found are not suitable for making a mux
- * out of them, since one of their branches cannot be reached from
- * the phi block. In that case we do not make a mux and return NULL.
- */
- if(operands[0] && operands[1]) {
- if (operands[0] == operands[1]) {
- /* there is no gain in using mux in this case, as
- it will be optimized away. We will NOT move the
- content of the blocks either
- */
- for (i = 0; i < 2; ++i)
- if(set[i] >= 0)
- bitset_set(positions, set[i]);
-
- *mux = operands[0];
- return *mux;
- }
-
- can_move[0] = can_move_to(operands[0], bl, info);
- can_move[1] = can_move_to(operands[1], bl, info);
-
- if (can_move[0] == SUCCESS && can_move[1] == SUCCESS) {
- if (info->allow_mux(projb, operands[0], operands[1])) {
- move_to(operands[0], bl);
- move_to(operands[1], bl);
-
- /* Make the mux. */
- *mux = new_r_Mux(current_ir_graph, bl, projb,
- operands[0], operands[1], get_irn_mode(operands[0]));
-
- *muxes_made += 1;
-
- DBG((dbg, LEVEL_2, "\t%n(%n, %n, %n)[%d, %d]\n",
- *mux, projb, operands[0], operands[1], set[0], set[1]));
-
- for(i = 0; i < 2; ++i)
- if(set[i] >= 0) {
- bitset_set(positions, set[i]);
-
- /* we have done one */
- hook_if_conversion(current_ir_graph, phi, set[i], *mux, IF_RESULT_SUCCESS);
- }
- }
- else {
- hook_if_conversion(current_ir_graph, phi, set[i], *mux, IF_RESULT_DENIED);
- }
- }
- else {
- if(can_move[0] != SUCCESS)
- hook_if_conversion(current_ir_graph, phi, set[0], NULL, can_move[0]);
- if(can_move[1] != SUCCESS)
- hook_if_conversion(current_ir_graph, phi, set[1], NULL, can_move[1]);
- }
- }
- else {
- if(operands[0])
- hook_if_conversion(current_ir_graph, phi, set[0], NULL, IF_RESULT_BAD_CF);
- if(operands[1])
- hook_if_conversion(current_ir_graph, phi, set[1], NULL, IF_RESULT_BAD_CF);
- }
-
- return *mux;
+ if (is_Mux(t)) {
+ ir_graph* irg = current_ir_graph;
+ ir_node* block = get_nodes_block(mux);
+ ir_mode* mode = get_irn_mode(mux);
+ ir_node* c0 = get_Mux_sel(mux);
+ ir_node* c1 = get_Mux_sel(t);
+ ir_node* t1 = get_Mux_true(t);
+ ir_node* f1 = get_Mux_false(t);
+ if (f == f1) {
+ /* Mux(c0, Mux(c1, x, y), y) -> typical if (c0 && c1) x else y */
+ ir_node* and_ = new_r_And(irg, block, c0, c1, mode_b);
+ ir_node* new_mux = new_r_Mux(irg, block, and_, f1, t1, mode);
+ exchange(mux, new_mux);
+ } else if (f == t1) {
+ /* Mux(c0, Mux(c1, x, y), x) */
+ ir_node* not_c1 = new_r_Not(irg, block, c1, mode_b);
+ ir_node* and_ = new_r_And(irg, block, c0, not_c1, mode_b);
+ ir_node* new_mux = new_r_Mux(irg, block, and_, t1, f1, mode);
+ exchange(mux, new_mux);
+ }
+ } else if (is_Mux(f)) {
+ ir_graph* irg = current_ir_graph;
+ ir_node* block = get_nodes_block(mux);
+ ir_mode* mode = get_irn_mode(mux);
+ ir_node* c0 = get_Mux_sel(mux);
+ ir_node* c1 = get_Mux_sel(f);
+ ir_node* t1 = get_Mux_true(f);
+ ir_node* f1 = get_Mux_false(f);
+ if (t == t1) {
+ /* Mux(c0, x, Mux(c1, x, y)) -> typical if (c0 || c1) x else y */
+ ir_node* or_ = new_r_Or(irg, block, c0, c1, mode_b);
+ ir_node* new_mux = new_r_Mux(irg, block, or_, f1, t1, mode);
+ exchange(mux, new_mux);
+ } else if (t == f1) {
+ /* Mux(c0, x, Mux(c1, y, x)) */
+ ir_node* not_c1 = new_r_Not(irg, block, c1, mode_b);
+ ir_node* or_ = new_r_Or(irg, block, c0, not_c1, mode_b);
+ ir_node* new_mux = new_r_Mux(irg, block, or_, t1, f1, mode);
+ exchange(mux, new_mux);
+ }
+ }