LCOV - code coverage report
Current view: top level - gcc - hierarchical_discriminator.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 95.3 % 128 122
Test Date: 2026-10-17 16:30:31 Functions: 100.0 % 8 8
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     11775973 : update_location_discriminator (location_t loc,
      43              :                                unsigned int multiplicity_factor,
      44              :                                unsigned int copyid)
      45              : {
      46     11775973 :   if (loc == UNKNOWN_LOCATION)
      47              :     return loc;
      48              : 
      49     11775973 :   discriminator_components comp = get_discriminator_components_from_loc (loc);
      50              : 
      51              :   /* Multiply existing multiplicity if requested.  */
      52     11775973 :   if (multiplicity_factor > 0)
      53              :     {
      54            2 :       unsigned int new_mult = (comp.multiplicity == 0)
      55       611666 :         ? multiplicity_factor
      56              :         : comp.multiplicity * multiplicity_factor;
      57       611666 :       if (new_mult > DISCR_MULTIPLICITY_MAX)
      58              :         new_mult = DISCR_MULTIPLICITY_MAX;
      59       611666 :       comp.multiplicity = new_mult;
      60              :     }
      61              : 
      62              :   /* Update copyid if requested.  */
      63     11775973 :   if (copyid > 0)
      64     11775973 :     comp.copyid = copyid;
      65              : 
      66     11775973 :   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        36228 : assign_discriminators_to_stmt (gimple* stmt,
      79              :                                unsigned int multiplicity_factor,
      80              :                                unsigned int copyid)
      81              : {
      82        36228 :   location_t loc = gimple_location (stmt);
      83              : 
      84        36228 :   if (loc != UNKNOWN_LOCATION)
      85              :     {
      86        36219 :       location_t new_loc
      87        36219 :         = update_location_discriminator (loc,
      88              :                                          multiplicity_factor,
      89              :                                          copyid);
      90        72438 :       gimple_set_location (stmt, new_loc);
      91              :     }
      92        36228 : }
      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      4738302 : assign_discriminators_to_bb (basic_block bb,
     105              :                              unsigned int multiplicity_factor,
     106              :                              unsigned int copyid)
     107              : {
     108      4738302 :   if (current_ir_type () != IR_GIMPLE)
     109              :     {
     110       709066 :       rtx_insn *insn;
     111      5497256 :       FOR_BB_INSNS (bb, insn)
     112              :         {
     113      4788190 :           if (!INSN_P (insn) || !INSN_HAS_LOCATION (insn))
     114      1638929 :             continue;
     115      3149261 :           location_t loc = INSN_LOCATION (insn);
     116      6298522 :           INSN_LOCATION (insn)
     117      3149261 :             = update_location_discriminator (loc, multiplicity_factor, copyid);
     118              :         }
     119       709066 :       return;
     120              :     }
     121              : 
     122      4029236 :   gimple_stmt_iterator gsi;
     123      4029236 :   gphi_iterator phi_gsi;
     124      4029236 :   edge e;
     125      4029236 :   edge_iterator ei;
     126              : 
     127              :   /* Update PHI statements.  */
     128      9402250 :   for (phi_gsi = gsi_start_phis (bb); !gsi_end_p (phi_gsi);
     129      5373014 :        gsi_next (&phi_gsi))
     130              :     {
     131      5373014 :       gphi *phi = phi_gsi.phi ();
     132      5373014 :       location_t loc = gimple_location (phi);
     133              : 
     134      5373014 :       if (loc != UNKNOWN_LOCATION)
     135              :         {
     136            0 :           location_t new_loc
     137            0 :             = update_location_discriminator (loc,
     138              :                                              multiplicity_factor,
     139              :                                              copyid);
     140            0 :           gimple_set_location (phi, new_loc);
     141              :         }
     142              :     }
     143              : 
     144              :   /* Update regular statements.  */
     145     33234075 :   for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
     146              :     {
     147     25175603 :       gimple *stmt = gsi_stmt (gsi);
     148              : 
     149     25175603 :       if (is_gimple_debug (stmt))
     150     16172175 :         continue;
     151              : 
     152      9003428 :       location_t loc = gimple_location (stmt);
     153      9003428 :       if (loc != UNKNOWN_LOCATION)
     154              :         {
     155      8583309 :           location_t new_loc
     156      8583309 :             = update_location_discriminator (loc,
     157              :                                              multiplicity_factor,
     158              :                                              copyid);
     159     17166618 :           gimple_set_location (stmt, new_loc);
     160              :         }
     161              :     }
     162              : 
     163              :   /* Update goto/edge locations.  */
     164     11351775 :   FOR_EACH_EDGE (e, ei, bb->succs)
     165              :     {
     166      7322539 :       location_t loc = e->goto_locus;
     167      7322539 :       if (loc != UNKNOWN_LOCATION)
     168              :         {
     169         7184 :           location_t new_loc
     170         7184 :             = update_location_discriminator (loc,
     171              :                                              multiplicity_factor,
     172              :                                              copyid);
     173         7184 :           e->goto_locus = new_loc;
     174              :         }
     175              :     }
     176              : }
     177              : 
     178              : /* Assign discriminators to all basic blocks in a loop.  This function is
     179              :    used by loop versioning passes to assign version IDs and vectorization
     180              :    factors to all statements in a loop version.  */
     181              : 
     182              : void
     183        52597 : assign_discriminators_to_loop (class loop *loop,
     184              :                                unsigned int multiplicity_factor,
     185              :                                unsigned int copyid)
     186              : {
     187        52597 :   basic_block *bbs;
     188        52597 :   unsigned int i;
     189              : 
     190              :   /* Get all basic blocks in the loop.  */
     191        52597 :   bbs = get_loop_body (loop);
     192              : 
     193              :   /* Assign discriminators to all blocks in the loop.  */
     194       212510 :   for (i = 0; i < loop->num_nodes; i++)
     195       107316 :     assign_discriminators_to_bb (bbs[i], multiplicity_factor, copyid);
     196              : 
     197        52597 :   free (bbs);
     198        52597 : }
     199              : 
     200              : 
     201              : /* Helper to update the copyid allocator map with a location's existing copyid.
     202              :    If the location has a non-zero copyid, record that we need to start
     203              :    allocating from copyid+1 for this location.  */
     204              : 
     205              : static void
     206     93440873 : record_existing_copyid (location_t loc, struct function *fn)
     207              : {
     208     93440873 :   if (loc == UNKNOWN_LOCATION)
     209     93424527 :     return;
     210              : 
     211     68186283 :   location_t pure_loc = get_pure_location (loc);
     212     68186283 :   unsigned int discr = get_discriminator_from_loc (loc);
     213     68186283 :   if (discr == 0)
     214              :     return;
     215              : 
     216              :   /* Extract copyid from discriminator.  */
     217     24585598 :   unsigned int copyid = (discr >> DISCR_COPYID_SHIFT) & DISCR_COPYID_MASK;
     218     24585598 :   if (copyid == 0)
     219              :     return;
     220              : 
     221              :   /* Update max copyid for this location.  */
     222        16346 :   unsigned int next_copyid = copyid + 1;
     223        16346 :   if (next_copyid > DISCR_COPYID_MAX)
     224            0 :     next_copyid = DISCR_COPYID_MAX;
     225              : 
     226        16346 :   unsigned int *existing = fn->copyid_alloc->location_map->get (pure_loc);
     227        16346 :   if (!existing || *existing <= copyid)
     228         9260 :     fn->copyid_alloc->location_map->put (pure_loc, next_copyid);
     229              : }
     230              : 
     231              : /* Initialize the per-function copyid allocator.  Walks the function
     232              :    body to find existing max copyids per location.  */
     233              : 
     234              : static void
     235      3160989 : init_copyid_allocator (struct function *fn)
     236              : {
     237      3160989 :   if (!fn)
     238              :     return;
     239              : 
     240      3160989 :   if (fn->copyid_alloc && fn->copyid_alloc->initialized)
     241              :     return;  /* Already initialized.  */
     242              : 
     243       388445 :   if (!fn->copyid_alloc)
     244              :     {
     245       388445 :       fn->copyid_alloc = XNEW (struct copyid_allocator);
     246       776890 :       fn->copyid_alloc->location_map
     247       388445 :         = new hash_map<int_hash<location_t, UNKNOWN_LOCATION,
     248              :                                UNKNOWN_LOCATION>, unsigned int>;
     249       388445 :       fn->copyid_alloc->initialized = false;
     250              :     }
     251              : 
     252              :   /* Only walk the body if not yet initialized.  */
     253       388445 :   if (fn->copyid_alloc->initialized)
     254              :     return;
     255              : 
     256              :   /* Walk the function body to find existing max copyids per location.
     257              :      This ensures we don't reuse copyids that were allocated in previous
     258              :      passes, during LTO, or brought in by inlining.  */
     259       388445 :   basic_block bb;
     260     11319852 :   FOR_EACH_BB_FN (bb, fn)
     261              :     {
     262     10931407 :       if (current_ir_type () == IR_GIMPLE)
     263              :         {
     264              :           /* Process PHI nodes.  */
     265     10253240 :           gphi_iterator phi_gsi;
     266     14191541 :           for (phi_gsi = gsi_start_phis (bb); !gsi_end_p (phi_gsi);
     267      3938301 :                gsi_next (&phi_gsi))
     268      3938301 :             record_existing_copyid (gimple_location (phi_gsi.phi ()), fn);
     269              : 
     270              :           /* Process regular statements.  */
     271     10253240 :           gimple_stmt_iterator gsi;
     272     90989199 :           for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
     273     70482719 :             record_existing_copyid (gimple_location (gsi_stmt (gsi)), fn);
     274              : 
     275              :           /* Process edge goto_locus locations.  */
     276     10253240 :           edge e;
     277     10253240 :           edge_iterator ei;
     278     25230925 :           FOR_EACH_EDGE (e, ei, bb->succs)
     279     14977685 :             record_existing_copyid (e->goto_locus, fn);
     280              :         }
     281              :       else
     282              :         {
     283              :           /* For RTL mode.  */
     284       678167 :           rtx_insn *insn;
     285      6228132 :           FOR_BB_INSNS (bb, insn)
     286              :             {
     287      5549965 :               if (INSN_P (insn))
     288      4042168 :                 record_existing_copyid (INSN_LOCATION (insn), fn);
     289              :             }
     290              :         }
     291              :     }
     292              : 
     293       388445 :   fn->copyid_alloc->initialized = true;
     294              : }
     295              : 
     296              : /* Allocate a unique copy_id base for the given location.
     297              :    STRIDE indicates how many copy_ids to reserve (for unrolling N times,
     298              :    use stride=N).  Returns the base copy_id.  */
     299              : 
     300              : unsigned int
     301      3160989 : allocate_copyid_base (location_t loc, unsigned int stride)
     302              : {
     303              :   /* Need current function context.  */
     304      3160989 :   if (!cfun)
     305              :     return 1;  /* No function context, return default.  */
     306              : 
     307      3160989 :   init_copyid_allocator (cfun);
     308              : 
     309      3160989 :   loc = get_pure_location (loc);
     310              : 
     311              :   /* Cannot allocate copyid for unknown location.  */
     312      3160989 :   if (loc == UNKNOWN_LOCATION)
     313              :     return 1;  /* Return default base copyid.  */
     314              : 
     315              :   /* Check if this location has been seen before.  */
     316      3160768 :   unsigned int *existing = cfun->copyid_alloc->location_map->get (loc);
     317      3160768 :   if (existing)
     318              :     {
     319              :       /* Location already duplicated before.  Allocate next copy_id for it.  */
     320      1889357 :       unsigned int base = *existing;
     321      1889357 :       *existing += stride;  /* Update for next duplication.  */
     322              : 
     323              :       /* Clamp to maximum.  */
     324      1889357 :       if (*existing > DISCR_COPYID_MAX)
     325            0 :         *existing = DISCR_COPYID_MAX;
     326              :       return base;
     327              :     }
     328              :   else
     329              :     {
     330              :       /* First duplication at this location in this function.
     331              :          Start at 1 (not 0, which means "no copyid").  */
     332      1271411 :       unsigned int base = 1;
     333      1271411 :       unsigned int next = base + stride;
     334      1271411 :       if (next > DISCR_COPYID_MAX)
     335            0 :         next = DISCR_COPYID_MAX;
     336              :       /* Record this location for future duplications.  */
     337      1271411 :       cfun->copyid_alloc->location_map->put (loc, next);
     338              : 
     339      1271411 :       return base;
     340              :     }
     341              : }
     342              : 
     343              : /* Free the copy_id allocator for a function.  Called when the function
     344              :    is being destroyed.  */
     345              : 
     346              : void
     347      1742678 : free_copyid_allocator (struct function *fn)
     348              : {
     349      1742678 :   if (fn && fn->copyid_alloc)
     350              :     {
     351       683678 :       delete fn->copyid_alloc->location_map;
     352       341839 :       XDELETE (fn->copyid_alloc);
     353       341839 :       fn->copyid_alloc = NULL;
     354              :     }
     355      1742678 : }
        

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