X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=gcc%2Fvalue-prof.c;h=67bc2c8ea8e86423ed877d435280d724c3fa418a;hb=6c84d5762f1e1a60b1d4cee0caf8b4e7e0ba5f6f;hp=b75c36f87f7eeb6435babd8d946f2eccf34c80d5;hpb=9696c52909efcdb631f5fd7e8a8261656a25cc1b;p=gcc.git diff --git a/gcc/value-prof.c b/gcc/value-prof.c index b75c36f87f7..67bc2c8ea8e 100644 --- a/gcc/value-prof.c +++ b/gcc/value-prof.c @@ -1,6 +1,5 @@ /* Transformations based on profile information for values. - Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 - Free Software Foundation, Inc. + Copyright (C) 2003-2013 Free Software Foundation, Inc. This file is part of GCC. @@ -45,6 +44,7 @@ along with GCC; see the file COPYING3. If not see #include "dumpfile.h" #include "pointer-set.h" #include "profile.h" +#include "data-streamer.h" /* In this file value profile based optimizations are placed. Currently the following optimizations are implemented (for more detailed descriptions @@ -73,7 +73,7 @@ along with GCC; see the file COPYING3. If not see to profile. There are different histogram types (see HIST_TYPE_* in value-prof.h) and each transformation can request one or more histogram types per GIMPLE statement. The function gimple_find_values_to_profile() - collects the values to profile in a VEC, and adds the number of counters + collects the values to profile in a vec, and adds the number of counters required for the different histogram types. For a -fprofile-generate run, the statements for which values should be @@ -334,9 +334,97 @@ dump_histogram_value (FILE *dump_file, histogram_value hist) } fprintf (dump_file, ".\n"); break; + case HIST_TYPE_MAX: + gcc_unreachable (); } } +/* Dump information about HIST to DUMP_FILE. */ + +void +stream_out_histogram_value (struct output_block *ob, histogram_value hist) +{ + struct bitpack_d bp; + unsigned int i; + + bp = bitpack_create (ob->main_stream); + bp_pack_enum (&bp, hist_type, HIST_TYPE_MAX, hist->type); + bp_pack_value (&bp, hist->hvalue.next != NULL, 1); + streamer_write_bitpack (&bp); + switch (hist->type) + { + case HIST_TYPE_INTERVAL: + streamer_write_hwi (ob, hist->hdata.intvl.int_start); + streamer_write_uhwi (ob, hist->hdata.intvl.steps); + break; + default: + break; + } + for (i = 0; i < hist->n_counters; i++) + streamer_write_gcov_count (ob, hist->hvalue.counters[i]); + if (hist->hvalue.next) + stream_out_histogram_value (ob, hist->hvalue.next); +} +/* Dump information about HIST to DUMP_FILE. */ + +void +stream_in_histogram_value (struct lto_input_block *ib, gimple stmt) +{ + enum hist_type type; + unsigned int ncounters = 0; + struct bitpack_d bp; + unsigned int i; + histogram_value new_val; + bool next; + histogram_value *next_p = NULL; + + do + { + bp = streamer_read_bitpack (ib); + type = bp_unpack_enum (&bp, hist_type, HIST_TYPE_MAX); + next = bp_unpack_value (&bp, 1); + new_val = gimple_alloc_histogram_value (cfun, type, stmt, NULL); + switch (type) + { + case HIST_TYPE_INTERVAL: + new_val->hdata.intvl.int_start = streamer_read_hwi (ib); + new_val->hdata.intvl.steps = streamer_read_uhwi (ib); + ncounters = new_val->hdata.intvl.steps + 2; + break; + + case HIST_TYPE_POW2: + case HIST_TYPE_AVERAGE: + ncounters = 2; + break; + + case HIST_TYPE_SINGLE_VALUE: + case HIST_TYPE_INDIR_CALL: + ncounters = 3; + break; + + case HIST_TYPE_CONST_DELTA: + ncounters = 4; + break; + + case HIST_TYPE_IOR: + ncounters = 1; + break; + case HIST_TYPE_MAX: + gcc_unreachable (); + } + new_val->hvalue.counters = XNEWVAR (gcov_type, sizeof (*new_val->hvalue.counters) * ncounters); + new_val->n_counters = ncounters; + for (i = 0; i < ncounters; i++) + new_val->hvalue.counters[i] = streamer_read_gcov_count (ib); + if (!next_p) + gimple_add_histogram_value (cfun, stmt, new_val); + else + *next_p = new_val; + next_p = &new_val->hvalue.next; + } + while (next); +} + /* Dump all histograms attached to STMT to DUMP_FILE. */ void @@ -592,7 +680,7 @@ gimple_divmod_fixed_value (gimple stmt, tree value, int prob, gcov_type count, gcov_type all) { gimple stmt1, stmt2, stmt3; - tree tmp0, tmp1, tmp2, tmpv; + tree tmp0, tmp1, tmp2; gimple bb1end, bb2end, bb3end; basic_block bb, bb2, bb3, bb4; tree optype, op1, op2; @@ -610,20 +698,17 @@ gimple_divmod_fixed_value (gimple stmt, tree value, int prob, gcov_type count, bb = gimple_bb (stmt); gsi = gsi_for_stmt (stmt); - tmpv = create_tmp_reg (optype, "PROF"); - tmp0 = make_ssa_name (tmpv, NULL); - tmp1 = make_ssa_name (tmpv, NULL); + tmp0 = make_temp_ssa_name (optype, NULL, "PROF"); + tmp1 = make_temp_ssa_name (optype, NULL, "PROF"); stmt1 = gimple_build_assign (tmp0, fold_convert (optype, value)); - SSA_NAME_DEF_STMT (tmp0) = stmt1; stmt2 = gimple_build_assign (tmp1, op2); - SSA_NAME_DEF_STMT (tmp1) = stmt2; stmt3 = gimple_build_cond (NE_EXPR, tmp1, tmp0, NULL_TREE, NULL_TREE); gsi_insert_before (&gsi, stmt1, GSI_SAME_STMT); gsi_insert_before (&gsi, stmt2, GSI_SAME_STMT); gsi_insert_before (&gsi, stmt3, GSI_SAME_STMT); bb1end = stmt3; - tmp2 = make_rename_temp (optype, "PROF"); + tmp2 = create_tmp_reg (optype, "PROF"); stmt1 = gimple_build_assign_with_ops (gimple_assign_rhs_code (stmt), tmp2, op1, tmp0); gsi_insert_before (&gsi, stmt1, GSI_SAME_STMT); @@ -716,7 +801,7 @@ gimple_divmod_fixed_value_transform (gimple_stmt_iterator *si) /* Compute probability of taking the optimal path. */ if (all > 0) - prob = (count * REG_BR_PROB_BASE + all / 2) / all; + prob = GCOV_COMPUTE_SCALE (count, all); else prob = 0; @@ -749,7 +834,7 @@ static tree gimple_mod_pow2 (gimple stmt, int prob, gcov_type count, gcov_type all) { gimple stmt1, stmt2, stmt3, stmt4; - tree tmp2, tmp3, tmpv; + tree tmp2, tmp3; gimple bb1end, bb2end, bb3end; basic_block bb, bb2, bb3, bb4; tree optype, op1, op2; @@ -767,15 +852,12 @@ gimple_mod_pow2 (gimple stmt, int prob, gcov_type count, gcov_type all) bb = gimple_bb (stmt); gsi = gsi_for_stmt (stmt); - result = make_rename_temp (optype, "PROF"); - tmpv = create_tmp_var (optype, "PROF"); - tmp2 = make_ssa_name (tmpv, NULL); - tmp3 = make_ssa_name (tmpv, NULL); + result = create_tmp_reg (optype, "PROF"); + tmp2 = make_temp_ssa_name (optype, NULL, "PROF"); + tmp3 = make_temp_ssa_name (optype, NULL, "PROF"); stmt2 = gimple_build_assign_with_ops (PLUS_EXPR, tmp2, op2, build_int_cst (optype, -1)); - SSA_NAME_DEF_STMT (tmp2) = stmt2; stmt3 = gimple_build_assign_with_ops (BIT_AND_EXPR, tmp3, tmp2, op2); - SSA_NAME_DEF_STMT (tmp3) = stmt3; stmt4 = gimple_build_cond (NE_EXPR, tmp3, build_int_cst (optype, 0), NULL_TREE, NULL_TREE); gsi_insert_before (&gsi, stmt2, GSI_SAME_STMT); @@ -879,7 +961,7 @@ gimple_mod_pow2_value_transform (gimple_stmt_iterator *si) return false; if (all > 0) - prob = (count * REG_BR_PROB_BASE + all / 2) / all; + prob = GCOV_COMPUTE_SCALE (count, all); else prob = 0; @@ -923,11 +1005,10 @@ gimple_mod_subtract (gimple stmt, int prob1, int prob2, int ncounts, bb = gimple_bb (stmt); gsi = gsi_for_stmt (stmt); - result = make_rename_temp (optype, "PROF"); - tmp1 = make_ssa_name (create_tmp_var (optype, "PROF"), NULL); + result = create_tmp_reg (optype, "PROF"); + tmp1 = make_temp_ssa_name (optype, NULL, "PROF"); stmt1 = gimple_build_assign (result, op1); stmt2 = gimple_build_assign (tmp1, op2); - SSA_NAME_DEF_STMT (tmp1) = stmt2; stmt3 = gimple_build_cond (LT_EXPR, result, tmp1, NULL_TREE, NULL_TREE); gsi_insert_before (&gsi, stmt1, GSI_SAME_STMT); gsi_insert_before (&gsi, stmt2, GSI_SAME_STMT); @@ -1074,8 +1155,8 @@ gimple_mod_subtract_transform (gimple_stmt_iterator *si) /* Compute probability of taking the optimal path(s). */ if (all > 0) { - prob1 = (count1 * REG_BR_PROB_BASE + all / 2) / all; - prob2 = (count2 * REG_BR_PROB_BASE + all / 2) / all; + prob1 = GCOV_COMPUTE_SCALE (count1, all); + prob2 = GCOV_COMPUTE_SCALE (count2, all); } else { @@ -1092,7 +1173,8 @@ gimple_mod_subtract_transform (gimple_stmt_iterator *si) return true; } -static VEC(cgraph_node_ptr, heap) *cgraph_node_map = NULL; +static vec cgraph_node_map + = vNULL; /* Initialize map from FUNCDEF_NO to CGRAPH_NODE. */ @@ -1102,14 +1184,12 @@ init_node_map (void) struct cgraph_node *n; if (get_last_funcdef_no ()) - VEC_safe_grow_cleared (cgraph_node_ptr, heap, - cgraph_node_map, get_last_funcdef_no ()); + cgraph_node_map.safe_grow_cleared (get_last_funcdef_no ()); FOR_EACH_FUNCTION (n) { if (DECL_STRUCT_FUNCTION (n->symbol.decl)) - VEC_replace (cgraph_node_ptr, cgraph_node_map, - DECL_STRUCT_FUNCTION (n->symbol.decl)->funcdef_no, n); + cgraph_node_map[DECL_STRUCT_FUNCTION (n->symbol.decl)->funcdef_no] = n; } } @@ -1118,8 +1198,7 @@ init_node_map (void) void del_node_map (void) { - VEC_free (cgraph_node_ptr, heap, cgraph_node_map); - cgraph_node_map = NULL; + cgraph_node_map.release (); } /* Return cgraph node for function with pid */ @@ -1128,9 +1207,7 @@ static inline struct cgraph_node* find_func_by_funcdef_no (int func_id) { int max_id = get_last_funcdef_no (); - if (func_id >= max_id || VEC_index (cgraph_node_ptr, - cgraph_node_map, - func_id) == NULL) + if (func_id >= max_id || cgraph_node_map[func_id] == NULL) { if (flag_profile_correction) inform (DECL_SOURCE_LOCATION (current_function_decl), @@ -1141,7 +1218,7 @@ find_func_by_funcdef_no (int func_id) return NULL; } - return VEC_index (cgraph_node_ptr, cgraph_node_map, func_id); + return cgraph_node_map[func_id]; } /* Perform sanity check on the indirect call target. Due to race conditions, @@ -1154,7 +1231,7 @@ static bool check_ic_target (gimple call_stmt, struct cgraph_node *target) { location_t locus; - if (gimple_check_call_matching_types (call_stmt, target->symbol.decl)) + if (gimple_check_call_matching_types (call_stmt, target->symbol.decl, true)) return true; locus = gimple_location (call_stmt); @@ -1176,7 +1253,7 @@ gimple_ic (gimple icall_stmt, struct cgraph_node *direct_call, int prob, gcov_type count, gcov_type all) { gimple dcall_stmt, load_stmt, cond_stmt; - tree tmp0, tmp1, tmpv, tmp; + tree tmp0, tmp1, tmp; basic_block cond_bb, dcall_bb, icall_bb, join_bb = NULL; tree optype = build_pointer_type (void_type_node); edge e_cd, e_ci, e_di, e_dj = NULL, e_ij; @@ -1186,18 +1263,15 @@ gimple_ic (gimple icall_stmt, struct cgraph_node *direct_call, cond_bb = gimple_bb (icall_stmt); gsi = gsi_for_stmt (icall_stmt); - tmpv = create_tmp_reg (optype, "PROF"); - tmp0 = make_ssa_name (tmpv, NULL); - tmp1 = make_ssa_name (tmpv, NULL); + tmp0 = make_temp_ssa_name (optype, NULL, "PROF"); + tmp1 = make_temp_ssa_name (optype, NULL, "PROF"); tmp = unshare_expr (gimple_call_fn (icall_stmt)); load_stmt = gimple_build_assign (tmp0, tmp); - SSA_NAME_DEF_STMT (tmp0) = load_stmt; gsi_insert_before (&gsi, load_stmt, GSI_SAME_STMT); tmp = fold_convert (optype, build_addr (direct_call->symbol.decl, current_function_decl)); load_stmt = gimple_build_assign (tmp1, tmp); - SSA_NAME_DEF_STMT (tmp1) = load_stmt; gsi_insert_before (&gsi, load_stmt, GSI_SAME_STMT); cond_stmt = gimple_build_cond (EQ_EXPR, tmp1, tmp0, NULL_TREE, NULL_TREE); @@ -1275,12 +1349,11 @@ gimple_ic (gimple icall_stmt, struct cgraph_node *direct_call, { tree result = gimple_call_lhs (icall_stmt); gimple phi = create_phi_node (result, join_bb); - SSA_NAME_DEF_STMT (result) = phi; gimple_call_set_lhs (icall_stmt, - make_ssa_name (SSA_NAME_VAR (result), icall_stmt)); + duplicate_ssa_name (result, icall_stmt)); add_phi_arg (phi, gimple_call_lhs (icall_stmt), e_ij, UNKNOWN_LOCATION); gimple_call_set_lhs (dcall_stmt, - make_ssa_name (SSA_NAME_VAR (result), dcall_stmt)); + duplicate_ssa_name (result, dcall_stmt)); add_phi_arg (phi, gimple_call_lhs (dcall_stmt), e_dj, UNKNOWN_LOCATION); } @@ -1356,7 +1429,7 @@ gimple_ic_transform (gimple_stmt_iterator *gsi) return false; if (all > 0) - prob = (count * REG_BR_PROB_BASE + all / 2) / all; + prob = GCOV_COMPUTE_SCALE (count, all); else prob = 0; direct_call = find_func_by_funcdef_no ((int)val); @@ -1432,7 +1505,7 @@ gimple_stringop_fixed_value (gimple vcall_stmt, tree icall_size, int prob, gcov_type count, gcov_type all) { gimple tmp_stmt, cond_stmt, icall_stmt; - tree tmp0, tmp1, tmpv, vcall_size, optype; + tree tmp0, tmp1, vcall_size, optype; basic_block cond_bb, icall_bb, vcall_bb, join_bb; edge e_ci, e_cv, e_iv, e_ij, e_vj; gimple_stmt_iterator gsi; @@ -1449,15 +1522,12 @@ gimple_stringop_fixed_value (gimple vcall_stmt, tree icall_size, int prob, vcall_size = gimple_call_arg (vcall_stmt, size_arg); optype = TREE_TYPE (vcall_size); - tmpv = create_tmp_var (optype, "PROF"); - tmp0 = make_ssa_name (tmpv, NULL); - tmp1 = make_ssa_name (tmpv, NULL); + tmp0 = make_temp_ssa_name (optype, NULL, "PROF"); + tmp1 = make_temp_ssa_name (optype, NULL, "PROF"); tmp_stmt = gimple_build_assign (tmp0, fold_convert (optype, icall_size)); - SSA_NAME_DEF_STMT (tmp0) = tmp_stmt; gsi_insert_before (&gsi, tmp_stmt, GSI_SAME_STMT); tmp_stmt = gimple_build_assign (tmp1, vcall_size); - SSA_NAME_DEF_STMT (tmp1) = tmp_stmt; gsi_insert_before (&gsi, tmp_stmt, GSI_SAME_STMT); cond_stmt = gimple_build_cond (EQ_EXPR, tmp1, tmp0, NULL_TREE, NULL_TREE); @@ -1507,12 +1577,11 @@ gimple_stringop_fixed_value (gimple vcall_stmt, tree icall_size, int prob, { tree result = gimple_call_lhs (vcall_stmt); gimple phi = create_phi_node (result, join_bb); - SSA_NAME_DEF_STMT (result) = phi; gimple_call_set_lhs (vcall_stmt, - make_ssa_name (SSA_NAME_VAR (result), vcall_stmt)); + duplicate_ssa_name (result, vcall_stmt)); add_phi_arg (phi, gimple_call_lhs (vcall_stmt), e_vj, UNKNOWN_LOCATION); gimple_call_set_lhs (icall_stmt, - make_ssa_name (SSA_NAME_VAR (result), icall_stmt)); + duplicate_ssa_name (result, icall_stmt)); add_phi_arg (phi, gimple_call_lhs (icall_stmt), e_ij, UNKNOWN_LOCATION); } @@ -1566,7 +1635,7 @@ gimple_stringops_transform (gimple_stmt_iterator *gsi) if (check_counter (stmt, "value", &count, &all, gimple_bb (stmt)->count)) return false; if (all > 0) - prob = (count * REG_BR_PROB_BASE + all / 2) / all; + prob = GCOV_COMPUTE_SCALE (count, all); else prob = 0; dest = gimple_call_arg (stmt, 0); @@ -1682,13 +1751,12 @@ gimple_divmod_values_to_profile (gimple stmt, histogram_values *values) divisor = gimple_assign_rhs2 (stmt); op0 = gimple_assign_rhs1 (stmt); - VEC_reserve (histogram_value, heap, *values, 3); + values->reserve (3); - if (is_gimple_reg (divisor)) + if (TREE_CODE (divisor) == SSA_NAME) /* Check for the case where the divisor is the same value most of the time. */ - VEC_quick_push (histogram_value, *values, - gimple_alloc_histogram_value (cfun, + values->quick_push (gimple_alloc_histogram_value (cfun, HIST_TYPE_SINGLE_VALUE, stmt, divisor)); @@ -1699,16 +1767,16 @@ gimple_divmod_values_to_profile (gimple stmt, histogram_values *values) { tree val; /* Check for a special case where the divisor is power of 2. */ - VEC_quick_push (histogram_value, *values, - gimple_alloc_histogram_value (cfun, HIST_TYPE_POW2, - stmt, divisor)); + values->quick_push (gimple_alloc_histogram_value (cfun, + HIST_TYPE_POW2, + stmt, divisor)); val = build2 (TRUNC_DIV_EXPR, type, op0, divisor); hist = gimple_alloc_histogram_value (cfun, HIST_TYPE_INTERVAL, stmt, val); hist->hdata.intvl.int_start = 0; hist->hdata.intvl.steps = 2; - VEC_quick_push (histogram_value, *values, hist); + values->quick_push (hist); } return; @@ -1732,11 +1800,10 @@ gimple_indirect_call_to_profile (gimple stmt, histogram_values *values) callee = gimple_call_fn (stmt); - VEC_reserve (histogram_value, heap, *values, 3); + values->reserve (3); - VEC_quick_push (histogram_value, *values, - gimple_alloc_histogram_value (cfun, HIST_TYPE_INDIR_CALL, - stmt, callee)); + values->quick_push (gimple_alloc_histogram_value (cfun, HIST_TYPE_INDIR_CALL, + stmt, callee)); return; } @@ -1765,17 +1832,15 @@ gimple_stringops_values_to_profile (gimple stmt, histogram_values *values) if (TREE_CODE (blck_size) != INTEGER_CST) { - VEC_safe_push (histogram_value, heap, *values, - gimple_alloc_histogram_value (cfun, HIST_TYPE_SINGLE_VALUE, - stmt, blck_size)); - VEC_safe_push (histogram_value, heap, *values, - gimple_alloc_histogram_value (cfun, HIST_TYPE_AVERAGE, - stmt, blck_size)); + values->safe_push (gimple_alloc_histogram_value (cfun, + HIST_TYPE_SINGLE_VALUE, + stmt, blck_size)); + values->safe_push (gimple_alloc_histogram_value (cfun, HIST_TYPE_AVERAGE, + stmt, blck_size)); } if (TREE_CODE (blck_size) != INTEGER_CST) - VEC_safe_push (histogram_value, heap, *values, - gimple_alloc_histogram_value (cfun, HIST_TYPE_IOR, - stmt, dest)); + values->safe_push (gimple_alloc_histogram_value (cfun, HIST_TYPE_IOR, + stmt, dest)); } /* Find values inside STMT for that we want to measure histograms and adds @@ -1797,12 +1862,12 @@ gimple_find_values_to_profile (histogram_values *values) unsigned i; histogram_value hist = NULL; - *values = NULL; + values->create (0); FOR_EACH_BB (bb) for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi)) gimple_values_to_profile (gsi_stmt (gsi), values); - FOR_EACH_VEC_ELT (histogram_value, *values, i, hist) + FOR_EACH_VEC_ELT (*values, i, hist) { switch (hist->type) {