Skip to content

Commit a4aef54

Browse files
committed
[AddressLowering] NFC: Add projection iterator.
Used the iterator to replace recursion in get*Storage functions with for loops.
1 parent d9cf437 commit a4aef54

File tree

1 file changed

+78
-21
lines changed

1 file changed

+78
-21
lines changed

lib/SILOptimizer/Mandatory/AddressLowering.h

Lines changed: 78 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,12 @@
1010
//
1111
//===----------------------------------------------------------------------===//
1212

13+
#include "swift/Basic/LLVM.h"
1314
#include "swift/SIL/SILArgument.h"
1415
#include "swift/SIL/SILInstruction.h"
1516
#include "swift/SIL/SILValue.h"
1617
#include "llvm/ADT/DenseMap.h"
18+
#include "llvm/ADT/STLExtras.h"
1719

1820
namespace swift {
1921

@@ -217,6 +219,63 @@ class ValueStorageMap {
217219
SWIFT_ASSERT_ONLY_DECL(bool stableStorage = false);
218220

219221
public:
222+
class ProjectionIterator {
223+
public:
224+
using This = ProjectionIterator;
225+
using iterator_category = std::forward_iterator_tag;
226+
using value_type = ValueStoragePair const *;
227+
using difference_type = std::ptrdiff_t;
228+
using pointer = value_type *;
229+
using reference = value_type &;
230+
231+
protected:
232+
value_type Cur;
233+
ValueStorageMap const ⤅
234+
235+
public:
236+
explicit ProjectionIterator(value_type cur, ValueStorageMap const &map)
237+
: Cur(cur), Map(map) {}
238+
ValueStoragePair const *operator->() const { return Cur; }
239+
ValueStoragePair const *operator*() const { return Cur; }
240+
241+
ValueStorage const &getStorage() const { return Cur->storage; }
242+
SILValue getValue() const { return Cur->value; }
243+
This &operator++() {
244+
assert(Cur && "incrementing past end()!");
245+
if (Cur->storage.isProjection())
246+
Cur = &Map.getProjectedStorage(Cur->storage);
247+
else
248+
Cur = nullptr;
249+
return *this;
250+
}
251+
252+
This operator++(int unused) {
253+
This copy = *this;
254+
++*this;
255+
return copy;
256+
}
257+
258+
friend bool operator==(This lhs, This rhs) { return lhs.Cur == rhs.Cur; }
259+
friend bool operator!=(This lhs, This rhs) { return !(lhs == rhs); }
260+
};
261+
262+
ProjectionIterator projection_begin(SILValue value) const {
263+
return ProjectionIterator(&valueVector[getOrdinal(value)], *this);
264+
}
265+
ProjectionIterator projection_end() const {
266+
return ProjectionIterator(nullptr, *this);
267+
}
268+
/// Returns projections of the specified value from the inside out, starting
269+
/// from the projection for the value and walking outwards to its storage
270+
/// root.
271+
iterator_range<ProjectionIterator> getProjections(SILValue value) const {
272+
if (!contains(value))
273+
return {projection_end(), projection_end()};
274+
return {projection_begin(value), projection_end()};
275+
}
276+
277+
friend class ProjectionIterator;
278+
220279
bool empty() const { return valueVector.empty(); }
221280

222281
void clear() {
@@ -276,35 +335,33 @@ class ValueStorageMap {
276335
return valueVector[storage.projectedStorageID];
277336
}
278337

279-
/// Return the non-projection storage that the given storage ultimately refers
280-
/// to by following all projections. After allocation, this storage always has
281-
/// a valid address.
282-
const ValueStorage &getBaseStorage(const ValueStorage &storage) {
283-
if (storage.isDefProjection || storage.isUseProjection)
284-
return getBaseStorage(getProjectedStorage(storage).storage);
285-
286-
return storage;
287-
}
288-
289338
/// Return the non-projection storage that the given storage ultimately refers
290339
/// to by following all projections.
291340
const ValueStorage &getBaseStorage(SILValue value) {
292-
return getBaseStorage(getStorage(value));
341+
ValueStorage const *last = nullptr;
342+
for (auto *pair : getProjections(value)) {
343+
last = &pair->storage;
344+
}
345+
return *last;
293346
}
294347

295348
/// Return the non-projection storage that this storage refers to. If this
296349
/// storage holds an Enum or any intermediate storage that projects into this
297350
/// storage holds an Enum, then return nullptr.
298-
const ValueStorage *getNonEnumBaseStorage(const ValueStorage &storage) {
299-
if (storage.initializesEnum)
300-
return nullptr;
301-
302-
if (storage.isUseProjection) {
303-
auto &storageAndValue = getProjectedStorage(storage);
304-
return getNonEnumBaseStorage(storageAndValue.storage);
351+
const ValueStorage *getNonEnumBaseStorage(SILValue value) {
352+
for (auto *pair : getProjections(value)) {
353+
auto const &storage = pair->storage;
354+
if (storage.initializesEnum)
355+
return nullptr;
356+
357+
if (storage.isUseProjection) {
358+
continue;
359+
}
360+
assert(!storage.isDefProjection &&
361+
"def projections should not reach here");
362+
return &storage;
305363
}
306-
assert(!storage.isDefProjection && "def projections should not reach here");
307-
return &storage;
364+
llvm_unreachable("found no non-projection storage!?");
308365
}
309366

310367
/// Return the non-projection storage that this storage refers to, or nullptr
@@ -313,7 +370,7 @@ class ValueStorageMap {
313370
if (allowInitEnum)
314371
return &getBaseStorage(value);
315372

316-
return getNonEnumBaseStorage(getStorage(value));
373+
return getNonEnumBaseStorage(value);
317374
}
318375

319376
void setStorageAddress(SILValue value, SILValue addr) {

0 commit comments

Comments
 (0)