@@ -30,6 +30,13 @@ namespace wasm::analysis {
3030template <Lattice L> struct Vector {
3131 using Element = std::vector<typename L::Element>;
3232
33+ // Represent a vector in which all but one of the elements are bottom without
34+ // materializing the full vector.
35+ struct SingletonElement : std::pair<size_t , typename L::Element> {
36+ SingletonElement (size_t i, typename L::Element&& elem)
37+ : std::pair<size_t , typename L::Element>{i, std::move (elem)} {}
38+ };
39+
3340 L lattice;
3441 const size_t size;
3542
@@ -39,13 +46,7 @@ template<Lattice L> struct Vector {
3946 return Element (size, lattice.getBottom ());
4047 }
4148
42- Element getTop () const noexcept
43- #if __cplusplus >= 202002L
44- requires FullLattice<L>
45- #endif
46- {
47- return Element (size, lattice.getTop ());
48- }
49+ Element getTop () const noexcept { return Element (size, lattice.getTop ()); }
4950
5051 // `a` <= `b` if their elements are pairwise <=, etc. Unless we determine
5152 // that there is no relation, we must check all the elements.
@@ -84,48 +85,70 @@ template<Lattice L> struct Vector {
8485 assert (joiner.size () == size);
8586 bool result = false ;
8687 for (size_t i = 0 ; i < size; ++i) {
87- if constexpr (std::is_same_v<typename L::Element, bool >) {
88- // The vector<bool> specialization does not expose references to the
89- // individual bools because they might be in a bitmap, so we need a
90- // workaround.
91- bool e = joinee[i];
92- if (lattice.join (e, joiner[i])) {
93- joinee[i] = e;
94- result = true ;
95- }
96- } else {
97- result |= lattice.join (joinee[i], joiner[i]);
98- }
88+ result |= joinAtIndex (joinee, i, joiner[i]);
9989 }
100-
10190 return result;
10291 }
10392
93+ bool join (Element& joinee, const SingletonElement& joiner) const noexcept {
94+ const auto & [index, elem] = joiner;
95+ assert (index < joinee.size ());
96+ return joinAtIndex (joinee, index, elem);
97+ }
98+
10499 // Pairwise meet on the elements.
105- bool meet (Element& meetee, const Element& meeter) const noexcept
106- #if __cplusplus >= 202002L
107- requires FullLattice<L>
108- #endif
109- {
100+ bool meet (Element& meetee, const Element& meeter) const noexcept {
110101 assert (meetee.size () == size);
111102 assert (meeter.size () == size);
112103 bool result = false ;
113104 for (size_t i = 0 ; i < size; ++i) {
114- if constexpr (std::is_same_v<typename L::Element, bool >) {
115- // The vector<bool> specialization does not expose references to the
116- // individual bools because they might be in a bitmap, so we need a
117- // workaround.
118- bool e = meetee[i];
119- if (lattice.meet (e, meeter[i])) {
120- meetee[i] = e;
121- result = true ;
122- }
123- } else {
124- result |= lattice.meet (meetee[i], meeter[i]);
125- }
105+ result |= meetAtIndex (meetee, i, meeter[i]);
126106 }
127107 return result;
128108 }
109+
110+ bool meet (Element& meetee, const SingletonElement& meeter) const noexcept {
111+ const auto & [index, elem] = meeter;
112+ assert (index < meetee.size ());
113+ return meetAtIndex (meetee, index, elem);
114+ }
115+
116+ private:
117+ bool joinAtIndex (Element& joinee,
118+ size_t i,
119+ const typename L::Element& elem) const noexcept {
120+ if constexpr (std::is_same_v<typename L::Element, bool >) {
121+ // The vector<bool> specialization does not expose references to the
122+ // individual bools because they might be in a bitmap, so we need a
123+ // workaround.
124+ bool e = joinee[i];
125+ if (lattice.join (e, elem)) {
126+ joinee[i] = e;
127+ return true ;
128+ }
129+ return false ;
130+ } else {
131+ return lattice.join (joinee[i], elem);
132+ }
133+ }
134+
135+ bool meetAtIndex (Element& meetee,
136+ size_t i,
137+ const typename L::Element& elem) const noexcept {
138+ if constexpr (std::is_same_v<typename L::Element, bool >) {
139+ // The vector<bool> specialization does not expose references to the
140+ // individual bools because they might be in a bitmap, so we need a
141+ // workaround.
142+ bool e = meetee[i];
143+ if (lattice.meet (e, elem)) {
144+ meetee[i] = e;
145+ return true ;
146+ }
147+ return false ;
148+ } else {
149+ return lattice.meet (meetee[i], elem);
150+ }
151+ }
129152};
130153
131154#if __cplusplus >= 202002L
0 commit comments