static void afdo_indirect_call (gimple_stmt_iterator *gsi, const icall_target_map &map, bool transform) { gimple gs = gsi_stmt (*gsi); tree callee; if (map.size () == 0) return; gcall *stmt = dyn_cast <gcall *> (gs); if ((!stmt) || gimple_call_fndecl (stmt) != NULL_TREE) return; callee = gimple_call_fn (stmt); histogram_value hist = gimple_alloc_histogram_value ( cfun, HIST_TYPE_INDIR_CALL, stmt, callee); hist->n_counters = 3; hist->hvalue.counters = XNEWVEC (gcov_type, hist->n_counters); gimple_add_histogram_value (cfun, stmt, hist); gcov_type total = 0; icall_target_map::const_iterator max_iter = map.end (); for (icall_target_map::const_iterator iter = map.begin (); iter != map.end (); ++iter) { total += iter->second; if (max_iter == map.end () || max_iter->second < iter->second) max_iter = iter; } hist->hvalue.counters[0] = (unsigned long long)afdo_string_table->get_name (max_iter->first); hist->hvalue.counters[1] = max_iter->second; hist->hvalue.counters[2] = total; if (!transform) return; struct cgraph_edge *indirect_edge = cgraph_node::get (current_function_decl)->get_edge (stmt); struct cgraph_node *direct_call = cgraph_node::get_for_asmname ( get_identifier ((const char *) hist->hvalue.counters[0])); if (direct_call == NULL || !check_ic_target (stmt, direct_call)) return; if (DECL_STRUCT_FUNCTION (direct_call->decl) == NULL) return; struct cgraph_edge *new_edge = indirect_edge->make_speculative (direct_call, 0, 0); new_edge->redirect_call_stmt_to_callee (); gimple_remove_histogram_value (cfun, stmt, hist); inline_call (new_edge, true, NULL, NULL, false); }
void inline_call_expression(CallExpression *the_call, ProcedureSymbol *target_proc) { // first dismantle it list<CallExpression *> call_list; force_call_dest_not_expr(the_call, &call_list); for (list<CallExpression*>::iterator siter = call_list.begin(); siter != call_list.end(); siter++) { CallExpression *cal_expr = *siter; CallStatement *st = dismantle_a_call_expression(cal_expr); inline_call(st, target_proc); } }