LCOV - code coverage report
Current view: top level - gcc - tree-assume.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 75.4 % 183 138
Test Date: 2024-12-21 13:15:12 Functions: 100.0 % 9 9
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: - 0 0

             Branch data     Line data    Source code
       1                 :             : /* Support for C++23 ASSUME keyword functionailty.
       2                 :             :    Copyright (C) 2023-2024 Free Software Foundation, Inc.
       3                 :             :    Contributed by Andrew MacLeod <amacleod@redhat.com>.
       4                 :             : 
       5                 :             : This file is part of GCC.
       6                 :             : 
       7                 :             : GCC is free software; you can redistribute it and/or modify
       8                 :             : it under the terms of the GNU General Public License as published by
       9                 :             : the Free Software Foundation; either version 3, or (at your option)
      10                 :             : any later version.
      11                 :             : 
      12                 :             : GCC is distributed in the hope that it will be useful,
      13                 :             : but WITHOUT ANY WARRANTY; without even the implied warranty of
      14                 :             : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      15                 :             : GNU General Public License for more details.
      16                 :             : 
      17                 :             : You should have received a copy of the GNU General Public License
      18                 :             : along with GCC; see the file COPYING3.  If not see
      19                 :             : <http://www.gnu.org/licenses/>.  */
      20                 :             : 
      21                 :             : #include "config.h"
      22                 :             : #include "system.h"
      23                 :             : #include "coretypes.h"
      24                 :             : #include "basic-block.h"
      25                 :             : #include "bitmap.h"
      26                 :             : #include "options.h"
      27                 :             : #include "function.h"
      28                 :             : #include "cfg.h"
      29                 :             : #include "tree.h"
      30                 :             : #include "gimple.h"
      31                 :             : #include "tree-pass.h"
      32                 :             : #include "ssa.h"
      33                 :             : #include "gimple-iterator.h"
      34                 :             : #include "gimple-range.h"
      35                 :             : #include "tree-dfa.h"
      36                 :             : #include "tree-cfg.h"
      37                 :             : #include "gimple-pretty-print.h"
      38                 :             : 
      39                 :             : // An assume query utilizes the current range query to implement the assume
      40                 :             : // keyword.
      41                 :             : // For any return value of 1 from the function, it attempts to determine
      42                 :             : // which paths lead to a 1 value being returned. On those paths, it determines
      43                 :             : // the ranges of any ssa_names listed in bitmap P (usually the parm list for
      44                 :             : // the function), and combines them all.
      45                 :             : // These ranges are then set as the global ranges for those parms in this
      46                 :             : // function.
      47                 :             : // Other functions which refer to this function in an assume builtin
      48                 :             : // will then pick up these ranges for the parameters via the inferred range
      49                 :             : // mechanism.
      50                 :             : //   See gimple-range-infer.cc::gimple_infer_range::check_assume_func ()
      51                 :             : //
      52                 :             : // my_func (int x)
      53                 :             : // {
      54                 :             : //   <...>
      55                 :             : //   assume [[(x == 1 || x ==4))]]
      56                 :             : //   if (x ==3)
      57                 :             : //
      58                 :             : // a small temporary assume function consisting of
      59                 :             : // assume_f1 (int x) { return x == 1 || x == 4; }
      60                 :             : // is constructed by the front end, and optimized, at the very end of
      61                 :             : // optimization, instead of generating code, we instead invoke the assume pass
      62                 :             : // which uses this query to set the the global value of parm x to [1,1][4,4]
      63                 :             : //
      64                 :             : // Meanwhile., my_func has been rewritten to be:
      65                 :             : //
      66                 :             : // my_func (int x_2)
      67                 :             : // {
      68                 :             : //   <...>
      69                 :             : //   assume_builtin_call  assume_f1 (x_2);
      70                 :             : //   if (x_2 == 3)
      71                 :             : //
      72                 :             : // When ranger is processing the assume_builtin_call, it looks up the global
      73                 :             : // value of the parameter in assume_f1, which is [1,1][4,4].  It then registers
      74                 :             : // and inferred range at this statement setting the value x_2 to [1,1][4,4]
      75                 :             : //
      76                 :             : // Any uses of x_2 after this statement will now utilize this inferred range.
      77                 :             : //
      78                 :             : // When VRP processes if (x_2 == 3), it picks up the inferred range, and
      79                 :             : // determines that x_2 can never be 3, and will rewrite the branch to
      80                 :             : //   if (0 != 0)
      81                 :             : 
      82                 :          86 : class assume_query
      83                 :             : {
      84                 :             : public:
      85                 :             :   assume_query (function *f, bitmap p);
      86                 :             : protected:
      87                 :          77 :   inline void process_stmts (gimple *s, vrange &lhs_range)
      88                 :             :   {
      89                 :         154 :     fur_depend src (s, get_range_query (m_func));
      90                 :          77 :     calculate_stmt (s, lhs_range, src);
      91                 :          77 :     update_parms (src);
      92                 :          77 :   }
      93                 :             :   void update_parms (fur_source &src);
      94                 :             :   void calculate_stmt (gimple *s, vrange &lhs_range, fur_source &src);
      95                 :             :   void calculate_op (tree op, gimple *s, vrange &lhs, fur_source &src);
      96                 :             :   void calculate_phi (gphi *phi, vrange &lhs_range);
      97                 :             : 
      98                 :             :   ssa_lazy_cache m_path;   // Values found on path
      99                 :             :   ssa_lazy_cache m_parms;  // Cumulative parameter value calculated
     100                 :             :   bitmap &m_parm_list;         // Parameter ssa-names list.
     101                 :             :   function *m_func;
     102                 :             : };
     103                 :             : 
     104                 :             : // If function F returns a integral value, and has a single return
     105                 :             : // statement, try to calculate the range of each value in P that leads
     106                 :             : // to the return statement returning TRUE.
     107                 :             : 
     108                 :         172 : assume_query::assume_query (function *f, bitmap p) : m_parm_list (p),
     109                 :          86 :                                                      m_func (f)
     110                 :             : {
     111                 :          86 :   basic_block exit_bb = EXIT_BLOCK_PTR_FOR_FN (f);
     112                 :             :   // If there is more than one predecessor to the exit block, bail.
     113                 :          86 :   if (!single_pred_p (exit_bb))
     114                 :           6 :     return;
     115                 :             : 
     116                 :          86 :   basic_block bb = single_pred (exit_bb);
     117                 :          86 :   gimple_stmt_iterator gsi = gsi_last_nondebug_bb (bb);
     118                 :          86 :   if (gsi_end_p (gsi))
     119                 :             :     return;
     120                 :          86 :   gimple *s = gsi_stmt (gsi);
     121                 :          86 :   if (!is_a<greturn *> (s))
     122                 :             :     return;
     123                 :             : 
     124                 :             :   // Check if the single return value is a symbolic and supported type.
     125                 :          86 :   greturn *gret = as_a<greturn *> (s);
     126                 :          86 :   tree op = gimple_return_retval (gret);
     127                 :          86 :   if (!gimple_range_ssa_p (op))
     128                 :             :     return;
     129                 :          80 :   tree lhs_type = TREE_TYPE (op);
     130                 :          80 :   if (!irange::supports_p (lhs_type))
     131                 :             :     return;
     132                 :             : 
     133                 :             :   // Only values of interest are when the return value is 1.  The definition
     134                 :             :   // of the return value must be in the same block, or we have
     135                 :             :   // complicated flow control we don't understand, and just return.
     136                 :          80 :   unsigned prec = TYPE_PRECISION (lhs_type);
     137                 :          80 :   int_range<2> lhs_range (lhs_type, wi::one (prec), wi::one (prec));
     138                 :             : 
     139                 :          80 :   gimple *def = SSA_NAME_DEF_STMT (op);
     140                 :          80 :   if (!def || gimple_get_lhs (def) != op || gimple_bb (def) != bb)
     141                 :           0 :     return;
     142                 :             : 
     143                 :             :   // Determine if this is a PHI or a linear sequence to deal with.
     144                 :          80 :   if (is_a<gphi *> (def))
     145                 :          21 :     calculate_phi (as_a<gphi *> (def), lhs_range);
     146                 :             :   else
     147                 :          59 :     process_stmts (def, lhs_range);
     148                 :             : 
     149                 :          80 :   if (dump_file)
     150                 :           0 :     fprintf (dump_file, "\n\nAssumptions :\n--------------\n");
     151                 :             : 
     152                 :             :   // Now export any interesting values that were found.
     153                 :          80 :   bitmap_iterator bi;
     154                 :          80 :   unsigned x;
     155                 :         197 :   EXECUTE_IF_SET_IN_BITMAP (m_parm_list, 0, x, bi)
     156                 :             :     {
     157                 :         117 :       tree name = ssa_name (x);
     158                 :         117 :       tree type = TREE_TYPE (name);
     159                 :         117 :       value_range assume_range (type);
     160                 :             :       // Set the global range of NAME to anything calculated.
     161                 :         117 :       if (m_parms.get_range (assume_range, name) && !assume_range.varying_p ())
     162                 :         102 :         set_range_info (name, assume_range);
     163                 :         117 :     }
     164                 :             : 
     165                 :          80 :   if (dump_file)
     166                 :             :    {
     167                 :           0 :      fputc ('\n', dump_file);
     168                 :           0 :      gimple_dump_cfg (dump_file, dump_flags & ~TDF_DETAILS);
     169                 :             :    }
     170                 :          80 : }
     171                 :             : 
     172                 :             : // This function will update all the current values of interesting parameters.
     173                 :             : // It tries, in order:
     174                 :             : //    a) a range found via path calculations.
     175                 :             : //    b) range of the parm at SRC point in the IL. (either edge or stmt)
     176                 :             : //    c) VARYING if those options fail.
     177                 :             : //  The value is then unioned with any existing value, allowing for the
     178                 :             : //  cumulation of all ranges leading to the return that return 1.
     179                 :             : 
     180                 :             : void
     181                 :          82 : assume_query::update_parms (fur_source &src)
     182                 :             : {
     183                 :          82 :   if (dump_file && (dump_flags & TDF_DETAILS))
     184                 :           0 :     fprintf (dump_file, "\nupdate parameters\n");
     185                 :             : 
     186                 :             :   // Merge any parameter values.
     187                 :          82 :   bitmap_iterator bi;
     188                 :          82 :   unsigned x;
     189                 :         201 :   EXECUTE_IF_SET_IN_BITMAP (m_parm_list, 0, x, bi)
     190                 :             :     {
     191                 :         119 :       tree name = ssa_name (x);
     192                 :         119 :       tree type = TREE_TYPE (name);
     193                 :             : 
     194                 :         119 :       if (dump_file && (dump_flags & TDF_DETAILS))
     195                 :             :         {
     196                 :           0 :           fprintf (dump_file, "PARAMETER ");
     197                 :           0 :           print_generic_expr (dump_file, name, TDF_SLIM);
     198                 :             :         }
     199                 :         119 :       value_range glob_range (type);
     200                 :             :       // Find a value from calculations.
     201                 :             :       // There will be a value in m_path if GORI calculated an operand value.
     202                 :         119 :       if (m_path.get_range (glob_range, name))
     203                 :             :         {
     204                 :          87 :           if (dump_file && (dump_flags & TDF_DETAILS))
     205                 :             :             {
     206                 :           0 :               fprintf (dump_file, "\n  Calculated path range:");
     207                 :           0 :               glob_range.dump (dump_file);
     208                 :             :             }
     209                 :             :         }
     210                 :             :       // Otherwise, let ranger determine the range at the SRC location.
     211                 :          32 :       else if (src.get_operand (glob_range, name))
     212                 :             :         {
     213                 :          32 :           if (dump_file && (dump_flags & TDF_DETAILS))
     214                 :             :             {
     215                 :           0 :               fprintf (dump_file, "\n  Ranger Computes path range:");
     216                 :           0 :               glob_range.dump (dump_file);
     217                 :             :             }
     218                 :             :         }
     219                 :             :       else
     220                 :           0 :         glob_range.set_varying (type);
     221                 :             : 
     222                 :             :       // Find any current saved value of parm, and combine them.
     223                 :         119 :       value_range parm_range (type);
     224                 :         119 :       if (m_parms.get_range (parm_range, name))
     225                 :           2 :         glob_range.union_ (parm_range);
     226                 :             : 
     227                 :         119 :       if (dump_file && (dump_flags & TDF_DETAILS))
     228                 :             :         {
     229                 :           0 :           fprintf (dump_file, "\n  Combine with previous range:");
     230                 :           0 :           parm_range.dump (dump_file);
     231                 :           0 :           fputc ('\n', dump_file);
     232                 :           0 :           print_generic_expr (dump_file, name, TDF_SLIM);
     233                 :           0 :           fprintf (dump_file, " = ");
     234                 :           0 :           glob_range.dump (dump_file);
     235                 :           0 :           fputc ('\n', dump_file);
     236                 :             :         }
     237                 :             :       // Set this new value.
     238                 :         119 :       m_parms.set_range (name, glob_range);
     239                 :         119 :     }
     240                 :             :   // Now reset the path values for the next path.
     241                 :          82 :   if (dump_file && (dump_flags & TDF_DETAILS))
     242                 :           0 :     fprintf (dump_file, "---------------------\n");
     243                 :          82 :   m_path.clear ();
     244                 :          82 : }
     245                 :             : 
     246                 :             : 
     247                 :             : // Evaluate PHI statement, using the provided LHS range.
     248                 :             : // Only process edge that are taken and return the LHS of the PHI.
     249                 :             : 
     250                 :             : void
     251                 :          21 : assume_query::calculate_phi (gphi *phi, vrange &lhs_range)
     252                 :             : {
     253                 :          21 :   if (dump_file && (dump_flags & TDF_DETAILS))
     254                 :             :     {
     255                 :           0 :       fprintf (dump_file, "Processing PHI feeding return value:\n");
     256                 :           0 :       print_gimple_stmt (dump_file, phi, 0, TDF_SLIM);
     257                 :             :     }
     258                 :          63 :   for (unsigned x= 0; x < gimple_phi_num_args (phi); x++)
     259                 :             :     {
     260                 :          42 :       tree arg = gimple_phi_arg_def (phi, x);
     261                 :          42 :       value_range arg_range (TREE_TYPE (arg));
     262                 :          42 :       edge e = gimple_phi_arg_edge (phi, x);
     263                 :          42 :       value_range edge_range (TREE_TYPE (arg));
     264                 :          42 :       if (dump_file && (dump_flags & TDF_DETAILS))
     265                 :             :         {
     266                 :           0 :           fprintf (dump_file, "\nArgument %d (bb%d->bb%d): ", x, e->src->index,
     267                 :           0 :                    e->dest->index);
     268                 :           0 :           print_generic_expr (dump_file, arg, TDF_SLIM);
     269                 :           0 :           fputc ('\n', dump_file);
     270                 :             :         }
     271                 :             :       // If we can't get an edge range, be conservative and assume the
     272                 :             :       // edge can be taken.
     273                 :          84 :       if (get_range_query (m_func)->range_on_edge (edge_range, e, arg))
     274                 :             :         {
     275                 :          42 :           if (gimple_range_ssa_p (arg))
     276                 :             :             {
     277                 :          21 :               arg_range = lhs_range;
     278                 :          21 :               range_cast (arg_range, TREE_TYPE (arg));
     279                 :             : 
     280                 :             :               // An SSA_NAME arg will start with the LHS value.
     281                 :             :               // Check the range of ARG on the edge leading here.  If that range
     282                 :             :               // cannot be any value from the LHS of the PHI, then this branch
     283                 :             :               // will not be taken to return the LHS value and can be ignored.
     284                 :          21 :               arg_range.intersect (edge_range);
     285                 :          21 :               if (arg_range.undefined_p ())
     286                 :             :                 {
     287                 :           3 :                   if (dump_file && (dump_flags & TDF_DETAILS))
     288                 :             :                     {
     289                 :           0 :                       fprintf (dump_file, "  IGNORE edge :  LHS range :");
     290                 :           0 :                       lhs_range.dump (dump_file);
     291                 :           0 :                       fprintf (dump_file, " Edge produces : ");
     292                 :           0 :                       edge_range.dump (dump_file);
     293                 :           0 :                       fputc ('\n', dump_file);
     294                 :             :                     }
     295                 :           3 :                   continue;
     296                 :             :                 }
     297                 :             : 
     298                 :             :               // If the def is in the immediate preceeding block, process it
     299                 :             :               // with GORI to determine what values can produce this
     300                 :             :               // argument value.  Otherwise there is more CFG flow, so query
     301                 :             :               // the edge for parm ranges.  This is conservative.
     302                 :          18 :               gimple *def_stmt = SSA_NAME_DEF_STMT (arg);
     303                 :          18 :               if (def_stmt && gimple_get_lhs (def_stmt) == arg
     304                 :          36 :                   && gimple_bb (def_stmt) == e->src)
     305                 :             :                 {
     306                 :          18 :                   process_stmts (def_stmt, arg_range);
     307                 :          18 :                   continue;
     308                 :             :                 }
     309                 :             :               // Fall through to process the parameter values on the edge.
     310                 :             :             }
     311                 :             :           else
     312                 :             :             {
     313                 :             :               // If this is a constant value that differs from LHS, this
     314                 :             :               // edge cannot be taken and we can ignore it. Otherwise fall
     315                 :             :               // thorugh and process the parameters on the edge.
     316                 :          21 :               edge_range.intersect (lhs_range);
     317                 :          21 :               if (edge_range.undefined_p ())
     318                 :             :                 {
     319                 :          16 :                   if (dump_file && (dump_flags & TDF_DETAILS))
     320                 :           0 :                     fprintf (dump_file, "  IGNORE : const edge not taken\n");
     321                 :          16 :                   continue;
     322                 :             :                 }
     323                 :           5 :               if (dump_file && (dump_flags & TDF_DETAILS))
     324                 :           0 :                 fprintf (dump_file,
     325                 :             :                          "  Const edge executed, compute incoming ranges.\n");
     326                 :             : 
     327                 :             :             }
     328                 :             :         }
     329                 :             :       // The parameters on the edge now need calculating.
     330                 :          10 :       fur_edge src (e, get_range_query (m_func));
     331                 :           5 :       update_parms (src);
     332                 :          42 :     }
     333                 :          21 : }
     334                 :             : 
     335                 :             : // Evaluate operand OP on statement S, using the provided LHS range.
     336                 :             : // If successful, set the range in path table, then visit OP's def stmt
     337                 :             : // if it is in the same BB.
     338                 :             : 
     339                 :             : void
     340                 :         160 : assume_query::calculate_op (tree op, gimple *s, vrange &lhs, fur_source &src)
     341                 :             : {
     342                 :         160 :   basic_block bb = gimple_bb (s);
     343                 :         160 :   value_range op_range (TREE_TYPE (op));
     344                 :         320 :   if (src.gori () &&
     345                 :         160 :       src.gori ()->compute_operand_range (op_range, s, lhs, op, src)
     346                 :         320 :       && !op_range.varying_p ())
     347                 :             :     {
     348                 :         160 :       if (dump_file && (dump_flags & TDF_DETAILS))
     349                 :             :         {
     350                 :           0 :           fprintf (dump_file, "  Operand ");
     351                 :           0 :           print_generic_expr (dump_file, op, TDF_SLIM);
     352                 :           0 :           fprintf (dump_file, " calculated as ");
     353                 :           0 :           op_range.dump (dump_file);
     354                 :             :         }
     355                 :             :       // Set the global range, merging if there is already a range.
     356                 :         160 :       m_path.merge_range (op, op_range);
     357                 :         160 :       m_path.get_range (op_range, op);
     358                 :         160 :       if (dump_file && (dump_flags & TDF_DETAILS))
     359                 :             :         {
     360                 :           0 :           fprintf (dump_file, "  New path range :");
     361                 :           0 :           op_range.dump (dump_file);
     362                 :           0 :           fputc ('\n', dump_file);
     363                 :             :         }
     364                 :         160 :       gimple *def_stmt = SSA_NAME_DEF_STMT (op);
     365                 :             :       // Terminate if the pathway leads to a different block as we
     366                 :             :       // are not dealing with flow. Ranger will make those queries.
     367                 :         160 :       if (def_stmt && gimple_get_lhs (def_stmt) == op
     368                 :         233 :           && gimple_bb (def_stmt) == bb)
     369                 :          70 :         calculate_stmt (def_stmt, op_range, src);
     370                 :             :     }
     371                 :         160 : }
     372                 :             : 
     373                 :             : // Evaluate statement S which produces range LHS_RANGE.  Use GORI to
     374                 :             : // determine what values the operands can have to produce the LHS,
     375                 :             : // and set these in the M_PATH table.
     376                 :             : 
     377                 :             : void
     378                 :         147 : assume_query::calculate_stmt (gimple *s, vrange &lhs_range, fur_source &src)
     379                 :             : {
     380                 :         147 :   if (dump_file && (dump_flags & TDF_DETAILS))
     381                 :             :     {
     382                 :           0 :       fprintf (dump_file, "  Processing stmt with LHS = ");
     383                 :           0 :       lhs_range.dump (dump_file);
     384                 :           0 :       fprintf (dump_file, " : ");
     385                 :           0 :       print_gimple_stmt (dump_file, s, 0, TDF_SLIM);
     386                 :             :     }
     387                 :         147 :   gimple_range_op_handler handler (s);
     388                 :         147 :   if (handler)
     389                 :             :     {
     390                 :         136 :       tree op = gimple_range_ssa_p (handler.operand1 ());
     391                 :         136 :       if (op)
     392                 :         136 :         calculate_op (op, s, lhs_range, src);
     393                 :         136 :       op = gimple_range_ssa_p (handler.operand2 ());
     394                 :         136 :       if (op)
     395                 :          24 :         calculate_op (op, s, lhs_range, src);
     396                 :             :     }
     397                 :         147 : }
     398                 :             : 
     399                 :             : namespace {
     400                 :             : 
     401                 :             : const pass_data pass_data_assumptions =
     402                 :             : {
     403                 :             :   GIMPLE_PASS, /* type */
     404                 :             :   "assumptions", /* name */
     405                 :             :   OPTGROUP_NONE, /* optinfo_flags */
     406                 :             :   TV_TREE_ASSUMPTIONS, /* tv_id */
     407                 :             :   PROP_ssa, /* properties_required */
     408                 :             :   PROP_assumptions_done, /* properties_provided */
     409                 :             :   0, /* properties_destroyed */
     410                 :             :   0, /* todo_flags_start */
     411                 :             :   0, /* todo_flags_end */
     412                 :             : };
     413                 :             : 
     414                 :             : 
     415                 :             : class pass_assumptions : public gimple_opt_pass
     416                 :             : {
     417                 :             : public:
     418                 :      280114 :   pass_assumptions (gcc::context *ctxt)
     419                 :      560228 :     : gimple_opt_pass (pass_data_assumptions, ctxt)
     420                 :             :   {}
     421                 :             : 
     422                 :             :   /* opt_pass methods: */
     423                 :     1416359 :   bool gate (function *fun) final override { return fun->assume_function; }
     424                 :         108 :   unsigned int execute (function *fun) final override
     425                 :             :     {
     426                 :             :       // Create a bitmap of all the parameters in this function.
     427                 :             :       // Invoke the assume_query to determine what values these parameters
     428                 :             :       // have when the function returns TRUE, and set the global values of
     429                 :             :       // those parameters in this function based on that.  This will later be
     430                 :             :       // utilized by ranger when processing builtin IFN_ASSUME function calls.
     431                 :             :       // See gimple-range-infer.cc::check_assume_func ().
     432                 :         108 :       auto_bitmap decls;
     433                 :         247 :       for (tree arg = DECL_ARGUMENTS (fun->decl); arg; arg = DECL_CHAIN (arg))
     434                 :             :         {
     435                 :         139 :           tree name = ssa_default_def (fun, arg);
     436                 :         139 :           if (!name || !gimple_range_ssa_p (name))
     437                 :          16 :             continue;
     438                 :         123 :           tree type = TREE_TYPE (name);
     439                 :         123 :           if (!value_range::supports_type_p (type))
     440                 :           0 :             continue;
     441                 :         123 :           bitmap_set_bit (decls, SSA_NAME_VERSION (name));
     442                 :             :         }
     443                 :             :       // If there are no parameters to map, simply return;
     444                 :         108 :       if (bitmap_empty_p (decls))
     445                 :             :         return TODO_discard_function;
     446                 :             : 
     447                 :          86 :       enable_ranger (fun);
     448                 :             : 
     449                 :             :       // This assume query will set any global values required.
     450                 :          86 :       assume_query query (fun, decls);
     451                 :             : 
     452                 :          86 :       disable_ranger (fun);
     453                 :          86 :       return TODO_discard_function;
     454                 :          86 :     }
     455                 :             : 
     456                 :             : }; // class pass_assumptions
     457                 :             : 
     458                 :             : } // anon namespace
     459                 :             : 
     460                 :             : gimple_opt_pass *
     461                 :      280114 : make_pass_assumptions (gcc::context *ctx)
     462                 :             : {
     463                 :      280114 :   return new pass_assumptions (ctx);
     464                 :             : }
        

Generated by: LCOV version 2.1-beta

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,rust,m2 --enable-host-shared. GCC test suite is run with the built compiler.