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