LCOV - code coverage report
Current view: top level - gcc - tree-profile.c (source / functions) Hit Total Coverage
Test: gcc.info Lines: 398 410 97.1 %
Date: 2020-04-04 11:58:09 Functions: 20 20 100.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 0 0 -

           Branch data     Line data    Source code
       1                 :            : /* Calculate branch probabilities, and basic block execution counts.
       2                 :            :    Copyright (C) 1990-2020 Free Software Foundation, Inc.
       3                 :            :    Contributed by James E. Wilson, UC Berkeley/Cygnus Support;
       4                 :            :    based on some ideas from Dain Samples of UC Berkeley.
       5                 :            :    Further mangling by Bob Manson, Cygnus Support.
       6                 :            :    Converted to use trees by Dale Johannesen, Apple Computer.
       7                 :            : 
       8                 :            : This file is part of GCC.
       9                 :            : 
      10                 :            : GCC is free software; you can redistribute it and/or modify it under
      11                 :            : the terms of the GNU General Public License as published by the Free
      12                 :            : Software Foundation; either version 3, or (at your option) any later
      13                 :            : version.
      14                 :            : 
      15                 :            : GCC is distributed in the hope that it will be useful, but WITHOUT ANY
      16                 :            : WARRANTY; without even the implied warranty of MERCHANTABILITY or
      17                 :            : FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
      18                 :            : for more details.
      19                 :            : 
      20                 :            : You should have received a copy of the GNU General Public License
      21                 :            : along with GCC; see the file COPYING3.  If not see
      22                 :            : <http://www.gnu.org/licenses/>.  */
      23                 :            : 
      24                 :            : /* Generate basic block profile instrumentation and auxiliary files.
      25                 :            :    Tree-based version.  See profile.c for overview.  */
      26                 :            : 
      27                 :            : #include "config.h"
      28                 :            : #include "system.h"
      29                 :            : #include "coretypes.h"
      30                 :            : #include "memmodel.h"
      31                 :            : #include "backend.h"
      32                 :            : #include "target.h"
      33                 :            : #include "tree.h"
      34                 :            : #include "gimple.h"
      35                 :            : #include "cfghooks.h"
      36                 :            : #include "tree-pass.h"
      37                 :            : #include "ssa.h"
      38                 :            : #include "cgraph.h"
      39                 :            : #include "coverage.h"
      40                 :            : #include "diagnostic-core.h"
      41                 :            : #include "fold-const.h"
      42                 :            : #include "varasm.h"
      43                 :            : #include "tree-nested.h"
      44                 :            : #include "gimplify.h"
      45                 :            : #include "gimple-iterator.h"
      46                 :            : #include "gimplify-me.h"
      47                 :            : #include "tree-cfg.h"
      48                 :            : #include "tree-into-ssa.h"
      49                 :            : #include "value-prof.h"
      50                 :            : #include "profile.h"
      51                 :            : #include "tree-cfgcleanup.h"
      52                 :            : #include "stringpool.h"
      53                 :            : #include "attribs.h"
      54                 :            : #include "tree-pretty-print.h"
      55                 :            : #include "langhooks.h"
      56                 :            : #include "stor-layout.h"
      57                 :            : #include "xregex.h"
      58                 :            : 
      59                 :            : static GTY(()) tree gcov_type_node;
      60                 :            : static GTY(()) tree tree_interval_profiler_fn;
      61                 :            : static GTY(()) tree tree_pow2_profiler_fn;
      62                 :            : static GTY(()) tree tree_topn_values_profiler_fn;
      63                 :            : static GTY(()) tree tree_indirect_call_profiler_fn;
      64                 :            : static GTY(()) tree tree_average_profiler_fn;
      65                 :            : static GTY(()) tree tree_ior_profiler_fn;
      66                 :            : static GTY(()) tree tree_time_profiler_counter;
      67                 :            : 
      68                 :            : 
      69                 :            : static GTY(()) tree ic_tuple_var;
      70                 :            : static GTY(()) tree ic_tuple_counters_field;
      71                 :            : static GTY(()) tree ic_tuple_callee_field;
      72                 :            : 
      73                 :            : /* Do initialization work for the edge profiler.  */
      74                 :            : 
      75                 :            : /* Add code:
      76                 :            :    __thread gcov*       __gcov_indirect_call.counters; // pointer to actual counter
      77                 :            :    __thread void*       __gcov_indirect_call.callee; // actual callee address
      78                 :            :    __thread int __gcov_function_counter; // time profiler function counter
      79                 :            : */
      80                 :            : static void
      81                 :        390 : init_ic_make_global_vars (void)
      82                 :            : {
      83                 :        390 :   tree gcov_type_ptr;
      84                 :            : 
      85                 :        390 :   gcov_type_ptr = build_pointer_type (get_gcov_type ());
      86                 :            : 
      87                 :        390 :   tree tuple_type = lang_hooks.types.make_type (RECORD_TYPE);
      88                 :            : 
      89                 :            :   /* callee */
      90                 :        390 :   ic_tuple_callee_field = build_decl (BUILTINS_LOCATION, FIELD_DECL, NULL_TREE,
      91                 :            :                                       ptr_type_node);
      92                 :            : 
      93                 :            :   /* counters */
      94                 :        390 :   ic_tuple_counters_field = build_decl (BUILTINS_LOCATION, FIELD_DECL,
      95                 :            :                                         NULL_TREE, gcov_type_ptr);
      96                 :        390 :   DECL_CHAIN (ic_tuple_counters_field) = ic_tuple_callee_field;
      97                 :            : 
      98                 :        390 :   finish_builtin_struct (tuple_type, "indirect_call_tuple",
      99                 :            :                          ic_tuple_counters_field, NULL_TREE);
     100                 :            : 
     101                 :        390 :   ic_tuple_var
     102                 :        390 :     = build_decl (UNKNOWN_LOCATION, VAR_DECL,
     103                 :            :                   get_identifier ("__gcov_indirect_call"), tuple_type);
     104                 :        390 :   TREE_PUBLIC (ic_tuple_var) = 1;
     105                 :        390 :   DECL_ARTIFICIAL (ic_tuple_var) = 1;
     106                 :        390 :   DECL_INITIAL (ic_tuple_var) = NULL;
     107                 :        390 :   DECL_EXTERNAL (ic_tuple_var) = 1;
     108                 :        390 :   if (targetm.have_tls)
     109                 :        390 :     set_decl_tls_model (ic_tuple_var, decl_default_tls_model (ic_tuple_var));
     110                 :        390 : }
     111                 :            : 
     112                 :            : /* Create the type and function decls for the interface with gcov.  */
     113                 :            : 
     114                 :            : void
     115                 :       2024 : gimple_init_gcov_profiler (void)
     116                 :            : {
     117                 :       2024 :   tree interval_profiler_fn_type;
     118                 :       2024 :   tree pow2_profiler_fn_type;
     119                 :       2024 :   tree topn_values_profiler_fn_type;
     120                 :       2024 :   tree gcov_type_ptr;
     121                 :       2024 :   tree ic_profiler_fn_type;
     122                 :       2024 :   tree average_profiler_fn_type;
     123                 :       2024 :   const char *fn_name;
     124                 :            : 
     125                 :       2024 :   if (!gcov_type_node)
     126                 :            :     {
     127                 :        780 :       const char *fn_suffix
     128                 :        390 :         = flag_profile_update == PROFILE_UPDATE_ATOMIC ? "_atomic" : "";
     129                 :            : 
     130                 :        390 :       gcov_type_node = get_gcov_type ();
     131                 :        390 :       gcov_type_ptr = build_pointer_type (gcov_type_node);
     132                 :            : 
     133                 :            :       /* void (*) (gcov_type *, gcov_type, int, unsigned)  */
     134                 :        390 :       interval_profiler_fn_type
     135                 :        390 :               = build_function_type_list (void_type_node,
     136                 :            :                                           gcov_type_ptr, gcov_type_node,
     137                 :            :                                           integer_type_node,
     138                 :            :                                           unsigned_type_node, NULL_TREE);
     139                 :        390 :       fn_name = concat ("__gcov_interval_profiler", fn_suffix, NULL);
     140                 :        390 :       tree_interval_profiler_fn = build_fn_decl (fn_name,
     141                 :            :                                                  interval_profiler_fn_type);
     142                 :        390 :       free (CONST_CAST (char *, fn_name));
     143                 :        390 :       TREE_NOTHROW (tree_interval_profiler_fn) = 1;
     144                 :        390 :       DECL_ATTRIBUTES (tree_interval_profiler_fn)
     145                 :        390 :         = tree_cons (get_identifier ("leaf"), NULL,
     146                 :        390 :                      DECL_ATTRIBUTES (tree_interval_profiler_fn));
     147                 :            : 
     148                 :            :       /* void (*) (gcov_type *, gcov_type)  */
     149                 :        390 :       pow2_profiler_fn_type
     150                 :        390 :               = build_function_type_list (void_type_node,
     151                 :            :                                           gcov_type_ptr, gcov_type_node,
     152                 :            :                                           NULL_TREE);
     153                 :        390 :       fn_name = concat ("__gcov_pow2_profiler", fn_suffix, NULL);
     154                 :        390 :       tree_pow2_profiler_fn = build_fn_decl (fn_name, pow2_profiler_fn_type);
     155                 :        390 :       free (CONST_CAST (char *, fn_name));
     156                 :        390 :       TREE_NOTHROW (tree_pow2_profiler_fn) = 1;
     157                 :        390 :       DECL_ATTRIBUTES (tree_pow2_profiler_fn)
     158                 :        390 :         = tree_cons (get_identifier ("leaf"), NULL,
     159                 :        390 :                      DECL_ATTRIBUTES (tree_pow2_profiler_fn));
     160                 :            : 
     161                 :            :       /* void (*) (gcov_type *, gcov_type)  */
     162                 :        390 :       topn_values_profiler_fn_type
     163                 :        390 :               = build_function_type_list (void_type_node,
     164                 :            :                                           gcov_type_ptr, gcov_type_node,
     165                 :            :                                           NULL_TREE);
     166                 :        390 :       fn_name = concat ("__gcov_topn_values_profiler", fn_suffix, NULL);
     167                 :        390 :       tree_topn_values_profiler_fn
     168                 :        390 :         = build_fn_decl (fn_name, topn_values_profiler_fn_type);
     169                 :        390 :       free (CONST_CAST (char *, fn_name));
     170                 :            : 
     171                 :        390 :       TREE_NOTHROW (tree_topn_values_profiler_fn) = 1;
     172                 :        390 :       DECL_ATTRIBUTES (tree_topn_values_profiler_fn)
     173                 :        390 :         = tree_cons (get_identifier ("leaf"), NULL,
     174                 :        390 :                      DECL_ATTRIBUTES (tree_topn_values_profiler_fn));
     175                 :            : 
     176                 :        390 :       init_ic_make_global_vars ();
     177                 :            : 
     178                 :            :       /* void (*) (gcov_type, void *)  */
     179                 :        390 :       ic_profiler_fn_type
     180                 :        390 :                = build_function_type_list (void_type_node,
     181                 :            :                                           gcov_type_node,
     182                 :            :                                           ptr_type_node,
     183                 :            :                                           NULL_TREE);
     184                 :        390 :       fn_name = concat ("__gcov_indirect_call_profiler_v4", fn_suffix, NULL);
     185                 :        390 :       tree_indirect_call_profiler_fn
     186                 :        390 :         = build_fn_decl (fn_name, ic_profiler_fn_type);
     187                 :        390 :       free (CONST_CAST (char *, fn_name));
     188                 :            : 
     189                 :        390 :       TREE_NOTHROW (tree_indirect_call_profiler_fn) = 1;
     190                 :        390 :       DECL_ATTRIBUTES (tree_indirect_call_profiler_fn)
     191                 :        390 :         = tree_cons (get_identifier ("leaf"), NULL,
     192                 :        390 :                      DECL_ATTRIBUTES (tree_indirect_call_profiler_fn));
     193                 :            : 
     194                 :        390 :       tree_time_profiler_counter
     195                 :        390 :         = build_decl (UNKNOWN_LOCATION, VAR_DECL,
     196                 :            :                       get_identifier ("__gcov_time_profiler_counter"),
     197                 :            :                       get_gcov_type ());
     198                 :        390 :       TREE_PUBLIC (tree_time_profiler_counter) = 1;
     199                 :        390 :       DECL_EXTERNAL (tree_time_profiler_counter) = 1;
     200                 :        390 :       TREE_STATIC (tree_time_profiler_counter) = 1;
     201                 :        390 :       DECL_ARTIFICIAL (tree_time_profiler_counter) = 1;
     202                 :        390 :       DECL_INITIAL (tree_time_profiler_counter) = NULL;
     203                 :            : 
     204                 :            :       /* void (*) (gcov_type *, gcov_type)  */
     205                 :        390 :       average_profiler_fn_type
     206                 :        390 :               = build_function_type_list (void_type_node,
     207                 :            :                                           gcov_type_ptr, gcov_type_node, NULL_TREE);
     208                 :        390 :       fn_name = concat ("__gcov_average_profiler", fn_suffix, NULL);
     209                 :        390 :       tree_average_profiler_fn = build_fn_decl (fn_name,
     210                 :            :                                                 average_profiler_fn_type);
     211                 :        390 :       free (CONST_CAST (char *, fn_name));
     212                 :        390 :       TREE_NOTHROW (tree_average_profiler_fn) = 1;
     213                 :        390 :       DECL_ATTRIBUTES (tree_average_profiler_fn)
     214                 :        390 :         = tree_cons (get_identifier ("leaf"), NULL,
     215                 :        390 :                      DECL_ATTRIBUTES (tree_average_profiler_fn));
     216                 :        390 :       fn_name = concat ("__gcov_ior_profiler", fn_suffix, NULL);
     217                 :        390 :       tree_ior_profiler_fn = build_fn_decl (fn_name, average_profiler_fn_type);
     218                 :        390 :       free (CONST_CAST (char *, fn_name));
     219                 :        390 :       TREE_NOTHROW (tree_ior_profiler_fn) = 1;
     220                 :        390 :       DECL_ATTRIBUTES (tree_ior_profiler_fn)
     221                 :        390 :         = tree_cons (get_identifier ("leaf"), NULL,
     222                 :        390 :                      DECL_ATTRIBUTES (tree_ior_profiler_fn));
     223                 :            : 
     224                 :            :       /* LTO streamer needs assembler names.  Because we create these decls
     225                 :            :          late, we need to initialize them by hand.  */
     226                 :        390 :       DECL_ASSEMBLER_NAME (tree_interval_profiler_fn);
     227                 :        390 :       DECL_ASSEMBLER_NAME (tree_pow2_profiler_fn);
     228                 :        390 :       DECL_ASSEMBLER_NAME (tree_topn_values_profiler_fn);
     229                 :        390 :       DECL_ASSEMBLER_NAME (tree_indirect_call_profiler_fn);
     230                 :        390 :       DECL_ASSEMBLER_NAME (tree_average_profiler_fn);
     231                 :        390 :       DECL_ASSEMBLER_NAME (tree_ior_profiler_fn);
     232                 :            :     }
     233                 :       2024 : }
     234                 :            : 
     235                 :            : /* Output instructions as GIMPLE trees to increment the edge
     236                 :            :    execution count, and insert them on E.  We rely on
     237                 :            :    gsi_insert_on_edge to preserve the order.  */
     238                 :            : 
     239                 :            : void
     240                 :       5640 : gimple_gen_edge_profiler (int edgeno, edge e)
     241                 :            : {
     242                 :       5640 :   tree one;
     243                 :            : 
     244                 :       5640 :   one = build_int_cst (gcov_type_node, 1);
     245                 :            : 
     246                 :       5640 :   if (flag_profile_update == PROFILE_UPDATE_ATOMIC)
     247                 :            :     {
     248                 :            :       /* __atomic_fetch_add (&counter, 1, MEMMODEL_RELAXED); */
     249                 :        108 :       tree addr = tree_coverage_counter_addr (GCOV_COUNTER_ARCS, edgeno);
     250                 :        108 :       tree f = builtin_decl_explicit (LONG_LONG_TYPE_SIZE > 32
     251                 :            :                                       ? BUILT_IN_ATOMIC_FETCH_ADD_8:
     252                 :            :                                       BUILT_IN_ATOMIC_FETCH_ADD_4);
     253                 :        108 :       gcall *stmt = gimple_build_call (f, 3, addr, one,
     254                 :            :                                        build_int_cst (integer_type_node,
     255                 :        108 :                                                       MEMMODEL_RELAXED));
     256                 :        108 :       gsi_insert_on_edge (e, stmt);
     257                 :            :     }
     258                 :            :   else
     259                 :            :     {
     260                 :       5532 :       tree ref = tree_coverage_counter_ref (GCOV_COUNTER_ARCS, edgeno);
     261                 :       5532 :       tree gcov_type_tmp_var = make_temp_ssa_name (gcov_type_node,
     262                 :            :                                                    NULL, "PROF_edge_counter");
     263                 :       5532 :       gassign *stmt1 = gimple_build_assign (gcov_type_tmp_var, ref);
     264                 :       5532 :       gcov_type_tmp_var = make_temp_ssa_name (gcov_type_node,
     265                 :            :                                               NULL, "PROF_edge_counter");
     266                 :       5532 :       gassign *stmt2 = gimple_build_assign (gcov_type_tmp_var, PLUS_EXPR,
     267                 :            :                                             gimple_assign_lhs (stmt1), one);
     268                 :       5532 :       gassign *stmt3 = gimple_build_assign (unshare_expr (ref),
     269                 :            :                                             gimple_assign_lhs (stmt2));
     270                 :       5532 :       gsi_insert_on_edge (e, stmt1);
     271                 :       5532 :       gsi_insert_on_edge (e, stmt2);
     272                 :       5532 :       gsi_insert_on_edge (e, stmt3);
     273                 :            :     }
     274                 :       5640 : }
     275                 :            : 
     276                 :            : /* Emits code to get VALUE to instrument at GSI, and returns the
     277                 :            :    variable containing the value.  */
     278                 :            : 
     279                 :            : static tree
     280                 :        101 : prepare_instrumented_value (gimple_stmt_iterator *gsi, histogram_value value)
     281                 :            : {
     282                 :        101 :   tree val = value->hvalue.value;
     283                 :        101 :   if (POINTER_TYPE_P (TREE_TYPE (val)))
     284                 :         26 :     val = fold_convert (build_nonstandard_integer_type
     285                 :            :                           (TYPE_PRECISION (TREE_TYPE (val)), 1), val);
     286                 :        101 :   return force_gimple_operand_gsi (gsi, fold_convert (gcov_type_node, val),
     287                 :        101 :                                    true, NULL_TREE, true, GSI_SAME_STMT);
     288                 :            : }
     289                 :            : 
     290                 :            : /* Output instructions as GIMPLE trees to increment the interval histogram
     291                 :            :    counter.  VALUE is the expression whose value is profiled.  TAG is the
     292                 :            :    tag of the section for counters, BASE is offset of the counter position.  */
     293                 :            : 
     294                 :            : void
     295                 :          5 : gimple_gen_interval_profiler (histogram_value value, unsigned tag)
     296                 :            : {
     297                 :          5 :   gimple *stmt = value->hvalue.stmt;
     298                 :          5 :   gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
     299                 :          5 :   tree ref = tree_coverage_counter_ref (tag, 0), ref_ptr;
     300                 :          5 :   gcall *call;
     301                 :          5 :   tree val;
     302                 :         10 :   tree start = build_int_cst_type (integer_type_node,
     303                 :          5 :                                    value->hdata.intvl.int_start);
     304                 :         10 :   tree steps = build_int_cst_type (unsigned_type_node,
     305                 :          5 :                                    value->hdata.intvl.steps);
     306                 :            : 
     307                 :          5 :   ref_ptr = force_gimple_operand_gsi (&gsi,
     308                 :            :                                       build_addr (ref),
     309                 :            :                                       true, NULL_TREE, true, GSI_SAME_STMT);
     310                 :          5 :   val = prepare_instrumented_value (&gsi, value);
     311                 :          5 :   call = gimple_build_call (tree_interval_profiler_fn, 4,
     312                 :            :                             ref_ptr, val, start, steps);
     313                 :          5 :   gsi_insert_before (&gsi, call, GSI_NEW_STMT);
     314                 :          5 : }
     315                 :            : 
     316                 :            : /* Output instructions as GIMPLE trees to increment the power of two histogram
     317                 :            :    counter.  VALUE is the expression whose value is profiled.  TAG is the tag
     318                 :            :    of the section for counters.  */
     319                 :            : 
     320                 :            : void
     321                 :          5 : gimple_gen_pow2_profiler (histogram_value value, unsigned tag)
     322                 :            : {
     323                 :          5 :   gimple *stmt = value->hvalue.stmt;
     324                 :          5 :   gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
     325                 :          5 :   tree ref_ptr = tree_coverage_counter_addr (tag, 0);
     326                 :          5 :   gcall *call;
     327                 :          5 :   tree val;
     328                 :            : 
     329                 :          5 :   ref_ptr = force_gimple_operand_gsi (&gsi, ref_ptr,
     330                 :            :                                       true, NULL_TREE, true, GSI_SAME_STMT);
     331                 :          5 :   val = prepare_instrumented_value (&gsi, value);
     332                 :          5 :   call = gimple_build_call (tree_pow2_profiler_fn, 2, ref_ptr, val);
     333                 :          5 :   gsi_insert_before (&gsi, call, GSI_NEW_STMT);
     334                 :          5 : }
     335                 :            : 
     336                 :            : /* Output instructions as GIMPLE trees for code to find the most N common
     337                 :            :    values.  VALUE is the expression whose value is profiled.  TAG is the tag
     338                 :            :    of the section for counters.  */
     339                 :            : 
     340                 :            : void
     341                 :         39 : gimple_gen_topn_values_profiler (histogram_value value, unsigned tag)
     342                 :            : {
     343                 :         39 :   gimple *stmt = value->hvalue.stmt;
     344                 :         39 :   gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
     345                 :         39 :   tree ref_ptr = tree_coverage_counter_addr (tag, 0);
     346                 :         39 :   gcall *call;
     347                 :         39 :   tree val;
     348                 :            : 
     349                 :         39 :   ref_ptr = force_gimple_operand_gsi (&gsi, ref_ptr,
     350                 :            :                                       true, NULL_TREE, true, GSI_SAME_STMT);
     351                 :         39 :   val = prepare_instrumented_value (&gsi, value);
     352                 :         39 :   call = gimple_build_call (tree_topn_values_profiler_fn, 2, ref_ptr, val);
     353                 :         39 :   gsi_insert_before (&gsi, call, GSI_NEW_STMT);
     354                 :         39 : }
     355                 :            : 
     356                 :            : 
     357                 :            : /* Output instructions as GIMPLE trees for code to find the most
     358                 :            :    common called function in indirect call.
     359                 :            :    VALUE is the call expression whose indirect callee is profiled.
     360                 :            :    TAG is the tag of the section for counters.  */
     361                 :            : 
     362                 :            : void
     363                 :         35 : gimple_gen_ic_profiler (histogram_value value, unsigned tag)
     364                 :            : {
     365                 :         35 :   tree tmp1;
     366                 :         35 :   gassign *stmt1, *stmt2, *stmt3;
     367                 :         35 :   gimple *stmt = value->hvalue.stmt;
     368                 :         35 :   gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
     369                 :         35 :   tree ref_ptr = tree_coverage_counter_addr (tag, 0);
     370                 :            : 
     371                 :         35 :   ref_ptr = force_gimple_operand_gsi (&gsi, ref_ptr,
     372                 :            :                                       true, NULL_TREE, true, GSI_SAME_STMT);
     373                 :            : 
     374                 :            :   /* Insert code:
     375                 :            : 
     376                 :            :     stmt1: __gcov_indirect_call.counters = get_relevant_counter_ptr ();
     377                 :            :     stmt2: tmp1 = (void *) (indirect call argument value)
     378                 :            :     stmt3: __gcov_indirect_call.callee = tmp1;
     379                 :            : 
     380                 :            :     Example:
     381                 :            :       f_1 = foo;
     382                 :            :       __gcov_indirect_call.counters = &__gcov4.main[0];
     383                 :            :       PROF_9 = f_1;
     384                 :            :       __gcov_indirect_call.callee = PROF_9;
     385                 :            :       _4 = f_1 ();
     386                 :            :    */
     387                 :            : 
     388                 :         35 :   tree gcov_type_ptr = build_pointer_type (get_gcov_type ());
     389                 :            : 
     390                 :         35 :   tree counter_ref = build3 (COMPONENT_REF, gcov_type_ptr,
     391                 :            :                              ic_tuple_var, ic_tuple_counters_field, NULL_TREE);
     392                 :            : 
     393                 :         35 :   stmt1 = gimple_build_assign (counter_ref, ref_ptr);
     394                 :         35 :   tmp1 = make_temp_ssa_name (ptr_type_node, NULL, "PROF");
     395                 :         35 :   stmt2 = gimple_build_assign (tmp1, unshare_expr (value->hvalue.value));
     396                 :         35 :   tree callee_ref = build3 (COMPONENT_REF, ptr_type_node,
     397                 :            :                              ic_tuple_var, ic_tuple_callee_field, NULL_TREE);
     398                 :         35 :   stmt3 = gimple_build_assign (callee_ref, tmp1);
     399                 :            : 
     400                 :         35 :   gsi_insert_before (&gsi, stmt1, GSI_SAME_STMT);
     401                 :         35 :   gsi_insert_before (&gsi, stmt2, GSI_SAME_STMT);
     402                 :         35 :   gsi_insert_before (&gsi, stmt3, GSI_SAME_STMT);
     403                 :         35 : }
     404                 :            : 
     405                 :            : 
     406                 :            : /* Output instructions as GIMPLE trees for code to find the most
     407                 :            :    common called function in indirect call. Insert instructions at the
     408                 :            :    beginning of every possible called function.
     409                 :            :   */
     410                 :            : 
     411                 :            : void
     412                 :        486 : gimple_gen_ic_func_profiler (void)
     413                 :            : {
     414                 :        486 :   struct cgraph_node * c_node = cgraph_node::get (current_function_decl);
     415                 :        486 :   gcall *stmt1;
     416                 :        486 :   tree tree_uid, cur_func, void0;
     417                 :            : 
     418                 :        486 :   if (c_node->only_called_directly_p ())
     419                 :         27 :     return;
     420                 :            : 
     421                 :        459 :   gimple_init_gcov_profiler ();
     422                 :            : 
     423                 :        459 :   basic_block entry = ENTRY_BLOCK_PTR_FOR_FN (cfun);
     424                 :        459 :   basic_block cond_bb = split_edge (single_succ_edge (entry));
     425                 :        459 :   basic_block update_bb = split_edge (single_succ_edge (cond_bb));
     426                 :            : 
     427                 :            :   /* We need to do an extra split in order to not create an input
     428                 :            :      for a possible PHI node.  */
     429                 :        459 :   split_edge (single_succ_edge (update_bb));
     430                 :            : 
     431                 :        459 :   edge true_edge = single_succ_edge (cond_bb);
     432                 :        459 :   true_edge->flags = EDGE_TRUE_VALUE;
     433                 :            : 
     434                 :        459 :   profile_probability probability;
     435                 :        459 :   if (DECL_VIRTUAL_P (current_function_decl))
     436                 :         10 :     probability = profile_probability::very_likely ();
     437                 :            :   else
     438                 :        449 :     probability = profile_probability::unlikely ();
     439                 :            : 
     440                 :        459 :   true_edge->probability = probability;
     441                 :        459 :   edge e = make_edge (cond_bb, single_succ_edge (update_bb)->dest,
     442                 :            :                       EDGE_FALSE_VALUE);
     443                 :        459 :   e->probability = true_edge->probability.invert ();
     444                 :            : 
     445                 :            :   /* Insert code:
     446                 :            : 
     447                 :            :      if (__gcov_indirect_call.callee != NULL)
     448                 :            :        __gcov_indirect_call_profiler_v3 (profile_id, &current_function_decl);
     449                 :            : 
     450                 :            :      The function __gcov_indirect_call_profiler_v3 is responsible for
     451                 :            :      resetting __gcov_indirect_call.callee to NULL.  */
     452                 :            : 
     453                 :        459 :   gimple_stmt_iterator gsi = gsi_start_bb (cond_bb);
     454                 :        459 :   void0 = build_int_cst (ptr_type_node, 0);
     455                 :            : 
     456                 :        459 :   tree callee_ref = build3 (COMPONENT_REF, ptr_type_node,
     457                 :            :                             ic_tuple_var, ic_tuple_callee_field, NULL_TREE);
     458                 :            : 
     459                 :        459 :   tree ref = force_gimple_operand_gsi (&gsi, callee_ref, true, NULL_TREE,
     460                 :            :                                        true, GSI_SAME_STMT);
     461                 :            : 
     462                 :        459 :   gcond *cond = gimple_build_cond (NE_EXPR, ref,
     463                 :            :                                    void0, NULL, NULL);
     464                 :        459 :   gsi_insert_before (&gsi, cond, GSI_NEW_STMT);
     465                 :            : 
     466                 :        459 :   gsi = gsi_after_labels (update_bb);
     467                 :            : 
     468                 :        459 :   cur_func = force_gimple_operand_gsi (&gsi,
     469                 :            :                                        build_addr (current_function_decl),
     470                 :            :                                        true, NULL_TREE,
     471                 :            :                                        true, GSI_SAME_STMT);
     472                 :        459 :   tree_uid = build_int_cst
     473                 :        459 :               (gcov_type_node,
     474                 :        459 :                cgraph_node::get (current_function_decl)->profile_id);
     475                 :        459 :   stmt1 = gimple_build_call (tree_indirect_call_profiler_fn, 2,
     476                 :            :                              tree_uid, cur_func);
     477                 :        459 :   gsi_insert_before (&gsi, stmt1, GSI_SAME_STMT);
     478                 :            : }
     479                 :            : 
     480                 :            : /* Output instructions as GIMPLE tree at the beginning for each function.
     481                 :            :    TAG is the tag of the section for counters, BASE is offset of the
     482                 :            :    counter position and GSI is the iterator we place the counter.  */
     483                 :            : 
     484                 :            : void
     485                 :        487 : gimple_gen_time_profiler (unsigned tag)
     486                 :            : {
     487                 :        487 :   tree type = get_gcov_type ();
     488                 :        487 :   basic_block entry = ENTRY_BLOCK_PTR_FOR_FN (cfun);
     489                 :        487 :   basic_block cond_bb = split_edge (single_succ_edge (entry));
     490                 :        487 :   basic_block update_bb = split_edge (single_succ_edge (cond_bb));
     491                 :            : 
     492                 :            :   /* We need to do an extra split in order to not create an input
     493                 :            :      for a possible PHI node.  */
     494                 :        487 :   split_edge (single_succ_edge (update_bb));
     495                 :            : 
     496                 :        487 :   edge true_edge = single_succ_edge (cond_bb);
     497                 :        487 :   true_edge->flags = EDGE_TRUE_VALUE;
     498                 :        487 :   true_edge->probability = profile_probability::unlikely ();
     499                 :        487 :   edge e
     500                 :        487 :     = make_edge (cond_bb, single_succ_edge (update_bb)->dest, EDGE_FALSE_VALUE);
     501                 :        487 :   e->probability = true_edge->probability.invert ();
     502                 :            : 
     503                 :        487 :   gimple_stmt_iterator gsi = gsi_start_bb (cond_bb);
     504                 :        487 :   tree original_ref = tree_coverage_counter_ref (tag, 0);
     505                 :        487 :   tree ref = force_gimple_operand_gsi (&gsi, original_ref, true, NULL_TREE,
     506                 :            :                                        true, GSI_SAME_STMT);
     507                 :        487 :   tree one = build_int_cst (type, 1);
     508                 :            : 
     509                 :            :   /* Emit: if (counters[0] != 0).  */
     510                 :        487 :   gcond *cond = gimple_build_cond (EQ_EXPR, ref, build_int_cst (type, 0),
     511                 :            :                                    NULL, NULL);
     512                 :        487 :   gsi_insert_before (&gsi, cond, GSI_NEW_STMT);
     513                 :            : 
     514                 :        487 :   gsi = gsi_start_bb (update_bb);
     515                 :            : 
     516                 :            :   /* Emit: counters[0] = ++__gcov_time_profiler_counter.  */
     517                 :        487 :   if (flag_profile_update == PROFILE_UPDATE_ATOMIC)
     518                 :            :     {
     519                 :         14 :       tree ptr = make_temp_ssa_name (build_pointer_type (type), NULL,
     520                 :            :                                      "time_profiler_counter_ptr");
     521                 :         14 :       tree addr = build1 (ADDR_EXPR, TREE_TYPE (ptr),
     522                 :            :                           tree_time_profiler_counter);
     523                 :         14 :       gassign *assign = gimple_build_assign (ptr, NOP_EXPR, addr);
     524                 :         14 :       gsi_insert_before (&gsi, assign, GSI_NEW_STMT);
     525                 :         14 :       tree f = builtin_decl_explicit (LONG_LONG_TYPE_SIZE > 32
     526                 :            :                                       ? BUILT_IN_ATOMIC_ADD_FETCH_8:
     527                 :            :                                       BUILT_IN_ATOMIC_ADD_FETCH_4);
     528                 :         14 :       gcall *stmt = gimple_build_call (f, 3, ptr, one,
     529                 :            :                                        build_int_cst (integer_type_node,
     530                 :         14 :                                                       MEMMODEL_RELAXED));
     531                 :         14 :       tree result_type = TREE_TYPE (TREE_TYPE (f));
     532                 :         14 :       tree tmp = make_temp_ssa_name (result_type, NULL, "time_profile");
     533                 :         14 :       gimple_set_lhs (stmt, tmp);
     534                 :         14 :       gsi_insert_after (&gsi, stmt, GSI_NEW_STMT);
     535                 :         14 :       tmp = make_temp_ssa_name (type, NULL, "time_profile");
     536                 :         14 :       assign = gimple_build_assign (tmp, NOP_EXPR,
     537                 :            :                                     gimple_call_lhs (stmt));
     538                 :         14 :       gsi_insert_after (&gsi, assign, GSI_NEW_STMT);
     539                 :         14 :       assign = gimple_build_assign (original_ref, tmp);
     540                 :         14 :       gsi_insert_after (&gsi, assign, GSI_NEW_STMT);
     541                 :            :     }
     542                 :            :   else
     543                 :            :     {
     544                 :        473 :       tree tmp = make_temp_ssa_name (type, NULL, "time_profile");
     545                 :        473 :       gassign *assign = gimple_build_assign (tmp, tree_time_profiler_counter);
     546                 :        473 :       gsi_insert_before (&gsi, assign, GSI_NEW_STMT);
     547                 :            : 
     548                 :        473 :       tmp = make_temp_ssa_name (type, NULL, "time_profile");
     549                 :        473 :       assign = gimple_build_assign (tmp, PLUS_EXPR, gimple_assign_lhs (assign),
     550                 :            :                                     one);
     551                 :        473 :       gsi_insert_after (&gsi, assign, GSI_NEW_STMT);
     552                 :        473 :       assign = gimple_build_assign (original_ref, tmp);
     553                 :        473 :       gsi_insert_after (&gsi, assign, GSI_NEW_STMT);
     554                 :        473 :       assign = gimple_build_assign (tree_time_profiler_counter, tmp);
     555                 :        473 :       gsi_insert_after (&gsi, assign, GSI_NEW_STMT);
     556                 :            :     }
     557                 :        487 : }
     558                 :            : 
     559                 :            : /* Output instructions as GIMPLE trees to increment the average histogram
     560                 :            :    counter.  VALUE is the expression whose value is profiled.  TAG is the
     561                 :            :    tag of the section for counters, BASE is offset of the counter position.  */
     562                 :            : 
     563                 :            : void
     564                 :         26 : gimple_gen_average_profiler (histogram_value value, unsigned tag)
     565                 :            : {
     566                 :         26 :   gimple *stmt = value->hvalue.stmt;
     567                 :         26 :   gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
     568                 :         26 :   tree ref_ptr = tree_coverage_counter_addr (tag, 0);
     569                 :         26 :   gcall *call;
     570                 :         26 :   tree val;
     571                 :            : 
     572                 :         26 :   ref_ptr = force_gimple_operand_gsi (&gsi, ref_ptr,
     573                 :            :                                       true, NULL_TREE,
     574                 :            :                                       true, GSI_SAME_STMT);
     575                 :         26 :   val = prepare_instrumented_value (&gsi, value);
     576                 :         26 :   call = gimple_build_call (tree_average_profiler_fn, 2, ref_ptr, val);
     577                 :         26 :   gsi_insert_before (&gsi, call, GSI_NEW_STMT);
     578                 :         26 : }
     579                 :            : 
     580                 :            : /* Output instructions as GIMPLE trees to increment the ior histogram
     581                 :            :    counter.  VALUE is the expression whose value is profiled.  TAG is the
     582                 :            :    tag of the section for counters, BASE is offset of the counter position.  */
     583                 :            : 
     584                 :            : void
     585                 :         26 : gimple_gen_ior_profiler (histogram_value value, unsigned tag)
     586                 :            : {
     587                 :         26 :   gimple *stmt = value->hvalue.stmt;
     588                 :         26 :   gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
     589                 :         26 :   tree ref_ptr = tree_coverage_counter_addr (tag, 0);
     590                 :         26 :   gcall *call;
     591                 :         26 :   tree val;
     592                 :            : 
     593                 :         26 :   ref_ptr = force_gimple_operand_gsi (&gsi, ref_ptr,
     594                 :            :                                       true, NULL_TREE, true, GSI_SAME_STMT);
     595                 :         26 :   val = prepare_instrumented_value (&gsi, value);
     596                 :         26 :   call = gimple_build_call (tree_ior_profiler_fn, 2, ref_ptr, val);
     597                 :         26 :   gsi_insert_before (&gsi, call, GSI_NEW_STMT);
     598                 :         26 : }
     599                 :            : 
     600                 :            : static vec<regex_t> profile_filter_files;
     601                 :            : static vec<regex_t> profile_exclude_files;
     602                 :            : 
     603                 :            : /* Parse list of provided REGEX (separated with semi-collon) and
     604                 :            :    create expressions (of type regex_t) and save them into V vector.
     605                 :            :    If there is a regular expression parsing error, error message is
     606                 :            :    printed for FLAG_NAME.  */
     607                 :            : 
     608                 :            : static void
     609                 :       1088 : parse_profile_filter (const char *regex, vec<regex_t> *v,
     610                 :            :                       const char *flag_name)
     611                 :            : {
     612                 :       1088 :   v->create (4);
     613                 :       1088 :   if (regex != NULL)
     614                 :            :     {
     615                 :          3 :       char *str = xstrdup (regex);
     616                 :          6 :       for (char *p = strtok (str, ";"); p != NULL; p = strtok (NULL, ";"))
     617                 :            :         {
     618                 :          3 :           regex_t r;
     619                 :          3 :           if (regcomp (&r, p, REG_EXTENDED | REG_NOSUB) != 0)
     620                 :            :             {
     621                 :          0 :               error ("invalid regular expression %qs in %qs",
     622                 :            :                      p, flag_name);
     623                 :          0 :               return;
     624                 :            :             }
     625                 :            : 
     626                 :          3 :           v->safe_push (r);
     627                 :            :         }
     628                 :            :     }
     629                 :            : }
     630                 :            : 
     631                 :            : /* Parse values of -fprofile-filter-files and -fprofile-exclude-files
     632                 :            :    options.  */
     633                 :            : 
     634                 :            : static void
     635                 :        544 : parse_profile_file_filtering ()
     636                 :            : {
     637                 :        544 :   parse_profile_filter (flag_profile_filter_files, &profile_filter_files,
     638                 :            :                         "-fprofile-filter-files");
     639                 :        544 :   parse_profile_filter (flag_profile_exclude_files, &profile_exclude_files,
     640                 :            :                         "-fprofile-exclude-files");
     641                 :        544 : }
     642                 :            : 
     643                 :            : /* Parse vectors of regular expressions.  */
     644                 :            : 
     645                 :            : static void
     646                 :        544 : release_profile_file_filtering ()
     647                 :            : {
     648                 :        544 :   profile_filter_files.release ();
     649                 :        544 :   profile_exclude_files.release ();
     650                 :        544 : }
     651                 :            : 
     652                 :            : /* Return true when FILENAME should be instrumented based on
     653                 :            :    -fprofile-filter-files and -fprofile-exclude-files options.  */
     654                 :            : 
     655                 :            : static bool
     656                 :       2063 : include_source_file_for_profile (const char *filename)
     657                 :            : {
     658                 :            :   /* First check whether file is included in flag_profile_exclude_files.  */
     659                 :       4126 :   for (unsigned i = 0; i < profile_exclude_files.length (); i++)
     660                 :          2 :     if (regexec (&profile_exclude_files[i],
     661                 :            :                  filename, 0, NULL, 0) == REG_NOERROR)
     662                 :            :       return false;
     663                 :            : 
     664                 :            :   /* For non-empty flag_profile_filter_files include only files matching a
     665                 :            :      regex in the flag.  */
     666                 :       2061 :   if (profile_filter_files.is_empty ())
     667                 :            :     return true;
     668                 :            : 
     669                 :          4 :   for (unsigned i = 0; i < profile_filter_files.length (); i++)
     670                 :          2 :     if (regexec (&profile_filter_files[i], filename, 0, NULL, 0) == REG_NOERROR)
     671                 :            :       return true;
     672                 :            : 
     673                 :            :   return false;
     674                 :            : }
     675                 :            : 
     676                 :            : #ifndef HAVE_sync_compare_and_swapsi
     677                 :            : #define HAVE_sync_compare_and_swapsi 0
     678                 :            : #endif
     679                 :            : #ifndef HAVE_atomic_compare_and_swapsi
     680                 :            : #define HAVE_atomic_compare_and_swapsi 0
     681                 :            : #endif
     682                 :            : 
     683                 :            : #ifndef HAVE_sync_compare_and_swapdi
     684                 :            : #define HAVE_sync_compare_and_swapdi 0
     685                 :            : #endif
     686                 :            : #ifndef HAVE_atomic_compare_and_swapdi
     687                 :            : #define HAVE_atomic_compare_and_swapdi 0
     688                 :            : #endif
     689                 :            : 
     690                 :            : /* Profile all functions in the callgraph.  */
     691                 :            : 
     692                 :            : static unsigned int
     693                 :        544 : tree_profiling (void)
     694                 :            : {
     695                 :        544 :   struct cgraph_node *node;
     696                 :            : 
     697                 :            :   /* Verify whether we can utilize atomic update operations.  */
     698                 :        544 :   bool can_support_atomic = false;
     699                 :        544 :   unsigned HOST_WIDE_INT gcov_type_size
     700                 :        544 :     = tree_to_uhwi (TYPE_SIZE_UNIT (get_gcov_type ()));
     701                 :        544 :   if (gcov_type_size == 4)
     702                 :          0 :     can_support_atomic
     703                 :          0 :       = HAVE_sync_compare_and_swapsi || HAVE_atomic_compare_and_swapsi;
     704                 :        544 :   else if (gcov_type_size == 8)
     705                 :        544 :     can_support_atomic
     706                 :        544 :       = HAVE_sync_compare_and_swapdi || HAVE_atomic_compare_and_swapdi;
     707                 :            : 
     708                 :        544 :   if (flag_profile_update == PROFILE_UPDATE_ATOMIC
     709                 :          6 :       && !can_support_atomic)
     710                 :            :     {
     711                 :          0 :       warning (0, "target does not support atomic profile update, "
     712                 :            :                "single mode is selected");
     713                 :          0 :       flag_profile_update = PROFILE_UPDATE_SINGLE;
     714                 :            :     }
     715                 :        544 :   else if (flag_profile_update == PROFILE_UPDATE_PREFER_ATOMIC)
     716                 :          8 :     flag_profile_update = can_support_atomic
     717                 :          8 :       ? PROFILE_UPDATE_ATOMIC : PROFILE_UPDATE_SINGLE;
     718                 :            : 
     719                 :            :   /* This is a small-ipa pass that gets called only once, from
     720                 :            :      cgraphunit.c:ipa_passes().  */
     721                 :        544 :   gcc_assert (symtab->state == IPA_SSA);
     722                 :            : 
     723                 :        544 :   init_node_map (true);
     724                 :        544 :   parse_profile_file_filtering ();
     725                 :            : 
     726                 :       5670 :   FOR_EACH_DEFINED_FUNCTION (node)
     727                 :            :     {
     728                 :       2291 :       bool thunk = false;
     729                 :       2291 :       if (!gimple_has_body_p (node->decl) && !node->thunk.thunk_p)
     730                 :        221 :         continue;
     731                 :            : 
     732                 :            :       /* Don't profile functions produced for builtin stuff.  */
     733                 :       2070 :       if (DECL_SOURCE_LOCATION (node->decl) == BUILTINS_LOCATION)
     734                 :          0 :         continue;
     735                 :            : 
     736                 :       2070 :       if (lookup_attribute ("no_profile_instrument_function",
     737                 :       2070 :                             DECL_ATTRIBUTES (node->decl)))
     738                 :          2 :         continue;
     739                 :            :       /* Do not instrument extern inline functions when testing coverage.
     740                 :            :          While this is not perfectly consistent (early inlined extern inlines
     741                 :            :          will get acocunted), testsuite expects that.  */
     742                 :       2068 :       if (DECL_EXTERNAL (node->decl)
     743                 :       2068 :           && flag_test_coverage)
     744                 :          5 :         continue;
     745                 :            : 
     746                 :       2063 :       const char *file = LOCATION_FILE (DECL_SOURCE_LOCATION (node->decl));
     747                 :       2063 :       if (!include_source_file_for_profile (file))
     748                 :          2 :         continue;
     749                 :            : 
     750                 :       2061 :       if (node->thunk.thunk_p)
     751                 :            :         {
     752                 :            :           /* We cannot expand variadic thunks to Gimple.  */
     753                 :         14 :           if (stdarg_p (TREE_TYPE (node->decl)))
     754                 :          0 :             continue;
     755                 :         14 :           thunk = true;
     756                 :            :           /* When generate profile, expand thunk to gimple so it can be
     757                 :            :              instrumented same way as other functions.  */
     758                 :         14 :           if (profile_arc_flag)
     759                 :          7 :             node->expand_thunk (false, true);
     760                 :            :           /* Read cgraph profile but keep function as thunk at profile-use
     761                 :            :              time.  */
     762                 :            :           else
     763                 :            :             {
     764                 :          7 :               read_thunk_profile (node);
     765                 :          7 :               continue;
     766                 :            :             }
     767                 :            :         }
     768                 :            : 
     769                 :       2054 :       push_cfun (DECL_STRUCT_FUNCTION (node->decl));
     770                 :            : 
     771                 :       2054 :       if (dump_file)
     772                 :        137 :         dump_function_header (dump_file, cfun->decl, dump_flags);
     773                 :            : 
     774                 :            :       /* Local pure-const may imply need to fixup the cfg.  */
     775                 :       2054 :       if (gimple_has_body_p (node->decl)
     776                 :       2054 :           && (execute_fixup_cfg () & TODO_cleanup_cfg))
     777                 :        265 :         cleanup_tree_cfg ();
     778                 :            : 
     779                 :       2054 :       branch_prob (thunk);
     780                 :            : 
     781                 :       2054 :       if (! flag_branch_probabilities
     782                 :       1579 :           && flag_profile_values)
     783                 :        486 :         gimple_gen_ic_func_profiler ();
     784                 :            : 
     785                 :       2054 :       if (flag_branch_probabilities
     786                 :        475 :           && !thunk
     787                 :        475 :           && flag_profile_values
     788                 :        332 :           && flag_value_profile_transformations
     789                 :        332 :           && profile_status_for_fn (cfun) == PROFILE_READ)
     790                 :        265 :         gimple_value_profile_transformations ();
     791                 :            : 
     792                 :            :       /* The above could hose dominator info.  Currently there is
     793                 :            :          none coming in, this is a safety valve.  It should be
     794                 :            :          easy to adjust it, if and when there is some.  */
     795                 :       2054 :       free_dominance_info (CDI_DOMINATORS);
     796                 :       2054 :       free_dominance_info (CDI_POST_DOMINATORS);
     797                 :       2054 :       pop_cfun ();
     798                 :            :     }
     799                 :            : 
     800                 :        544 :   release_profile_file_filtering ();
     801                 :            : 
     802                 :            :   /* Drop pure/const flags from instrumented functions.  */
     803                 :        544 :   if (profile_arc_flag || flag_test_coverage)
     804                 :       4414 :     FOR_EACH_DEFINED_FUNCTION (node)
     805                 :            :       {
     806                 :       1797 :         if (!gimple_has_body_p (node->decl)
     807                 :       1797 :             || !(!node->clone_of
     808                 :          0 :             || node->decl != node->clone_of->decl))
     809                 :        208 :           continue;
     810                 :            : 
     811                 :            :         /* Don't profile functions produced for builtin stuff.  */
     812                 :       1589 :         if (DECL_SOURCE_LOCATION (node->decl) == BUILTINS_LOCATION)
     813                 :          0 :           continue;
     814                 :            : 
     815                 :       1589 :         node->set_const_flag (false, false);
     816                 :       1589 :         node->set_pure_flag (false, false);
     817                 :            :       }
     818                 :            : 
     819                 :            :   /* Update call statements and rebuild the cgraph.  */
     820                 :       5670 :   FOR_EACH_DEFINED_FUNCTION (node)
     821                 :            :     {
     822                 :       2291 :       basic_block bb;
     823                 :            : 
     824                 :       2291 :       if (!gimple_has_body_p (node->decl)
     825                 :       2291 :           || !(!node->clone_of
     826                 :          0 :           || node->decl != node->clone_of->decl))
     827                 :        228 :         continue;
     828                 :            : 
     829                 :            :       /* Don't profile functions produced for builtin stuff.  */
     830                 :       2063 :       if (DECL_SOURCE_LOCATION (node->decl) == BUILTINS_LOCATION)
     831                 :          0 :         continue;
     832                 :            : 
     833                 :       2063 :       push_cfun (DECL_STRUCT_FUNCTION (node->decl));
     834                 :            : 
     835                 :      15149 :       FOR_EACH_BB_FN (bb, cfun)
     836                 :            :         {
     837                 :      13086 :           gimple_stmt_iterator gsi;
     838                 :      67084 :           for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
     839                 :            :             {
     840                 :      40912 :               gimple *stmt = gsi_stmt (gsi);
     841                 :      40912 :               if (is_gimple_call (stmt))
     842                 :      45052 :                 update_stmt (stmt);
     843                 :            :             }
     844                 :            :         }
     845                 :            : 
     846                 :            :       /* re-merge split blocks.  */
     847                 :       2063 :       cleanup_tree_cfg ();
     848                 :       2063 :       update_ssa (TODO_update_ssa);
     849                 :            : 
     850                 :       2063 :       cgraph_edge::rebuild_edges ();
     851                 :            : 
     852                 :       2063 :       pop_cfun ();
     853                 :            :     }
     854                 :            : 
     855                 :        544 :   handle_missing_profiles ();
     856                 :            : 
     857                 :        544 :   del_node_map ();
     858                 :        544 :   return 0;
     859                 :            : }
     860                 :            : 
     861                 :            : namespace {
     862                 :            : 
     863                 :            : const pass_data pass_data_ipa_tree_profile =
     864                 :            : {
     865                 :            :   SIMPLE_IPA_PASS, /* type */
     866                 :            :   "profile", /* name */
     867                 :            :   OPTGROUP_NONE, /* optinfo_flags */
     868                 :            :   TV_IPA_PROFILE, /* tv_id */
     869                 :            :   0, /* properties_required */
     870                 :            :   0, /* properties_provided */
     871                 :            :   0, /* properties_destroyed */
     872                 :            :   0, /* todo_flags_start */
     873                 :            :   TODO_dump_symtab, /* todo_flags_finish */
     874                 :            : };
     875                 :            : 
     876                 :            : class pass_ipa_tree_profile : public simple_ipa_opt_pass
     877                 :            : {
     878                 :            : public:
     879                 :     200773 :   pass_ipa_tree_profile (gcc::context *ctxt)
     880                 :     401546 :     : simple_ipa_opt_pass (pass_data_ipa_tree_profile, ctxt)
     881                 :            :   {}
     882                 :            : 
     883                 :            :   /* opt_pass methods: */
     884                 :            :   virtual bool gate (function *);
     885                 :        544 :   virtual unsigned int execute (function *) { return tree_profiling (); }
     886                 :            : 
     887                 :            : }; // class pass_ipa_tree_profile
     888                 :            : 
     889                 :            : bool
     890                 :     163439 : pass_ipa_tree_profile::gate (function *)
     891                 :            : {
     892                 :            :   /* When profile instrumentation, use or test coverage shall be performed.
     893                 :            :      But for AutoFDO, this there is no instrumentation, thus this pass is
     894                 :            :      disabled.  */
     895                 :     163439 :   return (!in_lto_p && !flag_auto_profile
     896                 :     326878 :           && (flag_branch_probabilities || flag_test_coverage
     897                 :     163162 :               || profile_arc_flag));
     898                 :            : }
     899                 :            : 
     900                 :            : } // anon namespace
     901                 :            : 
     902                 :            : simple_ipa_opt_pass *
     903                 :     200773 : make_pass_ipa_tree_profile (gcc::context *ctxt)
     904                 :            : {
     905                 :     200773 :   return new pass_ipa_tree_profile (ctxt);
     906                 :            : }
     907                 :            : 
     908                 :            : #include "gt-tree-profile.h"

Generated by: LCOV version 1.0

LCOV profile is generated on x86_64 machine using following configure options: configure --disable-bootstrap --enable-coverage=opt --enable-languages=c,c++,fortran,go,jit,lto --enable-host-shared. GCC test suite is run with the built compiler.