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