LCOV - code coverage report
Current view: top level - gcc - ipa-modref-tree.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 93.4 % 574 536
Test Date: 2026-02-28 14:20:25 Functions: 71.4 % 42 30
Legend: Lines:     hit not hit

            Line data    Source code
       1              : /* Data structure for the modref pass.
       2              :    Copyright (C) 2020-2026 Free Software Foundation, Inc.
       3              :    Contributed by David Cepelik and Jan Hubicka
       4              : 
       5              : This file is part of GCC.
       6              : 
       7              : GCC is free software; you can redistribute it and/or modify it under
       8              : the terms of the GNU General Public License as published by the Free
       9              : Software Foundation; either version 3, or (at your option) any later
      10              : version.
      11              : 
      12              : GCC is distributed in the hope that it will be useful, but WITHOUT ANY
      13              : WARRANTY; without even the implied warranty of MERCHANTABILITY or
      14              : FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
      15              : 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 "backend.h"
      25              : #include "tree.h"
      26              : #include "ipa-modref-tree.h"
      27              : #include "selftest.h"
      28              : #include "tree-ssa-alias.h"
      29              : #include "gimple.h"
      30              : #include "cgraph.h"
      31              : #include "tree-streamer.h"
      32              : 
      33              : /* Return true if both accesses are the same.  */
      34              : bool
      35      2195422 : modref_access_node::operator == (const modref_access_node &a) const
      36              : {
      37      2195422 :   if (parm_index != a.parm_index)
      38              :     return false;
      39      1043696 :   if (parm_index != MODREF_UNKNOWN_PARM
      40      1043696 :       && parm_index != MODREF_GLOBAL_MEMORY_PARM)
      41              :     {
      42      1043696 :       if (parm_offset_known != a.parm_offset_known)
      43              :         return false;
      44      1043696 :       if (parm_offset_known
      45      1043696 :           && !known_eq (parm_offset, a.parm_offset))
      46              :         return false;
      47              :     }
      48       731908 :   if (range_info_useful_p () != a.range_info_useful_p ())
      49              :     return false;
      50       731908 :   if (range_info_useful_p ()
      51       731908 :       && (!known_eq (a.offset, offset)
      52        22826 :           || !known_eq (a.size, size)
      53            0 :           || !known_eq (a.max_size, max_size)))
      54              :     return false;
      55              :   return true;
      56              : }
      57              : 
      58              : /* Return true A is a subaccess.  */
      59              : bool
      60     25565086 : modref_access_node::contains (const modref_access_node &a) const
      61              : {
      62     25565086 :   poly_offset_int aoffset_adj = 0;
      63     25565086 :   if (parm_index != MODREF_UNKNOWN_PARM)
      64              :     {
      65     25565083 :       if (parm_index != a.parm_index)
      66              :         return false;
      67     15727545 :       if (parm_offset_known)
      68              :         {
      69     14625836 :            if (!a.parm_offset_known)
      70              :              return false;
      71              :            /* Accesses are never below parm_offset, so look
      72              :               for smaller offset.
      73              :               If access ranges are known still allow merging
      74              :               when bit offsets comparison passes.  */
      75     14612962 :            if (!known_le (parm_offset, a.parm_offset)
      76     14612962 :                && !range_info_useful_p ())
      77              :              return false;
      78              :            /* We allow negative aoffset_adj here in case
      79              :               there is an useful range.  This is because adding
      80              :               a.offset may result in non-negative offset again.
      81              :               Ubsan fails on val << LOG_BITS_PER_UNIT where val
      82              :               is negative.  */
      83     14612962 :            aoffset_adj = (poly_offset_int::from (a.parm_offset, SIGNED)
      84     14612962 :                           - poly_offset_int::from (parm_offset, SIGNED))
      85     29225924 :                          * BITS_PER_UNIT;
      86              :         }
      87              :     }
      88     15714674 :   if (range_info_useful_p ())
      89              :     {
      90     14612962 :       if (!a.range_info_useful_p ())
      91              :         return false;
      92              :       /* Sizes of stores are used to check that object is big enough
      93              :          to fit the store, so smaller or unknown store is more general
      94              :          than large store.  */
      95     14612962 :       if (known_size_p (size)
      96     14612962 :           && (!known_size_p (a.size)
      97     14353989 :               || !known_le (size, a.size)))
      98              :         return false;
      99     12838895 :       if (known_size_p (max_size))
     100     12678222 :         return known_subrange_p (poly_offset_int::from (a.offset, SIGNED)
     101     25356444 :                                  + aoffset_adj, a.max_size,
     102     12678222 :                                  poly_offset_int::from (offset, SIGNED),
     103     12678222 :                                  max_size);
     104              :       else
     105       160673 :         return known_le (poly_offset_int::from (offset, SIGNED),
     106              :                          poly_offset_int::from (a.offset, SIGNED)
     107              :                          + aoffset_adj);
     108              :     }
     109              :   return true;
     110              : }
     111              : 
     112              : /* Update access range to new parameters.
     113              :    If RECORD_ADJUSTMENTS is true, record number of changes in the access
     114              :    and if threshold is exceeded start dropping precision
     115              :    so only constantly many updates are possible.  This makes dataflow
     116              :    to converge.  */
     117              : void
     118      1042790 : modref_access_node::update (poly_int64 parm_offset1,
     119              :                             poly_int64 offset1, poly_int64 size1,
     120              :                             poly_int64 max_size1, bool record_adjustments)
     121              : {
     122      1042790 :   if (known_eq (parm_offset, parm_offset1)
     123      1018728 :       && known_eq (offset, offset1)
     124       785473 :       && known_eq (size, size1)
     125      1813256 :       && known_eq (max_size, max_size1))
     126              :     return;
     127      1037747 :   if (!record_adjustments
     128      1037747 :       || (++adjustments) < param_modref_max_adjustments)
     129              :     {
     130      1037689 :       parm_offset = parm_offset1;
     131      1037689 :       offset = offset1;
     132      1037689 :       size = size1;
     133      1037689 :       max_size = max_size1;
     134              :     }
     135              :   else
     136              :     {
     137           58 :       if (dump_file)
     138            1 :         fprintf (dump_file, "--param modref-max-adjustments limit reached:");
     139           58 :       if (!known_eq (parm_offset, parm_offset1))
     140              :         {
     141            0 :           if (dump_file)
     142            0 :             fprintf (dump_file, " parm_offset cleared");
     143            0 :           parm_offset_known = false;
     144              :         }
     145           58 :       if (!known_eq (size, size1))
     146              :         {
     147            0 :           size = -1;
     148            0 :           if (dump_file)
     149            0 :             fprintf (dump_file, " size cleared");
     150              :         }
     151           58 :       if (!known_eq (max_size, max_size1))
     152              :         {
     153           58 :           max_size = -1;
     154           58 :           if (dump_file)
     155            1 :             fprintf (dump_file, " max_size cleared");
     156              :         }
     157           58 :       if (!known_eq (offset, offset1))
     158              :         {
     159            0 :           offset = 0;
     160            0 :           if (dump_file)
     161            0 :             fprintf (dump_file, " offset cleared");
     162              :         }
     163           58 :       if (dump_file)
     164            1 :         fprintf (dump_file, "\n");
     165              :     }
     166              : }
     167              : 
     168              : /* Merge in access A if it is possible to do without losing
     169              :    precision.  Return true if successful.
     170              :    If RECORD_ADJUSTMENTs is true, remember how many interval
     171              :    was prolonged and punt when there are too many.  */
     172              : bool
     173      4485722 : modref_access_node::merge (const modref_access_node &a,
     174              :                            bool record_adjustments)
     175              : {
     176      4485722 :   poly_int64 offset1 = 0;
     177      4485722 :   poly_int64 aoffset1 = 0;
     178      4485722 :   poly_int64 new_parm_offset = 0;
     179              : 
     180              :   /* We assume that containment was tested earlier.  */
     181      4485722 :   gcc_checking_assert (!contains (a) && !a.contains (*this));
     182      4485722 :   if (parm_index != MODREF_UNKNOWN_PARM)
     183              :     {
     184      4485722 :       if (parm_index != a.parm_index)
     185              :         return false;
     186      2684728 :       if (parm_offset_known)
     187              :         {
     188      2684728 :           if (!a.parm_offset_known)
     189              :             return false;
     190      2684728 :           if (!combined_offsets (a, &new_parm_offset, &offset1, &aoffset1))
     191              :             return false;
     192              :         }
     193              :     }
     194              :   /* See if we can merge ranges.  */
     195      2684728 :   if (range_info_useful_p ())
     196              :     {
     197              :       /* In this case we have containment that should be
     198              :          handled earlier.  */
     199      2684728 :       gcc_checking_assert (a.range_info_useful_p ());
     200              : 
     201              :       /* If a.size is less specified than size, merge only
     202              :          if intervals are otherwise equivalent.  */
     203      2684728 :       if (known_size_p (size)
     204      2684728 :           && (!known_size_p (a.size) || known_lt (a.size, size)))
     205              :         {
     206       286129 :           if (((known_size_p (max_size) || known_size_p (a.max_size))
     207       286097 :                && !known_eq (max_size, a.max_size))
     208       294293 :                || !known_eq (offset1, aoffset1))
     209              :             return false;
     210            0 :           update (new_parm_offset, offset1, a.size, max_size,
     211              :                   record_adjustments);
     212            0 :           return true;
     213              :         }
     214              :       /* If sizes are same, we can extend the interval.  */
     215      2398599 :       if ((known_size_p (size) || known_size_p (a.size))
     216      2411503 :           && !known_eq (size, a.size))
     217              :         return false;
     218      2108456 :       if (known_le (offset1, aoffset1))
     219              :         {
     220      1408747 :           if (!known_size_p (max_size)
     221      1408747 :               || known_ge (offset1 + max_size, aoffset1))
     222              :             {
     223       759178 :               update2 (new_parm_offset, offset1, size, max_size,
     224              :                        aoffset1, a.size, a.max_size,
     225              :                        record_adjustments);
     226       759178 :               return true;
     227              :             }
     228              :         }
     229       699709 :       else if (known_le (aoffset1, offset1))
     230              :         {
     231       699709 :           if (!known_size_p (a.max_size)
     232       699709 :               || known_ge (aoffset1 + a.max_size, offset1))
     233              :             {
     234       229966 :               update2 (new_parm_offset, offset1, size, max_size,
     235              :                        aoffset1, a.size, a.max_size,
     236              :                        record_adjustments);
     237       229966 :               return true;
     238              :             }
     239              :         }
     240              :       return false;
     241              :     }
     242            0 :   update (new_parm_offset, offset1,
     243              :           size, max_size, record_adjustments);
     244            0 :   return true;
     245              : }
     246              : 
     247              : /* Return true if A1 and B1 can be merged with lower information
     248              :    less than A2 and B2.
     249              :    Assume that no containment or lossless merging is possible.  */
     250              : bool
     251       173487 : modref_access_node::closer_pair_p (const modref_access_node &a1,
     252              :                                    const modref_access_node &b1,
     253              :                                    const modref_access_node &a2,
     254              :                                    const modref_access_node &b2)
     255              : {
     256              :   /* Merging different parm indexes comes to complete loss
     257              :      of range info.  */
     258       173487 :   if (a1.parm_index != b1.parm_index)
     259              :     return false;
     260        90172 :   if (a2.parm_index != b2.parm_index)
     261              :     return true;
     262              :   /* If parm is known and parm indexes are the same we should
     263              :      already have containment.  */
     264        89052 :   gcc_checking_assert (a1.parm_offset_known && b1.parm_offset_known);
     265        89052 :   gcc_checking_assert (a2.parm_offset_known && b2.parm_offset_known);
     266              : 
     267              :   /* First normalize offsets for parm offsets.  */
     268        89052 :   poly_int64 new_parm_offset, offseta1, offsetb1, offseta2, offsetb2;
     269        89052 :   if (!a1.combined_offsets (b1, &new_parm_offset, &offseta1, &offsetb1)
     270        89052 :       || !a2.combined_offsets (b2, &new_parm_offset, &offseta2, &offsetb2))
     271            0 :     gcc_unreachable ();
     272              : 
     273              : 
     274              :   /* Now compute distance of the intervals.  */
     275        89052 :   poly_offset_int dist1, dist2;
     276        89052 :   if (known_le (offseta1, offsetb1))
     277              :     {
     278        86153 :       if (!known_size_p (a1.max_size))
     279            0 :         dist1 = 0;
     280              :       else
     281       172306 :         dist1 = (poly_offset_int)offsetb1
     282       172306 :                 - (poly_offset_int)offseta1
     283       172306 :                 - (poly_offset_int)a1.max_size;
     284              :     }
     285              :   else
     286              :     {
     287         2899 :       if (!known_size_p (b1.max_size))
     288            0 :         dist1 = 0;
     289              :       else
     290         5798 :         dist1 = (poly_offset_int)offseta1
     291         5798 :                  - (poly_offset_int)offsetb1
     292         5798 :                  - (poly_offset_int)b1.max_size;
     293              :     }
     294        89052 :   if (known_le (offseta2, offsetb2))
     295              :     {
     296        85668 :       if (!known_size_p (a2.max_size))
     297            0 :         dist2 = 0;
     298              :       else
     299       171336 :         dist2 = (poly_offset_int)offsetb2
     300       171336 :                 - (poly_offset_int)offseta2
     301       171336 :                 - (poly_offset_int)a2.max_size;
     302              :     }
     303              :   else
     304              :     {
     305         3384 :       if (!known_size_p (b2.max_size))
     306            0 :         dist2 = 0;
     307              :       else
     308         3384 :         dist2 = offseta2
     309         6768 :                 - (poly_offset_int)offsetb2
     310         6768 :                 - (poly_offset_int)b2.max_size;
     311              :     }
     312              :   /* It may happen that intervals overlap in case size
     313              :      is different.  Prefer the overlap to non-overlap.  */
     314        89052 :   if (known_lt (dist1, 0) && known_ge (dist2, 0))
     315           64 :     return true;
     316        88988 :   if (known_lt (dist2, 0) && known_ge (dist1, 0))
     317         4650 :     return false;
     318        84338 :   if (known_lt (dist1, 0))
     319              :     /* If both overlaps minimize overlap.  */
     320          371 :     return known_le (dist2, dist1);
     321              :   else
     322              :     /* If both are disjoint look for smaller distance.  */
     323        83967 :     return known_le (dist1, dist2);
     324              : }
     325              : 
     326              : /* Merge in access A while losing precision.  */
     327              : void
     328         1291 : modref_access_node::forced_merge (const modref_access_node &a,
     329              :                                   bool record_adjustments)
     330              : {
     331         1291 :   if (parm_index != a.parm_index)
     332              :     {
     333            3 :       gcc_checking_assert (parm_index != MODREF_UNKNOWN_PARM);
     334            3 :       parm_index = MODREF_UNKNOWN_PARM;
     335            3 :       return;
     336              :     }
     337              : 
     338              :   /* We assume that containment and lossless merging
     339              :      was tested earlier.  */
     340         1288 :   gcc_checking_assert (!contains (a) && !a.contains (*this)
     341              :                        && !merge (a, record_adjustments));
     342         1288 :   gcc_checking_assert (parm_offset_known && a.parm_offset_known);
     343              : 
     344         1288 :   poly_int64 new_parm_offset, offset1, aoffset1;
     345         1288 :   if (!combined_offsets (a, &new_parm_offset, &offset1, &aoffset1))
     346              :     {
     347            0 :       parm_offset_known = false;
     348            0 :       return;
     349              :     }
     350         1288 :   gcc_checking_assert (range_info_useful_p ()
     351              :                        && a.range_info_useful_p ());
     352         1288 :   if (record_adjustments)
     353            0 :     adjustments += a.adjustments;
     354         1288 :   update2 (new_parm_offset,
     355              :            offset1, size, max_size,
     356              :            aoffset1, a.size, a.max_size,
     357              :            record_adjustments);
     358              : }
     359              : 
     360              : /* Merge two ranges both starting at parm_offset1 and update THIS
     361              :    with result.  */
     362              : void
     363       990432 : modref_access_node::update2 (poly_int64 parm_offset1,
     364              :                              poly_int64 offset1, poly_int64 size1,
     365              :                              poly_int64 max_size1,
     366              :                              poly_int64 offset2, poly_int64 size2,
     367              :                              poly_int64 max_size2,
     368              :                              bool record_adjustments)
     369              : {
     370       990432 :   poly_int64 new_size = size1;
     371              : 
     372       990432 :   if (!known_size_p (size2)
     373       990432 :       || known_le (size2, size1))
     374       989756 :     new_size = size2;
     375              :   else
     376              :     gcc_checking_assert (known_le (size1, size2));
     377              : 
     378       990432 :   if (known_le (offset1, offset2))
     379              :     ;
     380       229984 :   else if (known_le (offset2, offset1))
     381              :     {
     382       229984 :       std::swap (offset1, offset2);
     383       229984 :       std::swap (max_size1, max_size2);
     384              :     }
     385              :   else
     386              :     gcc_unreachable ();
     387              : 
     388       990432 :   poly_int64 new_max_size;
     389              : 
     390       990432 :   if (!known_size_p (max_size1))
     391            2 :     new_max_size = max_size1;
     392       990430 :   else if (!known_size_p (max_size2))
     393         1413 :     new_max_size = max_size2;
     394              :   else
     395              :     {
     396      2967051 :       poly_offset_int s = (poly_offset_int)max_size2
     397      1978034 :                           + (poly_offset_int)offset2
     398       989017 :                           - (poly_offset_int)offset1;
     399       989017 :       if (s.to_shwi (&new_max_size))
     400              :         {
     401       989017 :           if (known_le (new_max_size, max_size1))
     402           55 :             new_max_size = max_size1;
     403              :         }
     404              :       else
     405            0 :         new_max_size = -1;
     406              :     }
     407              : 
     408       990432 :   update (parm_offset1, offset1,
     409              :           new_size, new_max_size, record_adjustments);
     410       990432 : }
     411              : 
     412              : /* Given access nodes THIS and A, return true if they
     413              :    can be done with common parm_offsets.  In this case
     414              :    return parm offset in new_parm_offset, new_offset
     415              :    which is start of range in THIS and new_aoffset that
     416              :    is start of range in A.  */
     417              : bool
     418      3772378 : modref_access_node::combined_offsets (const modref_access_node &a,
     419              :                                       poly_int64 *new_parm_offset,
     420              :                                       poly_int64 *new_offset,
     421              :                                       poly_int64 *new_aoffset) const
     422              : {
     423      3772378 :   gcc_checking_assert (parm_offset_known && a.parm_offset_known);
     424      3772378 :   if (known_le (a.parm_offset, parm_offset))
     425              :     {
     426      3008780 :       *new_offset = offset
     427      3008780 :                     + ((parm_offset - a.parm_offset)
     428      3008780 :                        << LOG2_BITS_PER_UNIT);
     429      3008780 :       *new_aoffset = a.offset;
     430      3008780 :       *new_parm_offset = a.parm_offset;
     431      3008780 :       return true;
     432              :     }
     433       763598 :   else if (known_le (parm_offset, a.parm_offset))
     434              :     {
     435       763598 :       *new_aoffset = a.offset
     436       763598 :                       + ((a.parm_offset - parm_offset)
     437       763598 :                          << LOG2_BITS_PER_UNIT);
     438       763598 :       *new_offset = offset;
     439       763598 :       *new_parm_offset = parm_offset;
     440       763598 :       return true;
     441              :     }
     442              :   else
     443              :     return false;
     444              : }
     445              : 
     446              : /* Try to optimize the access ACCESSES list after entry INDEX was modified.  */
     447              : void
     448      1010105 : modref_access_node::try_merge_with (vec <modref_access_node, va_gc> *&accesses,
     449              :                                     size_t index)
     450              : {
     451      1010105 :   size_t i;
     452              : 
     453      2740522 :   for (i = 0; i < accesses->length ();)
     454      1730417 :     if (i != index)
     455              :       {
     456       689936 :         bool found = false, restart = false;
     457       689936 :         modref_access_node *a = &(*accesses)[i];
     458       689936 :         modref_access_node *n = &(*accesses)[index];
     459              : 
     460       689936 :         if (n->contains (*a))
     461              :           found = true;
     462       682619 :         if (!found && n->merge (*a, false))
     463              :           found = restart = true;
     464       657251 :         gcc_checking_assert (found || !a->merge (*n, false));
     465       689936 :         if (found)
     466              :           {
     467        40002 :             accesses->unordered_remove (i);
     468        40002 :             if (index == accesses->length ())
     469              :               {
     470         2216 :                 index = i;
     471         2216 :                 i++;
     472              :               }
     473        40002 :             if (restart)
     474        32685 :               i = 0;
     475              :           }
     476              :         else
     477       649934 :           i++;
     478              :       }
     479              :     else
     480      1040481 :       i++;
     481      1010105 : }
     482              : 
     483              : /* Stream out to OB.  */
     484              : 
     485              : void
     486        28983 : modref_access_node::stream_out (struct output_block *ob) const
     487              : {
     488        28983 :   streamer_write_hwi (ob, parm_index);
     489        28983 :   if (parm_index != MODREF_UNKNOWN_PARM)
     490              :     {
     491        28697 :       streamer_write_uhwi (ob, parm_offset_known);
     492        28697 :       if (parm_offset_known)
     493              :         {
     494        19337 :           streamer_write_poly_int64 (ob, parm_offset);
     495        19337 :           streamer_write_poly_int64 (ob, offset);
     496        19337 :           streamer_write_poly_int64 (ob, size);
     497        19337 :           streamer_write_poly_int64 (ob, max_size);
     498              :         }
     499              :     }
     500        28983 : }
     501              : 
     502              : modref_access_node
     503        21603 : modref_access_node::stream_in (struct lto_input_block *ib)
     504              : {
     505        21603 :   int parm_index = streamer_read_hwi (ib);
     506        21603 :   bool parm_offset_known = false;
     507        21603 :   poly_int64 parm_offset = 0;
     508        21603 :   poly_int64 offset = 0;
     509        21603 :   poly_int64 size = -1;
     510        21603 :   poly_int64 max_size = -1;
     511              : 
     512        21603 :   if (parm_index != MODREF_UNKNOWN_PARM)
     513              :     {
     514        21317 :       parm_offset_known = streamer_read_uhwi (ib);
     515        21317 :       if (parm_offset_known)
     516              :         {
     517        13908 :           parm_offset = streamer_read_poly_int64 (ib);
     518        13908 :           offset = streamer_read_poly_int64 (ib);
     519        13908 :           size = streamer_read_poly_int64 (ib);
     520        13908 :           max_size = streamer_read_poly_int64 (ib);
     521              :         }
     522              :     }
     523        21603 :   return {offset, size, max_size, parm_offset, parm_index,
     524        21603 :           parm_offset_known, false};
     525              : }
     526              : 
     527              : /* Insert access with OFFSET and SIZE.
     528              :    Collapse tree if it has more than MAX_ACCESSES entries.
     529              :    If RECORD_ADJUSTMENTs is true avoid too many interval extensions.
     530              :    Return true if record was changed.
     531              : 
     532              :    Return 0 if nothing changed, 1 if insert was successful and -1
     533              :    if entries should be collapsed.  */
     534              : int
     535      9226365 : modref_access_node::insert (vec <modref_access_node, va_gc> *&accesses,
     536              :                             modref_access_node a, size_t max_accesses,
     537              :                             bool record_adjustments)
     538              : {
     539      9226365 :   size_t i, j;
     540      9226365 :   modref_access_node *a2;
     541              : 
     542              :   /* Verify that list does not contain redundant accesses.  */
     543      9226365 :   if (flag_checking)
     544              :     {
     545              :       size_t i, i2;
     546              :       modref_access_node *a, *a2;
     547              : 
     548     19705006 :       FOR_EACH_VEC_SAFE_ELT (accesses, i, a)
     549              :         {
     550     23490012 :           FOR_EACH_VEC_SAFE_ELT (accesses, i2, a2)
     551     13011360 :             if (i != i2)
     552      7772034 :               gcc_assert (!a->contains (*a2));
     553              :         }
     554              :     }
     555              : 
     556     11421787 :   FOR_EACH_VEC_SAFE_ELT (accesses, i, a2)
     557              :     {
     558      4923566 :       if (a2->contains (a))
     559              :         return 0;
     560      3204239 :       if (a.contains (*a2))
     561              :         {
     562        52358 :           a.adjustments = 0;
     563        52358 :           a2->parm_index = a.parm_index;
     564        52358 :           a2->parm_offset_known = a.parm_offset_known;
     565        52358 :           a2->update (a.parm_offset, a.offset, a.size, a.max_size,
     566              :                       record_adjustments);
     567        52358 :           modref_access_node::try_merge_with (accesses, i);
     568        52358 :           return 1;
     569              :         }
     570      3151881 :       if (a2->merge (a, record_adjustments))
     571              :         {
     572       956459 :           modref_access_node::try_merge_with (accesses, i);
     573       956459 :           return 1;
     574              :         }
     575      2195422 :       gcc_checking_assert (!(a == *a2));
     576              :     }
     577              : 
     578              :   /* If this base->ref pair has too many accesses stored, we will clear
     579              :      all accesses and bail out.  */
     580      6498221 :   if (accesses && accesses->length () >= max_accesses)
     581              :     {
     582         1291 :       if (max_accesses < 2)
     583              :         return -1;
     584              :       /* Find least harmful merge and perform it.  */
     585              :       int best1 = -1, best2 = -1;
     586        21863 :       FOR_EACH_VEC_SAFE_ELT (accesses, i, a2)
     587              :         {
     588       174778 :           for (j = i + 1; j < accesses->length (); j++)
     589       154206 :             if (best1 < 0
     590       307121 :                 || modref_access_node::closer_pair_p
     591       305830 :                      (*a2, (*accesses)[j],
     592       152915 :                       (*accesses)[best1],
     593       151486 :                       best2 < 0 ? a : (*accesses)[best2]))
     594              :               {
     595        15876 :                 best1 = i;
     596        15876 :                 best2 = j;
     597              :               }
     598        20572 :           if (modref_access_node::closer_pair_p
     599        41144 :                      (*a2, a,
     600        20572 :                       (*accesses)[best1],
     601        19865 :                       best2 < 0 ? a : (*accesses)[best2]))
     602              :             {
     603         1184 :               best1 = i;
     604         1184 :               best2 = -1;
     605              :             }
     606              :         }
     607         1291 :       (*accesses)[best1].forced_merge (best2 < 0 ? a : (*accesses)[best2],
     608              :                                        record_adjustments);
     609              :       /* Check that merging indeed merged ranges.  */
     610         1291 :       gcc_checking_assert ((*accesses)[best1].contains
     611              :                                (best2 < 0 ? a : (*accesses)[best2]));
     612         1291 :       if (!(*accesses)[best1].useful_p ())
     613              :         return -1;
     614         1288 :       if (dump_file && best2 >= 0)
     615            1 :         fprintf (dump_file,
     616              :                  "--param modref-max-accesses limit reached;"
     617              :                  " merging %i and %i\n", best1, best2);
     618         1287 :       else if (dump_file)
     619            1 :         fprintf (dump_file,
     620              :                  "--param modref-max-accesses limit reached;"
     621              :                  " merging with %i\n", best1);
     622         1288 :       modref_access_node::try_merge_with (accesses, best1);
     623         1288 :       if (best2 >= 0)
     624          200 :         insert (accesses, a, max_accesses, record_adjustments);
     625         1288 :       return 1;
     626              :     }
     627      6496930 :   a.adjustments = 0;
     628      6496930 :   vec_safe_push (accesses, a);
     629      6496930 :   return 1;
     630              : }
     631              : 
     632              : /* Return true if range info is useful.  */
     633              : bool
     634     61906700 : modref_access_node::range_info_useful_p () const
     635              : {
     636     61906700 :   return parm_index != MODREF_UNKNOWN_PARM
     637     61906700 :          && parm_index != MODREF_GLOBAL_MEMORY_PARM
     638     53342565 :          && parm_offset_known
     639    114289633 :          && (known_size_p (size)
     640       566280 :              || known_size_p (max_size)
     641       212470 :              || known_ge (offset, 0));
     642              : }
     643              : 
     644              : /* Dump range to debug OUT.  */
     645              : void
     646          616 : modref_access_node::dump (FILE *out)
     647              : {
     648          616 :   if (parm_index != MODREF_UNKNOWN_PARM)
     649              :     {
     650          539 :       if (parm_index == MODREF_GLOBAL_MEMORY_PARM)
     651            4 :         fprintf (out, " Base in global memory");
     652          535 :       else if (parm_index >= 0)
     653          530 :         fprintf (out, " Parm %i", parm_index);
     654            5 :       else if (parm_index == MODREF_STATIC_CHAIN_PARM)
     655            5 :         fprintf (out, " Static chain");
     656              :       else
     657            0 :         gcc_unreachable ();
     658          539 :       if (parm_offset_known)
     659              :         {
     660          386 :           fprintf (out, " param offset:");
     661          386 :           print_dec ((poly_int64)parm_offset, out, SIGNED);
     662              :         }
     663              :     }
     664          616 :   if (range_info_useful_p ())
     665              :     {
     666          386 :       fprintf (out, " offset:");
     667          386 :       print_dec ((poly_int64)offset, out, SIGNED);
     668          386 :       fprintf (out, " size:");
     669          386 :       print_dec ((poly_int64)size, out, SIGNED);
     670          386 :       fprintf (out, " max_size:");
     671          386 :       print_dec ((poly_int64)max_size, out, SIGNED);
     672          386 :       if (adjustments)
     673            1 :         fprintf (out, " adjusted %i times", adjustments);
     674              :     }
     675          616 :   fprintf (out, "\n");
     676          616 : }
     677              : 
     678              : /* Return tree corresponding to parameter of the range in STMT.  */
     679              : tree
     680     13854537 : modref_access_node::get_call_arg (const gcall *stmt) const
     681              : {
     682     13854537 :   if (parm_index == MODREF_UNKNOWN_PARM
     683     13854537 :       || parm_index == MODREF_GLOBAL_MEMORY_PARM)
     684              :     return NULL;
     685     13853475 :   if (parm_index == MODREF_STATIC_CHAIN_PARM)
     686       357426 :     return gimple_call_chain (stmt);
     687              :   /* MODREF_RETSLOT_PARM should not happen in access trees since the store
     688              :      is seen explicitly in the caller.  */
     689     13496049 :   gcc_checking_assert (parm_index >= 0);
     690     13496049 :   if (parm_index >= (int)gimple_call_num_args (stmt))
     691              :     return NULL;
     692     13496029 :   return gimple_call_arg (stmt, parm_index);
     693              : }
     694              : 
     695              : /* Return tree corresponding to parameter of the range in STMT.  */
     696              : bool
     697      7965956 : modref_access_node::get_ao_ref (const gcall *stmt, ao_ref *ref) const
     698              : {
     699      7965956 :   tree arg;
     700              : 
     701      7965956 :   if (!parm_offset_known
     702      6172748 :       || !(arg = get_call_arg (stmt))
     703     14138694 :       || !POINTER_TYPE_P (TREE_TYPE (arg)))
     704      1793276 :     return false;
     705      6172680 :   poly_offset_int off = (poly_offset_int)offset
     706      6172680 :         + ((poly_offset_int)parm_offset << LOG2_BITS_PER_UNIT);
     707      6172680 :   poly_int64 off2;
     708      6172680 :   if (!off.to_shwi (&off2))
     709              :     return false;
     710      6172680 :   ao_ref_init_from_ptr_and_range (ref, arg, true, off2, size, max_size);
     711      6172680 :   return true;
     712              : }
     713              : 
     714              : /* Return true A is a subkill.  */
     715              : bool
     716      4200265 : modref_access_node::contains_for_kills (const modref_access_node &a) const
     717              : {
     718      4200265 :   poly_int64 aoffset_adj = 0;
     719              : 
     720      4200265 :   gcc_checking_assert (parm_index != MODREF_UNKNOWN_PARM
     721              :                        && a.parm_index != MODREF_UNKNOWN_PARM);
     722      4200265 :   if (parm_index != a.parm_index)
     723              :     return false;
     724      3389205 :   gcc_checking_assert (parm_offset_known && a.parm_offset_known);
     725      3389205 :   aoffset_adj = (a.parm_offset - parm_offset)
     726      3389205 :                 * BITS_PER_UNIT;
     727      3389205 :   gcc_checking_assert (range_info_useful_p () && a.range_info_useful_p ());
     728      3389205 :   return known_subrange_p (a.offset + aoffset_adj,
     729      3389205 :                            a.max_size, offset, max_size);
     730              : }
     731              : 
     732              : /* Merge two ranges both starting at parm_offset1 and update THIS
     733              :    with result.  */
     734              : bool
     735       458511 : modref_access_node::update_for_kills (poly_int64 parm_offset1,
     736              :                                       poly_int64 offset1,
     737              :                                       poly_int64 max_size1,
     738              :                                       poly_int64 offset2,
     739              :                                       poly_int64 max_size2,
     740              :                                       bool record_adjustments)
     741              : {
     742       458511 :   if (known_le (offset1, offset2))
     743              :     ;
     744        51317 :   else if (known_le (offset2, offset1))
     745              :     {
     746        51317 :       std::swap (offset1, offset2);
     747        51317 :       std::swap (max_size1, max_size2);
     748              :     }
     749              :   else
     750              :     gcc_unreachable ();
     751              : 
     752       458511 :   poly_int64 new_max_size = max_size2 + offset2 - offset1;
     753       458511 :   if (known_le (new_max_size, max_size1))
     754              :     new_max_size = max_size1;
     755       458511 :   if (known_eq (parm_offset, parm_offset1)
     756       442229 :       && known_eq (offset, offset1)
     757       401561 :       && known_eq (size, new_max_size)
     758       458511 :       && known_eq (max_size, new_max_size))
     759              :     return false;
     760              : 
     761       458511 :   if (!record_adjustments
     762       458511 :       || (++adjustments) < param_modref_max_adjustments)
     763              :     {
     764       458511 :       parm_offset = parm_offset1;
     765       458511 :       offset = offset1;
     766       458511 :       max_size = new_max_size;
     767       458511 :       size = new_max_size;
     768       458511 :       gcc_checking_assert (useful_for_kill_p ());
     769              :       return true;
     770              :     }
     771              :   return false;
     772              : }
     773              : 
     774              : /* Merge in access A if it is possible to do without losing
     775              :    precision.  Return true if successful.
     776              :    Unlike merge assume that both accesses are always executed
     777              :    and merge size the same was as max_size.  */
     778              : bool
     779      1161567 : modref_access_node::merge_for_kills (const modref_access_node &a,
     780              :                                      bool record_adjustments)
     781              : {
     782      1161567 :   poly_int64 offset1 = 0;
     783      1161567 :   poly_int64 aoffset1 = 0;
     784      1161567 :   poly_int64 new_parm_offset = 0;
     785              : 
     786              :   /* We assume that containment was tested earlier.  */
     787      1161567 :   gcc_checking_assert (!contains_for_kills (a) && !a.contains_for_kills (*this)
     788              :                        && useful_for_kill_p () && a.useful_for_kill_p ());
     789              : 
     790      1161567 :   if (parm_index != a.parm_index
     791      1161567 :       || !combined_offsets (a, &new_parm_offset, &offset1, &aoffset1))
     792       253309 :     return false;
     793              : 
     794       908258 :   if (known_le (offset1, aoffset1))
     795              :    {
     796       720971 :      if (!known_size_p (max_size)
     797       720971 :          || known_ge (offset1 + max_size, aoffset1))
     798       407194 :        return update_for_kills (new_parm_offset, offset1, max_size,
     799       407194 :                                 aoffset1, a.max_size, record_adjustments);
     800              :    }
     801       187287 :   else if (known_le (aoffset1, offset1))
     802              :    {
     803       187287 :      if (!known_size_p (a.max_size)
     804       187287 :          || known_ge (aoffset1 + a.max_size, offset1))
     805        51317 :        return update_for_kills (new_parm_offset, offset1, max_size,
     806        51317 :                                 aoffset1, a.max_size, record_adjustments);
     807              :    }
     808              :   return false;
     809              : }
     810              : 
     811              : /* Insert new kill A into KILLS.  If RECORD_ADJUSTMENTS is true limit number
     812              :    of changes to each entry.  Return true if something changed.  */
     813              : 
     814              : bool
     815      1278989 : modref_access_node::insert_kill (vec<modref_access_node> &kills,
     816              :                                  modref_access_node &a, bool record_adjustments)
     817              : {
     818      1278989 :   size_t index;
     819      1278989 :   modref_access_node *a2;
     820      1278989 :   bool merge = false;
     821              : 
     822      1278989 :   gcc_checking_assert (a.useful_for_kill_p ());
     823              : 
     824              :   /* See if we have corresponding entry already or we can merge with
     825              :      neighboring entry.  */
     826      1614639 :   FOR_EACH_VEC_ELT (kills, index, a2)
     827              :     {
     828       877179 :       if (a2->contains_for_kills (a))
     829              :         return false;
     830       792600 :       if (a.contains_for_kills (*a2))
     831              :         {
     832        17802 :           a.adjustments = 0;
     833        17802 :           *a2 = a;
     834        17802 :           merge = true;
     835        17802 :           break;
     836              :         }
     837       774798 :       if (a2->merge_for_kills (a, record_adjustments))
     838              :         {
     839              :           merge = true;
     840              :           break;
     841              :         }
     842              :     }
     843              :   /* If entry was not found, insert it.  */
     844      1194410 :   if (!merge)
     845              :     {
     846       857423 :       if ((int)kills.length () >= param_modref_max_accesses)
     847              :         {
     848          158 :           if (dump_file)
     849            2 :             fprintf (dump_file, "--param modref-max-accesses limit reached:");
     850          158 :           return false;
     851              :         }
     852       737302 :       a.adjustments = 0;
     853       737302 :       kills.safe_push (a);
     854       737302 :       return true;
     855              :     }
     856              :   /* Extending range in an entry may make it possible to merge it with
     857              :      other entries.  */
     858              :   size_t i;
     859              : 
     860      1140615 :   for (i = 0; i < kills.length ();)
     861       683665 :     if (i != index)
     862              :       {
     863       207352 :         bool found = false, restart = false;
     864       207352 :         modref_access_node *a = &kills[i];
     865       207352 :         modref_access_node *n = &kills[index];
     866              : 
     867       207352 :         if (n->contains_for_kills (*a))
     868              :           found = true;
     869       203066 :         if (!found && n->merge_for_kills (*a, false))
     870              :           found = restart = true;
     871       187989 :         gcc_checking_assert (found || !a->merge_for_kills (*n, false));
     872       207352 :         if (found)
     873              :           {
     874        23649 :             kills.unordered_remove (i);
     875        23649 :             if (index == kills.length ())
     876              :               {
     877            0 :                 index = i;
     878            0 :                 i++;
     879              :               }
     880        23649 :             if (restart)
     881        19363 :               i = 0;
     882              :           }
     883              :         else
     884       183703 :           i++;
     885              :       }
     886              :     else
     887       476313 :       i++;
     888              :   return true;
     889              : }
     890              : 
     891              : 
     892              : #if CHECKING_P
     893              : 
     894              : namespace selftest {
     895              : 
     896              : static void
     897            4 : test_insert_search_collapse ()
     898              : {
     899            4 :   modref_base_node<alias_set_type> *base_node;
     900            4 :   modref_ref_node<alias_set_type> *ref_node;
     901            4 :   modref_access_node a = unspecified_modref_access_node;
     902              : 
     903            4 :   modref_tree<alias_set_type> *t = new modref_tree<alias_set_type>();
     904            4 :   ASSERT_FALSE (t->every_base);
     905              : 
     906              :   /* Insert into an empty tree.  */
     907            4 :   t->insert (1, 2, 2, 1, 2, a, false);
     908            4 :   ASSERT_NE (t->bases, NULL);
     909            4 :   ASSERT_EQ (t->bases->length (), 1);
     910            4 :   ASSERT_FALSE (t->every_base);
     911            4 :   ASSERT_EQ (t->search (2), NULL);
     912              : 
     913            4 :   base_node = t->search (1);
     914            4 :   ASSERT_NE (base_node, NULL);
     915            4 :   ASSERT_EQ (base_node->base, 1);
     916            4 :   ASSERT_NE (base_node->refs, NULL);
     917            4 :   ASSERT_EQ (base_node->refs->length (), 1);
     918            4 :   ASSERT_EQ (base_node->search (1), NULL);
     919              : 
     920            4 :   ref_node = base_node->search (2);
     921            4 :   ASSERT_NE (ref_node, NULL);
     922            4 :   ASSERT_EQ (ref_node->ref, 2);
     923              : 
     924              :   /* Insert when base exists but ref does not.  */
     925            4 :   t->insert (1, 2, 2, 1, 3, a, false);
     926            4 :   ASSERT_NE (t->bases, NULL);
     927            4 :   ASSERT_EQ (t->bases->length (), 1);
     928            4 :   ASSERT_EQ (t->search (1), base_node);
     929            4 :   ASSERT_EQ (t->search (2), NULL);
     930            4 :   ASSERT_NE (base_node->refs, NULL);
     931            4 :   ASSERT_EQ (base_node->refs->length (), 2);
     932              : 
     933            4 :   ref_node = base_node->search (3);
     934            4 :   ASSERT_NE (ref_node, NULL);
     935              : 
     936              :   /* Insert when base and ref exist, but access is not dominated by nor
     937              :      dominates other accesses.  */
     938            4 :   t->insert (1, 2, 2, 1, 2, a, false);
     939            4 :   ASSERT_EQ (t->bases->length (), 1);
     940            4 :   ASSERT_EQ (t->search (1), base_node);
     941              : 
     942            4 :   ref_node = base_node->search (2);
     943            4 :   ASSERT_NE (ref_node, NULL);
     944              : 
     945              :   /* Insert when base and ref exist and access is dominated.  */
     946            4 :   t->insert (1, 2, 2, 1, 2, a, false);
     947            4 :   ASSERT_EQ (t->search (1), base_node);
     948            4 :   ASSERT_EQ (base_node->search (2), ref_node);
     949              : 
     950              :   /* Insert ref to trigger ref list collapse for base 1.  */
     951            4 :   t->insert (1, 2, 2, 1, 4, a, false);
     952            4 :   ASSERT_EQ (t->search (1), base_node);
     953            4 :   ASSERT_EQ (base_node->refs, NULL);
     954            4 :   ASSERT_EQ (base_node->search (2), NULL);
     955            4 :   ASSERT_EQ (base_node->search (3), NULL);
     956            4 :   ASSERT_TRUE (base_node->every_ref);
     957              : 
     958              :   /* Further inserts to collapsed ref list are ignored.  */
     959            4 :   t->insert (1, 2, 2, 1, 5, a, false);
     960            4 :   ASSERT_EQ (t->search (1), base_node);
     961            4 :   ASSERT_EQ (base_node->refs, NULL);
     962            4 :   ASSERT_EQ (base_node->search (2), NULL);
     963            4 :   ASSERT_EQ (base_node->search (3), NULL);
     964            4 :   ASSERT_TRUE (base_node->every_ref);
     965              : 
     966              :   /* Insert base to trigger base list collapse.  */
     967            4 :   t->insert (1, 2, 2, 5, 0, a, false);
     968            4 :   ASSERT_TRUE (t->every_base);
     969            4 :   ASSERT_EQ (t->bases, NULL);
     970            4 :   ASSERT_EQ (t->search (1), NULL);
     971              : 
     972              :   /* Further inserts to collapsed base list are ignored.  */
     973            4 :   t->insert (1, 2, 2, 7, 8, a, false);
     974            4 :   ASSERT_TRUE (t->every_base);
     975            4 :   ASSERT_EQ (t->bases, NULL);
     976            4 :   ASSERT_EQ (t->search (1), NULL);
     977              : 
     978            4 :   delete t;
     979            4 : }
     980              : 
     981              : static void
     982            4 : test_merge ()
     983              : {
     984            4 :   modref_tree<alias_set_type> *t1, *t2;
     985            4 :   modref_base_node<alias_set_type> *base_node;
     986            4 :   modref_access_node a = unspecified_modref_access_node;
     987              : 
     988            4 :   t1 = new modref_tree<alias_set_type>();
     989            4 :   t1->insert (3, 4, 1, 1, 1, a, false);
     990            4 :   t1->insert (3, 4, 1, 1, 2, a, false);
     991            4 :   t1->insert (3, 4, 1, 1, 3, a, false);
     992            4 :   t1->insert (3, 4, 1, 2, 1, a, false);
     993            4 :   t1->insert (3, 4, 1, 3, 1, a, false);
     994              : 
     995            4 :   t2 = new modref_tree<alias_set_type>();
     996            4 :   t2->insert (10, 10, 10, 1, 2, a, false);
     997            4 :   t2->insert (10, 10, 10, 1, 3, a, false);
     998            4 :   t2->insert (10, 10, 10, 1, 4, a, false);
     999            4 :   t2->insert (10, 10, 10, 3, 2, a, false);
    1000            4 :   t2->insert (10, 10, 10, 3, 3, a, false);
    1001            4 :   t2->insert (10, 10, 10, 3, 4, a, false);
    1002            4 :   t2->insert (10, 10, 10, 3, 5, a, false);
    1003              : 
    1004            4 :   t1->merge (3, 4, 1, t2, NULL, NULL, false);
    1005              : 
    1006            4 :   ASSERT_FALSE (t1->every_base);
    1007            4 :   ASSERT_NE (t1->bases, NULL);
    1008            4 :   ASSERT_EQ (t1->bases->length (), 3);
    1009              : 
    1010            4 :   base_node = t1->search (1);
    1011            4 :   ASSERT_NE (base_node->refs, NULL);
    1012            4 :   ASSERT_FALSE (base_node->every_ref);
    1013            4 :   ASSERT_EQ (base_node->refs->length (), 4);
    1014              : 
    1015            4 :   base_node = t1->search (2);
    1016            4 :   ASSERT_NE (base_node->refs, NULL);
    1017            4 :   ASSERT_FALSE (base_node->every_ref);
    1018            4 :   ASSERT_EQ (base_node->refs->length (), 1);
    1019              : 
    1020            4 :   base_node = t1->search (3);
    1021            4 :   ASSERT_EQ (base_node->refs, NULL);
    1022            4 :   ASSERT_TRUE (base_node->every_ref);
    1023              : 
    1024            4 :   delete t1;
    1025            4 :   delete t2;
    1026            4 : }
    1027              : 
    1028              : 
    1029              : void
    1030            4 : ipa_modref_tree_cc_tests ()
    1031              : {
    1032            4 :   test_insert_search_collapse ();
    1033            4 :   test_merge ();
    1034            4 : }
    1035              : 
    1036              : } // namespace selftest
    1037              : 
    1038              : #endif
    1039              : 
    1040              : void
    1041     48707236 : gt_ggc_mx (modref_tree < int >*const &tt)
    1042              : {
    1043     48707236 :   if (tt->bases)
    1044              :     {
    1045      7549242 :       ggc_test_and_set_mark (tt->bases);
    1046      7549242 :       gt_ggc_mx (tt->bases);
    1047              :     }
    1048     48707236 : }
    1049              : 
    1050              : void
    1051       241220 : gt_ggc_mx (modref_tree < tree_node * >*const &tt)
    1052              : {
    1053       241220 :   if (tt->bases)
    1054              :     {
    1055       179215 :       ggc_test_and_set_mark (tt->bases);
    1056       179215 :       gt_ggc_mx (tt->bases);
    1057              :     }
    1058       241220 : }
    1059              : 
    1060            0 : void gt_pch_nx (modref_tree<int>* const&) {}
    1061            0 : void gt_pch_nx (modref_tree<tree_node*>* const&) {}
    1062            0 : void gt_pch_nx (modref_tree<int>* const&, gt_pointer_operator, void *) {}
    1063            0 : void gt_pch_nx (modref_tree<tree_node*>* const&, gt_pointer_operator, void *) {}
    1064              : 
    1065      8521294 : void gt_ggc_mx (modref_base_node<int>* &b)
    1066              : {
    1067      8521294 :   ggc_test_and_set_mark (b);
    1068      8521294 :   if (b->refs)
    1069              :     {
    1070      8520513 :       ggc_test_and_set_mark (b->refs);
    1071      8520513 :       gt_ggc_mx (b->refs);
    1072              :     }
    1073      8521294 : }
    1074              : 
    1075       188289 : void gt_ggc_mx (modref_base_node<tree_node*>* &b)
    1076              : {
    1077       188289 :   ggc_test_and_set_mark (b);
    1078       188289 :   if (b->refs)
    1079              :     {
    1080       188289 :       ggc_test_and_set_mark (b->refs);
    1081       188289 :       gt_ggc_mx (b->refs);
    1082              :     }
    1083       188289 :   if (b->base)
    1084       187749 :     gt_ggc_mx (b->base);
    1085       188289 : }
    1086              : 
    1087            0 : void gt_pch_nx (modref_base_node<int>*) {}
    1088            0 : void gt_pch_nx (modref_base_node<tree_node*>*) {}
    1089            0 : void gt_pch_nx (modref_base_node<int>*, gt_pointer_operator, void *) {}
    1090            0 : void gt_pch_nx (modref_base_node<tree_node*>*, gt_pointer_operator, void *) {}
    1091              : 
    1092     11170915 : void gt_ggc_mx (modref_ref_node<int>* &r)
    1093              : {
    1094     11170915 :   ggc_test_and_set_mark (r);
    1095     11170915 :   if (r->accesses)
    1096              :     {
    1097      8567252 :       ggc_test_and_set_mark (r->accesses);
    1098      8567252 :       gt_ggc_mx (r->accesses);
    1099              :     }
    1100     11170915 : }
    1101              : 
    1102       188313 : void gt_ggc_mx (modref_ref_node<tree_node*>* &r)
    1103              : {
    1104       188313 :   ggc_test_and_set_mark (r);
    1105       188313 :   if (r->accesses)
    1106              :     {
    1107         8341 :       ggc_test_and_set_mark (r->accesses);
    1108         8341 :       gt_ggc_mx (r->accesses);
    1109              :     }
    1110       188313 :   if (r->ref)
    1111       188237 :     gt_ggc_mx (r->ref);
    1112       188313 : }
    1113              : 
    1114            0 : void gt_pch_nx (modref_ref_node<int>* ) {}
    1115            0 : void gt_pch_nx (modref_ref_node<tree_node*>*) {}
    1116            0 : void gt_pch_nx (modref_ref_node<int>*, gt_pointer_operator, void *) {}
    1117            0 : void gt_pch_nx (modref_ref_node<tree_node*>*, gt_pointer_operator, void *) {}
    1118              : 
    1119     12204839 : void gt_ggc_mx (modref_access_node &)
    1120              : {
    1121     12204839 : }
        

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.