LLVM API Documentation
00001 //===- StratifiedSets.h - Abstract stratified sets implementation. --------===// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file is distributed under the University of Illinois Open Source 00006 // License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 00010 #ifndef LLVM_ADT_STRATIFIEDSETS_H 00011 #define LLVM_ADT_STRATIFIEDSETS_H 00012 00013 #include "llvm/ADT/DenseMap.h" 00014 #include "llvm/ADT/Optional.h" 00015 #include "llvm/ADT/SmallPtrSet.h" 00016 #include "llvm/ADT/SmallSet.h" 00017 #include "llvm/ADT/SmallVector.h" 00018 #include "llvm/Support/Compiler.h" 00019 #include <bitset> 00020 #include <cassert> 00021 #include <cmath> 00022 #include <limits> 00023 #include <type_traits> 00024 #include <utility> 00025 #include <vector> 00026 00027 namespace llvm { 00028 // \brief An index into Stratified Sets. 00029 typedef unsigned StratifiedIndex; 00030 // NOTE: ^ This can't be a short -- bootstrapping clang has a case where 00031 // ~1M sets exist. 00032 00033 // \brief Container of information related to a value in a StratifiedSet. 00034 struct StratifiedInfo { 00035 StratifiedIndex Index; 00036 // For field sensitivity, etc. we can tack attributes on to this struct. 00037 }; 00038 00039 // The number of attributes that StratifiedAttrs should contain. Attributes are 00040 // described below, and 32 was an arbitrary choice because it fits nicely in 32 00041 // bits (because we use a bitset for StratifiedAttrs). 00042 static const unsigned NumStratifiedAttrs = 32; 00043 00044 // These are attributes that the users of StratifiedSets/StratifiedSetBuilders 00045 // may use for various purposes. These also have the special property of that 00046 // they are merged down. So, if set A is above set B, and one decides to set an 00047 // attribute in set A, then the attribute will automatically be set in set B. 00048 typedef std::bitset<NumStratifiedAttrs> StratifiedAttrs; 00049 00050 // \brief A "link" between two StratifiedSets. 00051 struct StratifiedLink { 00052 // \brief This is a value used to signify "does not exist" where 00053 // the StratifiedIndex type is used. This is used instead of 00054 // Optional<StratifiedIndex> because Optional<StratifiedIndex> would 00055 // eat up a considerable amount of extra memory, after struct 00056 // padding/alignment is taken into account. 00057 static const StratifiedIndex SetSentinel; 00058 00059 // \brief The index for the set "above" current 00060 StratifiedIndex Above; 00061 00062 // \brief The link for the set "below" current 00063 StratifiedIndex Below; 00064 00065 // \brief Attributes for these StratifiedSets. 00066 StratifiedAttrs Attrs; 00067 00068 StratifiedLink() : Above(SetSentinel), Below(SetSentinel) {} 00069 00070 bool hasBelow() const { return Below != SetSentinel; } 00071 bool hasAbove() const { return Above != SetSentinel; } 00072 00073 void clearBelow() { Below = SetSentinel; } 00074 void clearAbove() { Above = SetSentinel; } 00075 }; 00076 00077 // \brief These are stratified sets, as described in "Fast algorithms for 00078 // Dyck-CFL-reachability with applications to Alias Analysis" by Zhang Q, Lyu M 00079 // R, Yuan H, and Su Z. -- in short, this is meant to represent different sets 00080 // of Value*s. If two Value*s are in the same set, or if both sets have 00081 // overlapping attributes, then the Value*s are said to alias. 00082 // 00083 // Sets may be related by position, meaning that one set may be considered as 00084 // above or below another. In CFL Alias Analysis, this gives us an indication 00085 // of how two variables are related; if the set of variable A is below a set 00086 // containing variable B, then at some point, a variable that has interacted 00087 // with B (or B itself) was either used in order to extract the variable A, or 00088 // was used as storage of variable A. 00089 // 00090 // Sets may also have attributes (as noted above). These attributes are 00091 // generally used for noting whether a variable in the set has interacted with 00092 // a variable whose origins we don't quite know (i.e. globals/arguments), or if 00093 // the variable may have had operations performed on it (modified in a function 00094 // call). All attributes that exist in a set A must exist in all sets marked as 00095 // below set A. 00096 template <typename T> class StratifiedSets { 00097 public: 00098 StratifiedSets() {} 00099 00100 StratifiedSets(DenseMap<T, StratifiedInfo> Map, 00101 std::vector<StratifiedLink> Links) 00102 : Values(std::move(Map)), Links(std::move(Links)) {} 00103 00104 StratifiedSets(StratifiedSets<T> &&Other) { *this = std::move(Other); } 00105 00106 StratifiedSets &operator=(StratifiedSets<T> &&Other) { 00107 Values = std::move(Other.Values); 00108 Links = std::move(Other.Links); 00109 return *this; 00110 } 00111 00112 Optional<StratifiedInfo> find(const T &Elem) const { 00113 auto Iter = Values.find(Elem); 00114 if (Iter == Values.end()) { 00115 return NoneType(); 00116 } 00117 return Iter->second; 00118 } 00119 00120 const StratifiedLink &getLink(StratifiedIndex Index) const { 00121 assert(inbounds(Index)); 00122 return Links[Index]; 00123 } 00124 00125 private: 00126 DenseMap<T, StratifiedInfo> Values; 00127 std::vector<StratifiedLink> Links; 00128 00129 bool inbounds(StratifiedIndex Idx) const { return Idx < Links.size(); } 00130 }; 00131 00132 // \brief Generic Builder class that produces StratifiedSets instances. 00133 // 00134 // The goal of this builder is to efficiently produce correct StratifiedSets 00135 // instances. To this end, we use a few tricks: 00136 // > Set chains (A method for linking sets together) 00137 // > Set remaps (A method for marking a set as an alias [irony?] of another) 00138 // 00139 // ==== Set chains ==== 00140 // This builder has a notion of some value A being above, below, or with some 00141 // other value B: 00142 // > The `A above B` relationship implies that there is a reference edge going 00143 // from A to B. Namely, it notes that A can store anything in B's set. 00144 // > The `A below B` relationship is the opposite of `A above B`. It implies 00145 // that there's a dereference edge going from A to B. 00146 // > The `A with B` relationship states that there's an assignment edge going 00147 // from A to B, and that A and B should be treated as equals. 00148 // 00149 // As an example, take the following code snippet: 00150 // 00151 // %a = alloca i32, align 4 00152 // %ap = alloca i32*, align 8 00153 // %app = alloca i32**, align 8 00154 // store %a, %ap 00155 // store %ap, %app 00156 // %aw = getelementptr %ap, 0 00157 // 00158 // Given this, the follow relations exist: 00159 // - %a below %ap & %ap above %a 00160 // - %ap below %app & %app above %ap 00161 // - %aw with %ap & %ap with %aw 00162 // 00163 // These relations produce the following sets: 00164 // [{%a}, {%ap, %aw}, {%app}] 00165 // 00166 // ...Which states that the only MayAlias relationship in the above program is 00167 // between %ap and %aw. 00168 // 00169 // Life gets more complicated when we actually have logic in our programs. So, 00170 // we either must remove this logic from our programs, or make consessions for 00171 // it in our AA algorithms. In this case, we have decided to select the latter 00172 // option. 00173 // 00174 // First complication: Conditionals 00175 // Motivation: 00176 // %ad = alloca int, align 4 00177 // %a = alloca int*, align 8 00178 // %b = alloca int*, align 8 00179 // %bp = alloca int**, align 8 00180 // %c = call i1 @SomeFunc() 00181 // %k = select %c, %ad, %bp 00182 // store %ad, %a 00183 // store %b, %bp 00184 // 00185 // %k has 'with' edges to both %a and %b, which ordinarily would not be linked 00186 // together. So, we merge the set that contains %a with the set that contains 00187 // %b. We then recursively merge the set above %a with the set above %b, and 00188 // the set below %a with the set below %b, etc. Ultimately, the sets for this 00189 // program would end up like: {%ad}, {%a, %b, %k}, {%bp}, where {%ad} is below 00190 // {%a, %b, %c} is below {%ad}. 00191 // 00192 // Second complication: Arbitrary casts 00193 // Motivation: 00194 // %ip = alloca int*, align 8 00195 // %ipp = alloca int**, align 8 00196 // %i = bitcast ipp to int 00197 // store %ip, %ipp 00198 // store %i, %ip 00199 // 00200 // This is impossible to construct with any of the rules above, because a set 00201 // containing both {%i, %ipp} is supposed to exist, the set with %i is supposed 00202 // to be below the set with %ip, and the set with %ip is supposed to be below 00203 // the set with %ipp. Because we don't allow circular relationships like this, 00204 // we merge all concerned sets into one. So, the above code would generate a 00205 // single StratifiedSet: {%ip, %ipp, %i}. 00206 // 00207 // ==== Set remaps ==== 00208 // More of an implementation detail than anything -- when merging sets, we need 00209 // to update the numbers of all of the elements mapped to those sets. Rather 00210 // than doing this at each merge, we note in the BuilderLink structure that a 00211 // remap has occurred, and use this information so we can defer renumbering set 00212 // elements until build time. 00213 template <typename T> class StratifiedSetsBuilder { 00214 // \brief Represents a Stratified Set, with information about the Stratified 00215 // Set above it, the set below it, and whether the current set has been 00216 // remapped to another. 00217 struct BuilderLink { 00218 const StratifiedIndex Number; 00219 00220 BuilderLink(StratifiedIndex N) : Number(N) { 00221 Remap = StratifiedLink::SetSentinel; 00222 } 00223 00224 bool hasAbove() const { 00225 assert(!isRemapped()); 00226 return Link.hasAbove(); 00227 } 00228 00229 bool hasBelow() const { 00230 assert(!isRemapped()); 00231 return Link.hasBelow(); 00232 } 00233 00234 void setBelow(StratifiedIndex I) { 00235 assert(!isRemapped()); 00236 Link.Below = I; 00237 } 00238 00239 void setAbove(StratifiedIndex I) { 00240 assert(!isRemapped()); 00241 Link.Above = I; 00242 } 00243 00244 void clearBelow() { 00245 assert(!isRemapped()); 00246 Link.clearBelow(); 00247 } 00248 00249 void clearAbove() { 00250 assert(!isRemapped()); 00251 Link.clearAbove(); 00252 } 00253 00254 StratifiedIndex getBelow() const { 00255 assert(!isRemapped()); 00256 assert(hasBelow()); 00257 return Link.Below; 00258 } 00259 00260 StratifiedIndex getAbove() const { 00261 assert(!isRemapped()); 00262 assert(hasAbove()); 00263 return Link.Above; 00264 } 00265 00266 StratifiedAttrs &getAttrs() { 00267 assert(!isRemapped()); 00268 return Link.Attrs; 00269 } 00270 00271 void setAttr(unsigned index) { 00272 assert(!isRemapped()); 00273 assert(index < NumStratifiedAttrs); 00274 Link.Attrs.set(index); 00275 } 00276 00277 void setAttrs(const StratifiedAttrs &other) { 00278 assert(!isRemapped()); 00279 Link.Attrs |= other; 00280 } 00281 00282 bool isRemapped() const { return Remap != StratifiedLink::SetSentinel; } 00283 00284 // \brief For initial remapping to another set 00285 void remapTo(StratifiedIndex Other) { 00286 assert(!isRemapped()); 00287 Remap = Other; 00288 } 00289 00290 StratifiedIndex getRemapIndex() const { 00291 assert(isRemapped()); 00292 return Remap; 00293 } 00294 00295 // \brief Should only be called when we're already remapped. 00296 void updateRemap(StratifiedIndex Other) { 00297 assert(isRemapped()); 00298 Remap = Other; 00299 } 00300 00301 // \brief Prefer the above functions to calling things directly on what's 00302 // returned from this -- they guard against unexpected calls when the 00303 // current BuilderLink is remapped. 00304 const StratifiedLink &getLink() const { return Link; } 00305 00306 private: 00307 StratifiedLink Link; 00308 StratifiedIndex Remap; 00309 }; 00310 00311 // \brief This function performs all of the set unioning/value renumbering 00312 // that we've been putting off, and generates a vector<StratifiedLink> that 00313 // may be placed in a StratifiedSets instance. 00314 void finalizeSets(std::vector<StratifiedLink> &StratLinks) { 00315 DenseMap<StratifiedIndex, StratifiedIndex> Remaps; 00316 for (auto &Link : Links) { 00317 if (Link.isRemapped()) { 00318 continue; 00319 } 00320 00321 StratifiedIndex Number = StratLinks.size(); 00322 Remaps.insert(std::make_pair(Link.Number, Number)); 00323 StratLinks.push_back(Link.getLink()); 00324 } 00325 00326 for (auto &Link : StratLinks) { 00327 if (Link.hasAbove()) { 00328 auto &Above = linksAt(Link.Above); 00329 auto Iter = Remaps.find(Above.Number); 00330 assert(Iter != Remaps.end()); 00331 Link.Above = Iter->second; 00332 } 00333 00334 if (Link.hasBelow()) { 00335 auto &Below = linksAt(Link.Below); 00336 auto Iter = Remaps.find(Below.Number); 00337 assert(Iter != Remaps.end()); 00338 Link.Below = Iter->second; 00339 } 00340 } 00341 00342 for (auto &Pair : Values) { 00343 auto &Info = Pair.second; 00344 auto &Link = linksAt(Info.Index); 00345 auto Iter = Remaps.find(Link.Number); 00346 assert(Iter != Remaps.end()); 00347 Info.Index = Iter->second; 00348 } 00349 } 00350 00351 // \brief There's a guarantee in StratifiedLink where all bits set in a 00352 // Link.externals will be set in all Link.externals "below" it. 00353 static void propagateAttrs(std::vector<StratifiedLink> &Links) { 00354 const auto getHighestParentAbove = [&Links](StratifiedIndex Idx) { 00355 const auto *Link = &Links[Idx]; 00356 while (Link->hasAbove()) { 00357 Idx = Link->Above; 00358 Link = &Links[Idx]; 00359 } 00360 return Idx; 00361 }; 00362 00363 SmallSet<StratifiedIndex, 16> Visited; 00364 for (unsigned I = 0, E = Links.size(); I < E; ++I) { 00365 auto CurrentIndex = getHighestParentAbove(I); 00366 if (!Visited.insert(CurrentIndex)) { 00367 continue; 00368 } 00369 00370 while (Links[CurrentIndex].hasBelow()) { 00371 auto &CurrentBits = Links[CurrentIndex].Attrs; 00372 auto NextIndex = Links[CurrentIndex].Below; 00373 auto &NextBits = Links[NextIndex].Attrs; 00374 NextBits |= CurrentBits; 00375 CurrentIndex = NextIndex; 00376 } 00377 } 00378 } 00379 00380 public: 00381 // \brief Builds a StratifiedSet from the information we've been given since 00382 // either construction or the prior build() call. 00383 StratifiedSets<T> build() { 00384 std::vector<StratifiedLink> StratLinks; 00385 finalizeSets(StratLinks); 00386 propagateAttrs(StratLinks); 00387 Links.clear(); 00388 return StratifiedSets<T>(std::move(Values), std::move(StratLinks)); 00389 } 00390 00391 std::size_t size() const { return Values.size(); } 00392 std::size_t numSets() const { return Links.size(); } 00393 00394 bool has(const T &Elem) const { return get(Elem).hasValue(); } 00395 00396 bool add(const T &Main) { 00397 if (get(Main).hasValue()) 00398 return false; 00399 00400 auto NewIndex = getNewUnlinkedIndex(); 00401 return addAtMerging(Main, NewIndex); 00402 } 00403 00404 // \brief Restructures the stratified sets as necessary to make "ToAdd" in a 00405 // set above "Main". There are some cases where this is not possible (see 00406 // above), so we merge them such that ToAdd and Main are in the same set. 00407 bool addAbove(const T &Main, const T &ToAdd) { 00408 assert(has(Main)); 00409 auto Index = *indexOf(Main); 00410 if (!linksAt(Index).hasAbove()) 00411 addLinkAbove(Index); 00412 00413 auto Above = linksAt(Index).getAbove(); 00414 return addAtMerging(ToAdd, Above); 00415 } 00416 00417 // \brief Restructures the stratified sets as necessary to make "ToAdd" in a 00418 // set below "Main". There are some cases where this is not possible (see 00419 // above), so we merge them such that ToAdd and Main are in the same set. 00420 bool addBelow(const T &Main, const T &ToAdd) { 00421 assert(has(Main)); 00422 auto Index = *indexOf(Main); 00423 if (!linksAt(Index).hasBelow()) 00424 addLinkBelow(Index); 00425 00426 auto Below = linksAt(Index).getBelow(); 00427 return addAtMerging(ToAdd, Below); 00428 } 00429 00430 bool addWith(const T &Main, const T &ToAdd) { 00431 assert(has(Main)); 00432 auto MainIndex = *indexOf(Main); 00433 return addAtMerging(ToAdd, MainIndex); 00434 } 00435 00436 void noteAttribute(const T &Main, unsigned AttrNum) { 00437 assert(has(Main)); 00438 assert(AttrNum < StratifiedLink::SetSentinel); 00439 auto *Info = *get(Main); 00440 auto &Link = linksAt(Info->Index); 00441 Link.setAttr(AttrNum); 00442 } 00443 00444 void noteAttributes(const T &Main, const StratifiedAttrs &NewAttrs) { 00445 assert(has(Main)); 00446 auto *Info = *get(Main); 00447 auto &Link = linksAt(Info->Index); 00448 Link.setAttrs(NewAttrs); 00449 } 00450 00451 StratifiedAttrs getAttributes(const T &Main) { 00452 assert(has(Main)); 00453 auto *Info = *get(Main); 00454 auto *Link = &linksAt(Info->Index); 00455 auto Attrs = Link->getAttrs(); 00456 while (Link->hasAbove()) { 00457 Link = &linksAt(Link->getAbove()); 00458 Attrs |= Link->getAttrs(); 00459 } 00460 00461 return Attrs; 00462 } 00463 00464 bool getAttribute(const T &Main, unsigned AttrNum) { 00465 assert(AttrNum < StratifiedLink::SetSentinel); 00466 auto Attrs = getAttributes(Main); 00467 return Attrs[AttrNum]; 00468 } 00469 00470 // \brief Gets the attributes that have been applied to the set that Main 00471 // belongs to. It ignores attributes in any sets above the one that Main 00472 // resides in. 00473 StratifiedAttrs getRawAttributes(const T &Main) { 00474 assert(has(Main)); 00475 auto *Info = *get(Main); 00476 auto &Link = linksAt(Info->Index); 00477 return Link.getAttrs(); 00478 } 00479 00480 // \brief Gets an attribute from the attributes that have been applied to the 00481 // set that Main belongs to. It ignores attributes in any sets above the one 00482 // that Main resides in. 00483 bool getRawAttribute(const T &Main, unsigned AttrNum) { 00484 assert(AttrNum < StratifiedLink::SetSentinel); 00485 auto Attrs = getRawAttributes(Main); 00486 return Attrs[AttrNum]; 00487 } 00488 00489 private: 00490 DenseMap<T, StratifiedInfo> Values; 00491 std::vector<BuilderLink> Links; 00492 00493 // \brief Adds the given element at the given index, merging sets if 00494 // necessary. 00495 bool addAtMerging(const T &ToAdd, StratifiedIndex Index) { 00496 StratifiedInfo Info = {Index}; 00497 auto Pair = Values.insert(std::make_pair(ToAdd, Info)); 00498 if (Pair.second) 00499 return true; 00500 00501 auto &Iter = Pair.first; 00502 auto &IterSet = linksAt(Iter->second.Index); 00503 auto &ReqSet = linksAt(Index); 00504 00505 // Failed to add where we wanted to. Merge the sets. 00506 if (&IterSet != &ReqSet) 00507 merge(IterSet.Number, ReqSet.Number); 00508 00509 return false; 00510 } 00511 00512 // \brief Gets the BuilderLink at the given index, taking set remapping into 00513 // account. 00514 BuilderLink &linksAt(StratifiedIndex Index) { 00515 auto *Start = &Links[Index]; 00516 if (!Start->isRemapped()) 00517 return *Start; 00518 00519 auto *Current = Start; 00520 while (Current->isRemapped()) 00521 Current = &Links[Current->getRemapIndex()]; 00522 00523 auto NewRemap = Current->Number; 00524 00525 // Run through everything that has yet to be updated, and update them to 00526 // remap to NewRemap 00527 Current = Start; 00528 while (Current->isRemapped()) { 00529 auto *Next = &Links[Current->getRemapIndex()]; 00530 Current->updateRemap(NewRemap); 00531 Current = Next; 00532 } 00533 00534 return *Current; 00535 } 00536 00537 // \brief Merges two sets into one another. Assumes that these sets are not 00538 // already one in the same 00539 void merge(StratifiedIndex Idx1, StratifiedIndex Idx2) { 00540 assert(inbounds(Idx1) && inbounds(Idx2)); 00541 assert(&linksAt(Idx1) != &linksAt(Idx2) && 00542 "Merging a set into itself is not allowed"); 00543 00544 // CASE 1: If the set at `Idx1` is above or below `Idx2`, we need to merge 00545 // both the 00546 // given sets, and all sets between them, into one. 00547 if (tryMergeUpwards(Idx1, Idx2)) 00548 return; 00549 00550 if (tryMergeUpwards(Idx2, Idx1)) 00551 return; 00552 00553 // CASE 2: The set at `Idx1` is not in the same chain as the set at `Idx2`. 00554 // We therefore need to merge the two chains together. 00555 mergeDirect(Idx1, Idx2); 00556 } 00557 00558 // \brief Merges two sets assuming that the set at `Idx1` is unreachable from 00559 // traversing above or below the set at `Idx2`. 00560 void mergeDirect(StratifiedIndex Idx1, StratifiedIndex Idx2) { 00561 assert(inbounds(Idx1) && inbounds(Idx2)); 00562 00563 auto *LinksInto = &linksAt(Idx1); 00564 auto *LinksFrom = &linksAt(Idx2); 00565 // Merging everything above LinksInto then proceeding to merge everything 00566 // below LinksInto becomes problematic, so we go as far "up" as possible! 00567 while (LinksInto->hasAbove() && LinksFrom->hasAbove()) { 00568 LinksInto = &linksAt(LinksInto->getAbove()); 00569 LinksFrom = &linksAt(LinksFrom->getAbove()); 00570 } 00571 00572 if (LinksFrom->hasAbove()) { 00573 LinksInto->setAbove(LinksFrom->getAbove()); 00574 auto &NewAbove = linksAt(LinksInto->getAbove()); 00575 NewAbove.setBelow(LinksInto->Number); 00576 } 00577 00578 // Merging strategy: 00579 // > If neither has links below, stop. 00580 // > If only `LinksInto` has links below, stop. 00581 // > If only `LinksFrom` has links below, reset `LinksInto.Below` to 00582 // match `LinksFrom.Below` 00583 // > If both have links above, deal with those next. 00584 while (LinksInto->hasBelow() && LinksFrom->hasBelow()) { 00585 auto &FromAttrs = LinksFrom->getAttrs(); 00586 LinksInto->setAttrs(FromAttrs); 00587 00588 // Remap needs to happen after getBelow(), but before 00589 // assignment of LinksFrom 00590 auto *NewLinksFrom = &linksAt(LinksFrom->getBelow()); 00591 LinksFrom->remapTo(LinksInto->Number); 00592 LinksFrom = NewLinksFrom; 00593 LinksInto = &linksAt(LinksInto->getBelow()); 00594 } 00595 00596 if (LinksFrom->hasBelow()) { 00597 LinksInto->setBelow(LinksFrom->getBelow()); 00598 auto &NewBelow = linksAt(LinksInto->getBelow()); 00599 NewBelow.setAbove(LinksInto->Number); 00600 } 00601 00602 LinksFrom->remapTo(LinksInto->Number); 00603 } 00604 00605 // \brief Checks to see if lowerIndex is at a level lower than upperIndex. 00606 // If so, it will merge lowerIndex with upperIndex (and all of the sets 00607 // between) and return true. Otherwise, it will return false. 00608 bool tryMergeUpwards(StratifiedIndex LowerIndex, StratifiedIndex UpperIndex) { 00609 assert(inbounds(LowerIndex) && inbounds(UpperIndex)); 00610 auto *Lower = &linksAt(LowerIndex); 00611 auto *Upper = &linksAt(UpperIndex); 00612 if (Lower == Upper) 00613 return true; 00614 00615 SmallVector<BuilderLink *, 8> Found; 00616 auto *Current = Lower; 00617 auto Attrs = Current->getAttrs(); 00618 while (Current->hasAbove() && Current != Upper) { 00619 Found.push_back(Current); 00620 Attrs |= Current->getAttrs(); 00621 Current = &linksAt(Current->getAbove()); 00622 } 00623 00624 if (Current != Upper) 00625 return false; 00626 00627 Upper->setAttrs(Attrs); 00628 00629 if (Lower->hasBelow()) { 00630 auto NewBelowIndex = Lower->getBelow(); 00631 Upper->setBelow(NewBelowIndex); 00632 auto &NewBelow = linksAt(NewBelowIndex); 00633 NewBelow.setAbove(UpperIndex); 00634 } else { 00635 Upper->clearBelow(); 00636 } 00637 00638 for (const auto &Ptr : Found) 00639 Ptr->remapTo(Upper->Number); 00640 00641 return true; 00642 } 00643 00644 Optional<const StratifiedInfo *> get(const T &Val) const { 00645 auto Result = Values.find(Val); 00646 if (Result == Values.end()) 00647 return NoneType(); 00648 return &Result->second; 00649 } 00650 00651 Optional<StratifiedInfo *> get(const T &Val) { 00652 auto Result = Values.find(Val); 00653 if (Result == Values.end()) 00654 return NoneType(); 00655 return &Result->second; 00656 } 00657 00658 Optional<StratifiedIndex> indexOf(const T &Val) { 00659 auto MaybeVal = get(Val); 00660 if (!MaybeVal.hasValue()) 00661 return NoneType(); 00662 auto *Info = *MaybeVal; 00663 auto &Link = linksAt(Info->Index); 00664 return Link.Number; 00665 } 00666 00667 StratifiedIndex addLinkBelow(StratifiedIndex Set) { 00668 auto At = addLinks(); 00669 Links[Set].setBelow(At); 00670 Links[At].setAbove(Set); 00671 return At; 00672 } 00673 00674 StratifiedIndex addLinkAbove(StratifiedIndex Set) { 00675 auto At = addLinks(); 00676 Links[At].setBelow(Set); 00677 Links[Set].setAbove(At); 00678 return At; 00679 } 00680 00681 StratifiedIndex getNewUnlinkedIndex() { return addLinks(); } 00682 00683 StratifiedIndex addLinks() { 00684 auto Link = Links.size(); 00685 Links.push_back(BuilderLink(Link)); 00686 return Link; 00687 } 00688 00689 bool inbounds(StratifiedIndex N) const { return N < Links.size(); } 00690 }; 00691 } 00692 #endif // LLVM_ADT_STRATIFIEDSETS_H