StratifiedSets.h 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692
  1. //===- StratifiedSets.h - Abstract stratified sets implementation. --------===//
  2. //
  3. // The LLVM Compiler Infrastructure
  4. //
  5. // This file is distributed under the University of Illinois Open Source
  6. // License. See LICENSE.TXT for details.
  7. //
  8. //===----------------------------------------------------------------------===//
  9. #ifndef LLVM_ADT_STRATIFIEDSETS_H
  10. #define LLVM_ADT_STRATIFIEDSETS_H
  11. #include "llvm/ADT/DenseMap.h"
  12. #include "llvm/ADT/Optional.h"
  13. #include "llvm/ADT/SmallPtrSet.h"
  14. #include "llvm/ADT/SmallSet.h"
  15. #include "llvm/ADT/SmallVector.h"
  16. #include "llvm/Support/Compiler.h"
  17. #include <bitset>
  18. #include <cassert>
  19. #include <cmath>
  20. #include <limits>
  21. #include <type_traits>
  22. #include <utility>
  23. #include <vector>
  24. namespace llvm {
  25. // \brief An index into Stratified Sets.
  26. typedef unsigned StratifiedIndex;
  27. // NOTE: ^ This can't be a short -- bootstrapping clang has a case where
  28. // ~1M sets exist.
  29. // \brief Container of information related to a value in a StratifiedSet.
  30. struct StratifiedInfo {
  31. StratifiedIndex Index;
  32. // For field sensitivity, etc. we can tack attributes on to this struct.
  33. };
  34. // The number of attributes that StratifiedAttrs should contain. Attributes are
  35. // described below, and 32 was an arbitrary choice because it fits nicely in 32
  36. // bits (because we use a bitset for StratifiedAttrs).
  37. static const unsigned NumStratifiedAttrs = 32;
  38. // These are attributes that the users of StratifiedSets/StratifiedSetBuilders
  39. // may use for various purposes. These also have the special property of that
  40. // they are merged down. So, if set A is above set B, and one decides to set an
  41. // attribute in set A, then the attribute will automatically be set in set B.
  42. typedef std::bitset<NumStratifiedAttrs> StratifiedAttrs;
  43. // \brief A "link" between two StratifiedSets.
  44. struct StratifiedLink {
  45. // \brief This is a value used to signify "does not exist" where
  46. // the StratifiedIndex type is used. This is used instead of
  47. // Optional<StratifiedIndex> because Optional<StratifiedIndex> would
  48. // eat up a considerable amount of extra memory, after struct
  49. // padding/alignment is taken into account.
  50. static const StratifiedIndex SetSentinel;
  51. // \brief The index for the set "above" current
  52. StratifiedIndex Above;
  53. // \brief The link for the set "below" current
  54. StratifiedIndex Below;
  55. // \brief Attributes for these StratifiedSets.
  56. StratifiedAttrs Attrs;
  57. StratifiedLink() : Above(SetSentinel), Below(SetSentinel) {}
  58. bool hasBelow() const { return Below != SetSentinel; }
  59. bool hasAbove() const { return Above != SetSentinel; }
  60. void clearBelow() { Below = SetSentinel; }
  61. void clearAbove() { Above = SetSentinel; }
  62. };
  63. // \brief These are stratified sets, as described in "Fast algorithms for
  64. // Dyck-CFL-reachability with applications to Alias Analysis" by Zhang Q, Lyu M
  65. // R, Yuan H, and Su Z. -- in short, this is meant to represent different sets
  66. // of Value*s. If two Value*s are in the same set, or if both sets have
  67. // overlapping attributes, then the Value*s are said to alias.
  68. //
  69. // Sets may be related by position, meaning that one set may be considered as
  70. // above or below another. In CFL Alias Analysis, this gives us an indication
  71. // of how two variables are related; if the set of variable A is below a set
  72. // containing variable B, then at some point, a variable that has interacted
  73. // with B (or B itself) was either used in order to extract the variable A, or
  74. // was used as storage of variable A.
  75. //
  76. // Sets may also have attributes (as noted above). These attributes are
  77. // generally used for noting whether a variable in the set has interacted with
  78. // a variable whose origins we don't quite know (i.e. globals/arguments), or if
  79. // the variable may have had operations performed on it (modified in a function
  80. // call). All attributes that exist in a set A must exist in all sets marked as
  81. // below set A.
  82. template <typename T> class StratifiedSets {
  83. public:
  84. StratifiedSets() {}
  85. StratifiedSets(DenseMap<T, StratifiedInfo> Map,
  86. std::vector<StratifiedLink> Links)
  87. : Values(std::move(Map)), Links(std::move(Links)) {}
  88. StratifiedSets(StratifiedSets<T> &&Other) { *this = std::move(Other); }
  89. StratifiedSets &operator=(StratifiedSets<T> &&Other) {
  90. Values = std::move(Other.Values);
  91. Links = std::move(Other.Links);
  92. return *this;
  93. }
  94. Optional<StratifiedInfo> find(const T &Elem) const {
  95. auto Iter = Values.find(Elem);
  96. if (Iter == Values.end()) {
  97. return NoneType();
  98. }
  99. return Iter->second;
  100. }
  101. const StratifiedLink &getLink(StratifiedIndex Index) const {
  102. assert(inbounds(Index));
  103. return Links[Index];
  104. }
  105. private:
  106. DenseMap<T, StratifiedInfo> Values;
  107. std::vector<StratifiedLink> Links;
  108. bool inbounds(StratifiedIndex Idx) const { return Idx < Links.size(); }
  109. };
  110. // \brief Generic Builder class that produces StratifiedSets instances.
  111. //
  112. // The goal of this builder is to efficiently produce correct StratifiedSets
  113. // instances. To this end, we use a few tricks:
  114. // > Set chains (A method for linking sets together)
  115. // > Set remaps (A method for marking a set as an alias [irony?] of another)
  116. //
  117. // ==== Set chains ====
  118. // This builder has a notion of some value A being above, below, or with some
  119. // other value B:
  120. // > The `A above B` relationship implies that there is a reference edge going
  121. // from A to B. Namely, it notes that A can store anything in B's set.
  122. // > The `A below B` relationship is the opposite of `A above B`. It implies
  123. // that there's a dereference edge going from A to B.
  124. // > The `A with B` relationship states that there's an assignment edge going
  125. // from A to B, and that A and B should be treated as equals.
  126. //
  127. // As an example, take the following code snippet:
  128. //
  129. // %a = alloca i32, align 4
  130. // %ap = alloca i32*, align 8
  131. // %app = alloca i32**, align 8
  132. // store %a, %ap
  133. // store %ap, %app
  134. // %aw = getelementptr %ap, 0
  135. //
  136. // Given this, the follow relations exist:
  137. // - %a below %ap & %ap above %a
  138. // - %ap below %app & %app above %ap
  139. // - %aw with %ap & %ap with %aw
  140. //
  141. // These relations produce the following sets:
  142. // [{%a}, {%ap, %aw}, {%app}]
  143. //
  144. // ...Which states that the only MayAlias relationship in the above program is
  145. // between %ap and %aw.
  146. //
  147. // Life gets more complicated when we actually have logic in our programs. So,
  148. // we either must remove this logic from our programs, or make consessions for
  149. // it in our AA algorithms. In this case, we have decided to select the latter
  150. // option.
  151. //
  152. // First complication: Conditionals
  153. // Motivation:
  154. // %ad = alloca int, align 4
  155. // %a = alloca int*, align 8
  156. // %b = alloca int*, align 8
  157. // %bp = alloca int**, align 8
  158. // %c = call i1 @SomeFunc()
  159. // %k = select %c, %ad, %bp
  160. // store %ad, %a
  161. // store %b, %bp
  162. //
  163. // %k has 'with' edges to both %a and %b, which ordinarily would not be linked
  164. // together. So, we merge the set that contains %a with the set that contains
  165. // %b. We then recursively merge the set above %a with the set above %b, and
  166. // the set below %a with the set below %b, etc. Ultimately, the sets for this
  167. // program would end up like: {%ad}, {%a, %b, %k}, {%bp}, where {%ad} is below
  168. // {%a, %b, %c} is below {%ad}.
  169. //
  170. // Second complication: Arbitrary casts
  171. // Motivation:
  172. // %ip = alloca int*, align 8
  173. // %ipp = alloca int**, align 8
  174. // %i = bitcast ipp to int
  175. // store %ip, %ipp
  176. // store %i, %ip
  177. //
  178. // This is impossible to construct with any of the rules above, because a set
  179. // containing both {%i, %ipp} is supposed to exist, the set with %i is supposed
  180. // to be below the set with %ip, and the set with %ip is supposed to be below
  181. // the set with %ipp. Because we don't allow circular relationships like this,
  182. // we merge all concerned sets into one. So, the above code would generate a
  183. // single StratifiedSet: {%ip, %ipp, %i}.
  184. //
  185. // ==== Set remaps ====
  186. // More of an implementation detail than anything -- when merging sets, we need
  187. // to update the numbers of all of the elements mapped to those sets. Rather
  188. // than doing this at each merge, we note in the BuilderLink structure that a
  189. // remap has occurred, and use this information so we can defer renumbering set
  190. // elements until build time.
  191. template <typename T> class StratifiedSetsBuilder {
  192. // \brief Represents a Stratified Set, with information about the Stratified
  193. // Set above it, the set below it, and whether the current set has been
  194. // remapped to another.
  195. struct BuilderLink {
  196. const StratifiedIndex Number;
  197. BuilderLink(StratifiedIndex N) : Number(N) {
  198. Remap = StratifiedLink::SetSentinel;
  199. }
  200. bool hasAbove() const {
  201. assert(!isRemapped());
  202. return Link.hasAbove();
  203. }
  204. bool hasBelow() const {
  205. assert(!isRemapped());
  206. return Link.hasBelow();
  207. }
  208. void setBelow(StratifiedIndex I) {
  209. assert(!isRemapped());
  210. Link.Below = I;
  211. }
  212. void setAbove(StratifiedIndex I) {
  213. assert(!isRemapped());
  214. Link.Above = I;
  215. }
  216. void clearBelow() {
  217. assert(!isRemapped());
  218. Link.clearBelow();
  219. }
  220. void clearAbove() {
  221. assert(!isRemapped());
  222. Link.clearAbove();
  223. }
  224. StratifiedIndex getBelow() const {
  225. assert(!isRemapped());
  226. assert(hasBelow());
  227. return Link.Below;
  228. }
  229. StratifiedIndex getAbove() const {
  230. assert(!isRemapped());
  231. assert(hasAbove());
  232. return Link.Above;
  233. }
  234. StratifiedAttrs &getAttrs() {
  235. assert(!isRemapped());
  236. return Link.Attrs;
  237. }
  238. void setAttr(unsigned index) {
  239. assert(!isRemapped());
  240. assert(index < NumStratifiedAttrs);
  241. Link.Attrs.set(index);
  242. }
  243. void setAttrs(const StratifiedAttrs &other) {
  244. assert(!isRemapped());
  245. Link.Attrs |= other;
  246. }
  247. bool isRemapped() const { return Remap != StratifiedLink::SetSentinel; }
  248. // \brief For initial remapping to another set
  249. void remapTo(StratifiedIndex Other) {
  250. assert(!isRemapped());
  251. Remap = Other;
  252. }
  253. StratifiedIndex getRemapIndex() const {
  254. assert(isRemapped());
  255. return Remap;
  256. }
  257. // \brief Should only be called when we're already remapped.
  258. void updateRemap(StratifiedIndex Other) {
  259. assert(isRemapped());
  260. Remap = Other;
  261. }
  262. // \brief Prefer the above functions to calling things directly on what's
  263. // returned from this -- they guard against unexpected calls when the
  264. // current BuilderLink is remapped.
  265. const StratifiedLink &getLink() const { return Link; }
  266. private:
  267. StratifiedLink Link;
  268. StratifiedIndex Remap;
  269. };
  270. // \brief This function performs all of the set unioning/value renumbering
  271. // that we've been putting off, and generates a vector<StratifiedLink> that
  272. // may be placed in a StratifiedSets instance.
  273. void finalizeSets(std::vector<StratifiedLink> &StratLinks) {
  274. DenseMap<StratifiedIndex, StratifiedIndex> Remaps;
  275. for (auto &Link : Links) {
  276. if (Link.isRemapped()) {
  277. continue;
  278. }
  279. StratifiedIndex Number = StratLinks.size();
  280. Remaps.insert(std::make_pair(Link.Number, Number));
  281. StratLinks.push_back(Link.getLink());
  282. }
  283. for (auto &Link : StratLinks) {
  284. if (Link.hasAbove()) {
  285. auto &Above = linksAt(Link.Above);
  286. auto Iter = Remaps.find(Above.Number);
  287. assert(Iter != Remaps.end());
  288. Link.Above = Iter->second;
  289. }
  290. if (Link.hasBelow()) {
  291. auto &Below = linksAt(Link.Below);
  292. auto Iter = Remaps.find(Below.Number);
  293. assert(Iter != Remaps.end());
  294. Link.Below = Iter->second;
  295. }
  296. }
  297. for (auto &Pair : Values) {
  298. auto &Info = Pair.second;
  299. auto &Link = linksAt(Info.Index);
  300. auto Iter = Remaps.find(Link.Number);
  301. assert(Iter != Remaps.end());
  302. Info.Index = Iter->second;
  303. }
  304. }
  305. // \brief There's a guarantee in StratifiedLink where all bits set in a
  306. // Link.externals will be set in all Link.externals "below" it.
  307. static void propagateAttrs(std::vector<StratifiedLink> &Links) {
  308. const auto getHighestParentAbove = [&Links](StratifiedIndex Idx) {
  309. const auto *Link = &Links[Idx];
  310. while (Link->hasAbove()) {
  311. Idx = Link->Above;
  312. Link = &Links[Idx];
  313. }
  314. return Idx;
  315. };
  316. SmallSet<StratifiedIndex, 16> Visited;
  317. for (unsigned I = 0, E = Links.size(); I < E; ++I) {
  318. auto CurrentIndex = getHighestParentAbove(I);
  319. if (!Visited.insert(CurrentIndex).second) {
  320. continue;
  321. }
  322. while (Links[CurrentIndex].hasBelow()) {
  323. auto &CurrentBits = Links[CurrentIndex].Attrs;
  324. auto NextIndex = Links[CurrentIndex].Below;
  325. auto &NextBits = Links[NextIndex].Attrs;
  326. NextBits |= CurrentBits;
  327. CurrentIndex = NextIndex;
  328. }
  329. }
  330. }
  331. public:
  332. // \brief Builds a StratifiedSet from the information we've been given since
  333. // either construction or the prior build() call.
  334. StratifiedSets<T> build() {
  335. std::vector<StratifiedLink> StratLinks;
  336. finalizeSets(StratLinks);
  337. propagateAttrs(StratLinks);
  338. Links.clear();
  339. return StratifiedSets<T>(std::move(Values), std::move(StratLinks));
  340. }
  341. std::size_t size() const { return Values.size(); }
  342. std::size_t numSets() const { return Links.size(); }
  343. bool has(const T &Elem) const { return get(Elem).hasValue(); }
  344. bool add(const T &Main) {
  345. if (get(Main).hasValue())
  346. return false;
  347. auto NewIndex = getNewUnlinkedIndex();
  348. return addAtMerging(Main, NewIndex);
  349. }
  350. // \brief Restructures the stratified sets as necessary to make "ToAdd" in a
  351. // set above "Main". There are some cases where this is not possible (see
  352. // above), so we merge them such that ToAdd and Main are in the same set.
  353. bool addAbove(const T &Main, const T &ToAdd) {
  354. assert(has(Main));
  355. auto Index = *indexOf(Main);
  356. if (!linksAt(Index).hasAbove())
  357. addLinkAbove(Index);
  358. auto Above = linksAt(Index).getAbove();
  359. return addAtMerging(ToAdd, Above);
  360. }
  361. // \brief Restructures the stratified sets as necessary to make "ToAdd" in a
  362. // set below "Main". There are some cases where this is not possible (see
  363. // above), so we merge them such that ToAdd and Main are in the same set.
  364. bool addBelow(const T &Main, const T &ToAdd) {
  365. assert(has(Main));
  366. auto Index = *indexOf(Main);
  367. if (!linksAt(Index).hasBelow())
  368. addLinkBelow(Index);
  369. auto Below = linksAt(Index).getBelow();
  370. return addAtMerging(ToAdd, Below);
  371. }
  372. bool addWith(const T &Main, const T &ToAdd) {
  373. assert(has(Main));
  374. auto MainIndex = *indexOf(Main);
  375. return addAtMerging(ToAdd, MainIndex);
  376. }
  377. void noteAttribute(const T &Main, unsigned AttrNum) {
  378. assert(has(Main));
  379. assert(AttrNum < StratifiedLink::SetSentinel);
  380. auto *Info = *get(Main);
  381. auto &Link = linksAt(Info->Index);
  382. Link.setAttr(AttrNum);
  383. }
  384. void noteAttributes(const T &Main, const StratifiedAttrs &NewAttrs) {
  385. assert(has(Main));
  386. auto *Info = *get(Main);
  387. auto &Link = linksAt(Info->Index);
  388. Link.setAttrs(NewAttrs);
  389. }
  390. StratifiedAttrs getAttributes(const T &Main) {
  391. assert(has(Main));
  392. auto *Info = *get(Main);
  393. auto *Link = &linksAt(Info->Index);
  394. auto Attrs = Link->getAttrs();
  395. while (Link->hasAbove()) {
  396. Link = &linksAt(Link->getAbove());
  397. Attrs |= Link->getAttrs();
  398. }
  399. return Attrs;
  400. }
  401. bool getAttribute(const T &Main, unsigned AttrNum) {
  402. assert(AttrNum < StratifiedLink::SetSentinel);
  403. auto Attrs = getAttributes(Main);
  404. return Attrs[AttrNum];
  405. }
  406. // \brief Gets the attributes that have been applied to the set that Main
  407. // belongs to. It ignores attributes in any sets above the one that Main
  408. // resides in.
  409. StratifiedAttrs getRawAttributes(const T &Main) {
  410. assert(has(Main));
  411. auto *Info = *get(Main);
  412. auto &Link = linksAt(Info->Index);
  413. return Link.getAttrs();
  414. }
  415. // \brief Gets an attribute from the attributes that have been applied to the
  416. // set that Main belongs to. It ignores attributes in any sets above the one
  417. // that Main resides in.
  418. bool getRawAttribute(const T &Main, unsigned AttrNum) {
  419. assert(AttrNum < StratifiedLink::SetSentinel);
  420. auto Attrs = getRawAttributes(Main);
  421. return Attrs[AttrNum];
  422. }
  423. private:
  424. DenseMap<T, StratifiedInfo> Values;
  425. std::vector<BuilderLink> Links;
  426. // \brief Adds the given element at the given index, merging sets if
  427. // necessary.
  428. bool addAtMerging(const T &ToAdd, StratifiedIndex Index) {
  429. StratifiedInfo Info = {Index};
  430. auto Pair = Values.insert(std::make_pair(ToAdd, Info));
  431. if (Pair.second)
  432. return true;
  433. auto &Iter = Pair.first;
  434. auto &IterSet = linksAt(Iter->second.Index);
  435. auto &ReqSet = linksAt(Index);
  436. // Failed to add where we wanted to. Merge the sets.
  437. if (&IterSet != &ReqSet)
  438. merge(IterSet.Number, ReqSet.Number);
  439. return false;
  440. }
  441. // \brief Gets the BuilderLink at the given index, taking set remapping into
  442. // account.
  443. BuilderLink &linksAt(StratifiedIndex Index) {
  444. auto *Start = &Links[Index];
  445. if (!Start->isRemapped())
  446. return *Start;
  447. auto *Current = Start;
  448. while (Current->isRemapped())
  449. Current = &Links[Current->getRemapIndex()];
  450. auto NewRemap = Current->Number;
  451. // Run through everything that has yet to be updated, and update them to
  452. // remap to NewRemap
  453. Current = Start;
  454. while (Current->isRemapped()) {
  455. auto *Next = &Links[Current->getRemapIndex()];
  456. Current->updateRemap(NewRemap);
  457. Current = Next;
  458. }
  459. return *Current;
  460. }
  461. // \brief Merges two sets into one another. Assumes that these sets are not
  462. // already one in the same
  463. void merge(StratifiedIndex Idx1, StratifiedIndex Idx2) {
  464. assert(inbounds(Idx1) && inbounds(Idx2));
  465. assert(&linksAt(Idx1) != &linksAt(Idx2) &&
  466. "Merging a set into itself is not allowed");
  467. // CASE 1: If the set at `Idx1` is above or below `Idx2`, we need to merge
  468. // both the
  469. // given sets, and all sets between them, into one.
  470. if (tryMergeUpwards(Idx1, Idx2))
  471. return;
  472. if (tryMergeUpwards(Idx2, Idx1))
  473. return;
  474. // CASE 2: The set at `Idx1` is not in the same chain as the set at `Idx2`.
  475. // We therefore need to merge the two chains together.
  476. mergeDirect(Idx1, Idx2);
  477. }
  478. // \brief Merges two sets assuming that the set at `Idx1` is unreachable from
  479. // traversing above or below the set at `Idx2`.
  480. void mergeDirect(StratifiedIndex Idx1, StratifiedIndex Idx2) {
  481. assert(inbounds(Idx1) && inbounds(Idx2));
  482. auto *LinksInto = &linksAt(Idx1);
  483. auto *LinksFrom = &linksAt(Idx2);
  484. // Merging everything above LinksInto then proceeding to merge everything
  485. // below LinksInto becomes problematic, so we go as far "up" as possible!
  486. while (LinksInto->hasAbove() && LinksFrom->hasAbove()) {
  487. LinksInto = &linksAt(LinksInto->getAbove());
  488. LinksFrom = &linksAt(LinksFrom->getAbove());
  489. }
  490. if (LinksFrom->hasAbove()) {
  491. LinksInto->setAbove(LinksFrom->getAbove());
  492. auto &NewAbove = linksAt(LinksInto->getAbove());
  493. NewAbove.setBelow(LinksInto->Number);
  494. }
  495. // Merging strategy:
  496. // > If neither has links below, stop.
  497. // > If only `LinksInto` has links below, stop.
  498. // > If only `LinksFrom` has links below, reset `LinksInto.Below` to
  499. // match `LinksFrom.Below`
  500. // > If both have links above, deal with those next.
  501. while (LinksInto->hasBelow() && LinksFrom->hasBelow()) {
  502. auto &FromAttrs = LinksFrom->getAttrs();
  503. LinksInto->setAttrs(FromAttrs);
  504. // Remap needs to happen after getBelow(), but before
  505. // assignment of LinksFrom
  506. auto *NewLinksFrom = &linksAt(LinksFrom->getBelow());
  507. LinksFrom->remapTo(LinksInto->Number);
  508. LinksFrom = NewLinksFrom;
  509. LinksInto = &linksAt(LinksInto->getBelow());
  510. }
  511. if (LinksFrom->hasBelow()) {
  512. LinksInto->setBelow(LinksFrom->getBelow());
  513. auto &NewBelow = linksAt(LinksInto->getBelow());
  514. NewBelow.setAbove(LinksInto->Number);
  515. }
  516. LinksFrom->remapTo(LinksInto->Number);
  517. }
  518. // \brief Checks to see if lowerIndex is at a level lower than upperIndex.
  519. // If so, it will merge lowerIndex with upperIndex (and all of the sets
  520. // between) and return true. Otherwise, it will return false.
  521. bool tryMergeUpwards(StratifiedIndex LowerIndex, StratifiedIndex UpperIndex) {
  522. assert(inbounds(LowerIndex) && inbounds(UpperIndex));
  523. auto *Lower = &linksAt(LowerIndex);
  524. auto *Upper = &linksAt(UpperIndex);
  525. if (Lower == Upper)
  526. return true;
  527. SmallVector<BuilderLink *, 8> Found;
  528. auto *Current = Lower;
  529. auto Attrs = Current->getAttrs();
  530. while (Current->hasAbove() && Current != Upper) {
  531. Found.push_back(Current);
  532. Attrs |= Current->getAttrs();
  533. Current = &linksAt(Current->getAbove());
  534. }
  535. if (Current != Upper)
  536. return false;
  537. Upper->setAttrs(Attrs);
  538. if (Lower->hasBelow()) {
  539. auto NewBelowIndex = Lower->getBelow();
  540. Upper->setBelow(NewBelowIndex);
  541. auto &NewBelow = linksAt(NewBelowIndex);
  542. NewBelow.setAbove(UpperIndex);
  543. } else {
  544. Upper->clearBelow();
  545. }
  546. for (const auto &Ptr : Found)
  547. Ptr->remapTo(Upper->Number);
  548. return true;
  549. }
  550. Optional<const StratifiedInfo *> get(const T &Val) const {
  551. auto Result = Values.find(Val);
  552. if (Result == Values.end())
  553. return NoneType();
  554. return &Result->second;
  555. }
  556. Optional<StratifiedInfo *> get(const T &Val) {
  557. auto Result = Values.find(Val);
  558. if (Result == Values.end())
  559. return NoneType();
  560. return &Result->second;
  561. }
  562. Optional<StratifiedIndex> indexOf(const T &Val) {
  563. auto MaybeVal = get(Val);
  564. if (!MaybeVal.hasValue())
  565. return NoneType();
  566. auto *Info = *MaybeVal;
  567. auto &Link = linksAt(Info->Index);
  568. return Link.Number;
  569. }
  570. StratifiedIndex addLinkBelow(StratifiedIndex Set) {
  571. auto At = addLinks();
  572. Links[Set].setBelow(At);
  573. Links[At].setAbove(Set);
  574. return At;
  575. }
  576. StratifiedIndex addLinkAbove(StratifiedIndex Set) {
  577. auto At = addLinks();
  578. Links[At].setBelow(Set);
  579. Links[Set].setAbove(At);
  580. return At;
  581. }
  582. StratifiedIndex getNewUnlinkedIndex() { return addLinks(); }
  583. StratifiedIndex addLinks() {
  584. auto Link = Links.size();
  585. Links.push_back(BuilderLink(Link));
  586. return Link;
  587. }
  588. bool inbounds(StratifiedIndex N) const { return N < Links.size(); }
  589. };
  590. }
  591. #endif // LLVM_ADT_STRATIFIEDSETS_H