/** * Transforms a Cmp into the appropriate soft float function. */ static bool lower_Cmp(ir_node *const n) { ir_node *const left = get_Cmp_left(n); ir_mode *const op_mode = get_irn_mode(left); if (!mode_is_float(op_mode)) return false; dbg_info *const dbgi = get_irn_dbg_info(n); ir_graph *const irg = get_irn_irg(n); ir_node *const zero = new_rd_Const_null(dbgi, irg, mode_Is); char const *name = NULL; char const *name2 = NULL; ir_node *result = NULL; ir_relation relation = get_Cmp_relation(n); switch (relation) { case ir_relation_false: result = zero; break; case ir_relation_equal: name = "eq"; break; case ir_relation_less: name = "lt"; break; case ir_relation_greater: name = "gt"; break; case ir_relation_unordered: name = "unord"; relation = ir_relation_less_greater; break; case ir_relation_less_equal: name = "le"; break; case ir_relation_greater_equal: name = "ge"; break; case ir_relation_less_greater: name = "unord"; name2 = "ne"; break; case ir_relation_less_equal_greater: name = "unord"; relation = ir_relation_equal; break; case ir_relation_unordered_equal: name = "unord"; relation = ir_relation_less_greater; name2 = "ne"; break; case ir_relation_unordered_less: name = "ge"; relation = ir_relation_less; break; case ir_relation_unordered_less_equal: name = "gt"; relation = ir_relation_less_equal; break; case ir_relation_unordered_greater: name = "le"; relation = ir_relation_greater; break; case ir_relation_unordered_greater_equal: name = "lt"; relation = ir_relation_greater_equal; break; case ir_relation_unordered_less_greater: name = "eq"; relation = ir_relation_less_greater; break; case ir_relation_true: result = zero; break; } ir_node *const block = get_nodes_block(n); ir_node *const right = get_Cmp_right(n); if (result == NULL) { ir_node *const in[] = { left, right }; result = make_softfloat_call(n, name, ARRAY_SIZE(in), in); } ir_node *cmp = new_r_Cmp(block, result, zero, relation); /* We need two calls into the softfloat library */ if (name2 != NULL) { ir_node *const in[] = { left, right }; result = make_softfloat_call(n, name2, ARRAY_SIZE(in), in); relation = get_Cmp_relation(n); ir_node *const mux = new_rd_Mux(dbgi, block, cmp, result, zero); arch_allow_ifconv_func const allow_ifconv = be_get_backend_param()->allow_ifconv; if (!allow_ifconv(cmp, result, zero)) ir_nodeset_insert(&created_mux_nodes, mux); cmp = new_r_Cmp(block, mux, zero, relation); } exchange(n, cmp); return true; }
/** * Compute the weight of a method parameter * * @param arg The parameter them weight muss be computed. */ static unsigned calc_method_param_weight(ir_node *arg) { /* We mark the nodes to avoid endless recursion */ mark_irn_visited(arg); unsigned weight = null_weight; for (int i = get_irn_n_outs(arg); i-- > 0; ) { ir_node *succ = get_irn_out(arg, i); if (irn_visited(succ)) continue; /* We should not walk over the memory edge.*/ if (get_irn_mode(succ) == mode_M) continue; switch (get_irn_opcode(succ)) { case iro_Call: if (get_Call_ptr(succ) == arg) { /* the arguments is used as an pointer input for a call, we can probably change an indirect Call into a direct one. */ weight += indirect_call_weight; } break; case iro_Cmp: { /* We have reached a cmp and we must increase the weight with the cmp_weight. */ ir_node *op; if (get_Cmp_left(succ) == arg) op = get_Cmp_right(succ); else op = get_Cmp_left(succ); if (is_irn_constlike(op)) { weight += const_cmp_weight; } else weight += cmp_weight; break; } case iro_Cond: /* the argument is used for a SwitchCond, a big win */ weight += const_cmp_weight * get_irn_n_outs(succ); break; case iro_Id: /* when looking backward we might find Id nodes */ weight += calc_method_param_weight(succ); break; case iro_Tuple: /* unoptimized tuple */ for (int j = get_Tuple_n_preds(succ); j-- > 0; ) { ir_node *pred = get_Tuple_pred(succ, j); if (pred == arg) { /* look for Proj(j) */ for (int k = get_irn_n_outs(succ); k-- > 0; ) { ir_node *succ_succ = get_irn_out(succ, k); if (is_Proj(succ_succ)) { if (get_Proj_proj(succ_succ) == j) { /* found */ weight += calc_method_param_weight(succ_succ); } } else { /* this should NOT happen */ } } } } break; default: if (is_binop(succ)) { /* We have reached a BinOp and we must increase the weight with the binop_weight. If the other operand of the BinOp is a constant we increase the weight with const_binop_weight and call the function recursive. */ ir_node *op; if (get_binop_left(succ) == arg) op = get_binop_right(succ); else op = get_binop_left(succ); if (is_irn_constlike(op)) { weight += const_binop_weight; weight += calc_method_param_weight(succ); } else weight += binop_weight; } else if (get_irn_arity(succ) == 1) { /* We have reached a binop and we must increase the weight with the const_binop_weight and call the function recursive.*/ weight += const_binop_weight; weight += calc_method_param_weight(succ); } break; } } set_irn_link(arg, NULL); return weight; }