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