void gimple_gen_ic_profiler (histogram_value value, unsigned tag, unsigned base) { tree tmp1; gassign *stmt1, *stmt2, *stmt3; gimple stmt = value->hvalue.stmt; gimple_stmt_iterator gsi = gsi_for_stmt (stmt); tree ref_ptr = tree_coverage_counter_addr (tag, base); if ( (PARAM_VALUE (PARAM_INDIR_CALL_TOPN_PROFILE) && tag == GCOV_COUNTER_V_INDIR) || (!PARAM_VALUE (PARAM_INDIR_CALL_TOPN_PROFILE) && tag == GCOV_COUNTER_ICALL_TOPNV)) return; ref_ptr = force_gimple_operand_gsi (&gsi, ref_ptr, true, NULL_TREE, true, GSI_SAME_STMT); /* Insert code: stmt1: __gcov_indirect_call_counters = get_relevant_counter_ptr (); stmt2: tmp1 = (void *) (indirect call argument value) stmt3: __gcov_indirect_call_callee = tmp1; */ stmt1 = gimple_build_assign (ic_gcov_type_ptr_var, ref_ptr); tmp1 = make_temp_ssa_name (ptr_void, NULL, "PROF"); stmt2 = gimple_build_assign (tmp1, unshare_expr (value->hvalue.value)); stmt3 = gimple_build_assign (ic_void_ptr_var, gimple_assign_lhs (stmt2)); gsi_insert_before (&gsi, stmt1, GSI_SAME_STMT); gsi_insert_before (&gsi, stmt2, GSI_SAME_STMT); gsi_insert_before (&gsi, stmt3, GSI_SAME_STMT); }
static tree adjust_return_value_with_ops (enum tree_code code, const char *label, tree acc, tree op1, gimple_stmt_iterator gsi) { tree ret_type = TREE_TYPE (DECL_RESULT (current_function_decl)); tree result = make_temp_ssa_name (ret_type, NULL, label); gimple stmt; if (POINTER_TYPE_P (ret_type)) { gcc_assert (code == PLUS_EXPR && TREE_TYPE (acc) == sizetype); code = POINTER_PLUS_EXPR; } if (types_compatible_p (TREE_TYPE (acc), TREE_TYPE (op1)) && code != POINTER_PLUS_EXPR) stmt = gimple_build_assign_with_ops (code, result, acc, op1); else { tree tem; if (code == POINTER_PLUS_EXPR) tem = fold_build2 (code, TREE_TYPE (op1), op1, acc); else tem = fold_build2 (code, TREE_TYPE (op1), fold_convert (TREE_TYPE (op1), acc), op1); tree rhs = fold_convert (ret_type, tem); rhs = force_gimple_operand_gsi (&gsi, rhs, false, NULL, true, GSI_SAME_STMT); stmt = gimple_build_assign (result, rhs); } gsi_insert_before (&gsi, stmt, GSI_NEW_STMT); return result; }
void gimple_gen_edge_profiler (int edgeno, edge e) { tree ref, one, gcov_type_tmp_var; gassign *stmt1, *stmt2, *stmt3; ref = tree_coverage_counter_ref (GCOV_COUNTER_ARCS, edgeno); one = build_int_cst (gcov_type_node, 1); gcov_type_tmp_var = make_temp_ssa_name (gcov_type_node, NULL, "PROF_edge_counter"); stmt1 = gimple_build_assign (gcov_type_tmp_var, ref); gcov_type_tmp_var = make_temp_ssa_name (gcov_type_node, NULL, "PROF_edge_counter"); stmt2 = gimple_build_assign (gcov_type_tmp_var, PLUS_EXPR, gimple_assign_lhs (stmt1), one); stmt3 = gimple_build_assign (unshare_expr (ref), gimple_assign_lhs (stmt2)); gsi_insert_on_edge (e, stmt1); gsi_insert_on_edge (e, stmt2); gsi_insert_on_edge (e, stmt3); }
static tree create_tailcall_accumulator (const char *label, basic_block bb, tree init) { tree ret_type = TREE_TYPE (DECL_RESULT (current_function_decl)); if (POINTER_TYPE_P (ret_type)) ret_type = sizetype; tree tmp = make_temp_ssa_name (ret_type, NULL, label); gimple phi; phi = create_phi_node (tmp, bb); /* RET_TYPE can be a float when -ffast-maths is enabled. */ add_phi_arg (phi, fold_convert (ret_type, init), single_pred_edge (bb), UNKNOWN_LOCATION); return PHI_RESULT (phi); }