X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=ir%2Fopt%2Fopt_inline.c;h=59e10edb5bf1106c9bc112345b7b14a70caa9eeb;hb=7213344d377bb242491dfb0c291b43157c3c81d6;hp=ccd33dc0761d51271924d45b95ceddd59dbc7f8e;hpb=b6945a03ace58eb97cfaf05d0711d02af71b36c0;p=libfirm diff --git a/ir/opt/opt_inline.c b/ir/opt/opt_inline.c index ccd33dc07..59e10edb5 100644 --- a/ir/opt/opt_inline.c +++ b/ir/opt/opt_inline.c @@ -164,15 +164,10 @@ static void copy_node(ir_node *n, void *env) { } copy_node_attr(n, nn); -#ifdef DEBUG_libfirm - { - int copy_node_nr = env != NULL; - if (copy_node_nr) { - /* for easier debugging, we want to copy the node numbers too */ - nn->node_nr = n->node_nr; - } + if (env != NULL) { + /* for easier debugging, we want to copy the node numbers too */ + nn->node_nr = n->node_nr; } -#endif set_new_node(n, nn); hook_dead_node_elim_subst(current_ir_graph, n, nn); @@ -221,9 +216,10 @@ static void copy_preds(ir_node *n, void *env) { in array contained Bads. Now it's possible. We don't call optimize_in_place as it requires that the fields in ir_graph are set properly. */ - if ((get_opt_control_flow_straightening()) && - (get_Block_n_cfgpreds(nn) == 1) && - is_Jmp(get_Block_cfgpred(nn, 0))) { + if (!has_Block_entity(nn) && + get_opt_control_flow_straightening() && + get_Block_n_cfgpreds(nn) == 1 && + is_Jmp(get_Block_cfgpred(nn, 0))) { ir_node *old = get_nodes_block(get_Block_cfgpred(nn, 0)); if (nn == old) { /* Jmp jumps into the block it is in -- deal self cycle. */ @@ -730,14 +726,15 @@ static void copy_node_inline(ir_node *n, void *env) { copy_node(n, NULL); if (is_Sel(n)) { - nn = get_new_node (n); + nn = get_new_node(n); assert(is_Sel(nn)); + /* use copied entities from the new frame */ if (get_entity_owner(get_Sel_entity(n)) == frame_tp) { set_Sel_entity(nn, get_entity_link(get_Sel_entity(n))); } } else if (is_Block(n)) { - nn = get_new_node (n); - nn->attr.block.irg = current_ir_graph; + nn = get_new_node(n); + nn->attr.block.irg.irg = current_ir_graph; } } @@ -767,10 +764,16 @@ static void copy_preds_inline(ir_node *n, void *env) { */ static void find_addr(ir_node *node, void *env) { int *allow_inline = env; - if (is_Proj(node) && - is_Start(get_Proj_pred(node)) && - get_Proj_proj(node) == pn_Start_P_value_arg_base) { - *allow_inline = 0; + if (is_Sel(node)) { + ir_graph *irg = current_ir_graph; + if (get_Sel_ptr(node) == get_irg_frame(irg)) { + /* access to frame */ + ir_entity *ent = get_Sel_entity(node); + if (get_entity_owner(ent) != get_irg_frame_type(irg)) { + /* access to value_type */ + *allow_inline = 0; + } + } } else if (is_Alloc(node) && get_Alloc_where(node) == stack_alloc) { /* From GCC: * Refuse to inline alloca call unless user explicitly forced so as this @@ -859,19 +862,22 @@ int inline_method(ir_node *call, ir_graph *called_graph) { mtp = get_entity_type(ent); ctp = get_Call_type(call); - if (get_method_n_params(mtp) > get_method_n_params(ctp)) { - /* this is a bad feature of C: without a prototype, we can can call a function with less - parameters than needed. Currently we don't support this, although it would be - to use Unknown than. */ + n_params = get_method_n_params(mtp); + n_res = get_method_n_ress(mtp); + if (n_params > get_method_n_params(ctp)) { + /* this is a bad feature of C: without a prototype, we can + * call a function with less parameters than needed. Currently + * we don't support this, although we could use Unknown than. */ + return 0; + } + if (n_res != get_method_n_ress(ctp)) { return 0; } /* Argh, compiling C has some bad consequences: - the call type AND the method type might be different. - It is implementation defendant what happens in that case. - We support inlining, if the bitsize of the types matches AND - the same arithmetic is used. */ - n_params = get_method_n_params(mtp); + * It is implementation dependent what happens in that case. + * We support inlining, if the bitsize of the types matches AND + * the same arithmetic is used. */ for (i = n_params - 1; i >= 0; --i) { ir_type *param_tp = get_method_param_type(mtp, i); ir_type *arg_tp = get_method_param_type(ctp, i); @@ -889,6 +895,22 @@ int inline_method(ir_node *call, ir_graph *called_graph) { /* otherwise we can simply "reinterpret" the bits */ } } + for (i = n_res - 1; i >= 0; --i) { + ir_type *decl_res_tp = get_method_res_type(mtp, i); + ir_type *used_res_tp = get_method_res_type(ctp, i); + + if (decl_res_tp != used_res_tp) { + ir_mode *decl_mode = get_type_mode(decl_res_tp); + ir_mode *used_mode = get_type_mode(used_res_tp); + if (decl_mode == NULL || used_mode == NULL) + return 0; + if (get_mode_size_bits(decl_mode) != get_mode_size_bits(used_mode)) + return 0; + if (get_mode_arithmetic(decl_mode) != get_mode_arithmetic(used_mode)) + return 0; + /* otherwise we can "reinterpret" the bits */ + } + } irg = get_irn_irg(call); @@ -925,6 +947,7 @@ int inline_method(ir_node *call, ir_graph *called_graph) { set_irg_doms_inconsistent(irg); set_irg_loopinfo_inconsistent(irg); set_irg_callee_info_state(irg, irg_callee_info_inconsistent); + set_irg_entity_usage_state(irg, ir_entity_usage_not_computed); /* -- Check preconditions -- */ assert(is_Call(call)); @@ -960,7 +983,7 @@ int inline_method(ir_node *call, ir_graph *called_graph) { ir_mode *mode = get_type_mode(param_tp); if (mode != get_irn_mode(arg)) { - arg = new_r_Conv(irg, block, arg, mode); + arg = new_r_Conv(block, arg, mode); } args_in[i] = arg; } @@ -977,9 +1000,7 @@ int inline_method(ir_node *call, ir_graph *called_graph) { in[pn_Start_P_frame_base] = get_irg_frame(irg); in[pn_Start_P_tls] = get_irg_tls(irg); in[pn_Start_T_args] = new_Tuple(n_params, args_in); - /* in[pn_Start_P_value_arg_base] = ??? */ - assert(pn_Start_P_value_arg_base == pn_Start_max - 1 && "pn_Start_P_value_arg_base not supported, fix"); - pre_call = new_Tuple(pn_Start_max - 1, in); + pre_call = new_Tuple(pn_Start_max, in); post_call = call; /* -- @@ -1087,7 +1108,7 @@ int inline_method(ir_node *call, ir_graph *called_graph) { ir_node *ret; ret = get_Block_cfgpred(end_bl, i); if (is_Return(ret)) { - cf_pred[n_ret] = new_r_Jmp(irg, get_nodes_block(ret)); + cf_pred[n_ret] = new_r_Jmp(get_nodes_block(ret)); n_ret++; } } @@ -1115,11 +1136,18 @@ int inline_method(ir_node *call, ir_graph *called_graph) { /* Now the real results */ if (n_res > 0) { for (j = 0; j < n_res; j++) { + ir_type *res_type = get_method_res_type(ctp, j); + ir_mode *res_mode = get_type_mode(res_type); n_ret = 0; for (i = 0; i < arity; i++) { ret = get_Block_cfgpred(end_bl, i); if (is_Return(ret)) { - cf_pred[n_ret] = get_Return_res(ret, j); + ir_node *res = get_Return_res(ret, j); + if (get_irn_mode(res) != res_mode) { + ir_node *block = get_nodes_block(res); + res = new_r_Conv(block, res, res_mode); + } + cf_pred[n_ret] = res; n_ret++; } } @@ -1166,7 +1194,9 @@ int inline_method(ir_node *call, ir_graph *called_graph) { } } if (n_exc > 0) { - new_Block(n_exc, cf_pred); /* watch it: current_block is changed! */ + ir_node *block = new_Block(n_exc, cf_pred); + set_cur_block(block); + set_Tuple_pred(call, pn_Call_X_except, new_Jmp()); /* The Phi for the memories with the exception objects */ n_exc = 0; @@ -1174,14 +1204,14 @@ int inline_method(ir_node *call, ir_graph *called_graph) { ir_node *ret; ret = skip_Proj(get_Block_cfgpred(end_bl, i)); if (is_Call(ret)) { - cf_pred[n_exc] = new_r_Proj(irg, get_nodes_block(ret), ret, mode_M, 3); + cf_pred[n_exc] = new_r_Proj(get_nodes_block(ret), ret, mode_M, 3); n_exc++; } else if (is_fragile_op(ret)) { /* We rely that all cfops have the memory output at the same position. */ - cf_pred[n_exc] = new_r_Proj(irg, get_nodes_block(ret), ret, mode_M, 0); + cf_pred[n_exc] = new_r_Proj(get_nodes_block(ret), ret, mode_M, 0); n_exc++; } else if (is_Raise(ret)) { - cf_pred[n_exc] = new_r_Proj(irg, get_nodes_block(ret), ret, mode_M, 1); + cf_pred[n_exc] = new_r_Proj(get_nodes_block(ret), ret, mode_M, 1); n_exc++; } } @@ -1215,8 +1245,8 @@ int inline_method(ir_node *call, ir_graph *called_graph) { for (i = 0; i < n_exc; ++i) end_preds[main_end_bl_arity + i] = cf_pred[i]; set_irn_in(main_end_bl, n_exc + main_end_bl_arity, end_preds); - set_Tuple_pred(call, pn_Call_X_except, new_Bad()); - set_Tuple_pred(call, pn_Call_M_except, new_Bad()); + set_Tuple_pred(call, pn_Call_X_except, new_Bad()); + set_Tuple_pred(call, pn_Call_M_except, new_Bad()); free(end_preds); } free(res_pred);