Skip to content

Commit abe37fe

Browse files
committed
Refactor the collection of type-dependent operands
Should be NFC in impact, but some of the existing patterns can produce redundant dependencies in probably-obscure cases, so it's not purely a refactor.
1 parent 0d666e2 commit abe37fe

File tree

1 file changed

+82
-56
lines changed

1 file changed

+82
-56
lines changed

lib/SIL/IR/SILInstructions.cpp

Lines changed: 82 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -43,70 +43,105 @@ static void *allocateTrailingInst(SILFunction &F, CountTypes... counts) {
4343
alignof(Inst));
4444
}
4545

46+
namespace {
47+
class TypeDependentOperandCollector {
48+
SmallVector<CanOpenedArchetypeType, 4> rootOpenedArchetypes;
49+
bool hasDynamicSelf = false;
50+
public:
51+
void collect(CanType type);
52+
void collect(SubstitutionMap subs);
53+
void collect(SILType type) {
54+
collect(type.getASTType());
55+
}
56+
template <class T>
57+
void collect(ArrayRef<T> array) {
58+
for (auto &elt: array)
59+
collect(elt);
60+
}
61+
62+
void collectAll() {}
63+
template <class T, class... Ts>
64+
void collectAll(T &&first, Ts &&...rest) {
65+
collect(first);
66+
collectAll(std::forward<Ts>(rest)...);
67+
}
68+
69+
void addTo(SmallVectorImpl<SILValue> &typeDependentOperands,
70+
SILFunction &f);
71+
};
72+
73+
}
74+
4675
/// Collect root open archetypes from a given type into \p RootOpenedArchetypes.
4776
/// \p RootOpenedArchetypes is being used as a set. We don't use a real set type
4877
/// here for performance reasons.
49-
static void collectDependentTypeInfo(
50-
CanType Ty, SmallVectorImpl<CanOpenedArchetypeType> &RootOpenedArchetypes,
51-
bool &hasDynamicSelf) {
52-
if (!Ty)
78+
void TypeDependentOperandCollector::collect(CanType type) {
79+
if (!type)
5380
return;
54-
if (Ty->hasDynamicSelfType())
81+
if (type->hasDynamicSelfType())
5582
hasDynamicSelf = true;
56-
if (!Ty->hasOpenedExistential())
83+
if (!type->hasOpenedExistential())
5784
return;
58-
Ty.visit([&](CanType t) {
85+
type.visit([&](CanType t) {
5986
if (const auto opened = dyn_cast<OpenedArchetypeType>(t)) {
6087
const auto root = opened.getRoot();
6188

6289
// Add this root opened archetype if it was not seen yet.
6390
// We don't use a set here, because the number of open archetypes
6491
// is usually very small and using a real set may introduce too
6592
// much overhead.
66-
if (std::find(RootOpenedArchetypes.begin(), RootOpenedArchetypes.end(),
67-
root) == RootOpenedArchetypes.end())
68-
RootOpenedArchetypes.push_back(root);
93+
if (std::find(rootOpenedArchetypes.begin(), rootOpenedArchetypes.end(),
94+
root) == rootOpenedArchetypes.end())
95+
rootOpenedArchetypes.push_back(root);
6996
}
7097
});
7198
}
7299

73-
/// Takes a set of root opened archetypes as input and produces a set of
74-
/// references to their definitions.
75-
static void buildTypeDependentOperands(
76-
SmallVectorImpl<CanOpenedArchetypeType> &RootOpenedArchetypes,
77-
bool hasDynamicSelf, SmallVectorImpl<SILValue> &TypeDependentOperands,
78-
SILFunction &F) {
100+
/// Collect type dependencies from the replacement types of a
101+
/// substitution map.
102+
void TypeDependentOperandCollector::collect(SubstitutionMap subs) {
103+
for (Type replacement : subs.getReplacementTypes()) {
104+
// Substitutions in SIL should really be canonical.
105+
auto ReplTy = replacement->getCanonicalType();
106+
collect(ReplTy);
107+
}
108+
}
79109

80-
for (const auto &archetype : RootOpenedArchetypes) {
110+
/// Given that we've collected a set of type dependencies, add operands
111+
/// for those dependencies to the given vector.
112+
void TypeDependentOperandCollector::addTo(SmallVectorImpl<SILValue> &operands,
113+
SILFunction &F) {
114+
size_t firstArchetypeOperand = operands.size();
115+
for (CanOpenedArchetypeType archetype : rootOpenedArchetypes) {
81116
SILValue def = F.getModule().getRootOpenedArchetypeDef(archetype, &F);
82117
assert(def->getFunction() == &F &&
83118
"def of root opened archetype is in wrong function");
84-
TypeDependentOperands.push_back(def);
119+
120+
// The archetypes in rootOpenedArchetypes have already been uniqued,
121+
// but a single instruction can open multiple archetypes (e.g.
122+
// open_pack_element), so we also unique the actual operand values.
123+
// As above, we assume there are very few values in practice and so
124+
// a linear scan is better than maintaining a set.
125+
if (std::find(operands.begin() + firstArchetypeOperand, operands.end(),
126+
def) == operands.end())
127+
operands.push_back(def);
85128
}
86129
if (hasDynamicSelf)
87-
TypeDependentOperands.push_back(F.getDynamicSelfMetadata());
130+
operands.push_back(F.getDynamicSelfMetadata());
88131
}
89132

90133
/// Collects all root opened archetypes from a type and a substitution list, and
91134
/// forms a corresponding list of operands.
92135
/// We need to know the number of root opened archetypes to estimate the number
93136
/// of corresponding operands for the instruction being formed, because we need
94137
/// to reserve enough memory for these operands.
138+
template <class... Sources>
95139
static void collectTypeDependentOperands(
96-
SmallVectorImpl<SILValue> &TypeDependentOperands,
97-
SILFunction &F,
98-
CanType Ty,
99-
SubstitutionMap subs = { }) {
100-
SmallVector<CanOpenedArchetypeType, 4> RootOpenedArchetypes;
101-
bool hasDynamicSelf = false;
102-
collectDependentTypeInfo(Ty, RootOpenedArchetypes, hasDynamicSelf);
103-
for (Type replacement : subs.getReplacementTypes()) {
104-
// Substitutions in SIL should really be canonical.
105-
auto ReplTy = replacement->getCanonicalType();
106-
collectDependentTypeInfo(ReplTy, RootOpenedArchetypes, hasDynamicSelf);
107-
}
108-
buildTypeDependentOperands(RootOpenedArchetypes, hasDynamicSelf,
109-
TypeDependentOperands, F);
140+
SmallVectorImpl<SILValue> &typeDependentOperands,
141+
SILFunction &F, Sources &&... sources) {
142+
TypeDependentOperandCollector collector;
143+
collector.collectAll(std::forward<Sources>(sources)...);
144+
collector.addTo(typeDependentOperands, F);
110145
}
111146

112147
//===----------------------------------------------------------------------===//
@@ -284,10 +319,7 @@ AllocRefInst *AllocRefInst::create(SILDebugLocation Loc, SILFunction &F,
284319
assert(!objc || ElementTypes.empty());
285320
SmallVector<SILValue, 8> AllOperands(ElementCountOperands.begin(),
286321
ElementCountOperands.end());
287-
for (SILType ElemType : ElementTypes) {
288-
collectTypeDependentOperands(AllOperands, F, ElemType.getASTType());
289-
}
290-
collectTypeDependentOperands(AllOperands, F, ObjectType.getASTType());
322+
collectTypeDependentOperands(AllOperands, F, ElementTypes, ObjectType);
291323
auto Size = totalSizeToAlloc<swift::Operand, SILType>(AllOperands.size(),
292324
ElementTypes.size());
293325
auto Buffer = F.getModule().allocateInst(Size, alignof(AllocRefInst));
@@ -304,10 +336,7 @@ AllocRefDynamicInst::create(SILDebugLocation DebugLoc, SILFunction &F,
304336
SmallVector<SILValue, 8> AllOperands(ElementCountOperands.begin(),
305337
ElementCountOperands.end());
306338
AllOperands.push_back(metatypeOperand);
307-
collectTypeDependentOperands(AllOperands, F, ty.getASTType());
308-
for (SILType ElemType : ElementTypes) {
309-
collectTypeDependentOperands(AllOperands, F, ElemType.getASTType());
310-
}
339+
collectTypeDependentOperands(AllOperands, F, ty, ElementTypes);
311340
auto Size = totalSizeToAlloc<swift::Operand, SILType>(AllOperands.size(),
312341
ElementTypes.size());
313342
auto Buffer = F.getModule().allocateInst(Size, alignof(AllocRefDynamicInst));
@@ -1249,14 +1278,13 @@ UncheckedRefCastAddrInst *
12491278
UncheckedRefCastAddrInst::create(SILDebugLocation Loc, SILValue src,
12501279
CanType srcType, SILValue dest, CanType targetType, SILFunction &F) {
12511280
SILModule &Mod = F.getModule();
1252-
SmallVector<SILValue, 8> TypeDependentOperands;
1253-
collectTypeDependentOperands(TypeDependentOperands, F, srcType);
1254-
collectTypeDependentOperands(TypeDependentOperands, F, targetType);
1281+
SmallVector<SILValue, 4> allOperands;
1282+
collectTypeDependentOperands(allOperands, F, srcType, targetType);
12551283
unsigned size =
1256-
totalSizeToAlloc<swift::Operand>(2 + TypeDependentOperands.size());
1284+
totalSizeToAlloc<swift::Operand>(2 + allOperands.size());
12571285
void *Buffer = Mod.allocateInst(size, alignof(UncheckedRefCastAddrInst));
12581286
return ::new (Buffer) UncheckedRefCastAddrInst(Loc, src, srcType,
1259-
dest, targetType, TypeDependentOperands);
1287+
dest, targetType, allOperands);
12601288
}
12611289

12621290
UnconditionalCheckedCastAddrInst::UnconditionalCheckedCastAddrInst(
@@ -1269,14 +1297,13 @@ UnconditionalCheckedCastAddrInst *
12691297
UnconditionalCheckedCastAddrInst::create(SILDebugLocation Loc, SILValue src,
12701298
CanType srcType, SILValue dest, CanType targetType, SILFunction &F) {
12711299
SILModule &Mod = F.getModule();
1272-
SmallVector<SILValue, 8> TypeDependentOperands;
1273-
collectTypeDependentOperands(TypeDependentOperands, F, srcType);
1274-
collectTypeDependentOperands(TypeDependentOperands, F, targetType);
1300+
SmallVector<SILValue, 4> allOperands;
1301+
collectTypeDependentOperands(allOperands, F, srcType, targetType);
12751302
unsigned size =
1276-
totalSizeToAlloc<swift::Operand>(2 + TypeDependentOperands.size());
1303+
totalSizeToAlloc<swift::Operand>(2 + allOperands.size());
12771304
void *Buffer = Mod.allocateInst(size, alignof(UnconditionalCheckedCastAddrInst));
12781305
return ::new (Buffer) UnconditionalCheckedCastAddrInst(Loc, src, srcType,
1279-
dest, targetType, TypeDependentOperands);
1306+
dest, targetType, allOperands);
12801307
}
12811308

12821309
CheckedCastAddrBranchInst::CheckedCastAddrBranchInst(
@@ -1300,14 +1327,13 @@ CheckedCastAddrBranchInst::create(SILDebugLocation DebugLoc,
13001327
ProfileCounter Target1Count, ProfileCounter Target2Count,
13011328
SILFunction &F) {
13021329
SILModule &Mod = F.getModule();
1303-
SmallVector<SILValue, 8> TypeDependentOperands;
1304-
collectTypeDependentOperands(TypeDependentOperands, F, srcType);
1305-
collectTypeDependentOperands(TypeDependentOperands, F, targetType);
1330+
SmallVector<SILValue, 4> allOperands;
1331+
collectTypeDependentOperands(allOperands, F, srcType, targetType);
13061332
unsigned size =
1307-
totalSizeToAlloc<swift::Operand>(2 + TypeDependentOperands.size());
1333+
totalSizeToAlloc<swift::Operand>(2 + allOperands.size());
13081334
void *Buffer = Mod.allocateInst(size, alignof(CheckedCastAddrBranchInst));
13091335
return ::new (Buffer) CheckedCastAddrBranchInst(DebugLoc, consumptionKind,
1310-
src, srcType, dest, targetType, TypeDependentOperands,
1336+
src, srcType, dest, targetType, allOperands,
13111337
successBB, failureBB, Target1Count, Target2Count);
13121338
}
13131339

0 commit comments

Comments
 (0)