LCOV - code coverage report
Current view: top level - gcc - hierarchical_discriminator.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 80.2 % 121 97
Test Date: 2026-02-28 14:20:25 Functions: 75.0 % 8 6
Legend: Lines:     hit not hit

            Line data    Source code
       1              : /* Copyright The GNU Toolchain Authors
       2              : 
       3              : This file is part of GCC.
       4              : 
       5              : GCC is free software; you can redistribute it and/or modify it under
       6              : the terms of the GNU General Public License as published by the Free
       7              : Software Foundation; either version 3, or (at your option) any later
       8              : version.
       9              : 
      10              : GCC is distributed in the hope that it will be useful, but WITHOUT ANY
      11              : WARRANTY; without even the implied warranty of MERCHANTABILITY or
      12              : FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
      13              : for more details.
      14              : 
      15              : You should have received a copy of the GNU General Public License
      16              : along with GCC; see the file COPYING3.  If not see
      17              : <http://www.gnu.org/licenses/>.  */
      18              : 
      19              : #include "config.h"
      20              : #include "system.h"
      21              : #include "coretypes.h"
      22              : #include "backend.h"
      23              : #include "tree.h"
      24              : #include "gimple.h"
      25              : #include "tree-pass.h"
      26              : #include "ssa.h"
      27              : #include "gimple-iterator.h"
      28              : #include "tree-cfg.h"
      29              : #include "cfgloop.h"
      30              : #include "hierarchical_discriminator.h"
      31              : #include "cfghooks.h"
      32              : #include "diagnostic-core.h"
      33              : #include "function.h"
      34              : #include "rtl.h"
      35              : #include "basic-block.h"
      36              : 
      37              : /* Helper to update a location with new discriminator components.  If
      38              :    multiplicity_factor is non-zero, multiply existing multiplicity.
      39              :    If copyid is non-zero, set it (otherwise preserve existing).  */
      40              : 
      41              : static location_t
      42      3475088 : update_location_discriminator (location_t loc,
      43              :                                unsigned int multiplicity_factor,
      44              :                                unsigned int copyid)
      45              : {
      46      3475088 :   if (loc == UNKNOWN_LOCATION)
      47              :     return loc;
      48              : 
      49      3475088 :   discriminator_components comp = get_discriminator_components_from_loc (loc);
      50              : 
      51              :   /* Multiply existing multiplicity if requested.  */
      52      3475088 :   if (multiplicity_factor > 0)
      53              :     {
      54            2 :       unsigned int new_mult = (comp.multiplicity == 0)
      55       590375 :         ? multiplicity_factor
      56              :         : comp.multiplicity * multiplicity_factor;
      57       590375 :       if (new_mult > DISCR_MULTIPLICITY_MAX)
      58              :         new_mult = DISCR_MULTIPLICITY_MAX;
      59       590375 :       comp.multiplicity = new_mult;
      60              :     }
      61              : 
      62              :   /* Update copyid if requested.  */
      63      3475088 :   if (copyid > 0)
      64      3475088 :     comp.copyid = copyid;
      65              : 
      66      3475088 :   return location_with_discriminator_components (loc, comp);
      67              : }
      68              : 
      69              : /* Assign discriminators to a statement
      70              :    Updates the multiplicity and/or copyid discriminator components for
      71              :    all statements in the given basic block, while preserving the base
      72              :    discriminator.
      73              : 
      74              :    If multiplicity_factor > 0, multiply existing multiplicity by this factor.
      75              :    If copyid > 0, set it to this value.  */
      76              : 
      77              : void
      78            0 : assign_discriminators_to_stmt (gimple* stmt,
      79              :                                unsigned int multiplicity_factor,
      80              :                                unsigned int copyid)
      81              : {
      82            0 :   location_t loc = gimple_location (stmt);
      83              : 
      84            0 :   if (loc != UNKNOWN_LOCATION)
      85              :     {
      86            0 :       location_t new_loc
      87            0 :         = update_location_discriminator (loc,
      88              :                                          multiplicity_factor,
      89              :                                          copyid);
      90            0 :       gimple_set_location (stmt, new_loc);
      91              :     }
      92            0 : }
      93              : 
      94              : 
      95              : /* Assign discriminators to all statements in a basic block.  This
      96              :    function updates the multiplicity and/or copyid discriminator components for
      97              :    all statements in the given basic block, while preserving the base
      98              :    discriminator.
      99              : 
     100              :    If multiplicity_factor > 0, multiply existing multiplicity by this factor.
     101              :    If copyid > 0, set it to this value.  */
     102              : 
     103              : void
     104      1015021 : assign_discriminators_to_bb (basic_block bb,
     105              :                              unsigned int multiplicity_factor,
     106              :                              unsigned int copyid)
     107              : {
     108      1015021 :   gimple_stmt_iterator gsi;
     109      1015021 :   gphi_iterator phi_gsi;
     110      1015021 :   edge e;
     111      1015021 :   edge_iterator ei;
     112              : 
     113              :   /* Update PHI statements.  */
     114      2027667 :   for (phi_gsi = gsi_start_phis (bb); !gsi_end_p (phi_gsi);
     115      1012646 :        gsi_next (&phi_gsi))
     116              :     {
     117      1012646 :       gphi *phi = phi_gsi.phi ();
     118      1012646 :       location_t loc = gimple_location (phi);
     119              : 
     120      1012646 :       if (loc != UNKNOWN_LOCATION)
     121              :         {
     122            0 :           location_t new_loc
     123            0 :             = update_location_discriminator (loc,
     124              :                                              multiplicity_factor,
     125              :                                              copyid);
     126            0 :           gimple_set_location (phi, new_loc);
     127              :         }
     128              :     }
     129              : 
     130              :   /* Update regular statements.  */
     131      6316023 :   for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
     132              :     {
     133      4285981 :       gimple *stmt = gsi_stmt (gsi);
     134              : 
     135      4285981 :       if (is_gimple_debug (stmt))
     136       651225 :         continue;
     137              : 
     138      3634756 :       location_t loc = gimple_location (stmt);
     139      3634756 :       if (loc != UNKNOWN_LOCATION)
     140              :         {
     141      3467049 :           location_t new_loc
     142      3467049 :             = update_location_discriminator (loc,
     143              :                                              multiplicity_factor,
     144              :                                              copyid);
     145      6934098 :           gimple_set_location (stmt, new_loc);
     146              :         }
     147              :     }
     148              : 
     149              :   /* Update goto/edge locations.  */
     150      2600851 :   FOR_EACH_EDGE (e, ei, bb->succs)
     151              :     {
     152      1585830 :       location_t loc = e->goto_locus;
     153      1585830 :       if (loc != UNKNOWN_LOCATION)
     154              :         {
     155         8039 :           location_t new_loc
     156         8039 :             = update_location_discriminator (loc,
     157              :                                              multiplicity_factor,
     158              :                                              copyid);
     159         8039 :           e->goto_locus = new_loc;
     160              :         }
     161              :     }
     162      1015021 : }
     163              : 
     164              : /* Assign discriminators to all basic blocks in a loop.  This function is
     165              :    used by loop versioning passes to assign version IDs and vectorization
     166              :    factors to all statements in a loop version.  */
     167              : 
     168              : void
     169        77920 : assign_discriminators_to_loop (class loop *loop,
     170              :                                unsigned int multiplicity_factor,
     171              :                                unsigned int copyid)
     172              : {
     173        77920 :   basic_block *bbs;
     174        77920 :   unsigned int i;
     175              : 
     176              :   /* Get all basic blocks in the loop.  */
     177        77920 :   bbs = get_loop_body (loop);
     178              : 
     179              :   /* Assign discriminators to all blocks in the loop.  */
     180       325048 :   for (i = 0; i < loop->num_nodes; i++)
     181       169208 :     assign_discriminators_to_bb (bbs[i], multiplicity_factor, copyid);
     182              : 
     183        77920 :   free (bbs);
     184        77920 : }
     185              : 
     186              : 
     187              : /* Helper to update the copyid allocator map with a location's existing copyid.
     188              :    If the location has a non-zero copyid, record that we need to start
     189              :    allocating from copyid+1 for this location.  */
     190              : 
     191              : static void
     192     23238885 : record_existing_copyid (location_t loc, struct function *fn)
     193              : {
     194     23238885 :   if (loc == UNKNOWN_LOCATION)
     195     23238885 :     return;
     196              : 
     197     16944474 :   location_t pure_loc = get_pure_location (loc);
     198     16944474 :   unsigned int discr = get_discriminator_from_loc (loc);
     199     16944474 :   if (discr == 0)
     200              :     return;
     201              : 
     202              :   /* Extract copyid from discriminator.  */
     203      6482537 :   unsigned int copyid = (discr >> DISCR_COPYID_SHIFT) & DISCR_COPYID_MASK;
     204      6482537 :   if (copyid == 0)
     205              :     return;
     206              : 
     207              :   /* Update max copyid for this location.  */
     208            0 :   unsigned int next_copyid = copyid + 1;
     209            0 :   if (next_copyid > DISCR_COPYID_MAX)
     210            0 :     next_copyid = DISCR_COPYID_MAX;
     211              : 
     212            0 :   unsigned int *existing = fn->copyid_alloc->location_map->get (pure_loc);
     213            0 :   if (!existing || *existing <= copyid)
     214            0 :     fn->copyid_alloc->location_map->put (pure_loc, next_copyid);
     215              : }
     216              : 
     217              : /* Initialize the per-function copyid allocator.  Walks the function
     218              :    body to find existing max copyids per location.  */
     219              : 
     220              : static void
     221       324895 : init_copyid_allocator (struct function *fn)
     222              : {
     223       324895 :   if (!fn)
     224              :     return;
     225              : 
     226       324895 :   if (fn->copyid_alloc && fn->copyid_alloc->initialized)
     227              :     return;  /* Already initialized.  */
     228              : 
     229        71065 :   if (!fn->copyid_alloc)
     230              :     {
     231        71065 :       fn->copyid_alloc = XNEW (struct copyid_allocator);
     232       142130 :       fn->copyid_alloc->location_map
     233        71065 :         = new hash_map<int_hash<location_t, UNKNOWN_LOCATION,
     234              :                                UNKNOWN_LOCATION>, unsigned int>;
     235        71065 :       fn->copyid_alloc->initialized = false;
     236              :     }
     237              : 
     238              :   /* Only walk the body if not yet initialized.  */
     239        71065 :   if (fn->copyid_alloc->initialized)
     240              :     return;
     241              : 
     242              :   /* Walk the function body to find existing max copyids per location.
     243              :      This ensures we don't reuse copyids that were allocated in previous
     244              :      passes, during LTO, or brought in by inlining.  */
     245        71065 :   basic_block bb;
     246      2876799 :   FOR_EACH_BB_FN (bb, fn)
     247              :     {
     248      2805734 :       if (current_ir_type () == IR_GIMPLE)
     249              :         {
     250              :           /* Process PHI nodes.  */
     251      2166072 :           gphi_iterator phi_gsi;
     252      3545979 :           for (phi_gsi = gsi_start_phis (bb); !gsi_end_p (phi_gsi);
     253      1379907 :                gsi_next (&phi_gsi))
     254      1379907 :             record_existing_copyid (gimple_location (phi_gsi.phi ()), fn);
     255              : 
     256              :           /* Process regular statements.  */
     257      2166072 :           gimple_stmt_iterator gsi;
     258     18352987 :           for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
     259     14020843 :             record_existing_copyid (gimple_location (gsi_stmt (gsi)), fn);
     260              : 
     261              :           /* Process edge goto_locus locations.  */
     262      2166072 :           edge e;
     263      2166072 :           edge_iterator ei;
     264      5142724 :           FOR_EACH_EDGE (e, ei, bb->succs)
     265      2976652 :             record_existing_copyid (e->goto_locus, fn);
     266              :         }
     267              :       else
     268              :         {
     269              :           /* For RTL mode.  */
     270       639662 :           rtx_insn *insn;
     271      6528384 :           FOR_BB_INSNS (bb, insn)
     272              :             {
     273      5888722 :               if (INSN_P (insn))
     274      4861483 :                 record_existing_copyid (INSN_LOCATION (insn), fn);
     275              :             }
     276              :         }
     277              :     }
     278              : 
     279        71065 :   fn->copyid_alloc->initialized = true;
     280              : }
     281              : 
     282              : /* Allocate a unique copy_id base for the given location.
     283              :    STRIDE indicates how many copy_ids to reserve (for unrolling N times,
     284              :    use stride=N).  Returns the base copy_id.  */
     285              : 
     286              : unsigned int
     287       324895 : allocate_copyid_base (location_t loc, unsigned int stride)
     288              : {
     289              :   /* Need current function context.  */
     290       324895 :   if (!cfun)
     291              :     return 1;  /* No function context, return default.  */
     292              : 
     293       324895 :   init_copyid_allocator (cfun);
     294              : 
     295       324895 :   loc = get_pure_location (loc);
     296              : 
     297              :   /* Cannot allocate copyid for unknown location.  */
     298       324895 :   if (loc == UNKNOWN_LOCATION)
     299              :     return 1;  /* Return default base copyid.  */
     300              : 
     301              :   /* Check if this location has been seen before.  */
     302       324872 :   unsigned int *existing = cfun->copyid_alloc->location_map->get (loc);
     303       324872 :   if (existing)
     304              :     {
     305              :       /* Location already duplicated before.  Allocate next copy_id for it.  */
     306       174659 :       unsigned int base = *existing;
     307       174659 :       *existing += stride;  /* Update for next duplication.  */
     308              : 
     309              :       /* Clamp to maximum.  */
     310       174659 :       if (*existing > DISCR_COPYID_MAX)
     311            0 :         *existing = DISCR_COPYID_MAX;
     312       174659 :       return base;
     313              :     }
     314              :   else
     315              :     {
     316              :       /* First duplication at this location in this function.
     317              :          Start at 1 (not 0, which means "no copyid").  */
     318       150213 :       unsigned int base = 1;
     319       150213 :       unsigned int next = base + stride;
     320       150213 :       if (next > DISCR_COPYID_MAX)
     321            0 :         next = DISCR_COPYID_MAX;
     322              :       /* Record this location for future duplications.  */
     323       150213 :       cfun->copyid_alloc->location_map->put (loc, next);
     324              : 
     325       150213 :       return base;
     326              :     }
     327              : }
     328              : 
     329              : /* Free the copy_id allocator for a function.  Called when the function
     330              :    is being destroyed.  */
     331              : 
     332              : void
     333            0 : free_copyid_allocator (struct function *fn)
     334              : {
     335            0 :   if (fn && fn->copyid_alloc)
     336              :     {
     337            0 :       delete fn->copyid_alloc->location_map;
     338            0 :       XDELETE (fn->copyid_alloc);
     339            0 :       fn->copyid_alloc = NULL;
     340              :     }
     341            0 : }
        

Generated by: LCOV version 2.4-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.