Skip to content

Commit bfec410

Browse files
authored
Merge pull request swiftlang#27060 from gottesmm/pr-6e8972071ad9a8006749aecd85e288ae0cfb3a5f
[sil] Add new API ValueBase:getUsersOfType<T>().
2 parents 31b1674 + 7b2fc07 commit bfec410

File tree

3 files changed

+50
-31
lines changed

3 files changed

+50
-31
lines changed

include/swift/Basic/STLExtras.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -578,6 +578,8 @@ class OptionalTransformIterator {
578578
return *Op(*Current);
579579
}
580580

581+
reference operator*() { return *Op(*Current); }
582+
581583
OptionalTransformIterator &operator++() {
582584
++Current;
583585
skipNonMatching();

include/swift/SIL/SILInstruction.h

Lines changed: 8 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -3287,16 +3287,6 @@ class StoreInst
32873287

32883288
class EndBorrowInst;
32893289

3290-
struct UseToEndBorrow {
3291-
Optional<EndBorrowInst *> operator()(Operand *use) const {
3292-
if (auto endBorrow = dyn_cast<EndBorrowInst>(use->getUser())) {
3293-
return endBorrow;
3294-
} else {
3295-
return None;
3296-
}
3297-
}
3298-
};
3299-
33003290
/// Represents a load of a borrowed value. Must be paired with an end_borrow
33013291
/// instruction in its use-def list.
33023292
class LoadBorrowInst :
@@ -3310,14 +3300,14 @@ class LoadBorrowInst :
33103300
LValue->getType().getObjectType()) {}
33113301

33123302
using EndBorrowRange =
3313-
OptionalTransformRange<use_range, UseToEndBorrow, use_iterator>;
3303+
decltype(std::declval<ValueBase>().getUsersOfType<EndBorrowInst>());
33143304

33153305
/// Return a range over all EndBorrow instructions for this BeginBorrow.
33163306
EndBorrowRange getEndBorrows() const;
33173307
};
33183308

33193309
inline auto LoadBorrowInst::getEndBorrows() const -> EndBorrowRange {
3320-
return EndBorrowRange(getUses(), UseToEndBorrow());
3310+
return getUsersOfType<EndBorrowInst>();
33213311
}
33223312

33233313
/// Represents the begin scope of a borrowed value. Must be paired with an
@@ -3333,7 +3323,7 @@ class BeginBorrowInst
33333323

33343324
public:
33353325
using EndBorrowRange =
3336-
OptionalTransformRange<use_range, UseToEndBorrow, use_iterator>;
3326+
decltype(std::declval<ValueBase>().getUsersOfType<EndBorrowInst>());
33373327

33383328
/// Return a range over all EndBorrow instructions for this BeginBorrow.
33393329
EndBorrowRange getEndBorrows() const;
@@ -3348,7 +3338,7 @@ class BeginBorrowInst
33483338
};
33493339

33503340
inline auto BeginBorrowInst::getEndBorrows() const -> EndBorrowRange {
3351-
return EndBorrowRange(getUses(), UseToEndBorrow());
3341+
return getUsersOfType<EndBorrowInst>();
33523342
}
33533343

33543344
/// Represents a store of a borrowed value into an address. Returns the borrowed
@@ -3487,6 +3477,8 @@ enum class SILAccessEnforcement : uint8_t {
34873477
};
34883478
StringRef getSILAccessEnforcementName(SILAccessEnforcement enforcement);
34893479

3480+
class EndAccessInst;
3481+
34903482
/// Begins an access scope. Must be paired with an end_access instruction
34913483
/// along every path.
34923484
class BeginAccessInst
@@ -3558,13 +3550,8 @@ class BeginAccessInst
35583550
return getOperand();
35593551
}
35603552

3561-
private:
3562-
/// Predicate used to filter EndAccessRange.
3563-
struct UseToEndAccess;
3564-
3565-
public:
35663553
using EndAccessRange =
3567-
OptionalTransformRange<use_range, UseToEndAccess, use_iterator>;
3554+
decltype(std::declval<ValueBase>().getUsersOfType<EndAccessInst>());
35683555

35693556
/// Find all the associated end_access instructions for this begin_access.
35703557
EndAccessRange getEndAccesses() const;
@@ -3605,18 +3592,8 @@ class EndAccessInst
36053592
}
36063593
};
36073594

3608-
struct BeginAccessInst::UseToEndAccess {
3609-
Optional<EndAccessInst *> operator()(Operand *use) const {
3610-
if (auto access = dyn_cast<EndAccessInst>(use->getUser())) {
3611-
return access;
3612-
} else {
3613-
return None;
3614-
}
3615-
}
3616-
};
3617-
36183595
inline auto BeginAccessInst::getEndAccesses() const -> EndAccessRange {
3619-
return EndAccessRange(getUses(), UseToEndAccess());
3596+
return getUsersOfType<EndAccessInst>();
36203597
}
36213598

36223599
/// Begins an access without requiring a paired end_access.

include/swift/SIL/SILValue.h

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -275,6 +275,27 @@ class ValueBase : public SILNode, public SILAllocated<ValueBase> {
275275
template <class T>
276276
inline T *getSingleUserOfType() const;
277277

278+
/// Helper struct for DowncastUserFilterRange
279+
struct UseToUser;
280+
281+
template <typename Subclass>
282+
using DowncastUserFilterRange =
283+
DowncastFilterRange<Subclass,
284+
llvm::iterator_range<llvm::mapped_iterator<
285+
use_iterator, UseToUser, SILInstruction *>>>;
286+
287+
/// Iterate over the use list of this ValueBase visiting all users that are of
288+
/// class T.
289+
///
290+
/// Example:
291+
///
292+
/// ValueBase *v = ...;
293+
/// for (CopyValueInst *cvi : v->getUsersOfType<CopyValueInst>()) { ... }
294+
///
295+
/// NOTE: Uses llvm::dyn_cast internally.
296+
template <typename T>
297+
inline DowncastUserFilterRange<T> getUsersOfType() const;
298+
278299
/// Return the instruction that defines this value, or null if it is
279300
/// not defined by an instruction.
280301
const SILInstruction *getDefiningInstruction() const {
@@ -717,6 +738,25 @@ inline T *ValueBase::getSingleUserOfType() const {
717738
return Result;
718739
}
719740

741+
struct ValueBase::UseToUser {
742+
SILInstruction *operator()(const Operand *use) const {
743+
return const_cast<SILInstruction *>(use->getUser());
744+
}
745+
SILInstruction *operator()(const Operand &use) const {
746+
return const_cast<SILInstruction *>(use.getUser());
747+
}
748+
SILInstruction *operator()(Operand *use) { return use->getUser(); }
749+
SILInstruction *operator()(Operand &use) { return use.getUser(); }
750+
};
751+
752+
template <typename T>
753+
inline ValueBase::DowncastUserFilterRange<T> ValueBase::getUsersOfType() const {
754+
auto begin = llvm::map_iterator(use_begin(), UseToUser());
755+
auto end = llvm::map_iterator(use_end(), UseToUser());
756+
auto transformRange = llvm::make_range(begin, end);
757+
return makeDowncastFilterRange<T>(transformRange);
758+
}
759+
720760
/// A constant-size list of the operands of an instruction.
721761
template <unsigned N> class FixedOperandList {
722762
Operand Buffer[N];

0 commit comments

Comments
 (0)