LCOV - code coverage report
Current view: top level - gcc - ipa-modref-tree.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 93.2 % 571 532
Test Date: 2024-04-13 14:00:49 Functions: 71.4 % 42 30
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: - 0 0

             Branch data     Line data    Source code
       1                 :             : /* Data structure for the modref pass.
       2                 :             :    Copyright (C) 2020-2024 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                 :     2076556 : modref_access_node::operator == (modref_access_node &a) const
      36                 :             : {
      37                 :     2076556 :   if (parm_index != a.parm_index)
      38                 :             :     return false;
      39                 :      990227 :   if (parm_index != MODREF_UNKNOWN_PARM
      40                 :      990227 :       && parm_index != MODREF_GLOBAL_MEMORY_PARM)
      41                 :             :     {
      42                 :      990227 :       if (parm_offset_known != a.parm_offset_known)
      43                 :             :         return false;
      44                 :      990227 :       if (parm_offset_known
      45                 :      990227 :           && !known_eq (parm_offset, a.parm_offset))
      46                 :             :         return false;
      47                 :             :     }
      48                 :      752451 :   if (range_info_useful_p () != a.range_info_useful_p ())
      49                 :             :     return false;
      50                 :      752451 :   if (range_info_useful_p ()
      51                 :      752451 :       && (!known_eq (a.offset, offset)
      52                 :       60860 :           || !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                 :    24195398 : modref_access_node::contains (const modref_access_node &a) const
      61                 :             : {
      62                 :    24195398 :   poly_int64 aoffset_adj = 0;
      63                 :    24195398 :   if (parm_index != MODREF_UNKNOWN_PARM)
      64                 :             :     {
      65                 :    24195395 :       if (parm_index != a.parm_index)
      66                 :             :         return false;
      67                 :    14789376 :       if (parm_offset_known)
      68                 :             :         {
      69                 :    13744463 :            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                 :    13725059 :            if (!known_le (parm_offset, a.parm_offset)
      76                 :    13725059 :                && !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                 :    13725059 :            aoffset_adj = (a.parm_offset - parm_offset)
      84                 :    13725059 :                          * BITS_PER_UNIT;
      85                 :             :         }
      86                 :             :     }
      87                 :    14769975 :   if (range_info_useful_p ())
      88                 :             :     {
      89                 :    13725059 :       if (!a.range_info_useful_p ())
      90                 :             :         return false;
      91                 :             :       /* Sizes of stores are used to check that object is big enough
      92                 :             :          to fit the store, so smaller or unknown store is more general
      93                 :             :          than large store.  */
      94                 :    13725059 :       if (known_size_p (size)
      95                 :    13725059 :           && (!known_size_p (a.size)
      96                 :    13467997 :               || !known_le (size, a.size)))
      97                 :             :         return false;
      98                 :    11641054 :       if (known_size_p (max_size))
      99                 :    11485120 :         return known_subrange_p (a.offset + aoffset_adj,
     100                 :    11485120 :                                  a.max_size, offset, max_size);
     101                 :             :       else
     102                 :      155934 :         return known_le (offset, a.offset + aoffset_adj);
     103                 :             :     }
     104                 :             :   return true;
     105                 :             : }
     106                 :             : 
     107                 :             : /* Update access range to new parameters.
     108                 :             :    If RECORD_ADJUSTMENTS is true, record number of changes in the access
     109                 :             :    and if threshold is exceeded start dropping precision
     110                 :             :    so only constantly many updates are possible.  This makes dataflow
     111                 :             :    to converge.  */
     112                 :             : void
     113                 :      957244 : modref_access_node::update (poly_int64 parm_offset1,
     114                 :             :                             poly_int64 offset1, poly_int64 size1,
     115                 :             :                             poly_int64 max_size1, bool record_adjustments)
     116                 :             : {
     117                 :      957244 :   if (known_eq (parm_offset, parm_offset1)
     118                 :      938321 :       && known_eq (offset, offset1)
     119                 :      742009 :       && known_eq (size, size1)
     120                 :     1674455 :       && known_eq (max_size, max_size1))
     121                 :             :     return;
     122                 :      952544 :   if (!record_adjustments
     123                 :      952544 :       || (++adjustments) < param_modref_max_adjustments)
     124                 :             :     {
     125                 :      952486 :       parm_offset = parm_offset1;
     126                 :      952486 :       offset = offset1;
     127                 :      952486 :       size = size1;
     128                 :      952486 :       max_size = max_size1;
     129                 :             :     }
     130                 :             :   else
     131                 :             :     {
     132                 :          58 :       if (dump_file)
     133                 :           1 :         fprintf (dump_file, "--param modref-max-adjustments limit reached:");
     134                 :          58 :       if (!known_eq (parm_offset, parm_offset1))
     135                 :             :         {
     136                 :           0 :           if (dump_file)
     137                 :           0 :             fprintf (dump_file, " parm_offset cleared");
     138                 :           0 :           parm_offset_known = false;
     139                 :             :         }
     140                 :          58 :       if (!known_eq (size, size1))
     141                 :             :         {
     142                 :           0 :           size = -1;
     143                 :           0 :           if (dump_file)
     144                 :           0 :             fprintf (dump_file, " size cleared");
     145                 :             :         }
     146                 :          58 :       if (!known_eq (max_size, max_size1))
     147                 :             :         {
     148                 :          58 :           max_size = -1;
     149                 :          58 :           if (dump_file)
     150                 :           1 :             fprintf (dump_file, " max_size cleared");
     151                 :             :         }
     152                 :          58 :       if (!known_eq (offset, offset1))
     153                 :             :         {
     154                 :           0 :           offset = 0;
     155                 :           0 :           if (dump_file)
     156                 :           0 :             fprintf (dump_file, " offset cleared");
     157                 :             :         }
     158                 :          58 :       if (dump_file)
     159                 :           1 :         fprintf (dump_file, "\n");
     160                 :             :     }
     161                 :             : }
     162                 :             : 
     163                 :             : /* Merge in access A if it is possible to do without losing
     164                 :             :    precision.  Return true if successful.
     165                 :             :    If RECORD_ADJUSTMENTs is true, remember how many interval
     166                 :             :    was prolonged and punt when there are too many.  */
     167                 :             : bool
     168                 :     4240003 : modref_access_node::merge (const modref_access_node &a,
     169                 :             :                            bool record_adjustments)
     170                 :             : {
     171                 :     4240003 :   poly_int64 offset1 = 0;
     172                 :     4240003 :   poly_int64 aoffset1 = 0;
     173                 :     4240003 :   poly_int64 new_parm_offset = 0;
     174                 :             : 
     175                 :             :   /* We assume that containment was tested earlier.  */
     176                 :     4240003 :   gcc_checking_assert (!contains (a) && !a.contains (*this));
     177                 :     4240003 :   if (parm_index != MODREF_UNKNOWN_PARM)
     178                 :             :     {
     179                 :     4240003 :       if (parm_index != a.parm_index)
     180                 :             :         return false;
     181                 :     2538620 :       if (parm_offset_known)
     182                 :             :         {
     183                 :     2538620 :           if (!a.parm_offset_known)
     184                 :             :             return false;
     185                 :     2538620 :           if (!combined_offsets (a, &new_parm_offset, &offset1, &aoffset1))
     186                 :             :             return false;
     187                 :             :         }
     188                 :             :     }
     189                 :             :   /* See if we can merge ranges.  */
     190                 :     2538620 :   if (range_info_useful_p ())
     191                 :             :     {
     192                 :             :       /* In this case we have containment that should be
     193                 :             :          handled earlier.  */
     194                 :     2538620 :       gcc_checking_assert (a.range_info_useful_p ());
     195                 :             : 
     196                 :             :       /* If a.size is less specified than size, merge only
     197                 :             :          if intervals are otherwise equivalent.  */
     198                 :     2538620 :       if (known_size_p (size)
     199                 :     2538620 :           && (!known_size_p (a.size) || known_lt (a.size, size)))
     200                 :             :         {
     201                 :      408594 :           if (((known_size_p (max_size) || known_size_p (a.max_size))
     202                 :      408558 :                && !known_eq (max_size, a.max_size))
     203                 :      419438 :                || !known_eq (offset1, aoffset1))
     204                 :             :             return false;
     205                 :           0 :           update (new_parm_offset, offset1, a.size, max_size,
     206                 :             :                   record_adjustments);
     207                 :           0 :           return true;
     208                 :             :         }
     209                 :             :       /* If sizes are same, we can extend the interval.  */
     210                 :     2130026 :       if ((known_size_p (size) || known_size_p (a.size))
     211                 :     2143569 :           && !known_eq (size, a.size))
     212                 :             :         return false;
     213                 :     1823664 :       if (known_le (offset1, aoffset1))
     214                 :             :         {
     215                 :     1293179 :           if (!known_size_p (max_size)
     216                 :     1293179 :               || known_ge (offset1 + max_size, aoffset1))
     217                 :             :             {
     218                 :      710790 :               update2 (new_parm_offset, offset1, size, max_size,
     219                 :             :                        aoffset1, a.size, a.max_size,
     220                 :             :                        record_adjustments);
     221                 :      710790 :               return true;
     222                 :             :             }
     223                 :             :         }
     224                 :      530485 :       else if (known_le (aoffset1, offset1))
     225                 :             :         {
     226                 :      530485 :           if (!known_size_p (a.max_size)
     227                 :      530485 :               || known_ge (aoffset1 + a.max_size, offset1))
     228                 :             :             {
     229                 :      193192 :               update2 (new_parm_offset, offset1, size, max_size,
     230                 :             :                        aoffset1, a.size, a.max_size,
     231                 :             :                        record_adjustments);
     232                 :      193192 :               return true;
     233                 :             :             }
     234                 :             :         }
     235                 :             :       return false;
     236                 :             :     }
     237                 :           0 :   update (new_parm_offset, offset1,
     238                 :             :           size, max_size, record_adjustments);
     239                 :           0 :   return true;
     240                 :             : }
     241                 :             : 
     242                 :             : /* Return true if A1 and B1 can be merged with lower information
     243                 :             :    less than A2 and B2.
     244                 :             :    Assume that no containment or lossless merging is possible.  */
     245                 :             : bool
     246                 :      113682 : modref_access_node::closer_pair_p (const modref_access_node &a1,
     247                 :             :                                    const modref_access_node &b1,
     248                 :             :                                    const modref_access_node &a2,
     249                 :             :                                    const modref_access_node &b2)
     250                 :             : {
     251                 :             :   /* Merging different parm indexes comes to complete loss
     252                 :             :      of range info.  */
     253                 :      113682 :   if (a1.parm_index != b1.parm_index)
     254                 :             :     return false;
     255                 :       67826 :   if (a2.parm_index != b2.parm_index)
     256                 :             :     return true;
     257                 :             :   /* If parm is known and parm indexes are the same we should
     258                 :             :      already have containment.  */
     259                 :       67188 :   gcc_checking_assert (a1.parm_offset_known && b1.parm_offset_known);
     260                 :       67188 :   gcc_checking_assert (a2.parm_offset_known && b2.parm_offset_known);
     261                 :             : 
     262                 :             :   /* First normalize offsets for parm offsets.  */
     263                 :       67188 :   poly_int64 new_parm_offset, offseta1, offsetb1, offseta2, offsetb2;
     264                 :       67188 :   if (!a1.combined_offsets (b1, &new_parm_offset, &offseta1, &offsetb1)
     265                 :       67188 :       || !a2.combined_offsets (b2, &new_parm_offset, &offseta2, &offsetb2))
     266                 :           0 :     gcc_unreachable ();
     267                 :             : 
     268                 :             : 
     269                 :             :   /* Now compute distance of the intervals.  */
     270                 :       67188 :   poly_offset_int dist1, dist2;
     271                 :       67188 :   if (known_le (offseta1, offsetb1))
     272                 :             :     {
     273                 :       61043 :       if (!known_size_p (a1.max_size))
     274                 :           0 :         dist1 = 0;
     275                 :             :       else
     276                 :      122086 :         dist1 = (poly_offset_int)offsetb1
     277                 :      122086 :                 - (poly_offset_int)offseta1
     278                 :      122086 :                 - (poly_offset_int)a1.max_size;
     279                 :             :     }
     280                 :             :   else
     281                 :             :     {
     282                 :        6145 :       if (!known_size_p (b1.max_size))
     283                 :           0 :         dist1 = 0;
     284                 :             :       else
     285                 :       12290 :         dist1 = (poly_offset_int)offseta1
     286                 :       12290 :                  - (poly_offset_int)offsetb1
     287                 :       12290 :                  - (poly_offset_int)b1.max_size;
     288                 :             :     }
     289                 :       67188 :   if (known_le (offseta2, offsetb2))
     290                 :             :     {
     291                 :       55496 :       if (!known_size_p (a2.max_size))
     292                 :           0 :         dist2 = 0;
     293                 :             :       else
     294                 :      110992 :         dist2 = (poly_offset_int)offsetb2
     295                 :      110992 :                 - (poly_offset_int)offseta2
     296                 :      110992 :                 - (poly_offset_int)a2.max_size;
     297                 :             :     }
     298                 :             :   else
     299                 :             :     {
     300                 :       11692 :       if (!known_size_p (b2.max_size))
     301                 :           0 :         dist2 = 0;
     302                 :             :       else
     303                 :       11692 :         dist2 = offseta2
     304                 :       23384 :                 - (poly_offset_int)offsetb2
     305                 :       23384 :                 - (poly_offset_int)b2.max_size;
     306                 :             :     }
     307                 :             :   /* It may happen that intervals overlap in case size
     308                 :             :      is different.  Prefer the overlap to non-overlap.  */
     309                 :       67188 :   if (known_lt (dist1, 0) && known_ge (dist2, 0))
     310                 :          59 :     return true;
     311                 :       67129 :   if (known_lt (dist2, 0) && known_ge (dist1, 0))
     312                 :        2997 :     return false;
     313                 :       64132 :   if (known_lt (dist1, 0))
     314                 :             :     /* If both overlaps minimize overlap.  */
     315                 :         551 :     return known_le (dist2, dist1);
     316                 :             :   else
     317                 :             :     /* If both are disjoint look for smaller distance.  */
     318                 :       63581 :     return known_le (dist1, dist2);
     319                 :             : }
     320                 :             : 
     321                 :             : /* Merge in access A while losing precision.  */
     322                 :             : void
     323                 :         848 : modref_access_node::forced_merge (const modref_access_node &a,
     324                 :             :                                   bool record_adjustments)
     325                 :             : {
     326                 :         848 :   if (parm_index != a.parm_index)
     327                 :             :     {
     328                 :           3 :       gcc_checking_assert (parm_index != MODREF_UNKNOWN_PARM);
     329                 :           3 :       parm_index = MODREF_UNKNOWN_PARM;
     330                 :           3 :       return;
     331                 :             :     }
     332                 :             : 
     333                 :             :   /* We assume that containment and lossless merging
     334                 :             :      was tested earlier.  */
     335                 :         845 :   gcc_checking_assert (!contains (a) && !a.contains (*this)
     336                 :             :                        && !merge (a, record_adjustments));
     337                 :         845 :   gcc_checking_assert (parm_offset_known && a.parm_offset_known);
     338                 :             : 
     339                 :         845 :   poly_int64 new_parm_offset, offset1, aoffset1;
     340                 :         845 :   if (!combined_offsets (a, &new_parm_offset, &offset1, &aoffset1))
     341                 :             :     {
     342                 :           0 :       parm_offset_known = false;
     343                 :           0 :       return;
     344                 :             :     }
     345                 :         845 :   gcc_checking_assert (range_info_useful_p ()
     346                 :             :                        && a.range_info_useful_p ());
     347                 :         845 :   if (record_adjustments)
     348                 :           0 :     adjustments += a.adjustments;
     349                 :         845 :   update2 (new_parm_offset,
     350                 :             :            offset1, size, max_size,
     351                 :             :            aoffset1, a.size, a.max_size,
     352                 :             :            record_adjustments);
     353                 :             : }
     354                 :             : 
     355                 :             : /* Merge two ranges both starting at parm_offset1 and update THIS
     356                 :             :    with result.  */
     357                 :             : void
     358                 :      904827 : modref_access_node::update2 (poly_int64 parm_offset1,
     359                 :             :                              poly_int64 offset1, poly_int64 size1,
     360                 :             :                              poly_int64 max_size1,
     361                 :             :                              poly_int64 offset2, poly_int64 size2,
     362                 :             :                              poly_int64 max_size2,
     363                 :             :                              bool record_adjustments)
     364                 :             : {
     365                 :      904827 :   poly_int64 new_size = size1;
     366                 :             : 
     367                 :      904827 :   if (!known_size_p (size2)
     368                 :      904827 :       || known_le (size2, size1))
     369                 :      904536 :     new_size = size2;
     370                 :             :   else
     371                 :             :     gcc_checking_assert (known_le (size1, size2));
     372                 :             : 
     373                 :      904827 :   if (known_le (offset1, offset2))
     374                 :             :     ;
     375                 :      193293 :   else if (known_le (offset2, offset1))
     376                 :             :     {
     377                 :      193293 :       std::swap (offset1, offset2);
     378                 :      193293 :       std::swap (max_size1, max_size2);
     379                 :             :     }
     380                 :             :   else
     381                 :             :     gcc_unreachable ();
     382                 :             : 
     383                 :      904827 :   poly_int64 new_max_size;
     384                 :             : 
     385                 :      904827 :   if (!known_size_p (max_size1))
     386                 :           0 :     new_max_size = max_size1;
     387                 :      904827 :   else if (!known_size_p (max_size2))
     388                 :        1275 :     new_max_size = max_size2;
     389                 :             :   else
     390                 :             :     {
     391                 :     2710656 :       poly_offset_int s = (poly_offset_int)max_size2
     392                 :     1807104 :                           + (poly_offset_int)offset2
     393                 :      903552 :                           - (poly_offset_int)offset1;
     394                 :      903552 :       if (s.to_shwi (&new_max_size))
     395                 :             :         {
     396                 :      903552 :           if (known_le (new_max_size, max_size1))
     397                 :          89 :             new_max_size = max_size1;
     398                 :             :         }
     399                 :             :       else
     400                 :           0 :         new_max_size = -1;
     401                 :             :     }
     402                 :             : 
     403                 :      904827 :   update (parm_offset1, offset1,
     404                 :             :           new_size, new_max_size, record_adjustments);
     405                 :      904827 : }
     406                 :             : 
     407                 :             : /* Given access nodes THIS and A, return true if they
     408                 :             :    can be done with common parm_offsets.  In this case
     409                 :             :    return parm offset in new_parm_offset, new_offset
     410                 :             :    which is start of range in THIS and new_aoffset that
     411                 :             :    is start of range in A.  */
     412                 :             : bool
     413                 :     2975502 : modref_access_node::combined_offsets (const modref_access_node &a,
     414                 :             :                                       poly_int64 *new_parm_offset,
     415                 :             :                                       poly_int64 *new_offset,
     416                 :             :                                       poly_int64 *new_aoffset) const
     417                 :             : {
     418                 :     2975502 :   gcc_checking_assert (parm_offset_known && a.parm_offset_known);
     419                 :     2975502 :   if (known_le (a.parm_offset, parm_offset))
     420                 :             :     {
     421                 :     2395193 :       *new_offset = offset
     422                 :     2395193 :                     + ((parm_offset - a.parm_offset)
     423                 :     2395193 :                        << LOG2_BITS_PER_UNIT);
     424                 :     2395193 :       *new_aoffset = a.offset;
     425                 :     2395193 :       *new_parm_offset = a.parm_offset;
     426                 :     2395193 :       return true;
     427                 :             :     }
     428                 :      580309 :   else if (known_le (parm_offset, a.parm_offset))
     429                 :             :     {
     430                 :      580309 :       *new_aoffset = a.offset
     431                 :      580309 :                       + ((a.parm_offset - parm_offset)
     432                 :      580309 :                          << LOG2_BITS_PER_UNIT);
     433                 :      580309 :       *new_offset = offset;
     434                 :      580309 :       *new_parm_offset = parm_offset;
     435                 :      580309 :       return true;
     436                 :             :     }
     437                 :             :   else
     438                 :             :     return false;
     439                 :             : }
     440                 :             : 
     441                 :             : /* Try to optimize the access ACCESSES list after entry INDEX was modified.  */
     442                 :             : void
     443                 :      929657 : modref_access_node::try_merge_with (vec <modref_access_node, va_gc> *&accesses,
     444                 :             :                                     size_t index)
     445                 :             : {
     446                 :      929657 :   size_t i;
     447                 :             : 
     448                 :     2558012 :   for (i = 0; i < accesses->length ();)
     449                 :     1628355 :     if (i != index)
     450                 :             :       {
     451                 :      703720 :         bool found = false, restart = false;
     452                 :      703720 :         modref_access_node *a = &(*accesses)[i];
     453                 :      703720 :         modref_access_node *n = &(*accesses)[index];
     454                 :             : 
     455                 :      703720 :         if (n->contains (*a))
     456                 :             :           found = true;
     457                 :      656897 :         if (!found && n->merge (*a, false))
     458                 :             :           found = restart = true;
     459                 :      703720 :         gcc_checking_assert (found || !a->merge (*n, false));
     460                 :      703720 :         if (found)
     461                 :             :           {
     462                 :       74410 :             accesses->unordered_remove (i);
     463                 :       74410 :             if (index == accesses->length ())
     464                 :             :               {
     465                 :       32516 :                 index = i;
     466                 :       32516 :                 i++;
     467                 :             :               }
     468                 :       74410 :             if (restart)
     469                 :       27587 :               i = 0;
     470                 :             :           }
     471                 :             :         else
     472                 :      629310 :           i++;
     473                 :             :       }
     474                 :             :     else
     475                 :      924635 :       i++;
     476                 :      929657 : }
     477                 :             : 
     478                 :             : /* Stream out to OB.  */
     479                 :             : 
     480                 :             : void
     481                 :       26107 : modref_access_node::stream_out (struct output_block *ob) const
     482                 :             : {
     483                 :       26107 :   streamer_write_hwi (ob, parm_index);
     484                 :       26107 :   if (parm_index != MODREF_UNKNOWN_PARM)
     485                 :             :     {
     486                 :       25996 :       streamer_write_uhwi (ob, parm_offset_known);
     487                 :       25996 :       if (parm_offset_known)
     488                 :             :         {
     489                 :       17437 :           streamer_write_poly_int64 (ob, parm_offset);
     490                 :       17437 :           streamer_write_poly_int64 (ob, offset);
     491                 :       17437 :           streamer_write_poly_int64 (ob, size);
     492                 :       17437 :           streamer_write_poly_int64 (ob, max_size);
     493                 :             :         }
     494                 :             :     }
     495                 :       26107 : }
     496                 :             : 
     497                 :             : modref_access_node
     498                 :       19347 : modref_access_node::stream_in (struct lto_input_block *ib)
     499                 :             : {
     500                 :       19347 :   int parm_index = streamer_read_hwi (ib);
     501                 :       19347 :   bool parm_offset_known = false;
     502                 :       19347 :   poly_int64 parm_offset = 0;
     503                 :       19347 :   poly_int64 offset = 0;
     504                 :       19347 :   poly_int64 size = -1;
     505                 :       19347 :   poly_int64 max_size = -1;
     506                 :             : 
     507                 :       19347 :   if (parm_index != MODREF_UNKNOWN_PARM)
     508                 :             :     {
     509                 :       19236 :       parm_offset_known = streamer_read_uhwi (ib);
     510                 :       19236 :       if (parm_offset_known)
     511                 :             :         {
     512                 :       12226 :           parm_offset = streamer_read_poly_int64 (ib);
     513                 :       12226 :           offset = streamer_read_poly_int64 (ib);
     514                 :       12226 :           size = streamer_read_poly_int64 (ib);
     515                 :       12226 :           max_size = streamer_read_poly_int64 (ib);
     516                 :             :         }
     517                 :             :     }
     518                 :       19347 :   return {offset, size, max_size, parm_offset, parm_index,
     519                 :       19347 :           parm_offset_known, false};
     520                 :             : }
     521                 :             : 
     522                 :             : /* Insert access with OFFSET and SIZE.
     523                 :             :    Collapse tree if it has more than MAX_ACCESSES entries.
     524                 :             :    If RECORD_ADJUSTMENTs is true avoid too many interval extensions.
     525                 :             :    Return true if record was changed.
     526                 :             : 
     527                 :             :    Return 0 if nothing changed, 1 if insert was successful and -1
     528                 :             :    if entries should be collapsed.  */
     529                 :             : int
     530                 :     8155446 : modref_access_node::insert (vec <modref_access_node, va_gc> *&accesses,
     531                 :             :                             modref_access_node a, size_t max_accesses,
     532                 :             :                             bool record_adjustments)
     533                 :             : {
     534                 :     8155446 :   size_t i, j;
     535                 :     8155446 :   modref_access_node *a2;
     536                 :             : 
     537                 :             :   /* Verify that list does not contain redundant accesses.  */
     538                 :     8155446 :   if (flag_checking)
     539                 :             :     {
     540                 :             :       size_t i, i2;
     541                 :             :       modref_access_node *a, *a2;
     542                 :             : 
     543                 :    17780011 :       FOR_EACH_VEC_SAFE_ELT (accesses, i, a)
     544                 :             :         {
     545                 :    21908347 :           FOR_EACH_VEC_SAFE_ELT (accesses, i2, a2)
     546                 :    12283749 :             if (i != i2)
     547                 :     7471450 :               gcc_assert (!a->contains (*a2));
     548                 :             :         }
     549                 :             :     }
     550                 :             : 
     551                 :    10232002 :   FOR_EACH_VEC_SAFE_ELT (accesses, i, a2)
     552                 :             :     {
     553                 :     4532316 :       if (a2->contains (a))
     554                 :             :         return 0;
     555                 :     3005368 :       if (a.contains (*a2))
     556                 :             :         {
     557                 :       52417 :           a.adjustments = 0;
     558                 :       52417 :           a2->parm_index = a.parm_index;
     559                 :       52417 :           a2->parm_offset_known = a.parm_offset_known;
     560                 :       52417 :           a2->update (a.parm_offset, a.offset, a.size, a.max_size,
     561                 :             :                       record_adjustments);
     562                 :       52417 :           modref_access_node::try_merge_with (accesses, i);
     563                 :       52417 :           return 1;
     564                 :             :         }
     565                 :     2952951 :       if (a2->merge (a, record_adjustments))
     566                 :             :         {
     567                 :      876395 :           modref_access_node::try_merge_with (accesses, i);
     568                 :      876395 :           return 1;
     569                 :             :         }
     570                 :     2076556 :       gcc_checking_assert (!(a == *a2));
     571                 :             :     }
     572                 :             : 
     573                 :             :   /* If this base->ref pair has too many accesses stored, we will clear
     574                 :             :      all accesses and bail out.  */
     575                 :     5699686 :   if (accesses && accesses->length () >= max_accesses)
     576                 :             :     {
     577                 :         848 :       if (max_accesses < 2)
     578                 :             :         return -1;
     579                 :             :       /* Find least harmful merge and perform it.  */
     580                 :             :       int best1 = -1, best2 = -1;
     581                 :       14332 :       FOR_EACH_VEC_SAFE_ELT (accesses, i, a2)
     582                 :             :         {
     583                 :      114530 :           for (j = i + 1; j < accesses->length (); j++)
     584                 :      101046 :             if (best1 < 0
     585                 :      201244 :                 || modref_access_node::closer_pair_p
     586                 :      200396 :                      (*a2, (*accesses)[j],
     587                 :      100198 :                       (*accesses)[best1],
     588                 :       98826 :                       best2 < 0 ? a : (*accesses)[best2]))
     589                 :             :               {
     590                 :       10417 :                 best1 = i;
     591                 :       10417 :                 best2 = j;
     592                 :             :               }
     593                 :       13484 :           if (modref_access_node::closer_pair_p
     594                 :       26968 :                      (*a2, a,
     595                 :       13484 :                       (*accesses)[best1],
     596                 :       12924 :                       best2 < 0 ? a : (*accesses)[best2]))
     597                 :             :             {
     598                 :         719 :               best1 = i;
     599                 :         719 :               best2 = -1;
     600                 :             :             }
     601                 :             :         }
     602                 :         848 :       (*accesses)[best1].forced_merge (best2 < 0 ? a : (*accesses)[best2],
     603                 :             :                                        record_adjustments);
     604                 :             :       /* Check that merging indeed merged ranges.  */
     605                 :         848 :       gcc_checking_assert ((*accesses)[best1].contains
     606                 :             :                                (best2 < 0 ? a : (*accesses)[best2]));
     607                 :         848 :       if (!(*accesses)[best1].useful_p ())
     608                 :             :         return -1;
     609                 :         845 :       if (dump_file && best2 >= 0)
     610                 :           1 :         fprintf (dump_file,
     611                 :             :                  "--param modref-max-accesses limit reached;"
     612                 :             :                  " merging %i and %i\n", best1, best2);
     613                 :         844 :       else if (dump_file)
     614                 :           1 :         fprintf (dump_file,
     615                 :             :                  "--param modref-max-accesses limit reached;"
     616                 :             :                  " merging with %i\n", best1);
     617                 :         845 :       modref_access_node::try_merge_with (accesses, best1);
     618                 :         845 :       if (best2 >= 0)
     619                 :         189 :         insert (accesses, a, max_accesses, record_adjustments);
     620                 :         845 :       return 1;
     621                 :             :     }
     622                 :     5698838 :   a.adjustments = 0;
     623                 :     5698838 :   vec_safe_push (accesses, a);
     624                 :     5698838 :   return 1;
     625                 :             : }
     626                 :             : 
     627                 :             : /* Return true if range info is useful.  */
     628                 :             : bool
     629                 :    54336858 : modref_access_node::range_info_useful_p () const
     630                 :             : {
     631                 :    54336858 :   return parm_index != MODREF_UNKNOWN_PARM
     632                 :    54336858 :          && parm_index != MODREF_GLOBAL_MEMORY_PARM
     633                 :    46772373 :          && parm_offset_known
     634                 :   100174770 :          && (known_size_p (size)
     635                 :      520843 :              || known_size_p (max_size)
     636                 :      161162 :              || known_ge (offset, 0));
     637                 :             : }
     638                 :             : 
     639                 :             : /* Dump range to debug OUT.  */
     640                 :             : void
     641                 :         659 : modref_access_node::dump (FILE *out)
     642                 :             : {
     643                 :         659 :   if (parm_index != MODREF_UNKNOWN_PARM)
     644                 :             :     {
     645                 :         576 :       if (parm_index == MODREF_GLOBAL_MEMORY_PARM)
     646                 :           4 :         fprintf (out, " Base in global memory");
     647                 :         572 :       else if (parm_index >= 0)
     648                 :         567 :         fprintf (out, " Parm %i", parm_index);
     649                 :           5 :       else if (parm_index == MODREF_STATIC_CHAIN_PARM)
     650                 :           5 :         fprintf (out, " Static chain");
     651                 :             :       else
     652                 :           0 :         gcc_unreachable ();
     653                 :         576 :       if (parm_offset_known)
     654                 :             :         {
     655                 :         423 :           fprintf (out, " param offset:");
     656                 :         423 :           print_dec ((poly_int64)parm_offset, out, SIGNED);
     657                 :             :         }
     658                 :             :     }
     659                 :         659 :   if (range_info_useful_p ())
     660                 :             :     {
     661                 :         423 :       fprintf (out, " offset:");
     662                 :         423 :       print_dec ((poly_int64)offset, out, SIGNED);
     663                 :         423 :       fprintf (out, " size:");
     664                 :         423 :       print_dec ((poly_int64)size, out, SIGNED);
     665                 :         423 :       fprintf (out, " max_size:");
     666                 :         423 :       print_dec ((poly_int64)max_size, out, SIGNED);
     667                 :         423 :       if (adjustments)
     668                 :           1 :         fprintf (out, " adjusted %i times", adjustments);
     669                 :             :     }
     670                 :         659 :   fprintf (out, "\n");
     671                 :         659 : }
     672                 :             : 
     673                 :             : /* Return tree corresponding to parameter of the range in STMT.  */
     674                 :             : tree
     675                 :     8603173 : modref_access_node::get_call_arg (const gcall *stmt) const
     676                 :             : {
     677                 :     8603173 :   if (parm_index == MODREF_UNKNOWN_PARM
     678                 :     8603173 :       || parm_index == MODREF_GLOBAL_MEMORY_PARM)
     679                 :             :     return NULL;
     680                 :     8602168 :   if (parm_index == MODREF_STATIC_CHAIN_PARM)
     681                 :      380720 :     return gimple_call_chain (stmt);
     682                 :             :   /* MODREF_RETSLOT_PARM should not happen in access trees since the store
     683                 :             :      is seen explicitly in the caller.  */
     684                 :     8221448 :   gcc_checking_assert (parm_index >= 0);
     685                 :     8221448 :   if (parm_index >= (int)gimple_call_num_args (stmt))
     686                 :             :     return NULL;
     687                 :     8221428 :   return gimple_call_arg (stmt, parm_index);
     688                 :             : }
     689                 :             : 
     690                 :             : /* Return tree corresponding to parameter of the range in STMT.  */
     691                 :             : bool
     692                 :     5212194 : modref_access_node::get_ao_ref (const gcall *stmt, ao_ref *ref) const
     693                 :             : {
     694                 :     5212194 :   tree arg;
     695                 :             : 
     696                 :     5212194 :   if (!parm_offset_known
     697                 :     3530913 :       || !(arg = get_call_arg (stmt))
     698                 :     8743097 :       || !POINTER_TYPE_P (TREE_TYPE (arg)))
     699                 :     1681349 :     return false;
     700                 :     3530845 :   poly_offset_int off = (poly_offset_int)offset
     701                 :     3530845 :         + ((poly_offset_int)parm_offset << LOG2_BITS_PER_UNIT);
     702                 :     3530845 :   poly_int64 off2;
     703                 :     3530845 :   if (!off.to_shwi (&off2))
     704                 :             :     return false;
     705                 :     3530845 :   ao_ref_init_from_ptr_and_range (ref, arg, true, off2, size, max_size);
     706                 :     3530845 :   return true;
     707                 :             : }
     708                 :             : 
     709                 :             : /* Return true A is a subkill.  */
     710                 :             : bool
     711                 :     2430093 : modref_access_node::contains_for_kills (const modref_access_node &a) const
     712                 :             : {
     713                 :     2430093 :   poly_int64 aoffset_adj = 0;
     714                 :             : 
     715                 :     2430093 :   gcc_checking_assert (parm_index != MODREF_UNKNOWN_PARM
     716                 :             :                        && a.parm_index != MODREF_UNKNOWN_PARM);
     717                 :     2430093 :   if (parm_index != a.parm_index)
     718                 :             :     return false;
     719                 :     1748599 :   gcc_checking_assert (parm_offset_known && a.parm_offset_known);
     720                 :     1748599 :   aoffset_adj = (a.parm_offset - parm_offset)
     721                 :     1748599 :                 * BITS_PER_UNIT;
     722                 :     1748599 :   gcc_checking_assert (range_info_useful_p () && a.range_info_useful_p ());
     723                 :     1748599 :   return known_subrange_p (a.offset + aoffset_adj,
     724                 :     1748599 :                            a.max_size, offset, max_size);
     725                 :             : }
     726                 :             : 
     727                 :             : /* Merge two ranges both starting at parm_offset1 and update THIS
     728                 :             :    with result.  */
     729                 :             : bool
     730                 :      175212 : modref_access_node::update_for_kills (poly_int64 parm_offset1,
     731                 :             :                                       poly_int64 offset1,
     732                 :             :                                       poly_int64 max_size1,
     733                 :             :                                       poly_int64 offset2,
     734                 :             :                                       poly_int64 max_size2,
     735                 :             :                                       bool record_adjustments)
     736                 :             : {
     737                 :      175212 :   if (known_le (offset1, offset2))
     738                 :             :     ;
     739                 :       38944 :   else if (known_le (offset2, offset1))
     740                 :             :     {
     741                 :       38944 :       std::swap (offset1, offset2);
     742                 :       38944 :       std::swap (max_size1, max_size2);
     743                 :             :     }
     744                 :             :   else
     745                 :             :     gcc_unreachable ();
     746                 :             : 
     747                 :      175212 :   poly_int64 new_max_size = max_size2 + offset2 - offset1;
     748                 :      175212 :   if (known_le (new_max_size, max_size1))
     749                 :             :     new_max_size = max_size1;
     750                 :      175212 :   if (known_eq (parm_offset, parm_offset1)
     751                 :      165506 :       && known_eq (offset, offset1)
     752                 :      135420 :       && known_eq (size, new_max_size)
     753                 :      175212 :       && known_eq (max_size, new_max_size))
     754                 :             :     return false;
     755                 :             : 
     756                 :      175212 :   if (!record_adjustments
     757                 :      175212 :       || (++adjustments) < param_modref_max_adjustments)
     758                 :             :     {
     759                 :      175212 :       parm_offset = parm_offset1;
     760                 :      175212 :       offset = offset1;
     761                 :      175212 :       max_size = new_max_size;
     762                 :      175212 :       size = new_max_size;
     763                 :      175212 :       gcc_checking_assert (useful_for_kill_p ());
     764                 :             :       return true;
     765                 :             :     }
     766                 :             :   return false;
     767                 :             : }
     768                 :             : 
     769                 :             : /* Merge in access A if it is possible to do without losing
     770                 :             :    precision.  Return true if successful.
     771                 :             :    Unlike merge assume that both accesses are always executed
     772                 :             :    and merge size the same was as max_size.  */
     773                 :             : bool
     774                 :      511162 : modref_access_node::merge_for_kills (const modref_access_node &a,
     775                 :             :                                      bool record_adjustments)
     776                 :             : {
     777                 :      511162 :   poly_int64 offset1 = 0;
     778                 :      511162 :   poly_int64 aoffset1 = 0;
     779                 :      511162 :   poly_int64 new_parm_offset = 0;
     780                 :             : 
     781                 :             :   /* We assume that containment was tested earlier.  */
     782                 :      511162 :   gcc_checking_assert (!contains_for_kills (a) && !a.contains_for_kills (*this)
     783                 :             :                        && useful_for_kill_p () && a.useful_for_kill_p ());
     784                 :             : 
     785                 :      511162 :   if (parm_index != a.parm_index
     786                 :      511162 :       || !combined_offsets (a, &new_parm_offset, &offset1, &aoffset1))
     787                 :      209501 :     return false;
     788                 :             : 
     789                 :      301661 :   if (known_le (offset1, aoffset1))
     790                 :             :    {
     791                 :      219352 :      if (!known_size_p (max_size)
     792                 :      219352 :          || known_ge (offset1 + max_size, aoffset1))
     793                 :      136268 :        return update_for_kills (new_parm_offset, offset1, max_size,
     794                 :      136268 :                                 aoffset1, a.max_size, record_adjustments);
     795                 :             :    }
     796                 :       82309 :   else if (known_le (aoffset1, offset1))
     797                 :             :    {
     798                 :       82309 :      if (!known_size_p (a.max_size)
     799                 :       82309 :          || known_ge (aoffset1 + a.max_size, offset1))
     800                 :       38944 :        return update_for_kills (new_parm_offset, offset1, max_size,
     801                 :       38944 :                                 aoffset1, a.max_size, record_adjustments);
     802                 :             :    }
     803                 :             :   return false;
     804                 :             : }
     805                 :             : 
     806                 :             : /* Insert new kill A into KILLS.  If RECORD_ADJUSTMENTS is true limit number
     807                 :             :    of changes to each entry.  Return true if something changed.  */
     808                 :             : 
     809                 :             : bool
     810                 :     1413372 : modref_access_node::insert_kill (vec<modref_access_node> &kills,
     811                 :             :                                  modref_access_node &a, bool record_adjustments)
     812                 :             : {
     813                 :     1413372 :   size_t index;
     814                 :     1413372 :   modref_access_node *a2;
     815                 :     1413372 :   bool merge = false;
     816                 :             : 
     817                 :     1413372 :   gcc_checking_assert (a.useful_for_kill_p ());
     818                 :             : 
     819                 :             :   /* See if we have corresponding entry already or we can merge with
     820                 :             :      neighboring entry.  */
     821                 :     1583878 :   FOR_EACH_VEC_ELT (kills, index, a2)
     822                 :             :     {
     823                 :      955423 :       if (a2->contains_for_kills (a))
     824                 :             :         return false;
     825                 :      355684 :       if (a.contains_for_kills (*a2))
     826                 :             :         {
     827                 :       19516 :           a.adjustments = 0;
     828                 :       19516 :           *a2 = a;
     829                 :       19516 :           merge = true;
     830                 :       19516 :           break;
     831                 :             :         }
     832                 :      336168 :       if (a2->merge_for_kills (a, record_adjustments))
     833                 :             :         {
     834                 :             :           merge = true;
     835                 :             :           break;
     836                 :             :         }
     837                 :             :     }
     838                 :             :   /* If entry was not found, insert it.  */
     839                 :      813633 :   if (!merge)
     840                 :             :     {
     841                 :      690024 :       if ((int)kills.length () >= param_modref_max_accesses)
     842                 :             :         {
     843                 :         150 :           if (dump_file)
     844                 :           2 :             fprintf (dump_file, "--param modref-max-accesses limit reached:");
     845                 :         150 :           return false;
     846                 :             :         }
     847                 :      628305 :       a.adjustments = 0;
     848                 :      628305 :       kills.safe_push (a);
     849                 :      628305 :       return true;
     850                 :             :     }
     851                 :             :   /* Extending range in an entry may make it possible to merge it with
     852                 :             :      other entries.  */
     853                 :             :   size_t i;
     854                 :             : 
     855                 :      953136 :   for (i = 0; i < kills.length ();)
     856                 :      291390 :     if (i != index)
     857                 :             :       {
     858                 :       96662 :         bool found = false, restart = false;
     859                 :       96662 :         modref_access_node *a = &kills[i];
     860                 :       96662 :         modref_access_node *n = &kills[index];
     861                 :             : 
     862                 :       96662 :         if (n->contains_for_kills (*a))
     863                 :             :           found = true;
     864                 :       92272 :         if (!found && n->merge_for_kills (*a, false))
     865                 :             :           found = restart = true;
     866                 :       96662 :         gcc_checking_assert (found || !a->merge_for_kills (*n, false));
     867                 :       96662 :         if (found)
     868                 :             :           {
     869                 :       13940 :             kills.unordered_remove (i);
     870                 :       13940 :             if (index == kills.length ())
     871                 :             :               {
     872                 :           0 :                 index = i;
     873                 :           0 :                 i++;
     874                 :             :               }
     875                 :       13940 :             if (restart)
     876                 :        9550 :               i = 0;
     877                 :             :           }
     878                 :             :         else
     879                 :       82722 :           i++;
     880                 :             :       }
     881                 :             :     else
     882                 :      194728 :       i++;
     883                 :             :   return true;
     884                 :             : }
     885                 :             : 
     886                 :             : 
     887                 :             : #if CHECKING_P
     888                 :             : 
     889                 :             : namespace selftest {
     890                 :             : 
     891                 :             : static void
     892                 :           4 : test_insert_search_collapse ()
     893                 :             : {
     894                 :           4 :   modref_base_node<alias_set_type> *base_node;
     895                 :           4 :   modref_ref_node<alias_set_type> *ref_node;
     896                 :           4 :   modref_access_node a = unspecified_modref_access_node;
     897                 :             : 
     898                 :           4 :   modref_tree<alias_set_type> *t = new modref_tree<alias_set_type>();
     899                 :           4 :   ASSERT_FALSE (t->every_base);
     900                 :             : 
     901                 :             :   /* Insert into an empty tree.  */
     902                 :           4 :   t->insert (1, 2, 2, 1, 2, a, false);
     903                 :           4 :   ASSERT_NE (t->bases, NULL);
     904                 :           4 :   ASSERT_EQ (t->bases->length (), 1);
     905                 :           4 :   ASSERT_FALSE (t->every_base);
     906                 :           4 :   ASSERT_EQ (t->search (2), NULL);
     907                 :             : 
     908                 :           4 :   base_node = t->search (1);
     909                 :           4 :   ASSERT_NE (base_node, NULL);
     910                 :           4 :   ASSERT_EQ (base_node->base, 1);
     911                 :           4 :   ASSERT_NE (base_node->refs, NULL);
     912                 :           4 :   ASSERT_EQ (base_node->refs->length (), 1);
     913                 :           4 :   ASSERT_EQ (base_node->search (1), NULL);
     914                 :             : 
     915                 :           4 :   ref_node = base_node->search (2);
     916                 :           4 :   ASSERT_NE (ref_node, NULL);
     917                 :           4 :   ASSERT_EQ (ref_node->ref, 2);
     918                 :             : 
     919                 :             :   /* Insert when base exists but ref does not.  */
     920                 :           4 :   t->insert (1, 2, 2, 1, 3, a, false);
     921                 :           4 :   ASSERT_NE (t->bases, NULL);
     922                 :           4 :   ASSERT_EQ (t->bases->length (), 1);
     923                 :           4 :   ASSERT_EQ (t->search (1), base_node);
     924                 :           4 :   ASSERT_EQ (t->search (2), NULL);
     925                 :           4 :   ASSERT_NE (base_node->refs, NULL);
     926                 :           4 :   ASSERT_EQ (base_node->refs->length (), 2);
     927                 :             : 
     928                 :           4 :   ref_node = base_node->search (3);
     929                 :           4 :   ASSERT_NE (ref_node, NULL);
     930                 :             : 
     931                 :             :   /* Insert when base and ref exist, but access is not dominated by nor
     932                 :             :      dominates other accesses.  */
     933                 :           4 :   t->insert (1, 2, 2, 1, 2, a, false);
     934                 :           4 :   ASSERT_EQ (t->bases->length (), 1);
     935                 :           4 :   ASSERT_EQ (t->search (1), base_node);
     936                 :             : 
     937                 :           4 :   ref_node = base_node->search (2);
     938                 :           4 :   ASSERT_NE (ref_node, NULL);
     939                 :             : 
     940                 :             :   /* Insert when base and ref exist and access is dominated.  */
     941                 :           4 :   t->insert (1, 2, 2, 1, 2, a, false);
     942                 :           4 :   ASSERT_EQ (t->search (1), base_node);
     943                 :           4 :   ASSERT_EQ (base_node->search (2), ref_node);
     944                 :             : 
     945                 :             :   /* Insert ref to trigger ref list collapse for base 1.  */
     946                 :           4 :   t->insert (1, 2, 2, 1, 4, a, false);
     947                 :           4 :   ASSERT_EQ (t->search (1), base_node);
     948                 :           4 :   ASSERT_EQ (base_node->refs, NULL);
     949                 :           4 :   ASSERT_EQ (base_node->search (2), NULL);
     950                 :           4 :   ASSERT_EQ (base_node->search (3), NULL);
     951                 :           4 :   ASSERT_TRUE (base_node->every_ref);
     952                 :             : 
     953                 :             :   /* Further inserts to collapsed ref list are ignored.  */
     954                 :           4 :   t->insert (1, 2, 2, 1, 5, a, false);
     955                 :           4 :   ASSERT_EQ (t->search (1), base_node);
     956                 :           4 :   ASSERT_EQ (base_node->refs, NULL);
     957                 :           4 :   ASSERT_EQ (base_node->search (2), NULL);
     958                 :           4 :   ASSERT_EQ (base_node->search (3), NULL);
     959                 :           4 :   ASSERT_TRUE (base_node->every_ref);
     960                 :             : 
     961                 :             :   /* Insert base to trigger base list collapse.  */
     962                 :           4 :   t->insert (1, 2, 2, 5, 0, a, false);
     963                 :           4 :   ASSERT_TRUE (t->every_base);
     964                 :           4 :   ASSERT_EQ (t->bases, NULL);
     965                 :           4 :   ASSERT_EQ (t->search (1), NULL);
     966                 :             : 
     967                 :             :   /* Further inserts to collapsed base list are ignored.  */
     968                 :           4 :   t->insert (1, 2, 2, 7, 8, a, false);
     969                 :           4 :   ASSERT_TRUE (t->every_base);
     970                 :           4 :   ASSERT_EQ (t->bases, NULL);
     971                 :           4 :   ASSERT_EQ (t->search (1), NULL);
     972                 :             : 
     973                 :           4 :   delete t;
     974                 :           4 : }
     975                 :             : 
     976                 :             : static void
     977                 :           4 : test_merge ()
     978                 :             : {
     979                 :           4 :   modref_tree<alias_set_type> *t1, *t2;
     980                 :           4 :   modref_base_node<alias_set_type> *base_node;
     981                 :           4 :   modref_access_node a = unspecified_modref_access_node;
     982                 :             : 
     983                 :           4 :   t1 = new modref_tree<alias_set_type>();
     984                 :           4 :   t1->insert (3, 4, 1, 1, 1, a, false);
     985                 :           4 :   t1->insert (3, 4, 1, 1, 2, a, false);
     986                 :           4 :   t1->insert (3, 4, 1, 1, 3, a, false);
     987                 :           4 :   t1->insert (3, 4, 1, 2, 1, a, false);
     988                 :           4 :   t1->insert (3, 4, 1, 3, 1, a, false);
     989                 :             : 
     990                 :           4 :   t2 = new modref_tree<alias_set_type>();
     991                 :           4 :   t2->insert (10, 10, 10, 1, 2, a, false);
     992                 :           4 :   t2->insert (10, 10, 10, 1, 3, a, false);
     993                 :           4 :   t2->insert (10, 10, 10, 1, 4, a, false);
     994                 :           4 :   t2->insert (10, 10, 10, 3, 2, a, false);
     995                 :           4 :   t2->insert (10, 10, 10, 3, 3, a, false);
     996                 :           4 :   t2->insert (10, 10, 10, 3, 4, a, false);
     997                 :           4 :   t2->insert (10, 10, 10, 3, 5, a, false);
     998                 :             : 
     999                 :           4 :   t1->merge (3, 4, 1, t2, NULL, NULL, false);
    1000                 :             : 
    1001                 :           4 :   ASSERT_FALSE (t1->every_base);
    1002                 :           4 :   ASSERT_NE (t1->bases, NULL);
    1003                 :           4 :   ASSERT_EQ (t1->bases->length (), 3);
    1004                 :             : 
    1005                 :           4 :   base_node = t1->search (1);
    1006                 :           4 :   ASSERT_NE (base_node->refs, NULL);
    1007                 :           4 :   ASSERT_FALSE (base_node->every_ref);
    1008                 :           4 :   ASSERT_EQ (base_node->refs->length (), 4);
    1009                 :             : 
    1010                 :           4 :   base_node = t1->search (2);
    1011                 :           4 :   ASSERT_NE (base_node->refs, NULL);
    1012                 :           4 :   ASSERT_FALSE (base_node->every_ref);
    1013                 :           4 :   ASSERT_EQ (base_node->refs->length (), 1);
    1014                 :             : 
    1015                 :           4 :   base_node = t1->search (3);
    1016                 :           4 :   ASSERT_EQ (base_node->refs, NULL);
    1017                 :           4 :   ASSERT_TRUE (base_node->every_ref);
    1018                 :             : 
    1019                 :           4 :   delete t1;
    1020                 :           4 :   delete t2;
    1021                 :           4 : }
    1022                 :             : 
    1023                 :             : 
    1024                 :             : void
    1025                 :           4 : ipa_modref_tree_cc_tests ()
    1026                 :             : {
    1027                 :           4 :   test_insert_search_collapse ();
    1028                 :           4 :   test_merge ();
    1029                 :           4 : }
    1030                 :             : 
    1031                 :             : } // namespace selftest
    1032                 :             : 
    1033                 :             : #endif
    1034                 :             : 
    1035                 :             : void
    1036                 :    43936878 : gt_ggc_mx (modref_tree < int >*const &tt)
    1037                 :             : {
    1038                 :    43936878 :   if (tt->bases)
    1039                 :             :     {
    1040                 :     6801561 :       ggc_test_and_set_mark (tt->bases);
    1041                 :     6801561 :       gt_ggc_mx (tt->bases);
    1042                 :             :     }
    1043                 :    43936878 : }
    1044                 :             : 
    1045                 :             : void
    1046                 :      268544 : gt_ggc_mx (modref_tree < tree_node * >*const &tt)
    1047                 :             : {
    1048                 :      268544 :   if (tt->bases)
    1049                 :             :     {
    1050                 :      211542 :       ggc_test_and_set_mark (tt->bases);
    1051                 :      211542 :       gt_ggc_mx (tt->bases);
    1052                 :             :     }
    1053                 :      268544 : }
    1054                 :             : 
    1055                 :           0 : void gt_pch_nx (modref_tree<int>* const&) {}
    1056                 :           0 : void gt_pch_nx (modref_tree<tree_node*>* const&) {}
    1057                 :           0 : void gt_pch_nx (modref_tree<int>* const&, gt_pointer_operator, void *) {}
    1058                 :           0 : void gt_pch_nx (modref_tree<tree_node*>* const&, gt_pointer_operator, void *) {}
    1059                 :             : 
    1060                 :     7568696 : void gt_ggc_mx (modref_base_node<int>* &b)
    1061                 :             : {
    1062                 :     7568696 :   ggc_test_and_set_mark (b);
    1063                 :     7568696 :   if (b->refs)
    1064                 :             :     {
    1065                 :     7564559 :       ggc_test_and_set_mark (b->refs);
    1066                 :     7564559 :       gt_ggc_mx (b->refs);
    1067                 :             :     }
    1068                 :     7568696 : }
    1069                 :             : 
    1070                 :      219342 : void gt_ggc_mx (modref_base_node<tree_node*>* &b)
    1071                 :             : {
    1072                 :      219342 :   ggc_test_and_set_mark (b);
    1073                 :      219342 :   if (b->refs)
    1074                 :             :     {
    1075                 :      219342 :       ggc_test_and_set_mark (b->refs);
    1076                 :      219342 :       gt_ggc_mx (b->refs);
    1077                 :             :     }
    1078                 :      219342 :   if (b->base)
    1079                 :      219188 :     gt_ggc_mx (b->base);
    1080                 :      219342 : }
    1081                 :             : 
    1082                 :           0 : void gt_pch_nx (modref_base_node<int>*) {}
    1083                 :           0 : void gt_pch_nx (modref_base_node<tree_node*>*) {}
    1084                 :           0 : void gt_pch_nx (modref_base_node<int>*, gt_pointer_operator, void *) {}
    1085                 :           0 : void gt_pch_nx (modref_base_node<tree_node*>*, gt_pointer_operator, void *) {}
    1086                 :             : 
    1087                 :     9632123 : void gt_ggc_mx (modref_ref_node<int>* &r)
    1088                 :             : {
    1089                 :     9632123 :   ggc_test_and_set_mark (r);
    1090                 :     9632123 :   if (r->accesses)
    1091                 :             :     {
    1092                 :     7241947 :       ggc_test_and_set_mark (r->accesses);
    1093                 :     7241947 :       gt_ggc_mx (r->accesses);
    1094                 :             :     }
    1095                 :     9632123 : }
    1096                 :             : 
    1097                 :      219346 : void gt_ggc_mx (modref_ref_node<tree_node*>* &r)
    1098                 :             : {
    1099                 :      219346 :   ggc_test_and_set_mark (r);
    1100                 :      219346 :   if (r->accesses)
    1101                 :             :     {
    1102                 :        7749 :       ggc_test_and_set_mark (r->accesses);
    1103                 :        7749 :       gt_ggc_mx (r->accesses);
    1104                 :             :     }
    1105                 :      219346 :   if (r->ref)
    1106                 :      219296 :     gt_ggc_mx (r->ref);
    1107                 :      219346 : }
    1108                 :             : 
    1109                 :           0 : void gt_pch_nx (modref_ref_node<int>* ) {}
    1110                 :           0 : void gt_pch_nx (modref_ref_node<tree_node*>*) {}
    1111                 :           0 : void gt_pch_nx (modref_ref_node<int>*, gt_pointer_operator, void *) {}
    1112                 :           0 : void gt_pch_nx (modref_ref_node<tree_node*>*, gt_pointer_operator, void *) {}
    1113                 :             : 
    1114                 :    10504087 : void gt_ggc_mx (modref_access_node &)
    1115                 :             : {
    1116                 :    10504087 : }
        

Generated by: LCOV version 2.1-beta

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