@@ -30,6 +30,13 @@ namespace wasm::analysis {
30
30
template <Lattice L> struct Vector {
31
31
using Element = std::vector<typename L::Element>;
32
32
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
+
33
40
L lattice;
34
41
const size_t size;
35
42
@@ -39,13 +46,7 @@ template<Lattice L> struct Vector {
39
46
return Element (size, lattice.getBottom ());
40
47
}
41
48
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 ()); }
49
50
50
51
// `a` <= `b` if their elements are pairwise <=, etc. Unless we determine
51
52
// that there is no relation, we must check all the elements.
@@ -84,48 +85,70 @@ template<Lattice L> struct Vector {
84
85
assert (joiner.size () == size);
85
86
bool result = false ;
86
87
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]);
99
89
}
100
-
101
90
return result;
102
91
}
103
92
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
+
104
99
// 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 {
110
101
assert (meetee.size () == size);
111
102
assert (meeter.size () == size);
112
103
bool result = false ;
113
104
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]);
126
106
}
127
107
return result;
128
108
}
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
+ }
129
152
};
130
153
131
154
#if __cplusplus >= 202002L
0 commit comments